Ejemplo n.º 1
0
static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
			   char *buf, int len, struct super_block *sb)
{
	char *p;
	int n;

	AuTraceEnter();

	p = d_path(h_rootpath->dentry, h_rootpath->mnt, buf, len);
	if (IS_ERR(p))
		goto out;
	n = strlen(p);

	p = d_path(h_parent, h_rootpath->mnt, buf, len);
	if (IS_ERR(p))
		goto out;
	LKTRTrace("%s\n", p);
	if (n != 1)
		p += n;
	LKTRTrace("%p, %s, %ld\n",
		  p, p, (long)(p - buf));

	p = d_path(sb->s_root, au_sbi(sb)->si_mnt, buf, len - strlen(p));
	if (IS_ERR(p))
		goto out;
	if (n != 1)
		p[strlen(p)] = '/';
	LKTRTrace("%s\n", p);

 out:
	AuTraceErrPtr(p);
	return p;
}
Ejemplo n.º 2
0
static /* noinline_for_stack */
struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
				 ino_t dir_ino, struct au_nfsd_si_lock *nsi_lock)
{
	struct dentry *dentry, *parent;
	struct path path;

	LKTRTrace("i%lu, diri%lu\n",
		  (unsigned long)ino, (unsigned long)dir_ino);

	parent = sb->s_root;
	if (dir_ino != AUFS_ROOT_INO) {
		parent = decode_by_ino(sb, dir_ino, 0);
		dentry = parent;
		if (!parent)
			goto out;
		if (IS_ERR(parent))
			goto out;
		AuDebugOn(au_test_anon(parent));
	} else
		dget(parent);

	path.dentry = parent;
	path.mnt = au_sbi(sb)->si_mnt;
	dentry = au_lkup_by_ino(&path, ino, nsi_lock);
	dput(parent);

 out:
	AuTraceErrPtr(dentry);
	return dentry;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
int au_xigen_inc(struct inode *inode)
{
	int err;
	loff_t pos;
	ssize_t sz;
	__u32 igen;
	struct super_block *sb;
	struct au_sbinfo *sbinfo;

	LKTRTrace("i%lu\n", (unsigned long)inode->i_ino);

	err = 0;
	sb = inode->i_sb;
	if (unlikely(!au_opt_test_xino(au_mntflags(sb))))
		goto out;

	pos = inode->i_ino;
	pos *= sizeof(igen);
	igen = inode->i_generation + 1;
	sbinfo = au_sbi(sb);
	sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
			 sizeof(igen), &pos);
	if (sz == sizeof(igen))
		goto out; /* success */

	err = sz;
	if (unlikely(sz >= 0)) {
		err = -EIO;
		AuIOErr("xigen error (%zd)\n", sz);
	}

 out:
	AuTraceErr(err);
	return err;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
				  struct nameidata *nd)
{
	struct dentry *d;

	LKTRTrace("%.*s/%.*s, nd %d\n",
		  AuDLNPair(parent), AuLNPair(name), !!nd);
	if (nd)
		LKTRTrace("nd{0x%x}\n", nd->flags);
	IMustLock(parent->d_inode);

	d = __lookup_hash(name, parent, nd);
	if (!IS_ERR(d))
		au_update_fuse_h_inode(NULL, d); /*ignore*/
	return d;
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
void au_cpup_attr_nlink(struct inode *inode, int force)
{
	struct inode *h_inode;
	struct super_block *sb;
	aufs_bindex_t bindex, bend;

	LKTRTrace("i%lu\n", inode->i_ino);
	/* todo? IMustLock(inode); */
	AuDebugOn(!inode->i_mode);

	sb = inode->i_sb;
	bindex = au_ibstart(inode);
	h_inode = au_h_iptr(inode, bindex);

	if (!force
	    && !S_ISDIR(h_inode->i_mode)
	    && au_opt_test(au_mntflags(sb), PLINK)
	    && au_plink_test(sb, inode))
		return;

	inode->i_nlink = h_inode->i_nlink;

	/*
	 * fewer nlink makes find(1) noisy, but larger nlink doesn't.
	 * it may includes whplink directory.
	 */
	if (S_ISDIR(h_inode->i_mode)) {
		bend = au_ibend(inode);
		for (bindex++; bindex <= bend; bindex++) {
			h_inode = au_h_iptr(inode, bindex);
			if (h_inode)
				au_add_nlink(inode, h_inode);
		}
	}
}
Ejemplo n.º 11
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
Ejemplo n.º 12
0
/* common functions to regular file and dir */
struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags)
{
	struct dentry *hidden_dentry;
	struct inode *hidden_inode;
	struct super_block *sb;
	struct vfsmount *hidden_mnt;
	struct file *hidden_file;
	struct aufs_branch *br;
	loff_t old_size;
	int udba;

	LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags);
	DEBUG_ON(!dentry);
	hidden_dentry = au_h_dptr_i(dentry, bindex);
	DEBUG_ON(!hidden_dentry);
	hidden_inode = hidden_dentry->d_inode;
	DEBUG_ON(!hidden_inode);

	sb = dentry->d_sb;
	udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
	if (unlikely(udba)) {
		// test here?
	}

	br = stobr(sb, bindex);
	br_get(br);
	/* drop flags for writing */
	if (test_ro(sb, bindex, dentry->d_inode))
		flags = au_file_roflags(flags);
	flags &= ~O_CREAT;
	spin_lock(&hidden_inode->i_lock);
	old_size = i_size_read(hidden_inode);
	spin_unlock(&hidden_inode->i_lock);

	//DbgSleep(3);

	dget(hidden_dentry);
	hidden_mnt = mntget(br->br_mnt);
	hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags);
	//if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);}

	if (!IS_ERR(hidden_file)) {
#if 0 // remove this
		if (/* old_size && */ (flags & O_TRUNC)) {
			au_direval_dec(dentry);
			if (!IS_ROOT(dentry))
				au_direval_dec(dentry->d_parent);
		}
#endif
		return hidden_file;
	}

	br_put(br);
	TraceErrPtr(hidden_file);
	return hidden_file;
}
Ejemplo n.º 13
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);
}
Ejemplo n.º 14
0
int au_xigen_new(struct inode *inode)
{
	int err;
	loff_t pos;
	ssize_t sz;
	struct super_block *sb;
	struct au_sbinfo *sbinfo;
	struct file *file;

	LKTRTrace("i%lu\n", inode->i_ino);

	err = 0;
	/* todo: dirty, at mount time */
	if (inode->i_ino == AUFS_ROOT_INO)
		goto out;
	sb = inode->i_sb;
	if (unlikely(!au_opt_test_xino(au_mntflags(sb))))
		goto out;

	err = -EFBIG;
	pos = inode->i_ino;
	if (unlikely(Au_LOFF_MAX / sizeof(inode->i_generation) - 1 < pos)) {
		AuIOErr1("too large i%lld\n", pos);
		goto out;
	}
	pos *= sizeof(inode->i_generation);

	err = 0;
	sbinfo = au_sbi(sb);
	file = sbinfo->si_xigen;
	BUG_ON(!file);

	if (i_size_read(file->f_dentry->d_inode)
	    < pos + sizeof(inode->i_generation)) {
		inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
		sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
				 sizeof(inode->i_generation), &pos);
	} else
		sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
				sizeof(inode->i_generation), &pos);
	if (sz == sizeof(inode->i_generation))
		goto out; /* success */

	err = sz;
	if (unlikely(sz >= 0)) {
		err = -EIO;
		AuIOErr("xigen error (%zd)\n", sz);
	}

 out:
	AuTraceErr(err);
	return err;
}
Ejemplo n.º 15
0
struct file *vfsub_filp_open(const char *path, int oflags, int mode)
{
	struct file *err;

	LKTRTrace("%s\n", path);

	lockdep_off();
	err = filp_open(path, oflags, mode);
	lockdep_on();
	if (!IS_ERR(err))
		au_update_fuse_h_inode(err->f_vfsmnt, err->f_dentry); /*ignore*/
	return err;
}
Ejemplo n.º 16
0
void au_cpup_attr_timesizes(struct inode *inode)
{
	struct inode *h_inode;

	LKTRTrace("i%lu\n", inode->i_ino);
	/* todo? IMustLock(inode); */
	h_inode = au_h_iptr(inode, au_ibstart(inode));
	AuDebugOn(!h_inode);
	/* todo? IMustLock(!h_inode); */

	fsstack_copy_attr_times(inode, h_inode);
	vfsub_copy_inode_size(inode, h_inode);
}
Ejemplo n.º 17
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);
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
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);
}
Ejemplo n.º 22
0
int au_reopen_nondir(struct file *file)
{
	int err;
	struct dentry *dentry;
	aufs_bindex_t bstart, bindex, bend;
	struct file *hidden_file, *h_file_tmp;

	dentry = file->f_dentry;
	LKTRTrace("%.*s\n", DLNPair(dentry));
	DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
		 || !au_h_dptr(dentry)->d_inode);
	bstart = dbstart(dentry);

	h_file_tmp = NULL;
	if (fbstart(file) == bstart) {
		hidden_file = au_h_fptr(file);
		if (file->f_mode == hidden_file->f_mode)
			return 0; /* success */
		h_file_tmp = hidden_file;
		get_file(h_file_tmp);
		set_h_fptr(file, bstart, NULL);
	}
	DEBUG_ON(fbstart(file) < bstart
		 || ftofi(file)->fi_hfile[0 + bstart].hf_file);

	hidden_file = hidden_open(dentry, bstart, file->f_flags & ~O_TRUNC);
	//if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bstart));
	//hidden_file = ERR_PTR(-1);}
	err = PTR_ERR(hidden_file);
	if (IS_ERR(hidden_file))
		goto out; // close all?
	err = 0;
	//cpup_file_flags(hidden_file, file);
	set_fbstart(file, bstart);
	set_h_fptr(file, bstart, hidden_file);
	memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(file->f_ra)); //??

	/* close lower files */
	bend = fbend(file);
	for (bindex = bstart + 1; bindex <= bend; bindex++)
		set_h_fptr(file, bindex, NULL);
	set_fbend(file, bstart);

 out:
	if (h_file_tmp)
		fput(h_file_tmp);
	TraceErr(err);
	return err;
}
Ejemplo n.º 23
0
int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
{
	int err;

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

	lockdep_off();
	err = vfs_rmdir(dir, dentry);
	lockdep_on();
	/* dir inode is locked */
	if (!err)
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
	return err;
}
Ejemplo n.º 24
0
void au_cpup_attr_changeable(struct inode *inode)
{
	struct inode *h_inode;

	LKTRTrace("i%lu\n", inode->i_ino);
	/* todo? IMustLock(inode); */
	h_inode = au_h_iptr(inode, au_ibstart(inode));
	AuDebugOn(!h_inode);

	inode->i_mode = h_inode->i_mode;
	inode->i_uid = h_inode->i_uid;
	inode->i_gid = h_inode->i_gid;
	au_cpup_attr_timesizes(inode);
	au_cpup_attr_flags(inode, h_inode);
}
Ejemplo n.º 25
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;
}
Ejemplo n.º 26
0
int vfsub_path_lookup(const char *name, unsigned int flags,
		      struct nameidata *nd)
{
	int err;

	LKTRTrace("%s\n", name);

	/* lockdep_off(); */
	err = path_lookup(name, flags, nd);
	/* lockdep_on(); */
	if (!err)
		au_update_fuse_h_inode(nd->mnt, nd->dentry);
	/*ignore*/
	return err;
}
Ejemplo n.º 27
0
int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
	int err;

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

	err = vfs_mkdir(dir, dentry, mode);
	if (!err) {
		/* dir inode is locked */
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
	}
	return err;
}
Ejemplo n.º 28
0
ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
			 size_t count, loff_t *ppos)
{
	ssize_t err;

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

	lockdep_off();
	err = vfs_write(file, ubuf, count, ppos);
	lockdep_on();
	if (err >= 0)
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
	/*ignore*/
	return err;
}
Ejemplo n.º 29
0
static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
{
	int err;
	struct dentry *parent, *h_parent, *h_dentry;
	aufs_bindex_t bcpup;
	struct inode *h_dir, *h_inode, *dir;

	LKTRTrace("%.*s\n", DLNPair(dentry));
	DEBUG_ON(IS_ROOT(dentry));
	DiMustWriteLock(dentry);

	parent = dentry->d_parent; // dget_parent()
	di_write_lock_parent(parent);
	bcpup = err = find_rw_parent_br(dentry, bstart);
	//bcpup = err = find_rw_br(sb, bstart);
	if (unlikely(err < 0)) {
		err = 0; // stop copyup, it is not an error
		goto out;
	}
	err = 0;

	h_parent = au_h_dptr_i(parent, bcpup);
	if (!h_parent) {
		err = cpup_dirs(dentry, bcpup, NULL);
		if (unlikely(err))
			goto out;
		h_parent = au_h_dptr_i(parent, bcpup);
	}

	h_dir = h_parent->d_inode;
	h_dentry = au_h_dptr_i(dentry, bstart);
	h_inode = h_dentry->d_inode;
	dir = parent->d_inode;
	hdir_lock(h_dir, dir, bcpup);
	hi_lock_child(h_inode);
	DEBUG_ON(au_h_dptr_i(dentry, bcpup));
	err = sio_cpup_simple(dentry, bcpup, -1,
			      au_flags_cpup(CPUP_DTIME, parent));
	TraceErr(err);
	i_unlock(h_inode);
	hdir_unlock(h_dir, dir, bcpup);

 out:
	di_write_unlock(parent);
	TraceErr(err);
	return err;
}
Ejemplo n.º 30
0
void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
{
	LKTRTrace("%.*s, %u\n", AuDLNPair(d), lsc);
	SiMustAnyLock(d->d_sb);

	/* todo: always nested? */
	au_dbg_locking_di_reg(d, flags, lsc);
	au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
	au_dbg_locking_di_unreg(d, flags);
	au_dbg_locked_di_reg(d, flags, lsc);
	if (d->d_inode) {
		if (au_ftest_lock(flags, IW))
			do_ii_write_lock(d->d_inode, lsc);
		else if (au_ftest_lock(flags, IR))
			do_ii_read_lock(d->d_inode, lsc);
	}
}