コード例 #1
0
ファイル: i_op_del.c プロジェクト: ArthySundaram/firstrepo
/*
 * decide if a new whiteout for @dentry is necessary or not.
 * when it is necessary, prepare the parent dir for the upper branch whose
 * branch index is @bcpup for creation. the actual creation of the whiteout will
 * be done by caller.
 * return value:
 * 0: wh is unnecessary
 * plus: wh is necessary
 * minus: error
 */
int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
{
	int need_wh, err;
	aufs_bindex_t bstart;
	struct super_block *sb;

	sb = dentry->d_sb;
	bstart = au_dbstart(dentry);
	if (*bcpup < 0) {
		*bcpup = bstart;
		if (au_test_ro(sb, bstart, dentry->d_inode)) {
			err = AuWbrCopyup(au_sbi(sb), dentry);
			*bcpup = err;
			if (unlikely(err < 0))
				goto out;
		}
	} else
		AuDebugOn(bstart < *bcpup
			  || au_test_ro(sb, *bcpup, dentry->d_inode));
	AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);

	if (*bcpup != bstart) {
		err = au_cpup_dirs(dentry, *bcpup);
		if (unlikely(err))
			goto out;
		need_wh = 1;
	} else {
		aufs_bindex_t old_bend, new_bend, bdiropq = -1;

		old_bend = au_dbend(dentry);
		if (isdir) {
			bdiropq = au_dbdiropq(dentry);
			au_set_dbdiropq(dentry, -1);
		}
		need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
					 /*nd*/NULL);
		err = need_wh;
		if (isdir)
			au_set_dbdiropq(dentry, bdiropq);
		if (unlikely(err < 0))
			goto out;
		new_bend = au_dbend(dentry);
		if (!need_wh && old_bend != new_bend) {
			au_set_h_dptr(dentry, new_bend, NULL);
			au_set_dbend(dentry, old_bend);
		}
	}
	AuDbg("need_wh %d\n", need_wh);
	err = need_wh;

 out:
	return err;
}
コード例 #2
0
/*
 * decide if a new whiteout for @dentry is necessary or not.
 * when it is necessary, prepare the parent dir for the upper branch whose
 * branch index is @bcpup for creation. the actual creation of the whiteout will
 * be done by caller.
 * return value:
 * 0: wh is unnecessary
 * plus: wh is necessary
 * minus: error
 */
int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
{
	int need_wh, err;
	aufs_bindex_t bstart;
	struct super_block *sb;

	sb = dentry->d_sb;
	bstart = au_dbstart(dentry);
	if (*bcpup < 0) {
		*bcpup = bstart;
		if (au_test_ro(sb, bstart, dentry->d_inode)) {
			err = AuWbrCopyup(au_sbi(sb), dentry);
			*bcpup = err;
			if (unlikely(err < 0))
				goto out;
		}
	} else
		AuDebugOn(bstart < *bcpup
			  || au_test_ro(sb, *bcpup, dentry->d_inode));
	AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);

	if (*bcpup != bstart) {
		err = au_cpup_dirs(dentry, *bcpup);
		if (unlikely(err))
			goto out;
		need_wh = 1;
	} else {
		struct au_dinfo *dinfo, *tmp;

		need_wh = -ENOMEM;
		dinfo = au_di(dentry);
		tmp = au_di_alloc(sb, AuLsc_DI_TMP);
		if (tmp) {
			au_di_cp(tmp, dinfo);
			au_di_swap(tmp, dinfo);
			/* returns the number of positive dentries */
			need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
						 /*nd*/NULL);
			au_di_swap(tmp, dinfo);
			au_rw_write_unlock(&tmp->di_rwsem);
			au_di_free(tmp);
		}
	}
	AuDbg("need_wh %d\n", need_wh);
	err = need_wh;

out:
	return err;
}
コード例 #3
0
static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
			 u32 mask, u32 cookie __maybe_unused,
			 const char *h_child_name, struct inode *h_child_inode)
{
	struct au_hnotify *hnotify;
	struct qstr h_child_qstr = {
		.name = h_child_name
	};

	/* if IN_UNMOUNT happens, there must be another bug */
	AuDebugOn(mask & IN_UNMOUNT);
	if (mask & (IN_IGNORED | IN_UNMOUNT)) {
		put_inotify_watch(watch);
		return;
	}

#ifdef AuDbgHnotify
	au_debug(1);
	if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
		AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
		      " hi%lu\n",
		      watch->inode->i_ino, wd, mask, in_name(mask), cookie,
		      h_child_name ? h_child_name : "",
		      h_child_inode ? h_child_inode->i_ino : 0);
		WARN_ON(1);
	}
	au_debug(0);
#endif

	if (h_child_name)
		h_child_qstr.len = strlen(h_child_name);
	hnotify = container_of(watch, struct au_hnotify, hn_watch);
	au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
}
コード例 #4
0
ファイル: vfsub.c プロジェクト: chrmorais/miniemc2
static int au_conv_oflags(int flags)
{
	int mask = 0;

#ifdef CONFIG_IMA
	fmode_t fmode;

	/* mask = MAY_OPEN; */
	fmode = OPEN_FMODE(flags);
	if (fmode & FMODE_READ)
		mask |= MAY_READ;
	if ((fmode & FMODE_WRITE)
	    || (flags & O_TRUNC))
		mask |= MAY_WRITE;
	/*
	 * if (flags & O_APPEND)
	 *	mask |= MAY_APPEND;
	 */
	if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
		mask |= MAY_EXEC;

	AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
#endif

	return mask;
}
コード例 #5
0
ファイル: wbr_policy.c プロジェクト: GREYFOXRGR/BPI-M3-bsp
static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
{
	int err;
	struct dentry *parent;
	struct super_block *sb;
	struct au_wbr_mfs *mfs;

	err = au_wbr_create_exp(dentry);
	if (err >= 0)
		goto out;

	sb = dentry->d_sb;
	parent = NULL;
	if (au_ftest_wbr(flags, PARENT))
		parent = dget_parent(dentry);
	mfs = &au_sbi(sb)->si_wbr_mfs;
	mutex_lock(&mfs->mfs_lock);
	if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
	    || mfs->mfs_bindex < 0
	    || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
		au_mfs(dentry, parent);
	mutex_unlock(&mfs->mfs_lock);
	err = mfs->mfs_bindex;
	dput(parent);

	if (err >= 0)
		err = au_wbr_nonopq(dentry, err);

out:
	AuDbg("b%d\n", err);
	return err;
}
コード例 #6
0
static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
{
	int err;
	struct super_block *sb;
	struct au_wbr_mfs *mfs;

	err = au_wbr_create_exp(dentry);
	if (err >= 0)
		goto out;

	sb = dentry->d_sb;
	mfs = &au_sbi(sb)->si_wbr_mfs;
	mutex_lock(&mfs->mfs_lock);
	if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
	    || mfs->mfs_bindex < 0
	    || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
		au_mfs(dentry);
	mutex_unlock(&mfs->mfs_lock);
	err = mfs->mfs_bindex;

	if (err >= 0)
		err = au_wbr_nonopq(dentry, err);

out:
	AuDbg("b%d\n", err);
	return err;
}
コード例 #7
0
void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
{
	struct inode *h_inode, *inode = dentry->d_inode;
	struct dentry *h_dentry;
	aufs_bindex_t bindex, bend, bi;

	if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
		return;

	bend = au_dbend(dentry);
	bi = au_ibend(inode);
	if (bi < bend)
		bend = bi;
	bindex = au_dbstart(dentry);
	bi = au_ibstart(inode);
	if (bi > bindex)
		bindex = bi;

	for (; bindex <= bend; bindex++) {
		h_dentry = au_h_dptr(dentry, bindex);
		if (!h_dentry)
			continue;
		h_inode = au_h_iptr(inode, bindex);
		if (unlikely(h_inode != h_dentry->d_inode)) {
			au_debug_on();
			AuDbg("b%d, %s:%d\n", bindex, func, line);
			AuDbgDentry(dentry);
			AuDbgInode(inode);
			au_debug_off();
			BUG();
		}
	}
}
コード例 #8
0
ファイル: i_op.c プロジェクト: roalex/bravo-kernel
/*
 * decide the branch and the parent dir where we will create a new entry.
 * returns new bindex or an error.
 * copyup the parent dir if needed.
 */
int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
	      struct au_wr_dir_args *args)
{
	int err;
	aufs_bindex_t bcpup, bstart, src_bstart;
	const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
							 ADD_ENTRY);
	struct super_block *sb;
	struct dentry *parent;
	struct au_sbinfo *sbinfo;

	sb = dentry->d_sb;
	sbinfo = au_sbi(sb);
	parent = dget_parent(dentry);
	bstart = au_dbstart(dentry);
	bcpup = bstart;
	if (args->force_btgt < 0) {
		if (src_dentry) {
			src_bstart = au_dbstart(src_dentry);
			if (src_bstart < bstart)
				bcpup = src_bstart;
		} else if (add_entry) {
			err = AuWbrCreate(sbinfo, dentry,
					  au_ftest_wrdir(args->flags, ISDIR));
			bcpup = err;
		}

		if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
			if (add_entry)
				err = AuWbrCopyup(sbinfo, dentry);
			else {
				if (!IS_ROOT(dentry)) {
					di_read_lock_parent(parent, !AuLock_IR);
					err = AuWbrCopyup(sbinfo, dentry);
					di_read_unlock(parent, !AuLock_IR);
				} else
					err = AuWbrCopyup(sbinfo, dentry);
			}
			bcpup = err;
			if (unlikely(err < 0))
				goto out;
		}
	} else {
		bcpup = args->force_btgt;
		AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
	}
	AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
	err = bcpup;
	if (bcpup == bstart)
		goto out; /* success */
	else if (bstart < bcpup)
		au_update_dbrange(dentry, /*do_put_zero*/1);

	/* copyup the new parent into the branch we process */
	err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);

 out:
	dput(parent);
	return err;
}
コード例 #9
0
ファイル: mvdown.c プロジェクト: ammubhave/bargud
/* make sure the parent dir is fine */
static int au_mvd_args_parent(const unsigned char dmsg,
                              struct au_mvd_args *a)
{
    int err;
    aufs_bindex_t bindex;

    err = 0;
    if (unlikely(au_alive_dir(a->parent))) {
        err = -ENOENT;
        AU_MVD_PR(dmsg, "parent dir is dead\n");
        goto out;
    }

    a->bopq = au_dbdiropq(a->parent);
    bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
    AuDbg("b%d\n", bindex);
    if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
                 || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
        err = -EINVAL;
        a->mvd_errno = EAU_MVDOWN_OPAQUE;
        AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
                  a->bopq, a->mvd_bdst);
    }

out:
    AuTraceErr(err);
    return err;
}
コード例 #10
0
ファイル: i_op_add.c プロジェクト: khvalera/abuilds
/*
 * initial procedure of adding a new entry.
 * prepare writable branch and the parent dir, lock it,
 * and lookup whiteout for the new entry.
 */
static struct dentry*
lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
		  struct dentry *src_dentry, struct au_pin *pin,
		  struct au_wr_dir_args *wr_dir_args)
{
	struct dentry *wh_dentry, *h_parent;
	struct super_block *sb;
	struct au_branch *br;
	int err;
	unsigned int udba;
	aufs_bindex_t bcpup;

	AuDbg("%.*s\n", AuDLNPair(dentry));

	err = au_wr_dir(dentry, src_dentry, wr_dir_args);
	bcpup = err;
	wh_dentry = ERR_PTR(err);
	if (unlikely(err < 0))
		goto out;

	sb = dentry->d_sb;
	udba = au_opt_udba(sb);
	err = au_pin(pin, dentry, bcpup, udba,
		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
	wh_dentry = ERR_PTR(err);
	if (unlikely(err))
		goto out;

	h_parent = au_pinned_h_parent(pin);
	if (udba != AuOpt_UDBA_NONE
	    && au_dbstart(dentry) == bcpup)
		err = au_may_add(dentry, bcpup, h_parent,
				 au_ftest_wrdir(wr_dir_args->flags, ISDIR));
	else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
		err = -ENAMETOOLONG;
	wh_dentry = ERR_PTR(err);
	if (unlikely(err))
		goto out_unpin;

	br = au_sbr(sb, bcpup);
	if (dt) {
		struct path tmp = {
			.dentry	= h_parent,
			.mnt	= au_br_mnt(br)
		};
		au_dtime_store(dt, au_pinned_parent(pin), &tmp);
	}

	wh_dentry = NULL;
	if (bcpup != au_dbwh(dentry))
		goto out; /* success */

	wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);

out_unpin:
	if (IS_ERR(wh_dentry))
		au_unpin(pin);
out:
	return wh_dentry;
}
コード例 #11
0
ファイル: opts.c プロジェクト: bjayesh/chandra
static int noinline_for_stack
au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
{
	int err;
	struct path path;
	char *p;

	err = -EINVAL;
	mod->path = args[0].from;
	p = strchr(mod->path, '=');
	if (unlikely(!p)) {
		pr_err("no permssion %s\n", args[0].from);
		goto out;
	}

	*p++ = 0;
	err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
	if (unlikely(err)) {
		pr_err("lookup failed %s (%d)\n", mod->path, err);
		goto out;
	}

	mod->perm = br_perm_val(p);
	AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
	mod->h_root = dget(path.dentry);
	path_put(&path);

out:
	return err;
}
コード例 #12
0
ファイル: sysfs.c プロジェクト: hexianren/linux-3.7-Read
/*
 * the lifetime of branch is independent from the entry under sysfs.
 * sysfs handles the lifetime of the entry, and never call ->show() after it is
 * unlinked.
 */
static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
			 aufs_bindex_t bindex)
{
	int err;
	struct path path;
	struct dentry *root;
	struct au_branch *br;
	char *perm;

	AuDbg("b%d\n", bindex);

	err = 0;
	root = sb->s_root;
	di_read_lock_parent(root, !AuLock_IR);
	br = au_sbr(sb, bindex);
	path.mnt = br->br_mnt;
	path.dentry = au_h_dptr(root, bindex);
	au_seq_path(seq, &path);
	di_read_unlock(root, !AuLock_IR);
	perm = au_optstr_br_perm(br->br_perm);
	if (perm) {
		err = seq_printf(seq, "=%s\n", perm);
		kfree(perm);
		if (err == -1)
			err = -E2BIG;
	} else
		err = -ENOMEM;
	return err;
}
コード例 #13
0
ファイル: dentry.c プロジェクト: ammubhave/bargud
static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
			   struct dentry *dentry, aufs_bindex_t bindex)
{
	int err, valid;

	err = 0;
	if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
		goto out;

	AuDbg("b%d\n", bindex);
	/*
	 * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
	 * due to whiteout and branch permission.
	 */
	flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
		   | LOOKUP_FOLLOW | LOOKUP_EXCL);
	/* it may return tri-state */
	valid = h_dentry->d_op->d_revalidate(h_dentry, flags);

	if (unlikely(valid < 0))
		err = valid;
	else if (!valid)
		err = -EINVAL;

out:
	AuTraceErr(err);
	return err;
}
コード例 #14
0
void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
{
	int err;
	struct au_sbinfo *sbinfo;
	struct au_fhsm *fhsm;
	struct au_branch *br;
	struct au_br_fhsm *bf;

	AuDbg("b%d, force %d\n", bindex, force);
	SiMustAnyLock(sb);

	sbinfo = au_sbi(sb);
	fhsm = &sbinfo->si_fhsm;
	if (!au_ftest_si(sbinfo, FHSM)
	    || fhsm->fhsm_bottom == bindex)
		return;

	br = au_sbr(sb, bindex);
	bf = br->br_fhsm;
	AuDebugOn(!bf);
	mutex_lock(&bf->bf_lock);
	if (force
	    || au_fhsm_pid(fhsm)
	    || au_fhsm_test_jiffy(sbinfo, br))
		err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
				  /*do_notify*/1);
	mutex_unlock(&bf->bf_lock);
}
コード例 #15
0
ファイル: rdu.c プロジェクト: AKToronto/htc-kernel-msm7227
static int au_rdu_verify(struct aufs_rdu *rdu)
{
	AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
	      "%llu, b%d, 0x%x, g%u}\n",
	      rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
	      rdu->blk,
	      rdu->rent, rdu->shwh, rdu->full,
	      rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
	      rdu->cookie.generation);

	if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
		return 0;

	AuDbg("%u:%u\n",
	      rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
	return -EINVAL;
}
コード例 #16
0
/*
 * if valid returns 1, otherwise 0.
 */
static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
	int valid, err;
	unsigned int sigen;
	unsigned char do_udba;
	struct super_block *sb;
	struct inode *inode;

	err = -EINVAL;
	sb = dentry->d_sb;
	inode = dentry->d_inode;
	aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
	sigen = au_sigen(sb);
	if (au_digen(dentry) != sigen) {
		AuDebugOn(IS_ROOT(dentry));
		if (inode)
			err = au_reval_dpath(dentry, sigen);
		if (unlikely(err))
			goto out_dgrade;
		AuDebugOn(au_digen(dentry) != sigen);
	}
	if (inode && au_iigen(inode) != sigen) {
		AuDebugOn(IS_ROOT(dentry));
		err = au_refresh_hinode(inode, dentry);
		if (unlikely(err))
			goto out_dgrade;
		AuDebugOn(au_iigen(inode) != sigen);
	}
	di_downgrade_lock(dentry, AuLock_IR);

	AuDebugOn(au_digen(dentry) != sigen);
	AuDebugOn(inode && au_iigen(inode) != sigen);
	err = -EINVAL;
	do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
	if (do_udba && inode) {
		aufs_bindex_t bstart = au_ibstart(inode);

		if (bstart >= 0
		    && au_test_higen(inode, au_h_iptr(inode, bstart)))
			goto out;
	}

	err = h_d_revalidate(dentry, inode, nd, do_udba);
	if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
		/* both of real entry and whiteout found */
		err = -EIO;
	goto out;

 out_dgrade:
	di_downgrade_lock(dentry, AuLock_IR);
 out:
	aufs_read_unlock(dentry, AuLock_IR);
	AuTraceErr(err);
	valid = !err;
	if (!valid)
		AuDbg("%.*s invalid\n", AuDLNPair(dentry));
	return valid;
}
コード例 #17
0
ファイル: hfsnotify.c プロジェクト: jue-jiang/rc3-linux
static int au_hfsn_handle_event(struct fsnotify_group *group,
				struct fsnotify_mark *inode_mark,
				struct fsnotify_mark *vfsmount_mark,
				struct fsnotify_event *event)
{
	int err;
	struct au_hnotify *hnotify;
	struct inode *h_dir, *h_inode;
	__u32 mask;
	struct qstr h_child_qstr = {
		.name	= event->file_name,
		.len	= event->name_len
	};

	AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);

	err = 0;
	/* if FS_UNMOUNT happens, there must be another bug */
	mask = event->mask;
	AuDebugOn(mask & FS_UNMOUNT);
	if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
		goto out;

	h_dir = event->to_tell;
	h_inode = event->inode;
#ifdef AuDbgHnotify
	au_debug(1);
	if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
	    || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
		AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
		      h_dir->i_ino, mask, au_hfsn_name(mask),
		      AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
		/* WARN_ON(1); */
	}
	au_debug(0);
#endif

	AuDebugOn(!inode_mark);
	hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
	err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);

out:
	return err;
}

/* isn't it waste to ask every registered 'group'? */
/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
/* it should be exported to modules */
static bool au_hfsn_should_send_event(struct fsnotify_group *group,
				      struct inode *h_inode,
				      struct fsnotify_mark *inode_mark,
				      struct fsnotify_mark *vfsmount_mark,
				      __u32 mask, void *data, int data_type)
{
	mask = (mask & ~FS_EVENT_ON_CHILD);
	return inode_mark->mask & mask;
}
コード例 #18
0
/* copy-down the file */
static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
{
	int err;
	struct au_cp_generic cpg = {
		.dentry	= a->dentry,
		.bdst	= a->mvd_bdst,
		.bsrc	= a->mvd_bsrc,
		.len	= -1,
		.pin	= &a->pin,
		.flags	= AuCpup_DTIME | AuCpup_HOPEN
	};

	AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
	if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
		au_fset_cpup(cpg.flags, OVERWRITE);
	if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
		au_fset_cpup(cpg.flags, RWDST);
	err = au_sio_cpdown_simple(&cpg);
	if (unlikely(err))
		AU_MVD_PR(dmsg, "cpdown failed\n");

	AuTraceErr(err);
	return err;
}

/*
 * unlink the whiteout on bdst if exist which may be created by UDBA while we
 * were sleeping
 */
static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
{
	int err;
	struct path h_path;
	struct au_branch *br;

	br = au_sbr(a->sb, a->mvd_bdst);
	h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
	err = PTR_ERR(h_path.dentry);
	if (IS_ERR(h_path.dentry)) {
		AU_MVD_PR(dmsg, "wh_lkup failed\n");
		goto out;
	}

	err = 0;
	if (h_path.dentry->d_inode) {
		h_path.mnt = au_br_mnt(br);
		err = vfsub_unlink(a->mvd_h_dst_parent->d_inode, &h_path,
				   /*force*/0);
		if (unlikely(err))
			AU_MVD_PR(dmsg, "wh_unlink failed\n");
	}
	dput(h_path.dentry);

out:
	AuTraceErr(err);
	return err;
}
コード例 #19
0
ファイル: hfsnotify.c プロジェクト: jue-jiang/rc3-linux
static void au_hfsn_free_mark(struct fsnotify_mark *mark)
{
	struct au_hnotify *hn = container_of(mark, struct au_hnotify,
					     hn_mark);
	AuDbg("here\n");
	hn->hn_mark_dead = 1;
	smp_mb();
	wake_up_all(&au_hfsn_wq);
}
コード例 #20
0
ファイル: hfsnotify.c プロジェクト: KristofRobot/meta-sunxi
static void au_hfsn_free_mark(struct fsnotify_mark *mark)
{
	struct au_hnotify *hn = container_of(mark, struct au_hnotify,
					     hn_mark);
	AuDbg("here\n");
	au_cache_free_hnotify(hn);
	smp_mb__before_atomic_dec();
	atomic64_dec(&au_hfsn_ifree);
	wake_up(&au_hfsn_wq);
}
コード例 #21
0
ファイル: mvdown.c プロジェクト: JanLuca/aufs4-debian
/*
 * copy-down the file and unlink the bsrc file.
 * - unlink the bdst whout if exist
 * - copy-down the file (with whtmp name and rename)
 * - unlink the bsrc file
 */
static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
{
	int err;

	err = au_do_mkdir(dmsg, a);
	if (!err)
		err = au_do_lock(dmsg, a);
	if (unlikely(err))
		goto out;

	/*
	 * do not revert the activities we made on bdst since they should be
	 * harmless in aufs.
	 */

	err = au_do_cpdown(dmsg, a);
	if (!err)
		err = au_do_unlink_wh(dmsg, a);
	if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
		err = au_do_unlink(dmsg, a);
	if (unlikely(err))
		goto out_unlock;

	AuDbg("%pd2, 0x%x, %d --> %d\n",
	      a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
	if (find_lower_writable(a) < 0)
		a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;

	if (a->mvdown.flags & AUFS_MVDOWN_STFS)
		au_do_stfs(dmsg, a);

	/* maintain internal array */
	if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
		au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
		au_set_dbtop(a->dentry, a->mvd_bdst);
		au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
		au_set_ibtop(a->inode, a->mvd_bdst);
	} else {
		/* hide the lower */
		au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
		au_set_dbbot(a->dentry, a->mvd_bsrc);
		au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
		au_set_ibbot(a->inode, a->mvd_bsrc);
	}
	if (au_dbbot(a->dentry) < a->mvd_bdst)
		au_set_dbbot(a->dentry, a->mvd_bdst);
	if (au_ibbot(a->inode) < a->mvd_bdst)
		au_set_ibbot(a->inode, a->mvd_bdst);

out_unlock:
	au_do_unlock(dmsg, a);
out:
	AuTraceErr(err);
	return err;
}
コード例 #22
0
ファイル: wbr_policy.c プロジェクト: hexianren/linux-3.7-Read
/* most free space */
static void au_mfs(struct dentry *dentry)
{
	struct super_block *sb;
	struct au_branch *br;
	struct au_wbr_mfs *mfs;
	aufs_bindex_t bindex, bend;
	int err;
	unsigned long long b, bavail;
	struct path h_path;
	/* reduce the stack usage */
	struct kstatfs *st;

	st = kmalloc(sizeof(*st), GFP_NOFS);
	if (unlikely(!st)) {
		AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
		return;
	}

	bavail = 0;
	sb = dentry->d_sb;
	mfs = &au_sbi(sb)->si_wbr_mfs;
	MtxMustLock(&mfs->mfs_lock);
	mfs->mfs_bindex = -EROFS;
	mfs->mfsrr_bytes = 0;
	bend = au_sbend(sb);
	for (bindex = 0; bindex <= bend; bindex++) {
		br = au_sbr(sb, bindex);
		if (au_br_rdonly(br))
			continue;

		/* sb->s_root for NFS is unreliable */
		h_path.mnt = br->br_mnt;
		h_path.dentry = h_path.mnt->mnt_root;
		err = vfs_statfs(&h_path, st);
		if (unlikely(err)) {
			AuWarn1("failed statfs, b%d, %d\n", bindex, err);
			continue;
		}

		/* when the available size is equal, select the lower one */
		BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
			     || sizeof(b) < sizeof(st->f_bsize));
		b = st->f_bavail * st->f_bsize;
		br->br_wbr->wbr_bytes = b;
		if (b >= bavail) {
			bavail = b;
			mfs->mfs_bindex = bindex;
			mfs->mfs_jiffy = jiffies;
		}
	}

	mfs->mfsrr_bytes = bavail;
	AuDbg("b%d\n", mfs->mfs_bindex);
	kfree(st);
}
コード例 #23
0
ファイル: opts.c プロジェクト: shinsec/linux-parrot
int au_opts_remount(struct super_block *sb, struct au_opts *opts)
{
	int err, rerr;
	unsigned char no_dreval;
	struct inode *dir;
	struct au_opt_xino *opt_xino;
	struct au_opt *opt;
	struct au_sbinfo *sbinfo;

	SiMustWriteLock(sb);

	err = 0;
	dir = d_inode(sb->s_root);
	sbinfo = au_sbi(sb);
	opt_xino = NULL;
	opt = opts->opt;
	while (err >= 0 && opt->type != Opt_tail) {
		err = au_opt_simple(sb, opt, opts);
		if (!err)
			err = au_opt_br(sb, opt, opts);
		if (!err)
			err = au_opt_xino(sb, opt, &opt_xino, opts);
		opt++;
	}
	if (err > 0)
		err = 0;
	AuTraceErr(err);
	/* go on even err */

	no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
	rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
	if (unlikely(rerr && !err))
		err = rerr;

	if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
		au_fset_opts(opts->flags, REFRESH_IDOP);

	if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
		rerr = au_xib_trunc(sb);
		if (unlikely(rerr && !err))
			err = rerr;
	}

	/* will be handled by the caller */
	if (!au_ftest_opts(opts->flags, REFRESH)
	    && (opts->given_udba
		|| au_opt_test(sbinfo->si_mntflags, XINO)
		|| au_ftest_opts(opts->flags, REFRESH_IDOP)
		    ))
		au_fset_opts(opts->flags, REFRESH);

	AuDbg("status 0x%x\n", opts->flags);
	return err;
}
コード例 #24
0
/* round robin */
static int au_wbr_create_init_rr(struct super_block *sb)
{
	int err;

	err = au_wbr_bu(sb, au_sbend(sb));
	atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
	/* smp_mb(); */

	AuDbg("b%d\n", err);
	return err;
}
コード例 #25
0
ファイル: whout.c プロジェクト: bjayesh/chandra
/*
 * returns a negative dentry whose name is unique and temporary.
 */
struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
			     struct qstr *prefix)
{
	struct dentry *dentry;
	int i;
	char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
		*name, *p;
	/* strict atomic_t is unnecessary here */
	static unsigned short cnt;
	struct qstr qs;

	BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);

	name = defname;
	qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
	if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
		dentry = ERR_PTR(-ENAMETOOLONG);
		if (unlikely(qs.len > NAME_MAX))
			goto out;
		dentry = ERR_PTR(-ENOMEM);
		name = kmalloc(qs.len + 1, GFP_NOFS);
		if (unlikely(!name))
			goto out;
	}

	/* doubly whiteout-ed */
	memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
	p = name + AUFS_WH_PFX_LEN * 2;
	memcpy(p, prefix->name, prefix->len);
	p += prefix->len;
	*p++ = '.';
	AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);

	qs.name = name;
	for (i = 0; i < 3; i++) {
		sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
		dentry = au_sio_lkup_one(&qs, h_parent, br);
		if (IS_ERR(dentry) || !dentry->d_inode)
			goto out_name;
		dput(dentry);
	}
	/* pr_warn("could not get random name\n"); */
	dentry = ERR_PTR(-EEXIST);
	AuDbg("%.*s\n", AuLNPair(&qs));
	BUG();

out_name:
	if (name != defname)
		kfree(name);
out:
	AuTraceErrPtr(dentry);
	return dentry;
}
コード例 #26
0
static int au_wbr_create_rr(struct dentry *dentry, int isdir)
{
	int err, nbr;
	unsigned int u;
	aufs_bindex_t bindex, bend;
	struct super_block *sb;
	atomic_t *next;

	err = au_wbr_create_exp(dentry);
	if (err >= 0)
		goto out;

	sb = dentry->d_sb;
	next = &au_sbi(sb)->si_wbr_rr_next;
	bend = au_sbend(sb);
	nbr = bend + 1;
	for (bindex = 0; bindex <= bend; bindex++) {
		if (!isdir) {
			err = atomic_dec_return(next) + 1;
			/* modulo for 0 is meaningless */
			if (unlikely(!err))
				err = atomic_dec_return(next) + 1;
		} else
			err = atomic_read(next);
		AuDbg("%d\n", err);
		u = err;
		err = u % nbr;
		AuDbg("%d\n", err);
		if (!au_br_rdonly(au_sbr(sb, err)))
			break;
		err = -EROFS;
	}

	if (err >= 0)
		err = au_wbr_nonopq(dentry, err);

out:
	AuDbg("%d\n", err);
	return err;
}
コード例 #27
0
static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
			   unsigned int sigen, const unsigned int verbose)
{
	int err;
	unsigned long long max, ull;
	struct inode *i, **array;
	aufs_bindex_t bstart, bend;

	array = au_iarray_alloc(sb, &max);
	err = PTR_ERR(array);
	if (IS_ERR(array))
		goto out;

	err = 0;
	AuDbg("b%d\n", bindex);
	for (ull = 0; !err && ull < max; ull++) {
		i = array[ull];
		if (i->i_ino == AUFS_ROOT_INO)
			continue;

		/* AuDbgInode(i); */
		if (au_iigen(i) == sigen)
			ii_read_lock_child(i);
		else {
			ii_write_lock_child(i);
			err = au_refresh_hinode_self(i);
			au_iigen_dec(i);
			if (!err)
				ii_downgrade_lock(i);
			else {
				ii_write_unlock(i);
				break;
			}
		}

		bstart = au_ibstart(i);
		bend = au_ibend(i);
		if (bstart <= bindex
		    && bindex <= bend
		    && au_h_iptr(i, bindex)
		    && au_test_ibusy(i, bstart, bend)) {
			err = -EBUSY;
			AuVerbose(verbose, "busy i%lu\n", i->i_ino);
			AuDbgInode(i);
		}
		ii_read_unlock(i);
	}
	au_iarray_free(array, max);

out:
	return err;
}
コード例 #28
0
/* common function to regular file and dir */
int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
			  int wlock)
{
	int err;
	unsigned int sigen, figen;
	aufs_bindex_t bstart;
	unsigned char pseudo_link;
	struct dentry *dentry;
	struct inode *inode;

	err = 0;
	dentry = file->f_dentry;
	inode = dentry->d_inode;
	AuDebugOn(au_special_file(inode->i_mode));
	sigen = au_sigen(dentry->d_sb);
	fi_write_lock(file);
	figen = au_figen(file);
	di_write_lock_child(dentry);
	bstart = au_dbstart(dentry);
	pseudo_link = (bstart != au_ibstart(inode));
	if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
		if (!wlock) {
			di_downgrade_lock(dentry, AuLock_IR);
			fi_downgrade_lock(file);
		}
		goto out; /* success */
	}

	AuDbg("sigen %d, figen %d\n", sigen, figen);
	if (sigen != au_digen(dentry)
	    || sigen != au_iigen(inode)) {
		err = au_reval_dpath(dentry, sigen);
		if (unlikely(err < 0))
			goto out;
		AuDebugOn(au_digen(dentry) != sigen
			  || au_iigen(inode) != sigen);
	}

	err = refresh_file(file, reopen);
	if (!err) {
		if (!wlock) {
			di_downgrade_lock(dentry, AuLock_IR);
			fi_downgrade_lock(file);
		}
	} else {
		di_write_unlock(dentry);
		fi_write_unlock(file);
	}

out:
	return err;
}
コード例 #29
0
ファイル: opts.c プロジェクト: bjayesh/chandra
static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
{
	int err;

	del->pathname = args[0].from;
	AuDbg("del path %s\n", del->pathname);

	err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
	if (unlikely(err))
		pr_err("lookup failed %s (%d)\n", del->pathname, err);

	return err;
}
コード例 #30
0
ファイル: vdir.c プロジェクト: mobilehunter/trafficsqueezer
/* returns found or not */
int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
{
	struct hlist_head *head;
	struct au_vdir_wh *pos;
	struct au_vdir_destr *str;

	head = au_name_hash(whlist, name, nlen);
	hlist_for_each_entry(pos, head, wh_hash) {
		str = &pos->wh_str;
		AuDbg("%.*s\n", str->len, str->name);
		if (au_nhash_test_name(str, name, nlen))
			return 1;
	}