예제 #1
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;
}
예제 #2
0
static struct dentry *
lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
		    struct dtime *dt)
{
	struct dentry *wh_dentry;
	int err, need_wh;
	struct dentry *hidden_parent, *parent;
	struct inode *dir, *h_dir;
	struct lkup_args lkup;

	LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir);

	err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL);
	//err = -1;
	wh_dentry = ERR_PTR(err);
	if (unlikely(err < 0))
		goto out;

	parent = dentry->d_parent;
	dir = parent->d_inode;
	hidden_parent = au_h_dptr_i(parent, *bcpup);
	h_dir = hidden_parent->d_inode;
	hdir_lock(h_dir, dir, *bcpup);
	dtime_store(dt, parent, hidden_parent);
	if (!need_wh)
		return NULL; /* success, no need to create whiteout */

	lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
	lkup.dlgt = need_dlgt(dentry->d_sb);
	wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup);
	//wh_dentry = ERR_PTR(-1);
	if (!IS_ERR(wh_dentry))
		goto out; /* success */
	/* returns with the parent is locked and wh_dentry is DGETed */

	hdir_unlock(h_dir, dir, *bcpup);

 out:
	TraceErrPtr(wh_dentry);
	return wh_dentry;
}
예제 #3
0
static struct dentry *lkup_hash(const char *name, struct dentry *parent,
				int len, struct lkup_args *lkup)
{
	struct dentry *dentry;
	char *p;
	unsigned long hash;
	struct qstr this;
	unsigned int c;
	struct nameidata tmp_nd;

	dentry = ERR_PTR(-EACCES);
	this.name = name;
	this.len = len;
	if (unlikely(!len))
		goto out;

	p = (void*)name;
	hash = init_name_hash();
	while (len--) {
		c = *p++;
		if (unlikely(c == '/' || c == '\0'))
			goto out;
		hash = partial_name_hash(c, hash);
	}
	this.hash = end_name_hash(hash);

	memset(&tmp_nd, 0, sizeof(tmp_nd));
	tmp_nd.dentry = dget(parent);
	tmp_nd.mnt = mntget(lkup->nfsmnt);
#ifndef CONFIG_AUFS_DLGT
	dentry = __lookup_hash(&this, parent, &tmp_nd);
#else
	if (!lkup->dlgt)
		dentry = __lookup_hash(&this, parent, &tmp_nd);
	else {
		int wkq_err;
		struct lookup_hash_args args = {
			.errp	= &dentry,
			.name	= &this,
			.base	= parent,
			.nd	= &tmp_nd
		};
		wkq_err = au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1);
		if (unlikely(wkq_err))
			dentry = ERR_PTR(wkq_err);
	}
#endif
	path_release(&tmp_nd);

 out:
	TraceErrPtr(dentry);
	return dentry;
}
#elif defined(CONFIG_AUFS_DLGT)
static struct dentry *lkup_hash(const char *name, struct dentry *parent,
				int len, struct lkup_args *lkup)
{
	return ERR_PTR(-ENOSYS);
}
#endif

#ifdef CONFIG_AUFS_DLGT
struct lookup_one_len_args {
	struct dentry **errp;
	const char *name;
	struct dentry *parent;
	int len;
};

static void call_lookup_one_len(void *args)
{
	struct lookup_one_len_args *a = args;
	*a->errp = lookup_one_len(a->name, a->parent, a->len);
}
#endif /* CONFIG_AUFS_DLGT */

#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
/* cf. lookup_one_len() in linux/fs/namei.c */
struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
			struct lkup_args *lkup)
{
	struct dentry *dentry;

	LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n",
		  DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt);

	if (!lkup->nfsmnt) {
#ifndef CONFIG_AUFS_DLGT
		dentry = lookup_one_len(name, parent, len);
#else
		if (!lkup->dlgt)
			dentry = lookup_one_len(name, parent, len);
		else {
			int wkq_err;
			struct lookup_one_len_args args = {
				.errp	= &dentry,
				.name	= name,
				.parent	= parent,
				.len	= len
			};
			wkq_err = au_wkq_wait(call_lookup_one_len, &args,
					      /*dlgt*/1);
			if (unlikely(wkq_err))
				dentry = ERR_PTR(wkq_err);
		}
#endif
	} else