Commit 6a6be470 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'nfs-for-2.6.35' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'nfs-for-2.6.35' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (78 commits)
  SUNRPC: Don't spam gssd with upcall requests when the kerberos key expired
  SUNRPC: Reorder the struct rpc_task fields
  SUNRPC: Remove the 'tk_magic' debugging field
  SUNRPC: Move the task->tk_bytes_sent and tk_rtt to struct rpc_rqst
  NFS: Don't call iput() in nfs_access_cache_shrinker
  NFS: Clean up nfs_access_zap_cache()
  NFS: Don't run nfs_access_cache_shrinker() when the mask is GFP_NOFS
  SUNRPC: Ensure rpcauth_prune_expired() respects the nr_to_scan parameter
  SUNRPC: Ensure memory shrinker doesn't waste time in rpcauth_prune_expired()
  SUNRPC: Dont run rpcauth_cache_shrinker() when gfp_mask is GFP_NOFS
  NFS: Read requests can use GFP_KERNEL.
  NFS: Clean up nfs_create_request()
  NFS: Don't use GFP_KERNEL in rpcsec_gss downcalls
  NFSv4: Don't use GFP_KERNEL allocations in state recovery
  SUNRPC: Fix xs_setup_bc_tcp()
  SUNRPC: Replace jiffies-based metrics with ktime-based metrics
  ktime: introduce ktime_to_ms()
  SUNRPC: RPC metrics and RTT estimator should use same RTT value
  NFS: Calldata for nfs4_renew_done()
  NFS: Squelch compiler warning in nfs_add_server_stats()
  ...
parents 98c89cdd 126e216a
......@@ -934,7 +934,6 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
}
fsinfo.fattr = fattr;
nfs_fattr_init(fattr);
error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
if (error < 0)
goto out_error;
......@@ -1047,13 +1046,18 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_fh *mntfh)
{
struct nfs_server *server;
struct nfs_fattr fattr;
struct nfs_fattr *fattr;
int error;
server = nfs_alloc_server();
if (!server)
return ERR_PTR(-ENOMEM);
error = -ENOMEM;
fattr = nfs_alloc_fattr();
if (fattr == NULL)
goto error;
/* Get a client representation */
error = nfs_init_server(server, data);
if (error < 0)
......@@ -1064,7 +1068,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
/* Probe the root fh to retrieve its FSID */
error = nfs_probe_fsinfo(server, mntfh, &fattr);
error = nfs_probe_fsinfo(server, mntfh, fattr);
if (error < 0)
goto error;
if (server->nfs_client->rpc_ops->version == 3) {
......@@ -1077,14 +1081,14 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
server->namelen = NFS2_MAXNAMLEN;
}
if (!(fattr.valid & NFS_ATTR_FATTR)) {
error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
if (!(fattr->valid & NFS_ATTR_FATTR)) {
error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
if (error < 0) {
dprintk("nfs_create_server: getattr error = %d\n", -error);
goto error;
}
}
memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid));
memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
dprintk("Server FSID: %llx:%llx\n",
(unsigned long long) server->fsid.major,
......@@ -1096,9 +1100,11 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
spin_unlock(&nfs_client_lock);
server->mount_time = jiffies;
nfs_free_fattr(fattr);
return server;
error:
nfs_free_fattr(fattr);
nfs_free_server(server);
return ERR_PTR(error);
}
......@@ -1340,7 +1346,7 @@ error:
struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_fh *mntfh)
{
struct nfs_fattr fattr;
struct nfs_fattr *fattr;
struct nfs_server *server;
int error;
......@@ -1350,6 +1356,11 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
if (!server)
return ERR_PTR(-ENOMEM);
error = -ENOMEM;
fattr = nfs_alloc_fattr();
if (fattr == NULL)
goto error;
/* set up the general RPC client */
error = nfs4_init_server(server, data);
if (error < 0)
......@@ -1364,7 +1375,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
goto error;
/* Probe the root fh to retrieve its FSID */
error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
error = nfs4_get_rootfh(server, mntfh);
if (error < 0)
goto error;
......@@ -1375,7 +1386,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
nfs4_session_set_rwsize(server);
error = nfs_probe_fsinfo(server, mntfh, &fattr);
error = nfs_probe_fsinfo(server, mntfh, fattr);
if (error < 0)
goto error;
......@@ -1389,9 +1400,11 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
server->mount_time = jiffies;
dprintk("<-- nfs4_create_server() = %p\n", server);
nfs_free_fattr(fattr);
return server;
error:
nfs_free_fattr(fattr);
nfs_free_server(server);
dprintk("<-- nfs4_create_server() = error %d\n", error);
return ERR_PTR(error);
......@@ -1405,7 +1418,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
{
struct nfs_client *parent_client;
struct nfs_server *server, *parent_server;
struct nfs_fattr fattr;
struct nfs_fattr *fattr;
int error;
dprintk("--> nfs4_create_referral_server()\n");
......@@ -1414,6 +1427,11 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
if (!server)
return ERR_PTR(-ENOMEM);
error = -ENOMEM;
fattr = nfs_alloc_fattr();
if (fattr == NULL)
goto error;
parent_server = NFS_SB(data->sb);
parent_client = parent_server->nfs_client;
......@@ -1443,12 +1461,12 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
/* Probe the root fh to retrieve its FSID and filehandle */
error = nfs4_path_walk(server, mntfh, data->mnt_path);
error = nfs4_get_rootfh(server, mntfh);
if (error < 0)
goto error;
/* probe the filesystem info for this server filesystem */
error = nfs_probe_fsinfo(server, mntfh, &fattr);
error = nfs_probe_fsinfo(server, mntfh, fattr);
if (error < 0)
goto error;
......@@ -1466,10 +1484,12 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
server->mount_time = jiffies;
nfs_free_fattr(fattr);
dprintk("<-- nfs_create_referral_server() = %p\n", server);
return server;
error:
nfs_free_fattr(fattr);
nfs_free_server(server);
dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
return ERR_PTR(error);
......@@ -1485,7 +1505,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
struct nfs_fattr *fattr)
{
struct nfs_server *server;
struct nfs_fattr fattr_fsinfo;
struct nfs_fattr *fattr_fsinfo;
int error;
dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
......@@ -1496,6 +1516,11 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
if (!server)
return ERR_PTR(-ENOMEM);
error = -ENOMEM;
fattr_fsinfo = nfs_alloc_fattr();
if (fattr_fsinfo == NULL)
goto out_free_server;
/* Copy data from the source */
server->nfs_client = source->nfs_client;
atomic_inc(&server->nfs_client->cl_count);
......@@ -1512,7 +1537,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
nfs_init_server_aclclient(server);
/* probe the filesystem info for this server filesystem */
error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
error = nfs_probe_fsinfo(server, fh, fattr_fsinfo);
if (error < 0)
goto out_free_server;
......@@ -1534,10 +1559,12 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
server->mount_time = jiffies;
nfs_free_fattr(fattr_fsinfo);
dprintk("<-- nfs_clone_server() = %p\n", server);
return server;
out_free_server:
nfs_free_fattr(fattr_fsinfo);
nfs_free_server(server);
dprintk("<-- nfs_clone_server() = error %d\n", error);
return ERR_PTR(error);
......
......@@ -213,7 +213,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
struct nfs_delegation *freeme = NULL;
int status = 0;
delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
delegation = kmalloc(sizeof(*delegation), GFP_NOFS);
if (delegation == NULL)
return -ENOMEM;
memcpy(delegation->stateid.data, res->delegation.data,
......
......@@ -530,9 +530,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
nfs_readdir_descriptor_t my_desc,
*desc = &my_desc;
struct nfs_entry my_entry;
struct nfs_fh fh;
struct nfs_fattr fattr;
long res;
int res = -ENOMEM;
dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
......@@ -554,9 +552,11 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
my_entry.cookie = my_entry.prev_cookie = 0;
my_entry.eof = 0;
my_entry.fh = &fh;
my_entry.fattr = &fattr;
nfs_fattr_init(&fattr);
my_entry.fh = nfs_alloc_fhandle();
my_entry.fattr = nfs_alloc_fattr();
if (my_entry.fh == NULL || my_entry.fattr == NULL)
goto out_alloc_failed;
desc->entry = &my_entry;
nfs_block_sillyrename(dentry);
......@@ -598,7 +598,10 @@ out:
nfs_unblock_sillyrename(dentry);
if (res > 0)
res = 0;
dfprintk(FILE, "NFS: readdir(%s/%s) returns %ld\n",
out_alloc_failed:
nfs_free_fattr(my_entry.fattr);
nfs_free_fhandle(my_entry.fh);
dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
res);
return res;
......@@ -776,9 +779,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
struct inode *dir;
struct inode *inode;
struct dentry *parent;
struct nfs_fh *fhandle = NULL;
struct nfs_fattr *fattr = NULL;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
parent = dget_parent(dentry);
dir = parent->d_inode;
......@@ -811,14 +814,22 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
if (NFS_STALE(inode))
goto out_bad;
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
error = -ENOMEM;
fhandle = nfs_alloc_fhandle();
fattr = nfs_alloc_fattr();
if (fhandle == NULL || fattr == NULL)
goto out_error;
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error)
goto out_bad;
if (nfs_compare_fh(NFS_FH(inode), &fhandle))
if (nfs_compare_fh(NFS_FH(inode), fhandle))
goto out_bad;
if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
if ((error = nfs_refresh_inode(inode, fattr)) != 0)
goto out_bad;
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
out_set_verifier:
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
out_valid:
......@@ -842,11 +853,21 @@ out_zap_parent:
shrink_dcache_parent(dentry);
}
d_drop(dentry);
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
dput(parent);
dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
__func__, dentry->d_parent->d_name.name,
dentry->d_name.name);
return 0;
out_error:
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
dput(parent);
dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
__func__, dentry->d_parent->d_name.name,
dentry->d_name.name, error);
return error;
}
/*
......@@ -911,9 +932,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
struct dentry *res;
struct dentry *parent;
struct inode *inode = NULL;
struct nfs_fh *fhandle = NULL;
struct nfs_fattr *fattr = NULL;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
......@@ -923,7 +944,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
goto out;
res = ERR_PTR(-ENOMEM);
dentry->d_op = NFS_PROTO(dir)->dentry_ops;
/*
......@@ -936,17 +956,23 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
goto out;
}
res = ERR_PTR(-ENOMEM);
fhandle = nfs_alloc_fhandle();
fattr = nfs_alloc_fattr();
if (fhandle == NULL || fattr == NULL)
goto out;
parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent);
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error == -ENOENT)
goto no_entry;
if (error < 0) {
res = ERR_PTR(error);
goto out_unblock_sillyrename;
}
inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
res = (struct dentry *)inode;
if (IS_ERR(res))
goto out_unblock_sillyrename;
......@@ -962,6 +988,8 @@ no_entry:
out_unblock_sillyrename:
nfs_unblock_sillyrename(parent);
out:
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
return res;
}
......@@ -1669,28 +1697,33 @@ static void nfs_access_free_entry(struct nfs_access_entry *entry)
smp_mb__after_atomic_dec();
}
static void nfs_access_free_list(struct list_head *head)
{
struct nfs_access_entry *cache;
while (!list_empty(head)) {
cache = list_entry(head->next, struct nfs_access_entry, lru);
list_del(&cache->lru);
nfs_access_free_entry(cache);
}
}
int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
{
LIST_HEAD(head);
struct nfs_inode *nfsi;
struct nfs_access_entry *cache;
restart:
if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
return (nr_to_scan == 0) ? 0 : -1;
spin_lock(&nfs_access_lru_lock);
list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
struct rw_semaphore *s_umount;
struct inode *inode;
if (nr_to_scan-- == 0)
break;
s_umount = &nfsi->vfs_inode.i_sb->s_umount;
if (!down_read_trylock(s_umount))
continue;
inode = igrab(&nfsi->vfs_inode);
if (inode == NULL) {
up_read(s_umount);
continue;
}
inode = &nfsi->vfs_inode;
spin_lock(&inode->i_lock);
if (list_empty(&nfsi->access_cache_entry_lru))
goto remove_lru_entry;
......@@ -1704,61 +1737,47 @@ restart:
else {
remove_lru_entry:
list_del_init(&nfsi->access_cache_inode_lru);
smp_mb__before_clear_bit();
clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags);
smp_mb__after_clear_bit();
}
spin_unlock(&inode->i_lock);
spin_unlock(&nfs_access_lru_lock);
iput(inode);
up_read(s_umount);
goto restart;
}
spin_unlock(&nfs_access_lru_lock);
while (!list_empty(&head)) {
cache = list_entry(head.next, struct nfs_access_entry, lru);
list_del(&cache->lru);
nfs_access_free_entry(cache);
}
nfs_access_free_list(&head);
return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure;
}
static void __nfs_access_zap_cache(struct inode *inode)
static void __nfs_access_zap_cache(struct nfs_inode *nfsi, struct list_head *head)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct rb_root *root_node = &nfsi->access_cache;
struct rb_node *n, *dispose = NULL;
struct rb_node *n;
struct nfs_access_entry *entry;
/* Unhook entries from the cache */
while ((n = rb_first(root_node)) != NULL) {
entry = rb_entry(n, struct nfs_access_entry, rb_node);
rb_erase(n, root_node);
list_del(&entry->lru);
n->rb_left = dispose;
dispose = n;
list_move(&entry->lru, head);
}
nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS;
spin_unlock(&inode->i_lock);
/* Now kill them all! */
while (dispose != NULL) {
n = dispose;
dispose = n->rb_left;
nfs_access_free_entry(rb_entry(n, struct nfs_access_entry, rb_node));
}
}
void nfs_access_zap_cache(struct inode *inode)
{
LIST_HEAD(head);
if (test_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags) == 0)
return;
/* Remove from global LRU init */
if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) {
spin_lock(&nfs_access_lru_lock);
spin_lock(&nfs_access_lru_lock);
if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags))
list_del_init(&NFS_I(inode)->access_cache_inode_lru);
spin_unlock(&nfs_access_lru_lock);
}
spin_lock(&inode->i_lock);
/* This will release the spinlock */
__nfs_access_zap_cache(inode);
__nfs_access_zap_cache(NFS_I(inode), &head);
spin_unlock(&inode->i_lock);
spin_unlock(&nfs_access_lru_lock);
nfs_access_free_list(&head);
}
static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred)
......@@ -1809,8 +1828,8 @@ out_stale:
nfs_access_free_entry(cache);
return -ENOENT;
out_zap:
/* This will release the spinlock */
__nfs_access_zap_cache(inode);
spin_unlock(&inode->i_lock);
nfs_access_zap_cache(inode);
return -ENOENT;
}
......@@ -1865,9 +1884,11 @@ static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *s
smp_mb__after_atomic_inc();
/* Add inode to global LRU list */
if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) {
if (!test_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) {
spin_lock(&nfs_access_lru_lock);
list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list);
if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags))
list_add_tail(&NFS_I(inode)->access_cache_inode_lru,
&nfs_access_lru_list);
spin_unlock(&nfs_access_lru_lock);
}
}
......
......@@ -161,14 +161,17 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
struct nfs_server *server = NFS_SERVER(inode);
struct nfs_inode *nfsi = NFS_I(inode);
if (server->flags & NFS_MOUNT_NOAC)
goto force_reval;
if (nfs_have_delegated_attributes(inode))
goto out_noreval;
if (filp->f_flags & O_DIRECT)
goto force_reval;
if (nfsi->npages != 0)
return 0;
if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
return 0;
if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
goto force_reval;
if (nfs_attribute_timeout(inode))
goto force_reval;
out_noreval:
return 0;
force_reval:
return __nfs_revalidate_inode(server, inode);
}
......
......@@ -467,7 +467,8 @@ int __nfs_readpages_from_fscache(struct nfs_open_context *ctx,
struct list_head *pages,
unsigned *nr_pages)
{
int ret, npages = *nr_pages;
unsigned npages = *nr_pages;
int ret;
dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
NFS_I(inode)->fscache, npages, inode);
......
......@@ -78,159 +78,94 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
{
struct nfs_server *server = NFS_SB(sb);
struct nfs_fsinfo fsinfo;
struct nfs_fattr fattr;
struct dentry *mntroot;
struct dentry *ret;
struct inode *inode;
int error;
/* get the actual root for this mount */
fsinfo.fattr = &fattr;
fsinfo.fattr = nfs_alloc_fattr();
if (fsinfo.fattr == NULL)
return ERR_PTR(-ENOMEM);
error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
if (error < 0) {
dprintk("nfs_get_root: getattr error = %d\n", -error);
return ERR_PTR(error);
ret = ERR_PTR(error);
goto out;
}
inode = nfs_fhget(sb, mntfh, fsinfo.fattr);
if (IS_ERR(inode)) {
dprintk("nfs_get_root: get root inode failed\n");
return ERR_CAST(inode);
ret = ERR_CAST(inode);
goto out;
}
error = nfs_superblock_set_dummy_root(sb, inode);
if (error != 0)
return ERR_PTR(error);
if (error != 0) {
ret = ERR_PTR(error);
goto out;
}
/* root dentries normally start off anonymous and get spliced in later
* if the dentry tree reaches them; however if the dentry already
* exists, we'll pick it up at this point and use it as the root
*/
mntroot = d_obtain_alias(inode);
if (IS_ERR(mntroot)) {
ret = d_obtain_alias(inode);
if (IS_ERR(ret)) {
dprintk("nfs_get_root: get root dentry failed\n");
return mntroot;
goto out;
}
security_d_instantiate(mntroot, inode);
if (!mntroot->d_op)
mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops;
security_d_instantiate(ret, inode);
return mntroot;
if (ret->d_op == NULL)
ret->d_op = server->nfs_client->rpc_ops->dentry_ops;
out:
nfs_free_fattr(fsinfo.fattr);
return ret;
}