static int do_handle_to_path(int mountdirfd, struct file_handle *handle, struct path *path) { int retval = 0; int handle_dwords; path->mnt = get_vfsmount_from_fd(mountdirfd); if (IS_ERR(path->mnt)) { retval = PTR_ERR(path->mnt); goto out_err; } /* change the handle size to multiple of sizeof(u32) */ handle_dwords = handle->handle_bytes >> 2; path->dentry = exportfs_decode_fh(path->mnt, (struct fid *)handle->f_handle, handle_dwords, handle->handle_type, vfs_dentry_acceptable, NULL); if (IS_ERR(path->dentry)) { retval = PTR_ERR(path->dentry); goto out_mnt; } return 0; out_mnt: mntput(path->mnt); out_err: return retval; }
static struct dentry *handle_to_dentry(int mountdirfd, struct file_handle *handle, struct vfsmount **mntp) { int retval; int handle_size; struct vfsmount *mnt; struct dentry *dentry; struct handle_svc_export svc; const struct export_operations *exop; mnt = get_vfsmount_from_fd(mountdirfd); if(IS_ERR(mnt)) { retval = PTR_ERR(mnt); goto out_err; } exop = mnt->mnt_sb->s_export_op; /* change the handle size to multiple of sizeof(u32) */ handle_size = handle->handle_size >> 2; /* * GPFS overload acceptable callback. To make GPFS return * 1 set svc->ex_flags */ memset(&svc, 0, sizeof(svc)); svc.ex_flags = NFSEXP_NOSUBTREECHECK; dentry = CALL(exop, decode_fh) (mnt->mnt_sb, (__u32 *) handle->f_handle, handle_size, handle->handle_type, vfs_dentry_acceptable, &svc); if(IS_ERR(dentry)) { retval = PTR_ERR(dentry); goto out_mnt; } if(!dentry) { retval = -ESTALE; goto out_mnt; } *mntp = mnt; return dentry; out_mnt: mntput(mnt); out_err: return ERR_PTR(retval); }