Exemplo n.º 1
0
static int
au_call_encode_fh(struct dentry *h_dentry, __u32 *fh, int *max_len,
		  int connectable)
{
	/* in linux-2.6.24, it takes struct fid * as file handle */
	return exportfs_encode_fh(h_dentry, (void *)fh, max_len, connectable);
}
Exemplo n.º 2
0
/*
 * Compose a file handle for an NFS reply.
 *
 * Note that when first composed, the dentry may not yet have
 * an inode.  In this case a call to fh_update should be made
 * before the fh goes out on the wire ...
 */
static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
		struct dentry *dentry)
{
	if (dentry != exp->ex_path.dentry) {
		struct fid *fid = (struct fid *)
			(fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1);
		int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
		int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);

		fhp->fh_handle.fh_fileid_type =
			exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck);
		fhp->fh_handle.fh_size += maxsize * 4;
	} else {
		fhp->fh_handle.fh_fileid_type = FILEID_ROOT;
	}
}
Exemplo n.º 3
0
static long do_sys_name_to_handle(struct path *path,
				  struct file_handle __user *ufh,
				  int __user *mnt_id)
{
	long retval;
	struct file_handle f_handle;
	int handle_dwords, handle_bytes;
	struct file_handle *handle = NULL;

	/*
	 * We need t make sure wether the file system
	 * support decoding of the file handle
	 */
	if (!path->mnt->mnt_sb->s_export_op ||
	    !path->mnt->mnt_sb->s_export_op->fh_to_dentry)
		return -EOPNOTSUPP;

	if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
		return -EFAULT;

	if (f_handle.handle_bytes > MAX_HANDLE_SZ)
		return -EINVAL;

	handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
			 GFP_KERNEL);
	if (!handle)
		return -ENOMEM;

	/* convert handle size to  multiple of sizeof(u32) */
	handle_dwords = f_handle.handle_bytes >> 2;

	/* we ask for a non connected handle */
	retval = exportfs_encode_fh(path->dentry,
				    (struct fid *)handle->f_handle,
				    &handle_dwords,  0);
	handle->handle_type = retval;
	/* convert handle size to bytes */
	handle_bytes = handle_dwords * sizeof(u32);
	handle->handle_bytes = handle_bytes;
	if ((handle->handle_bytes > f_handle.handle_bytes) ||
	    (retval == 255) || (retval == -ENOSPC)) {
		/* As per old exportfs_encode_fh documentation
		 * we could return ENOSPC to indicate overflow
		 * But file system returned 255 always. So handle
		 * both the values
		 */
		/*
		 * set the handle size to zero so we copy only
		 * non variable part of the file_handle
		 */
		handle_bytes = 0;
		retval = -EOVERFLOW;
	} else
		retval = 0;
	/* copy the mount id */
	if (copy_to_user(mnt_id, &path->mnt->mnt_id, sizeof(*mnt_id)) ||
	    copy_to_user(ufh, handle,
			 sizeof(struct file_handle) + handle_bytes))
		retval = -EFAULT;
	kfree(handle);
	return retval;
}
Exemplo n.º 4
0
static struct dentry *
aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
		  int fh_type)
{
	struct dentry *dentry;
	__u32 *fh = fid->raw;
	ino_t ino, dir_ino;
	aufs_bindex_t bindex;
	struct au_nfsd_si_lock nsi_lock = {
		.force_lock	= 0
	};

	dentry = ERR_PTR(-ESTALE);
	/* it should never happen, but the file handle is unreliable */
	if (unlikely(fh_len < Fh_tail))
		goto out;
	nsi_lock.sigen = fh[Fh_sigen];
	nsi_lock.br_id = fh[Fh_br_id];

	/* branch id may be wrapped around */
	bindex = si_nfsd_read_lock(sb, &nsi_lock);
	if (unlikely(bindex < 0))
		goto out;
	nsi_lock.force_lock = 1;

	/* is this inode still cached? */
	ino = decode_ino(fh + Fh_ino);
	/* it should never happen */
	if (unlikely(ino == AUFS_ROOT_INO))
		goto out;

	dir_ino = decode_ino(fh + Fh_dir_ino);
	dentry = decode_by_ino(sb, ino, dir_ino);
	if (IS_ERR(dentry))
		goto out_unlock;
	if (dentry)
		goto accept;

	/* is the parent dir cached? */
	dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
	if (IS_ERR(dentry))
		goto out_unlock;
	if (dentry)
		goto accept;

	/* lookup path */
	dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
	if (IS_ERR(dentry))
		goto out_unlock;
	if (unlikely(!dentry))
		/* todo?: make it ESTALE */
		goto out_unlock;

 accept:
	if (dentry->d_inode->i_generation == fh[Fh_igen])
		goto out_unlock; /* success */

	dput(dentry);
	dentry = ERR_PTR(-ESTALE);
 out_unlock:
	si_read_unlock(sb);
 out:
	AuTraceErrPtr(dentry);
	return dentry;
}

#if 0 /* reserved for future use */
/* support subtreecheck option */
static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
					int fh_len, int fh_type)
{
	struct dentry *parent;
	__u32 *fh = fid->raw;
	ino_t dir_ino;

	dir_ino = decode_ino(fh + Fh_dir_ino);
	parent = decode_by_ino(sb, dir_ino, 0);
	if (IS_ERR(parent))
		goto out;
	if (!parent)
		parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
					dir_ino, fh, fh_len);

 out:
	AuTraceErrPtr(parent);
	return parent;
}
#endif

/* ---------------------------------------------------------------------- */

static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
			  int connectable)
{
	int err;
	aufs_bindex_t bindex, bend;
	struct super_block *sb, *h_sb;
	struct inode *inode;
	struct dentry *parent, *h_parent;
	struct au_branch *br;

	AuDebugOn(au_test_anon(dentry));

	parent = NULL;
	err = -ENOSPC;
	if (unlikely(*max_len <= Fh_tail)) {
		AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
		goto out;
	}

	err = FILEID_ROOT;
	if (IS_ROOT(dentry)) {
		AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
		goto out;
	}

	err = -EIO;
	h_parent = NULL;
	sb = dentry->d_sb;
	aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
	parent = dget_parent(dentry);
	di_read_lock_parent(parent, !AuLock_IR);
	inode = dentry->d_inode;
	AuDebugOn(!inode);
#ifdef CONFIG_AUFS_DEBUG
	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
		AuWarn1("NFS-exporting requires xino\n");
#endif

	bend = au_dbtaildir(parent);
	for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
		h_parent = au_h_dptr(parent, bindex);
		if (h_parent) {
			dget(h_parent);
			break;
		}
	}
	if (unlikely(!h_parent))
		goto out_unlock;

	err = -EPERM;
	br = au_sbr(sb, bindex);
	h_sb = br->br_mnt->mnt_sb;
	if (unlikely(!h_sb->s_export_op)) {
		AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
		goto out_dput;
	}

	fh[Fh_br_id] = br->br_id;
	fh[Fh_sigen] = au_sigen(sb);
	encode_ino(fh + Fh_ino, inode->i_ino);
	encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
	fh[Fh_igen] = inode->i_generation;

	*max_len -= Fh_tail;
	fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
					   max_len,
					   /*connectable or subtreecheck*/0);
	err = fh[Fh_h_type];
	*max_len += Fh_tail;
	/* todo: macros? */
	if (err != 255)
		err = 99;
	else
		AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));

 out_dput:
	dput(h_parent);
 out_unlock:
	di_read_unlock(parent, !AuLock_IR);
	dput(parent);
	aufs_read_unlock(dentry, AuLock_IR);
 out:
	if (unlikely(err < 0))
		err = 255;
	return err;
}