Example #1
0
static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
{
	struct dentry *wh = NULL;
	int hn;

	if (!dentry || IS_ERR(dentry)) {
		dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
		return -1;
	}
	/* do not call dget_parent() here */
	/* note: access d_xxx without d_lock */
	dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
	     bindex,
	     AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
	     dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
	     d_count(dentry), dentry->d_flags);
	hn = -1;
	if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
		struct au_iinfo *iinfo = au_ii(dentry->d_inode);
		if (iinfo) {
			hn = !!au_hn(iinfo->ii_hinode + bindex);
			wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
		}
	}
	do_pri_inode(bindex, dentry->d_inode, hn, wh);
	return 0;
}
static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
{
	int rerr;

	a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
				       a->br, /*nd*/NULL);
	rerr = PTR_ERR(a->h_path.dentry);
	if (IS_ERR(a->h_path.dentry)) {
		RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
		return;
	}
	if (a->h_path.dentry->d_inode) {
		d_drop(a->h_path.dentry);
		dput(a->h_path.dentry);
		return;
	}

	rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
	d_drop(a->h_path.dentry);
	dput(a->h_path.dentry);
	if (!rerr)
		au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
	else
		RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
}
Example #3
0
/*
 * for the moment, aufs supports the branch filesystem which does not support
 * link(2). testing on FAT which does not support i_op->setattr() fully either,
 * copyup failed. finally, such filesystem will not be used as the writable
 * branch.
 *
 * returns tri-state, see above.
 */
static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
			 int do_plink, struct au_wh_base base[],
			 struct path *h_path)
{
	int err;
	struct inode *h_dir;

	WbrWhMustWriteLock(wbr);

	err = test_linkable(h_root);
	if (unlikely(err)) {
		err = 1;
		goto out;
	}

	/*
	 * todo: should this create be done in /sbin/mount.aufs helper?
	 */
	err = -EEXIST;
	h_dir = h_root->d_inode;
	if (!base[AuBrWh_BASE].dentry->d_inode) {
		h_path->dentry = base[AuBrWh_BASE].dentry;
		err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true);
	} else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
		err = 0;
	else
		pr_err("unknown %.*s/%.*s exists\n",
		       AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
	if (unlikely(err))
		goto out;

	h_path->dentry = base[AuBrWh_PLINK].dentry;
	if (do_plink) {
		err = au_whdir(h_dir, h_path);
		if (unlikely(err))
			goto out;
		wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
	} else
		au_wh_clean(h_dir, h_path, /*isdir*/1);
	wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);

	h_path->dentry = base[AuBrWh_ORPH].dentry;
	err = au_whdir(h_dir, h_path);
	if (unlikely(err))
		goto out;
	wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);

out:
	return err;
}
Example #4
0
/*
 * test if the @wh_name exists under @h_parent.
 * @try_sio specifies the necessary of super-io.
 */
int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
	       struct au_branch *br, int try_sio)
{
	int err;
	struct dentry *wh_dentry;

	if (!try_sio)
		wh_dentry = vfsub_lkup_one(wh_name, h_parent);
	else
		wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
	err = PTR_ERR(wh_dentry);
	if (IS_ERR(wh_dentry))
		goto out;

	err = 0;
	if (!wh_dentry->d_inode)
		goto out_wh; /* success */

	err = 1;
	if (S_ISREG(wh_dentry->d_inode->i_mode))
		goto out_wh; /* success */

	err = -EIO;
	AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
		AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);

out_wh:
	dput(wh_dentry);
out:
	return err;
}
Example #5
0
/*
 * 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;
}
/* cf. aufs_rmdir() */
static int au_ren_del_whtmp(struct au_ren_args *a)
{
	int err;
	struct inode *dir;

	dir = a->dst_dir;
	SiMustAnyLock(dir->i_sb);
	if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
				     au_sbi(dir->i_sb)->si_dirwh)
	    || au_test_fs_remote(a->h_dst->d_sb)) {
		err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
		if (unlikely(err))
			pr_warning("failed removing whtmp dir %.*s (%d), "
				   "ignored.\n", AuDLNPair(a->h_dst), err);
	} else {
		au_nhash_wh_free(&a->thargs->whlist);
		a->thargs->whlist = a->whlist;
		a->whlist.nh_num = 0;
		au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
		dput(a->h_dst);
		a->thargs = NULL;
	}

	return 0;
}
static int au_wbr_init(struct au_branch *br, struct super_block *sb,
		       int perm, struct path *path)
{
	int err;
	struct kstatfs kst;
	struct au_wbr *wbr;
	struct dentry *h_dentry;

	wbr = br->br_wbr;
	au_rw_init(&wbr->wbr_wh_rwsem);
	memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
	atomic_set(&wbr->wbr_wh_running, 0);
	wbr->wbr_bytes = 0;

	/*
	 * a limit for rmdir/rename a dir
	 * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
	 */
	h_dentry = path->dentry;
	err = vfs_statfs(h_dentry, &kst);
	if (unlikely(err))
		goto out;
	err = -EINVAL;
	if (kst.f_namelen >= NAME_MAX)
		err = au_br_init_wh(sb, br, perm, h_dentry);
	else
		pr_err("%.*s(%s), unsupported namelen %ld\n",
		       AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
		       kst.f_namelen);

out:
	return err;
}
Example #8
0
ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
		    loff_t *pos)
{
	ssize_t err;

	LKTRTrace("%.*s, sz %zu, *pos %lld\n",
		  AuDLNPair(file->f_dentry), size, *pos);

	/* todo: signal block and no wkq? */
	/*
	 * it breaks RLIMIT_FSIZE and normal user's limit,
	 * users should care about quota and real 'filesystem full.'
	 */
	if (!au_test_wkq(current)) {
		int wkq_err;
		struct do_xino_fwrite_args args = {
			.errp	= &err,
			.func	= func,
			.file	= file,
			.buf	= buf,
			.size	= size,
			.pos	= pos
		};
		wkq_err = au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
		if (unlikely(wkq_err))
			err = wkq_err;
	} else
Example #9
0
static void call_unlink(void *args)
{
	struct unlink_args *a = args;
	struct inode *h_inode;
	const int stop_sillyrename = (au_test_nfs(a->dentry->d_sb)
				      && atomic_read(&a->dentry->d_count) == 1);

	LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
		  AuDLNPair(a->dentry), stop_sillyrename,
		  atomic_read(&a->dentry->d_count));

	if (!stop_sillyrename)
		dget(a->dentry);
	h_inode = a->dentry->d_inode;
	if (h_inode)
		atomic_inc_return(&h_inode->i_count);
	vfsub_ignore(a->vargs);
	*a->errp = do_vfsub_unlink(a->dir, a->dentry);
	if (unlikely(*a->errp || (a->dentry->d_flags & DCACHE_NFSFS_RENAMED)))
		vfsub_unignore(a->vargs);
	au_dbg_hin_list(a->vargs);
	if (!stop_sillyrename)
		dput(a->dentry);
	if (h_inode)
		iput(h_inode);

	AuTraceErr(*a->errp);
}
Example #10
0
void au_dtime_revert(struct au_dtime *dt)
{
	struct iattr attr;
	int err;
	struct au_hin_ignore ign[2];
	struct vfsub_args vargs;

	LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry));

	attr.ia_atime = dt->dt_atime;
	attr.ia_mtime = dt->dt_mtime;
	attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
		| ATTR_ATIME | ATTR_ATIME_SET;

	vfsub_args_init(&vargs, ign,
			au_test_dlgt(au_mntflags(dt->dt_dentry->d_sb)), 0);
	/*
	 * IN_ATTRIB should be divided into
	 * IN_ATTRIB_ATIME, IN_ATTRIB_MTIME ...,
	 * and define all ORed new IN_ATTRIB macro.
	 */
	vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hinode);
	vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hdir);
	err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs);
	if (unlikely(err))
		AuWarn("restoring timestamps failed(%d). ignored\n", err);
}
Example #11
0
ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
		   loff_t *pos)
{
	ssize_t err;
	mm_segment_t oldfs;

	LKTRTrace("%.*s, sz %zu, *pos %lld\n",
		  AuDLNPair(file->f_dentry), size, *pos);

	oldfs = get_fs();
	set_fs(KERNEL_DS);
	do {
		/* todo: signal_pending? */
		err = func(file, (char __user *)buf, size, pos);
	} while (err == -EAGAIN || err == -EINTR);
	set_fs(oldfs);

#if 0 /* reserved for future use */
	if (err > 0)
		fsnotify_access(file->f_dentry);
#endif

	AuTraceErr(err);
	return err;
}
Example #12
0
int vfsub_sio_notify_change(struct au_hinode *hdir, struct dentry *dentry,
			    struct iattr *ia)
{
	int err, wkq_err;
	struct au_hin_ignore ign;
	struct vfsub_args vargs;
	__u32 events;
	struct notify_change_args args = {
		.errp		= &err,
		.h_dentry	= dentry,
		.ia		= ia,
		.vargs		= &vargs
	};

	LKTRTrace("%.*s, 0x%x\n", AuDLNPair(dentry), ia->ia_valid);

	vfsub_args_init(&vargs, &ign, /*dlgt*/0, /*force_unlink*/0);
	events = vfsub_events_notify_change(ia);
	if (events)
		vfsub_ign_hinode(&vargs, events, hdir);
	wkq_err = au_wkq_wait(call_notify_change, &args, /*dlgt*/0);
	if (unlikely(wkq_err))
		err = wkq_err;

	AuTraceErr(err);
	return err;
}
Example #13
0
int vfsub_sio_rmdir(struct au_hinode *hdir, struct dentry *dentry, int dlgt)
{
	int err, do_sio, wkq_err;
	struct inode *dir = hdir->hi_inode;
	struct au_hin_ignore ign;
	struct vfsub_args vargs;

	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));

	vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0);
	vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
	do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
	if (!do_sio)
		err = vfsub_rmdir(dir, dentry, &vargs);
	else {
		struct au_vfsub_rmdir_args args = {
			.errp		= &err,
			.dir		= dir,
			.dentry		= dentry,
			.vargs		= &vargs
		};
		vfsub_fclr(vargs.flags, DLGT);
		wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args, /*dlgt*/0);
		if (unlikely(wkq_err))
			err = wkq_err;
	}

	AuTraceErr(err);
	return err;
}
Example #14
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;
}
Example #15
0
void di_write_unlock(struct dentry *d)
{
	LKTRTrace("%.*s\n", AuDLNPair(d));
	SiMustAnyLock(d->d_sb);

	if (d->d_inode)
		ii_write_unlock(d->d_inode);
	au_rw_write_unlock(&au_di(d)->di_rwsem);
	au_dbg_locked_di_unreg(d, AuLock_IW);
}
static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
{
	int rerr;

	a->h_path.dentry = a->src_wh_dentry;
	rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
	au_set_dbwh(a->src_dentry, a->src_bwh);
	if (rerr)
		RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
}
static void au_ren_rev_cpup(int err, struct au_ren_args *a)
{
	int rerr;

	a->h_path.dentry = a->dst_h_dentry;
	rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
	au_set_h_dptr(a->src_dentry, a->btgt, NULL);
	au_set_dbstart(a->src_dentry, a->src_bstart);
	if (rerr)
		RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
}
static void au_ren_rev_diropq(int err, struct au_ren_args *a)
{
	int rerr;

	au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
	rerr = au_diropq_remove(a->src_dentry, a->btgt);
	au_hn_imtx_unlock(a->src_hinode);
	au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
	if (rerr)
		RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
}
Example #19
0
static int test_linkable(struct dentry *h_root)
{
	struct inode *h_dir = h_root->d_inode;

	if (h_dir->i_op->link)
		return 0;

	pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
	       AuDLNPair(h_root), au_sbtype(h_root->d_sb));
	return -ENOSYS;
}
static void au_ren_rev_rename(int err, struct au_ren_args *a)
{
	int rerr;

	a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
				       a->br, /*nd*/NULL);
	rerr = PTR_ERR(a->h_path.dentry);
	if (IS_ERR(a->h_path.dentry)) {
		RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
		return;
	}

	rerr = vfsub_rename(a->dst_h_dir,
			    au_h_dptr(a->src_dentry, a->btgt),
			    a->src_h_dir, &a->h_path);
	d_drop(a->h_path.dentry);
	dput(a->h_path.dentry);
	/* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
	if (rerr)
		RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
}
Example #21
0
/*
 * final procedure of adding a new entry, except link(2).
 * remove whiteout, instantiate, copyup the parent dir's times and size
 * and update version.
 * if it failed, re-create the removed whiteout.
 */
static int epilog(struct inode *dir, aufs_bindex_t bindex,
		  struct dentry *wh_dentry, struct dentry *dentry)
{
	int err, rerr;
	aufs_bindex_t bwh;
	struct path h_path;
	struct inode *inode, *h_dir;
	struct dentry *wh;

	bwh = -1;
	if (wh_dentry) {
		h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
		IMustLock(h_dir);
		AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
		bwh = au_dbwh(dentry);
		h_path.dentry = wh_dentry;
		h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
		err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
					  dentry);
		if (unlikely(err))
			goto out;
	}

	inode = au_new_inode(dentry, /*must_new*/1);
	if (!IS_ERR(inode)) {
		d_instantiate(dentry, inode);
		dir = dentry->d_parent->d_inode; /* dir inode is locked */
		IMustLock(dir);
		if (au_ibstart(dir) == au_dbstart(dentry))
			au_cpup_attr_timesizes(dir);
		dir->i_version++;
		return 0; /* success */
	}

	err = PTR_ERR(inode);
	if (!wh_dentry)
		goto out;

	/* revert */
	/* dir inode is locked */
	wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
	rerr = PTR_ERR(wh);
	if (IS_ERR(wh)) {
		AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
			AuDLNPair(dentry), err, rerr);
		err = -EIO;
	} else
		dput(wh);

out:
	return err;
}
Example #22
0
static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
{
	struct dentry *wh = NULL;

	if (!dentry || IS_ERR(dentry)) {
		dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
		return -1;
	}
	/* do not call dget_parent() here */
	dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
	     bindex,
	     AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
	     dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
	     atomic_read(&dentry->d_count), dentry->d_flags);
	if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
		struct au_iinfo *iinfo = au_ii(dentry->d_inode);
		if (iinfo)
			wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
	}
	do_pri_inode(bindex, dentry->d_inode, wh);
	return 0;
}
Example #23
0
struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
				    int len)
{
	struct dentry *d;

	LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
	IMustLock(parent->d_inode);

	d = lookup_one_len(name, parent, len);
	if (!IS_ERR(d))
		au_update_fuse_h_inode(NULL, d); /*ignore*/
	return d;
}
Example #24
0
void di_write_lock(struct dentry *d, unsigned int lsc)
{
	LKTRTrace("%.*s, %u\n", AuDLNPair(d), lsc);
	SiMustAnyLock(d->d_sb);

	/* todo: always nested? */
	au_dbg_locking_di_reg(d, AuLock_IW, lsc);
	au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
	au_dbg_locking_di_unreg(d, AuLock_IW);
	au_dbg_locked_di_reg(d, AuLock_IW, lsc);
	if (d->d_inode)
		do_ii_write_lock(d->d_inode, lsc);
}
Example #25
0
int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
		  struct dentry *dentry)
{
	int err;

	LKTRTrace("%.*s, i%lu, %.*s\n",
		  AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
	IMustLock(dir);

	lockdep_off();
	err = vfs_link(src_dentry, dir, dentry);
	lockdep_on();
	if (!err) {
		LKTRTrace("src_i %p, dst_i %p\n",
			  src_dentry->d_inode, dentry->d_inode);
		/* fuse has different memory inode for the same inumber */
		au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
		/* dir inode is locked */
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
	}
	return err;
}
Example #26
0
int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
		    struct inode *dir, struct dentry *dentry)
{
	int err;

	LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
		  src_dir->i_ino, AuDLNPair(src_dentry),
		  dir->i_ino, AuDLNPair(dentry));
	IMustLock(dir);
	IMustLock(src_dir);
	AuDebugOn(src_dir != dir && !vfsub_is_rename_mutex_locked(dir->i_sb));

	lockdep_off();
	err = vfs_rename(src_dir, src_dentry, dir, dentry);
	lockdep_on();
	if (!err) {
		/* dir inode is locked */
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
	}
	return err;
}
Example #27
0
int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
{
	int err;

	LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));

	lockdep_off();
	err = vfs_readdir(file, filldir, arg);
	lockdep_on();
	if (err >= 0)
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
	/*ignore*/
	return err;
}
Example #28
0
void di_read_unlock(struct dentry *d, int flags)
{
	LKTRTrace("%.*s\n", AuDLNPair(d));
	SiMustAnyLock(d->d_sb);

	if (d->d_inode) {
		if (au_ftest_lock(flags, IW))
			ii_write_unlock(d->d_inode);
		else if (au_ftest_lock(flags, IR))
			ii_read_unlock(d->d_inode);
	}
	au_rw_read_unlock(&au_di(d)->di_rwsem);
	au_dbg_locked_di_unreg(d, flags);
}
Example #29
0
int vfsub_iterate_dir(struct file *file, struct dir_context *ctx)
{
	int err;

	AuDbg("%.*s, ctx{%pf, %llu}\n",
	      AuDLNPair(file->f_dentry), ctx->actor, ctx->pos);

	lockdep_off();
	err = iterate_dir(file, ctx);
	lockdep_on();
	if (err >= 0)
		vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
	return err;
}
Example #30
0
long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
			  loff_t *ppos, size_t len, unsigned int flags)
{
	long err;

	LKTRTrace("%.*s, pos %lld, len %zu, 0x%x\n",
		  AuDLNPair(out->f_dentry), *ppos, len, flags);

	lockdep_off();
	err = vfs_splice_from(pipe, out, ppos, len, flags);
	lockdep_on();
	if (err >= 0)
		au_update_fuse_h_inode(out->f_vfsmnt, out->f_dentry); /*ignore*/
	return err;
}