Esempio n. 1
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;
}
Esempio n. 2
0
static 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;
	struct path path;

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

	path.mnt = au_mnt_get(sb);
	dentry = au_lkup_by_ino(&path, ino, nsi_lock);
	path_put(&path);

 out:
	AuTraceErrPtr(dentry);
	return dentry;
}
Esempio n. 3
0
static
struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
			      ino_t ino, __u32 *fh, int fh_len,
			      struct au_nfsd_si_lock *nsi_lock)
{
	struct dentry *dentry, *h_parent, *root;
	struct super_block *h_sb;
	char *pathname, *p;
	struct vfsmount *h_mnt;
	struct au_branch *br;
	int err;
	struct path path;

	br = au_sbr(sb, bindex);
	/* au_br_get(br); */
	h_mnt = br->br_mnt;
	h_sb = h_mnt->mnt_sb;
	/* todo: call lower fh_to_dentry()? fh_to_parent()? */
	h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
				      fh_len - Fh_tail, fh[Fh_h_type],
				      h_acceptable, /*context*/NULL);
	dentry = h_parent;
	if (unlikely(!h_parent || IS_ERR(h_parent))) {
		AuWarn1("%s decode_fh failed, %ld\n",
			au_sbtype(h_sb), PTR_ERR(h_parent));
		goto out;
	}
	dentry = NULL;
	if (unlikely(au_test_anon(h_parent))) {
		AuWarn1("%s decode_fh returned a disconnected dentry\n",
			au_sbtype(h_sb));
		goto out_h_parent;
	}

	dentry = ERR_PTR(-ENOMEM);
	pathname = (void *)__get_free_page(GFP_NOFS);
	if (unlikely(!pathname))
		goto out_h_parent;

	root = sb->s_root;
	path.mnt = h_mnt;
	di_read_lock_parent(root, !AuLock_IR);
	path.dentry = au_h_dptr(root, bindex);
	di_read_unlock(root, !AuLock_IR);
	p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
	dentry = (void *)p;
	if (IS_ERR(p))
		goto out_pathname;

	si_read_unlock(sb);
	err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
	dentry = ERR_PTR(err);
	if (unlikely(err))
		goto out_relock;

	dentry = ERR_PTR(-ENOENT);
	AuDebugOn(au_test_anon(path.dentry));
	if (unlikely(!path.dentry->d_inode))
		goto out_path;

	if (ino != path.dentry->d_inode->i_ino)
		dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
	else
		dentry = dget(path.dentry);

 out_path:
	path_put(&path);
 out_relock:
	if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
		if (!IS_ERR(dentry)) {
			dput(dentry);
			dentry = ERR_PTR(-ESTALE);
		}
 out_pathname:
	free_page((unsigned long)pathname);
 out_h_parent:
	dput(h_parent);
 out:
	/* au_br_put(br); */
	AuTraceErrPtr(dentry);
	return dentry;
}