static stm_blk * _successor_non_stm(ptst_t *ptst, stm_tx *tx, stm_blk * tb) { stm_blk *chb, *pb, *plb; node_t *t, *ch, *p; if(tb == NULL) { return NULL; } else { t = init_stm_blk__(ptst, MEMORY, tb); if(GET_RIGHT(t) != NULL) { pb = GET_RIGHT(t); p = init_stm_blk__(ptst, MEMORY, pb); while ( (plb=GET_LEFT(p)) != NULL ) { pb = plb; p = init_stm_blk__(ptst, MEMORY, pb); } return pb; } else {//GET_RIGHT(t) == NULLL pb = GET_PARENT(t); p = init_stm_blk__(ptst, MEMORY, pb); chb = tb; ch = t; while(pb != NULL && chb == GET_RIGHT(p)) { chb = pb; ch = p; pb = GET_PARENT(p); p = init_stm_blk__(ptst, MEMORY, pb); } return pb; } } }
static int sift_up(GW_LARGE_INT start, HEAP_PNT child_p) { GW_LARGE_INT parent, child; HEAP_PNT heap_p; child = start; while (child > 1) { parent = GET_PARENT(child); seg_get(&search_heap, (char *)&heap_p, 0, parent); /* push parent point down if child is smaller */ if (heap_cmp(&child_p, &heap_p)) { seg_put(&search_heap, (char *)&heap_p, 0, child); child = parent; } else /* no more sifting up, found slot for child */ break; } /* add child to heap */ seg_put(&search_heap, (char *)&child_p, 0, child); return 0; }
static struct dentry *lookup_whiteout(struct dentry *dentry) { char *whname; int bindex = -1, bstart = -1, bend = -1; struct dentry *parent, *hidden_parent, *wh_dentry; whname = alloc_whname(dentry->d_name.name, dentry->d_name.len); if (IS_ERR(whname)) return (void *)whname; parent = GET_PARENT(dentry); lock_dentry(parent); bstart = dbstart(parent); bend = dbend(parent); wh_dentry = ERR_PTR(-ENOENT); for (bindex = bstart; bindex <= bend; bindex++) { hidden_parent = dtohd_index(parent, bindex); if (!hidden_parent) continue; wh_dentry = LOOKUP_ONE_LEN(whname, hidden_parent, dentry->d_name.len + WHLEN); if (IS_ERR(wh_dentry)) continue; if (wh_dentry->d_inode) break; DPUT(wh_dentry); wh_dentry = ERR_PTR(-ENOENT); } unlock_dentry(parent); DPUT(parent); KFREE(whname); return wh_dentry; }
// x must be already open for writing // x must have a parent static void _right_rotate(ptst_t *ptst, stm_tx *tx, stm_blk *sb, stm_blk *xb, node_t *x) { stm_blk *lb, *lrb, *pb; node_t *l, *lr, *p; lb = GET_LEFT(x); pb = GET_PARENT(x); l = WRITE_OBJ(lb); p = WRITE_OBJ(pb); lrb = GET_RIGHT(l); x = WRITE_OBJ(xb); SET_LEFT(x, lrb); if (lrb != NULL ) { lr = WRITE_OBJ(lrb); SET_PARENT(lr, xb); } SET_PARENT(l, pb); if(pb == NULL) { set_t * s = (set_t*) WRITE_OBJ(sb); SET_ROOT(s, lb); } else if ( xb == GET_RIGHT(p) ) { SET_RIGHT(p, lb); } else { SET_LEFT(p, lb); } SET_RIGHT(l, xb); SET_PARENT(x, lb); }//right_rotate
// x must be already open for writing // x must have a parent static void _left_rotate(ptst_t *ptst, stm_tx *tx, stm_blk *sb, stm_blk *xb, node_t *x) { stm_blk *rb, *rlb, *pb; node_t *r, *rl, *p; rb = GET_RIGHT(x); pb = GET_PARENT(x); r = WRITE_OBJ(rb); p = WRITE_OBJ(pb); rlb = GET_LEFT(r); x = WRITE_OBJ(xb); SET_RIGHT(x, rlb); if ( rlb != NULL ) { rl = WRITE_OBJ(rlb); SET_PARENT(rl, xb); } SET_PARENT(r, pb); if(pb == NULL) { set_t * s = (set_t*) WRITE_OBJ(sb); SET_ROOT(s, rb); } else if ( GET_LEFT(p) == xb ) { SET_LEFT(p, rb); } else { SET_RIGHT(p, rb); } SET_LEFT(r, xb); SET_PARENT(x, rb); }//left_rotate
/*得到node结点的外舅结点并将其存在uncle中*/ Status getUncle(RBTree node,RBTree &uncle){ RBTree parent = GET_PARENT(node); RBTree grandparent; if(!parent) return ERROR; else grandparent = GET_PARENT(parent); if(!node || !parent || !grandparent) return ERROR; if(parent == grandparent->lchild){ uncle = grandparent->rchild; if(uncle == NULL) return ERROR; return OK; }else{ uncle = grandparent->lchild; if(uncle == NULL) return ERROR; return OK; } }
static Status RBTree_delete_realize_case1(pt_RBRoot root,RBTree node){ RBTree replaceNodeChild,replaceNodeParent; ColorType replaceNodeColor; if(node->lchild && node->rchild){ RBTree replaceNode = node; replaceNode = node->rchild; while(replaceNode->lchild){ replaceNode = replaceNode->lchild; } if(GET_PARENT(node)){ if(node == node->parent->lchild){ node->parent->lchild = replaceNode; }else{ node->parent->rchild = replaceNode; } }else{ root->RBRootNode = replaceNode; } replaceNodeChild = replaceNode->rchild; replaceNodeParent = replaceNode->parent; replaceNodeColor = replaceNode->color; if(replaceNodeParent == node){ replaceNodeParent = replaceNode; }else{ if(replaceNodeChild){ replaceNodeChild->parent = replaceNodeParent; } replaceNodeParent->lchild = replaceNodeChild; replaceNode->rchild = node->rchild; node->rchild->parent = replaceNode; } replaceNode->parent = node->parent; replaceNode->color = node->color; replaceNode->lchild = node->lchild; node->lchild->parent = replaceNode; if(replaceNodeColor == BLACK){ if(!RBTree_delete_fixup(root,replaceNodeChild,replaceNodeParent)) return ERROR; } free(node); return OK; }else{ return ERROR; } }
/*this is used by the first node of a size*/ inline static int get_direction(void * bp) { void * parent = (void *)GET_PARENT(bp); if (parent == NULL_POINTER) { return 0; } if ((void *)GET_LEFT(parent) == bp) { return 1; } if ((void *)GET_RIGHT(parent) == bp) { return 2; } return -1; }
static void initialize_bucket(qt_hash h, size_t bucket) { size_t parent = GET_PARENT(bucket); marked_ptr_t cur; if (h->B[parent] == UNINITIALIZED) { initialize_bucket(h, parent); } hash_entry *dummy = qpool_alloc(hash_entry_pool); assert(dummy); dummy->hashed_key = so_dummykey(bucket); dummy->key = NULL; dummy->value = NULL; dummy->next = (hash_entry*)UNINITIALIZED; if (!qt_lf_list_insert(&(h->B[parent]), dummy, &cur, NULL, h->op_equals)) { qpool_free(hash_entry_pool, dummy); dummy = PTR_OF(cur); while (h->B[bucket] != CONSTRUCT(0, dummy)) ; } else { h->B[bucket] = CONSTRUCT(0, dummy); } }
static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry) { int err = 0; struct dentry *hidden_old_dentry; struct dentry *hidden_wh_dentry = NULL; struct dentry *hidden_old_dir_dentry, *hidden_new_dir_dentry; char *name = NULL; struct iattr newattrs; print_entry_location(); fist_print_dentry("IN unionfs_unlink_whiteout: ", dentry); /* create whiteout, get the leftmost underlying dentry and rename it */ hidden_old_dentry = dtohd(dentry); /* lookup .wh.foo first, MUST NOT EXIST */ name = KMALLOC(dentry->d_name.len + sizeof(".wh."), GFP_UNIONFS); if (!name) { err = -ENOMEM; goto out; } strcpy(name, ".wh."); strncat(name, dentry->d_name.name, dentry->d_name.len); name[4 + dentry->d_name.len] = '\0'; hidden_wh_dentry = LOOKUP_ONE_LEN(name, hidden_old_dentry->d_parent, dentry->d_name.len + 4); if (IS_ERR(hidden_wh_dentry)) { err = PTR_ERR(hidden_wh_dentry); goto out; } ASSERT(hidden_wh_dentry->d_inode == NULL); DGET(hidden_old_dentry); hidden_old_dir_dentry = GET_PARENT(hidden_old_dentry); hidden_new_dir_dentry = GET_PARENT(hidden_wh_dentry); double_lock(hidden_old_dir_dentry, hidden_new_dir_dentry); if (!(err = is_robranch(dentry))) { if (S_ISREG(hidden_old_dentry->d_inode->i_mode)) { err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry, hidden_new_dir_dentry->d_inode, hidden_wh_dentry); } else { err = vfs_unlink(hidden_old_dir_dentry->d_inode, hidden_old_dentry); if (!err) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) err = vfs_create(hidden_new_dir_dentry->d_inode, hidden_wh_dentry, 0666, NULL); #else err = vfs_create(hidden_new_dir_dentry->d_inode, hidden_wh_dentry, 0666); #endif } } double_unlock(hidden_old_dir_dentry, hidden_new_dir_dentry); DPUT(hidden_old_dentry); DPUT(hidden_wh_dentry); if (!err) { hidden_wh_dentry = LOOKUP_ONE_LEN(name, hidden_old_dentry->d_parent, dentry->d_name.len + 4); if (IS_ERR(hidden_wh_dentry)) { err = PTR_ERR(hidden_wh_dentry); goto out; } PASSERT(hidden_wh_dentry->d_inode); down(&hidden_wh_dentry->d_inode->i_sem); newattrs.ia_valid = ATTR_CTIME; if (hidden_wh_dentry->d_inode->i_size != 0) { newattrs.ia_valid |= ATTR_SIZE; newattrs.ia_size = 0; } /* We discard this error, because the entry is whited out * even if we fail here. */ notify_change(hidden_wh_dentry, &newattrs); up(&hidden_wh_dentry->d_inode->i_sem); DPUT(hidden_wh_dentry); } if (err) { if (dbstart(dentry) == 0) goto out; /* exit if the error returned was NOT -EROFS */ if (!IS_COPYUP_ERR(err)) goto out; err = create_whiteout(dentry, dbstart(dentry) - 1); } else { fist_copy_attr_all(dir, hidden_new_dir_dentry->d_inode); } out: KFREE(name); print_exit_status(err); return err; }
static int do_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, int bindex, struct dentry **wh_old) { int err = 0; struct dentry *hidden_old_dentry; struct dentry *hidden_new_dentry; struct dentry *hidden_old_dir_dentry; struct dentry *hidden_new_dir_dentry; struct dentry *hidden_wh_dentry; struct dentry *hidden_wh_dir_dentry; char *wh_name = NULL; print_entry(" bindex=%d", bindex); fist_print_dentry("IN: do_rename, old_dentry", old_dentry); fist_print_dentry("IN: do_rename, new_dentry", new_dentry); fist_dprint(7, "do_rename for bindex = %d\n", bindex); hidden_new_dentry = dtohd_index(new_dentry, bindex); hidden_old_dentry = dtohd_index(old_dentry, bindex); if (!hidden_new_dentry) { hidden_new_dentry = create_parents(new_dentry->d_parent->d_inode, new_dentry, bindex); if (IS_ERR(hidden_new_dentry)) { fist_dprint(7, "error creating directory tree for rename, bindex = %d\n", bindex); err = PTR_ERR(hidden_new_dentry); goto out; } } wh_name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len); if (IS_ERR(wh_name)) { err = PTR_ERR(wh_name); goto out; } hidden_wh_dentry = LOOKUP_ONE_LEN(wh_name, hidden_new_dentry->d_parent, new_dentry->d_name.len + WHLEN); if (IS_ERR(hidden_wh_dentry)) { err = PTR_ERR(hidden_wh_dentry); goto out; } if (hidden_wh_dentry->d_inode) { /* get rid of the whiteout that is existing */ if (hidden_new_dentry->d_inode) { printk(KERN_WARNING "Both a whiteout and a dentry exist when doing a rename!\n"); err = -EIO; DPUT(hidden_wh_dentry); goto out; } hidden_wh_dir_dentry = lock_parent(hidden_wh_dentry); if (!(err = is_robranch_super(old_dentry->d_sb, bindex))) { err = vfs_unlink(hidden_wh_dir_dentry->d_inode, hidden_wh_dentry); } DPUT(hidden_wh_dentry); unlock_dir(hidden_wh_dir_dentry); if (err) goto out; } else DPUT(hidden_wh_dentry); DGET(hidden_old_dentry); hidden_old_dir_dentry = GET_PARENT(hidden_old_dentry); hidden_new_dir_dentry = GET_PARENT(hidden_new_dentry); lock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry); err = is_robranch_super(old_dentry->d_sb, bindex); if (err) goto out_unlock; /* ready to whiteout for old_dentry. caller will create the actual whiteout, and must dput(*wh_old) */ if (wh_old) { char *whname; whname = alloc_whname(old_dentry->d_name.name, old_dentry->d_name.len); err = PTR_ERR(whname); if (IS_ERR(whname)) goto out_unlock; *wh_old = LOOKUP_ONE_LEN(whname, hidden_old_dir_dentry, old_dentry->d_name.len + WHLEN); KFREE(whname); err = PTR_ERR(*wh_old); if (IS_ERR(*wh_old)) { *wh_old = NULL; goto out_unlock; } } fist_print_dentry("NEWBEF", new_dentry); fist_print_dentry("OLDBEF", old_dentry); err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry, hidden_new_dir_dentry->d_inode, hidden_new_dentry); fist_print_dentry("NEWAFT", new_dentry); fist_print_dentry("OLDAFT", old_dentry); out_unlock: unlock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry); DPUT(hidden_old_dir_dentry); DPUT(hidden_new_dir_dentry); DPUT(hidden_old_dentry); out: if (!err) { /* Fixup the newdentry. */ if (bindex < dbstart(new_dentry)) set_dbstart(new_dentry, bindex); else if (bindex > dbend(new_dentry)) set_dbend(new_dentry, bindex); } KFREE(wh_name); fist_print_dentry("OUT: do_rename, old_dentry", old_dentry); fist_print_dentry("OUT: do_rename, new_dentry", new_dentry); print_exit_status(err); return err; }
struct dentry *unionfs_lookup_backend(struct dentry *dentry, int lookupmode) { int err = 0; struct dentry *hidden_dentry = NULL; struct dentry *wh_hidden_dentry = NULL; struct dentry *hidden_dir_dentry = NULL; struct dentry *parent_dentry = NULL; int bindex, bstart, bend, bopaque; int dentry_count = 0; /* Number of positive dentries. */ int first_dentry_offset = -1; struct dentry *first_hidden_dentry = NULL; int locked_parent = 0; int locked_child = 0; int opaque; char *whname = NULL; const char *name; int namelen; print_entry("mode = %d", lookupmode); /* We should already have a lock on this dentry in the case of a * partial lookup, or a revalidation. Otherwise it is returned from * new_dentry_private_data already locked. */ if (lookupmode == INTERPOSE_PARTIAL || lookupmode == INTERPOSE_REVAL || lookupmode == INTERPOSE_REVAL_NEG) { verify_locked(dentry); } else { BUG_ON(dtopd_nocheck(dentry) != NULL); locked_child = 1; } if (lookupmode != INTERPOSE_PARTIAL) if ((err = new_dentry_private_data(dentry))) goto out; /* must initialize dentry operations */ dentry->d_op = &unionfs_dops; parent_dentry = GET_PARENT(dentry); /* We never partial lookup the root directory. */ if (parent_dentry != dentry) { lock_dentry(parent_dentry); locked_parent = 1; } else { DPUT(parent_dentry); parent_dentry = NULL; goto out; } fist_print_dentry("IN unionfs_lookup (parent)", parent_dentry); fist_print_dentry("IN unionfs_lookup (child)", dentry); name = dentry->d_name.name; namelen = dentry->d_name.len; /* No dentries should get created for possible whiteout names. */ if (!is_validname(name)) { err = -EPERM; goto out_free; } /* Now start the actual lookup procedure. */ bstart = dbstart(parent_dentry); bend = dbend(parent_dentry); bopaque = dbopaque(parent_dentry); BUG_ON(bstart < 0); /* It would be ideal if we could convert partial lookups to only have * to do this work when they really need to. It could probably improve * performance quite a bit, and maybe simplify the rest of the code. */ if (lookupmode == INTERPOSE_PARTIAL) { bstart++; if ((bopaque != -1) && (bopaque < bend)) bend = bopaque; } fist_dprint(8, "bstart = %d, bend = %d\n", bstart, bend); for (bindex = bstart; bindex <= bend; bindex++) { hidden_dentry = dtohd_index(dentry, bindex); if (lookupmode == INTERPOSE_PARTIAL && hidden_dentry) continue; BUG_ON(hidden_dentry != NULL); hidden_dir_dentry = dtohd_index(parent_dentry, bindex); /* if the parent hidden dentry does not exist skip this */ if (!(hidden_dir_dentry && hidden_dir_dentry->d_inode)) continue; /* also skip it if the parent isn't a directory. */ if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode)) continue; /* Reuse the whiteout name because its value doesn't change. */ if (!whname) { whname = alloc_whname(name, namelen); if (IS_ERR(whname)) { err = PTR_ERR(whname); goto out_free; } } /* check if whiteout exists in this branch: lookup .wh.foo */ wh_hidden_dentry = LOOKUP_ONE_LEN(whname, hidden_dir_dentry, namelen + WHLEN); if (IS_ERR(wh_hidden_dentry)) { DPUT(first_hidden_dentry); err = PTR_ERR(wh_hidden_dentry); goto out_free; } if (wh_hidden_dentry->d_inode) { /* We found a whiteout so lets give up. */ fist_dprint(8, "whiteout found in %d\n", bindex); if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) { set_dbend(dentry, bindex); set_dbopaque(dentry, bindex); DPUT(wh_hidden_dentry); break; } err = -EIO; printk(KERN_NOTICE "EIO: Invalid whiteout entry type" " %d.\n", wh_hidden_dentry->d_inode->i_mode); DPUT(wh_hidden_dentry); DPUT(first_hidden_dentry); goto out_free; } DPUT(wh_hidden_dentry); wh_hidden_dentry = NULL; /* Now do regular lookup; lookup foo */ hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry, namelen); fist_print_generic_dentry("hidden result", hidden_dentry); if (IS_ERR(hidden_dentry)) { DPUT(first_hidden_dentry); err = PTR_ERR(hidden_dentry); goto out_free; } /* Store the first negative dentry specially, because if they * are all negative we need this for future creates. */ if (!hidden_dentry->d_inode) { if (!first_hidden_dentry && (dbstart(dentry) == -1)) { first_hidden_dentry = hidden_dentry; first_dentry_offset = bindex; } else { DPUT(hidden_dentry); } continue; } /* number of positive dentries */ dentry_count++; /* store underlying dentry */ if (dbstart(dentry) == -1) set_dbstart(dentry, bindex); set_dtohd_index(dentry, bindex, hidden_dentry); set_dbend(dentry, bindex); /* update parent directory's atime with the bindex */ fist_copy_attr_atime(parent_dentry->d_inode, hidden_dir_dentry->d_inode); /* We terminate file lookups here. */ if (!S_ISDIR(hidden_dentry->d_inode->i_mode)) { if (lookupmode == INTERPOSE_PARTIAL) continue; if (dentry_count == 1) goto out_positive; /* This can only happen with mixed D-*-F-* */ BUG_ON(!S_ISDIR(dtohd(dentry)->d_inode->i_mode)); continue; } opaque = is_opaque_dir(dentry, bindex); if (opaque < 0) { DPUT(first_hidden_dentry); err = opaque; goto out_free; } if (opaque) { set_dbend(dentry, bindex); set_dbopaque(dentry, bindex); break; } } if (dentry_count) goto out_positive; else goto out_negative; out_negative: if (lookupmode == INTERPOSE_PARTIAL) goto out; /* If we've only got negative dentries, then use the leftmost one. */ if (lookupmode == INTERPOSE_REVAL) { if (dentry->d_inode) { itopd(dentry->d_inode)->uii_stale = 1; } goto out; } /* This should only happen if we found a whiteout. */ if (first_dentry_offset == -1) { first_hidden_dentry = LOOKUP_ONE_LEN(name, hidden_dir_dentry, namelen); first_dentry_offset = bindex; if (IS_ERR(first_hidden_dentry)) { err = PTR_ERR(first_hidden_dentry); goto out; } } set_dtohd_index(dentry, first_dentry_offset, first_hidden_dentry); set_dbstart(dentry, first_dentry_offset); set_dbend(dentry, first_dentry_offset); if (lookupmode == INTERPOSE_REVAL_NEG) BUG_ON(dentry->d_inode != NULL); else d_add(dentry, NULL); goto out; /* This part of the code is for positive dentries. */ out_positive: BUG_ON(dentry_count <= 0); /* If we're holding onto the first negative dentry throw it out. */ DPUT(first_hidden_dentry); /* Partial lookups need to reinterpose, or throw away older negs. */ if (lookupmode == INTERPOSE_PARTIAL) { if (dentry->d_inode) { unionfs_reinterpose(dentry); goto out; } /* This somehow turned positive, so it is as if we had a * negative revalidation. */ lookupmode = INTERPOSE_REVAL_NEG; update_bstart(dentry); bstart = dbstart(dentry); bend = dbend(dentry); } err = unionfs_interpose(dentry, dentry->d_sb, lookupmode); if (err) goto out_drop; fist_checkinode(dentry->d_inode, "unionfs_lookup OUT: child"); fist_checkinode(parent_dentry->d_inode, "unionfs_lookup OUT: dir"); goto out; out_drop: d_drop(dentry); out_free: /* should dput all the underlying dentries on error condition */ bstart = dbstart(dentry); if (bstart >= 0) { bend = dbend(dentry); for (bindex = bstart; bindex <= bend; bindex++) DPUT(dtohd_index(dentry, bindex)); } KFREE(dtohd_ptr(dentry)); dtohd_ptr(dentry) = NULL; set_dbstart(dentry, -1); set_dbend(dentry, -1); out: if (!err && dtopd(dentry)) { BUG_ON(dbend(dentry) > dtopd(dentry)->udi_bcount); BUG_ON(dbend(dentry) > sbmax(dentry->d_sb)); BUG_ON(dbstart(dentry) < 0); } KFREE(whname); fist_print_dentry("OUT unionfs_lookup (parent)", parent_dentry); fist_print_dentry("OUT unionfs_lookup (child)", dentry); if (locked_parent) unlock_dentry(parent_dentry); DPUT(parent_dentry); if (locked_child) unlock_dentry(dentry); print_exit_status(err); return ERR_PTR(err); }
static void _fix_after_insertion(ptst_t *ptst, stm_tx *tx, stm_blk *sb, stm_blk *xb, node_t *x) { stm_blk *pb, *gpb, *yb, *lub; node_t *p, *gp, *y; SET_COLOUR(x, RED); // rebalance tree set_t * s = (set_t*)READ_OBJ(sb); while (xb != NULL && GET_PARENT(x) != NULL) { pb = GET_PARENT(x); p = READ_OBJ(pb); if (IS_BLACK(p)) // case 2 - parent is black break; gpb = GET_PARENT(p); gp = READ_OBJ(gpb); lub = GET_LEFT(gp); if (pb == lub) { // parent is red, p=GET_LEFT(g) yb = GET_RIGHT(gp); // y (uncle) y = READ_OBJ(yb); if (IS_RED(y)) { // case 3 - parent is red, uncle is red (p = GET_LEFT(gp)) p = WRITE_OBJ(pb); y = WRITE_OBJ(yb); gp = WRITE_OBJ(gpb); SET_COLOUR(p, BLACK); SET_COLOUR(y, BLACK); SET_COLOUR(gp, RED); xb = gpb; x = gp; } else { // parent is red, uncle is black (p = GET_LEFT(gp)) if ( xb == GET_RIGHT(p) ) { // case 4 - parent is red, uncle is black, x = GET_RIGHT(p), p = GET_LEFT(gp) xb = pb; x = WRITE_OBJ(pb); _left_rotate(ptst, tx, sb, xb, x); pb=GET_PARENT(x); } // case 5 - parent is red, uncle is black, x = GET_LEFT(p), p = GET_LEFT(gp) p = WRITE_OBJ(pb); gpb = GET_PARENT(p); gp = WRITE_OBJ(gpb); SET_COLOUR(p, BLACK); SET_COLOUR(gp, RED); if (gp != NULL) { _right_rotate(ptst, tx, sb, gpb, gp); } } } else { // parent is red, p = GET_RIGHT(gp) yb = lub; y = READ_OBJ(yb); if (IS_RED(y)) { // case 3 - parent is red, uncle is red (p = GET_RIGHT(gp)) p = WRITE_OBJ(pb); y = WRITE_OBJ(yb); gp = WRITE_OBJ(gpb); SET_COLOUR(p, BLACK); SET_COLOUR(y, BLACK); SET_COLOUR(gp, RED); xb = gpb; x = gp; } else { // parent is red, uncle is black (p = GET_RIGHT(gp)) if ( xb == GET_LEFT(p) ) { // case 4 - parent is red, uncle is black, x = GET_LEFT(p), p = GET_RIGHT(gp) xb = pb; x = WRITE_OBJ(pb); _right_rotate(ptst, tx, sb, xb, x); pb = GET_PARENT(x); } // case 5 - parent is red, uncle is black, x = GET_RIGHT(p), p = GET_RIGHT(gp) p = WRITE_OBJ(pb); gpb = GET_PARENT(p); gp = WRITE_OBJ(gpb); SET_COLOUR(p, BLACK); SET_COLOUR(gp, RED); if(gp != NULL) { _left_rotate(ptst, tx, sb, gpb, gp); } } } } s = (set_t*)READ_OBJ(sb); stm_blk * rob = GET_ROOT(s); node_t * ro = READ_OBJ(rob); if (IS_RED(ro)) { ro = WRITE_OBJ(rob); SET_COLOUR(ro,BLACK); } }
static void _fix_after_deletion(ptst_t *ptst, stm_tx *tx, stm_blk *sb, stm_blk *xb, node_t *x) { stm_blk *pb, *plb, *sibb, *siblb, *sibrb; node_t *p, *sib, *sibl, *sibr; set_t *s; while (GET_PARENT(x)!=NULL && IS_BLACK(x)) { pb = GET_PARENT(x); p = WRITE_OBJ(pb); plb = GET_LEFT(p); if ( xb == plb ) { sibb = GET_RIGHT(p); sib = WRITE_OBJ(sibb); if (IS_RED(sib)) { SET_COLOUR(sib, BLACK); SET_COLOUR(p, RED); _left_rotate(ptst, tx, sb, pb, p); pb = GET_PARENT(x); p=WRITE_OBJ(pb); sibb = GET_RIGHT(p); sib = WRITE_OBJ(sibb); } siblb = GET_LEFT(sib); sibl = READ_OBJ(siblb); sibrb = GET_RIGHT(sib); sibr = READ_OBJ(sibrb); if (IS_BLACK(sibl) && IS_BLACK(sibr)) { SET_COLOUR(sib, RED); xb = GET_PARENT(x); x = WRITE_OBJ(xb); } else { if (IS_BLACK(sibr)) { sibl = WRITE_OBJ(siblb); SET_COLOUR(sibl, BLACK); SET_COLOUR(sib,RED); _right_rotate(ptst, tx, sb, sibb, sib); pb = GET_PARENT(x); p = WRITE_OBJ(pb); sibb = GET_RIGHT(p); } sib = WRITE_OBJ(sibb); SET_COLOUR(sib, GET_COLOUR(p)); p = WRITE_OBJ(pb); SET_COLOUR(p, BLACK); sibrb = GET_RIGHT(sib); sibr = WRITE_OBJ(sibrb); SET_COLOUR(sibr, BLACK); _left_rotate(ptst, tx, sb, pb, p); s = (set_t*)READ_OBJ(sb); xb = GET_ROOT(s); x = WRITE_OBJ(xb); break; } } else { // inverse sibb = plb; sib = WRITE_OBJ(sibb); if (IS_RED(sib)) { SET_COLOUR(sib, BLACK); SET_COLOUR(p, RED); _right_rotate(ptst, tx, sb, pb, p); pb = GET_PARENT(x); p=WRITE_OBJ(pb); sibb = GET_LEFT(p); sib = WRITE_OBJ(sibb); } siblb = GET_LEFT(sib); sibl = READ_OBJ(siblb); sibrb = GET_RIGHT(sib); sibr = READ_OBJ(sibrb); if (IS_BLACK(sibl) && IS_BLACK(sibr)) { SET_COLOUR(sib, RED); xb = GET_PARENT(x); x = WRITE_OBJ(xb); } else { if (IS_BLACK(sibl)) { sibr = WRITE_OBJ(sibrb); SET_COLOUR(sibr, BLACK); SET_COLOUR(sib, RED); _left_rotate(ptst, tx, sb, sibb, sib); pb = GET_PARENT(x); p = WRITE_OBJ(pb); sibb = GET_LEFT(p); } sib = WRITE_OBJ(sibb); SET_COLOUR(sib, GET_COLOUR(p)); p = WRITE_OBJ(pb); SET_COLOUR(p, BLACK); siblb = GET_LEFT(sib); sibl = WRITE_OBJ(siblb); SET_COLOUR(sibl, BLACK); _right_rotate(ptst, tx, sb, pb, p); s = (set_t*)READ_OBJ(sb); xb = GET_ROOT(s); x = WRITE_OBJ(xb); break; } } } if(IS_RED(x)) { SET_COLOUR(x, BLACK); } }//fix_after_deletion
inline static void insert_node( void *bp ) { RESET_PREALLOC_INFO(GET_NEXT(bp)); //reset the second bit of the HDRPer of the next block if (GET_SIZE(bp) == 8) { PUT_LEFT(bp, list_for_8); list_for_8 = bp; /*used to be wrong with mistaking SET to RESET */ SET_PRE_8_INFO(GET_NEXT(bp)); return; } else if (GET_SIZE(bp) == 16){ if (list_for_16 == NULL_POINTER) { PUT_RIGHT(bp, list_for_16); PUT_LEFT(bp, NULL_POINTER); list_for_16 = bp; return; } PUT_RIGHT(bp, list_for_16); PUT_LEFT(list_for_16, bp); PUT_LEFT(bp, NULL_POINTER); list_for_16 = bp; } else { //use BST when block size > 16 if (root == NULL_POINTER) { PUT_LEFT(bp, NULL_POINTER); PUT_RIGHT(bp, NULL_POINTER); PUT_PARENT(bp, NULL_POINTER); PUT_BROTHER(bp, NULL_POINTER); root = bp; //root is also an address. return; } else { void *parent = root; void *temp = root; int flag = 0; /*flag = 0 : the root itself; flag = 1 : left; flag = 2 : right*/ while (temp != NULL_POINTER) { /*when finding the free block in BST with the same size*/ if (GET_SIZE(temp) == GET_SIZE(bp)) { PUT_LEFT(bp, GET_LEFT(temp)); PUT_RIGHT(bp, GET_RIGHT(temp)); PUT_BROTHER(bp, temp); PUT_PARENT(GET_LEFT(temp), bp); PUT_PARENT(GET_RIGHT(temp), bp); PUT_LEFT(temp, bp); PUT_PARENT(bp, GET_PARENT(temp)); if (flag == 0) { root = bp; } else if (flag == 1) { PUT_LEFT(parent, bp); } else { PUT_RIGHT(parent, bp); } return; /*SEARCH RIGHT CHILD*/ } else if (GET_SIZE(temp) < GET_SIZE(bp)) { parent = temp; temp = (void *)GET_RIGHT(temp); flag = 2; /*SEARCH LEFT CHILD*/ } else { parent = temp; temp = (void *)GET_LEFT(temp); flag = 1; } } /*insert new node*/ if (flag == 1) { PUT_LEFT(parent, bp); } else { PUT_RIGHT(parent, bp); } PUT_LEFT(bp, NULL_POINTER); PUT_RIGHT(bp, NULL_POINTER); PUT_PARENT(bp, parent); PUT_BROTHER(bp, NULL_POINTER); } } //BST_checker(root); }
static int unionfs_create(struct inode *parent, struct dentry *dentry, int mode, struct nameidata *nd) { int err = 0; struct dentry *hidden_dentry = NULL; struct dentry *whiteout_dentry = NULL; struct dentry *new_hidden_dentry; struct dentry *hidden_parent_dentry = NULL; int bindex = 0, bstart; char *name = NULL; print_entry_location(); lock_dentry(dentry); fist_print_dentry("IN unionfs_create", dentry); /* We start out in the leftmost branch. */ bstart = dbstart(dentry); hidden_dentry = dtohd(dentry); /* check if whiteout exists in this branch, i.e. lookup .wh.foo first */ name = alloc_whname(dentry->d_name.name, dentry->d_name.len); if (IS_ERR(name)) { err = PTR_ERR(name); goto out; } whiteout_dentry = LOOKUP_ONE_LEN(name, hidden_dentry->d_parent, dentry->d_name.len + WHLEN); if (IS_ERR(whiteout_dentry)) { err = PTR_ERR(whiteout_dentry); whiteout_dentry = NULL; goto out; } if (whiteout_dentry->d_inode) { /* .wh.foo has been found. */ /* First truncate it and then rename it to foo (hence having * the same overall effect as a normal create. * * XXX: This is not strictly correct. If we have unlinked the * file and it still has a reference count, then we should * actually unlink the whiteout so that user's data isn't * hosed over. */ struct dentry *hidden_dir_dentry; struct iattr newattrs; down(&whiteout_dentry->d_inode->i_sem); newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE | ATTR_KILL_SUID | ATTR_KILL_SGID; newattrs.ia_mode = mode & ~current->fs->umask; newattrs.ia_uid = current->fsuid; newattrs.ia_gid = current->fsgid; if (whiteout_dentry->d_inode->i_size != 0) { newattrs.ia_valid |= ATTR_SIZE; newattrs.ia_size = 0; } err = notify_change(whiteout_dentry, &newattrs); up(&whiteout_dentry->d_inode->i_sem); if (err) printk(KERN_WARNING "unionfs: %s:%d: notify_change failed: %d, ignoring..\n", __FILE__, __LINE__, err); new_hidden_dentry = dtohd(dentry); DGET(new_hidden_dentry); hidden_dir_dentry = GET_PARENT(whiteout_dentry); lock_rename(hidden_dir_dentry, hidden_dir_dentry); if (!(err = is_robranch_super(dentry->d_sb, bstart))) { err = vfs_rename(hidden_dir_dentry->d_inode, whiteout_dentry, hidden_dir_dentry->d_inode, new_hidden_dentry); } if (!err) { fist_copy_attr_timesizes(parent, new_hidden_dentry->d_parent-> d_inode); parent->i_nlink = get_nlinks(parent); } unlock_rename(hidden_dir_dentry, hidden_dir_dentry); DPUT(hidden_dir_dentry); DPUT(new_hidden_dentry); if (err) { /* exit if the error returned was NOT -EROFS */ if (!IS_COPYUP_ERR(err)) goto out; /* We were not able to create the file in this branch, * so, we try to create it in one branch to left */ bstart--; } else { /* reset the unionfs dentry to point to the .wh.foo entry. */ /* Discard any old reference. */ DPUT(dtohd(dentry)); /* Trade one reference to another. */ set_dtohd_index(dentry, bstart, whiteout_dentry); whiteout_dentry = NULL; err = unionfs_interpose(dentry, parent->i_sb, 0); goto out; } } for (bindex = bstart; bindex >= 0; bindex--) { hidden_dentry = dtohd_index(dentry, bindex); if (!hidden_dentry) { /* if hidden_dentry is NULL, create the entire * dentry directory structure in branch 'bindex'. * hidden_dentry will NOT be null when bindex == bstart * because lookup passed as a negative unionfs dentry * pointing to a lone negative underlying dentry */ hidden_dentry = create_parents(parent, dentry, bindex); if (!hidden_dentry || IS_ERR(hidden_dentry)) { if (IS_ERR(hidden_dentry)) err = PTR_ERR(hidden_dentry); continue; } } fist_checkinode(parent, "unionfs_create"); hidden_parent_dentry = lock_parent(hidden_dentry); if (IS_ERR(hidden_parent_dentry)) { err = PTR_ERR(hidden_parent_dentry); goto out; } /* We shouldn't create things in a read-only branch. */ if (!(err = is_robranch_super(dentry->d_sb, bindex))) { //DQ: vfs_create has a different prototype in 2.6 err = vfs_create(hidden_parent_dentry->d_inode, hidden_dentry, mode, nd); } if (err || !hidden_dentry->d_inode) { unlock_dir(hidden_parent_dentry); /* break out of for loop if the error wasn't -EROFS */ if (!IS_COPYUP_ERR(err)) break; } else { err = unionfs_interpose(dentry, parent->i_sb, 0); if (!err) { fist_copy_attr_timesizes(parent, hidden_parent_dentry-> d_inode); /* update number of links on parent directory */ parent->i_nlink = get_nlinks(parent); } unlock_dir(hidden_parent_dentry); break; } } out: DPUT(whiteout_dentry); KFREE(name); fist_print_dentry("OUT unionfs_create :", dentry); unlock_dentry(dentry); print_exit_status(err); return err; }