Esempio n. 1
0
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;
        }
    }
}
Esempio n. 2
0
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;
}
Esempio n. 3
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;
}
Esempio n. 4
0
// 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
Esempio n. 5
0
// 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
Esempio n. 6
0
/*得到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;
    }
}
Esempio n. 7
0
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;
    }
}
Esempio n. 8
0
/*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;

}
Esempio n. 9
0
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);
    }
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
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);
    }
}
Esempio n. 14
0
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
Esempio n. 15
0
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);
}
Esempio n. 16
0
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;
}