Commit 1b1bd561 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-4.0-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:
 "Highlights include:

   - Fix a regression in the NFSv4 open state recovery code
   - Fix a regression in the NFSv4 close code
   - Fix regressions and side-effects of the loop-back mounted NFS fixes
     in 3.18, that cause the NFS read() syscall to return EBUSY.
   - Fix regressions around the readdirplus code and how it interacts
     with the VFS lazy unmount changes that went into v3.18.
   - Fix issues with out-of-order RPC call replies replacing updated
     attributes with stale ones (particularly after a truncate()).
   - Fix an underflow checking issue with RPC/RDMA credits
   - Fix a number of issues with the NFSv4 delegation return/free code.
   - Fix issues around stale NFSv4.1 leases when doing a mount"

* tag 'nfs-for-4.0-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (24 commits)
  NFSv4.1: Clear the old state by our client id before establishing a new lease
  NFSv4: Fix a race in NFSv4.1 server trunking discovery
  NFS: Don't write enable new pages while an invalidation is proceeding
  NFS: Fix a regression in the read() syscall
  NFSv4: Ensure we skip delegations that are already being returned
  NFSv4: Pin the superblock while we're returning the delegation
  NFSv4: Ensure we honour NFS_DELEGATION_RETURNING in nfs_inode_set_delegation()
  NFSv4: Ensure that we don't reap a delegation that is being returned
  NFS: Fix stateid used for NFS v4 closes
  NFSv4: Don't call put_rpccred() under the rcu_read_lock()
  NFS: Don't require a filehandle to refresh the inode in nfs_prime_dcache()
  NFSv3: Use the readdir fileid as the mounted-on-fileid
  NFS: Don't invalidate a submounted dentry in nfs_prime_dcache()
  NFSv4: Set a barrier in the update_changeattr() helper
  NFS: Fix nfs_post_op_update_inode() to set an attribute barrier
  NFS: Remove size hack in nfs_inode_attrs_need_update()
  NFSv4: Add attribute update barriers to delegreturn and pNFS layoutcommit
  NFS: Add attribute update barriers to NFS writebacks
  NFS: Set an attribute barrier on all updates
  NFS: Add attribute update barriers to nfs_setattr_update_inode()
  ...
parents 99aedde0 e11259f9
...@@ -433,7 +433,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat ...@@ -433,7 +433,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
static bool nfs_client_init_is_complete(const struct nfs_client *clp) static bool nfs_client_init_is_complete(const struct nfs_client *clp)
{ {
return clp->cl_cons_state != NFS_CS_INITING; return clp->cl_cons_state <= NFS_CS_READY;
} }
int nfs_wait_client_init_complete(const struct nfs_client *clp) int nfs_wait_client_init_complete(const struct nfs_client *clp)
......
...@@ -181,8 +181,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, ...@@ -181,8 +181,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
clear_bit(NFS_DELEGATION_NEED_RECLAIM, clear_bit(NFS_DELEGATION_NEED_RECLAIM,
&delegation->flags); &delegation->flags);
spin_unlock(&delegation->lock); spin_unlock(&delegation->lock);
put_rpccred(oldcred);
rcu_read_unlock(); rcu_read_unlock();
put_rpccred(oldcred);
trace_nfs4_reclaim_delegation(inode, res->delegation_type); trace_nfs4_reclaim_delegation(inode, res->delegation_type);
} else { } else {
/* We appear to have raced with a delegation return. */ /* We appear to have raced with a delegation return. */
...@@ -370,7 +370,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct ...@@ -370,7 +370,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
delegation = NULL; delegation = NULL;
goto out; goto out;
} }
freeme = nfs_detach_delegation_locked(nfsi, if (test_and_set_bit(NFS_DELEGATION_RETURNING,
&old_delegation->flags))
goto out;
freeme = nfs_detach_delegation_locked(nfsi,
old_delegation, clp); old_delegation, clp);
if (freeme == NULL) if (freeme == NULL)
goto out; goto out;
...@@ -433,6 +436,8 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) ...@@ -433,6 +436,8 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
{ {
bool ret = false; bool ret = false;
if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
goto out;
if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
ret = true; ret = true;
if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) { if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) {
...@@ -444,6 +449,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) ...@@ -444,6 +449,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
ret = true; ret = true;
spin_unlock(&delegation->lock); spin_unlock(&delegation->lock);
} }
out:
return ret; return ret;
} }
...@@ -471,14 +477,20 @@ int nfs_client_return_marked_delegations(struct nfs_client *clp) ...@@ -471,14 +477,20 @@ int nfs_client_return_marked_delegations(struct nfs_client *clp)
super_list) { super_list) {
if (!nfs_delegation_need_return(delegation)) if (!nfs_delegation_need_return(delegation))
continue; continue;
inode = nfs_delegation_grab_inode(delegation); if (!nfs_sb_active(server->super))
if (inode == NULL)
continue; continue;
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) {
rcu_read_unlock();
nfs_sb_deactive(server->super);
goto restart;
}
delegation = nfs_start_delegation_return_locked(NFS_I(inode)); delegation = nfs_start_delegation_return_locked(NFS_I(inode));
rcu_read_unlock(); rcu_read_unlock();
err = nfs_end_delegation_return(inode, delegation, 0); err = nfs_end_delegation_return(inode, delegation, 0);
iput(inode); iput(inode);
nfs_sb_deactive(server->super);
if (!err) if (!err)
goto restart; goto restart;
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
...@@ -809,19 +821,30 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp) ...@@ -809,19 +821,30 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
list_for_each_entry_rcu(delegation, &server->delegations, list_for_each_entry_rcu(delegation, &server->delegations,
super_list) { super_list) {
if (test_bit(NFS_DELEGATION_RETURNING,
&delegation->flags))
continue;
if (test_bit(NFS_DELEGATION_NEED_RECLAIM, if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
&delegation->flags) == 0) &delegation->flags) == 0)
continue; continue;
inode = nfs_delegation_grab_inode(delegation); if (!nfs_sb_active(server->super))
if (inode == NULL)
continue; continue;
delegation = nfs_detach_delegation(NFS_I(inode), inode = nfs_delegation_grab_inode(delegation);
delegation, server); if (inode == NULL) {
rcu_read_unlock();
nfs_sb_deactive(server->super);
goto restart;
}
delegation = nfs_start_delegation_return_locked(NFS_I(inode));
rcu_read_unlock(); rcu_read_unlock();
if (delegation != NULL) {
if (delegation != NULL) delegation = nfs_detach_delegation(NFS_I(inode),
nfs_free_delegation(delegation); delegation, server);
if (delegation != NULL)
nfs_free_delegation(delegation);
}
iput(inode); iput(inode);
nfs_sb_deactive(server->super);
goto restart; goto restart;
} }
} }
......
...@@ -408,14 +408,22 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, ...@@ -408,14 +408,22 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc,
return 0; return 0;
} }
/* Match file and dirent using either filehandle or fileid
* Note: caller is responsible for checking the fsid
*/
static static
int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
{ {
struct nfs_inode *nfsi;
if (dentry->d_inode == NULL) if (dentry->d_inode == NULL)
goto different; goto different;
if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0)
goto different; nfsi = NFS_I(dentry->d_inode);
return 1; if (entry->fattr->fileid == nfsi->fileid)
return 1;
if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0)
return 1;
different: different:
return 0; return 0;
} }
...@@ -469,6 +477,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) ...@@ -469,6 +477,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
struct inode *inode; struct inode *inode;
int status; int status;
if (!(entry->fattr->valid & NFS_ATTR_FATTR_FILEID))
return;
if (!(entry->fattr->valid & NFS_ATTR_FATTR_FSID))
return;
if (filename.name[0] == '.') { if (filename.name[0] == '.') {
if (filename.len == 1) if (filename.len == 1)
return; return;
...@@ -479,6 +491,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) ...@@ -479,6 +491,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
dentry = d_lookup(parent, &filename); dentry = d_lookup(parent, &filename);
if (dentry != NULL) { if (dentry != NULL) {
/* Is there a mountpoint here? If so, just exit */
if (!nfs_fsid_equal(&NFS_SB(dentry->d_sb)->fsid,
&entry->fattr->fsid))
goto out;
if (nfs_same_file(dentry, entry)) { if (nfs_same_file(dentry, entry)) {
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
status = nfs_refresh_inode(dentry->d_inode, entry->fattr); status = nfs_refresh_inode(dentry->d_inode, entry->fattr);
......
...@@ -178,7 +178,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to) ...@@ -178,7 +178,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
iocb->ki_filp, iocb->ki_filp,
iov_iter_count(to), (unsigned long) iocb->ki_pos); iov_iter_count(to), (unsigned long) iocb->ki_pos);
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); result = nfs_revalidate_mapping_protected(inode, iocb->ki_filp->f_mapping);
if (!result) { if (!result) {
result = generic_file_read_iter(iocb, to); result = generic_file_read_iter(iocb, to);
if (result > 0) if (result > 0)
...@@ -199,7 +199,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, ...@@ -199,7 +199,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n", dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n",
filp, (unsigned long) count, (unsigned long long) *ppos); filp, (unsigned long) count, (unsigned long long) *ppos);
res = nfs_revalidate_mapping(inode, filp->f_mapping); res = nfs_revalidate_mapping_protected(inode, filp->f_mapping);
if (!res) { if (!res) {
res = generic_file_splice_read(filp, ppos, pipe, count, flags); res = generic_file_splice_read(filp, ppos, pipe, count, flags);
if (res > 0) if (res > 0)
...@@ -372,6 +372,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, ...@@ -372,6 +372,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
nfs_wait_bit_killable, TASK_KILLABLE); nfs_wait_bit_killable, TASK_KILLABLE);
if (ret) if (ret)
return ret; return ret;
/*
* Wait for O_DIRECT to complete
*/
nfs_inode_dio_wait(mapping->host);
page = grab_cache_page_write_begin(mapping, index, flags); page = grab_cache_page_write_begin(mapping, index, flags);
if (!page) if (!page)
...@@ -619,6 +623,9 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -619,6 +623,9 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
/* make sure the cache has finished storing the page */ /* make sure the cache has finished storing the page */
nfs_fscache_wait_on_page_write(NFS_I(inode), page); nfs_fscache_wait_on_page_write(NFS_I(inode), page);
wait_on_bit_action(&NFS_I(inode)->flags, NFS_INO_INVALIDATING,
nfs_wait_bit_killable, TASK_KILLABLE);
lock_page(page); lock_page(page);
mapping = page_file_mapping(page); mapping = page_file_mapping(page);
if (mapping != inode->i_mapping) if (mapping != inode->i_mapping)
......
...@@ -556,6 +556,7 @@ EXPORT_SYMBOL_GPL(nfs_setattr); ...@@ -556,6 +556,7 @@ EXPORT_SYMBOL_GPL(nfs_setattr);
* This is a copy of the common vmtruncate, but with the locking * This is a copy of the common vmtruncate, but with the locking
* corrected to take into account the fact that NFS requires * corrected to take into account the fact that NFS requires
* inode->i_size to be updated under the inode->i_lock. * inode->i_size to be updated under the inode->i_lock.
* Note: must be called with inode->i_lock held!
*/ */
static int nfs_vmtruncate(struct inode * inode, loff_t offset) static int nfs_vmtruncate(struct inode * inode, loff_t offset)
{ {
...@@ -565,14 +566,14 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset) ...@@ -565,14 +566,14 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset)
if (err) if (err)
goto out; goto out;
spin_lock(&inode->i_lock);
i_size_write(inode, offset); i_size_write(inode, offset);
/* Optimisation */ /* Optimisation */
if (offset == 0) if (offset == 0)
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA;
spin_unlock(&inode->i_lock);
spin_unlock(&inode->i_lock);
truncate_pagecache(inode, offset); truncate_pagecache(inode, offset);
spin_lock(&inode->i_lock);
out: out:
return err; return err;
} }
...@@ -585,10 +586,15 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset) ...@@ -585,10 +586,15 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset)
* Note: we do this in the *proc.c in order to ensure that * Note: we do this in the *proc.c in order to ensure that
* it works for things like exclusive creates too. * it works for things like exclusive creates too.
*/ */
void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
struct nfs_fattr *fattr)
{ {
/* Barrier: bump the attribute generation count. */
nfs_fattr_set_barrier(fattr);
spin_lock(&inode->i_lock);
NFS_I(inode)->attr_gencount = fattr->gencount;
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
spin_lock(&inode->i_lock);
if ((attr->ia_valid & ATTR_MODE) != 0) { if ((attr->ia_valid & ATTR_MODE) != 0) {
int mode = attr->ia_mode & S_IALLUGO; int mode = attr->ia_mode & S_IALLUGO;
mode |= inode->i_mode & ~S_IALLUGO; mode |= inode->i_mode & ~S_IALLUGO;
...@@ -600,12 +606,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) ...@@ -600,12 +606,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
inode->i_gid = attr->ia_gid; inode->i_gid = attr->ia_gid;
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL); | NFS_INO_INVALID_ACL);
spin_unlock(&inode->i_lock);
} }
if ((attr->ia_valid & ATTR_SIZE) != 0) { if ((attr->ia_valid & ATTR_SIZE) != 0) {
nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
nfs_vmtruncate(inode, attr->ia_size); nfs_vmtruncate(inode, attr->ia_size);
} }
nfs_update_inode(inode, fattr);
spin_unlock(&inode->i_lock);
} }
EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
...@@ -1028,6 +1035,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map ...@@ -1028,6 +1035,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map
if (mapping->nrpages != 0) { if (mapping->nrpages != 0) {
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
unmap_mapping_range(mapping, 0, 0, 0);
ret = nfs_sync_mapping(mapping); ret = nfs_sync_mapping(mapping);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1060,11 +1068,14 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode) ...@@ -1060,11 +1068,14 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode)
} }
/** /**
* nfs_revalidate_mapping - Revalidate the pagecache * __nfs_revalidate_mapping - Revalidate the pagecache
* @inode - pointer to host inode * @inode - pointer to host inode
* @mapping - pointer to mapping * @mapping - pointer to mapping
* @may_lock - take inode->i_mutex?
*/ */
int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) static int __nfs_revalidate_mapping(struct inode *inode,
struct address_space *mapping,
bool may_lock)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
unsigned long *bitlock = &nfsi->flags; unsigned long *bitlock = &nfsi->flags;
...@@ -1113,7 +1124,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) ...@@ -1113,7 +1124,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
trace_nfs_invalidate_mapping_enter(inode); trace_nfs_invalidate_mapping_enter(inode);
ret = nfs_invalidate_mapping(inode, mapping); if (may_lock) {
mutex_lock(&inode->i_mutex);
ret = nfs_invalidate_mapping(inode, mapping);
mutex_unlock(&inode->i_mutex);
} else
ret = nfs_invalidate_mapping(inode, mapping);
trace_nfs_invalidate_mapping_exit(inode, ret); trace_nfs_invalidate_mapping_exit(inode, ret);
clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); clear_bit_unlock(NFS_INO_INVALIDATING, bitlock);
...@@ -1123,6 +1139,29 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) ...@@ -1123,6 +1139,29 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
return ret; return ret;
} }
/**
* nfs_revalidate_mapping - Revalidate the pagecache
* @inode - pointer to host inode
* @mapping - pointer to mapping
*/
int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
{
return __nfs_revalidate_mapping(inode, mapping, false);
}
/**
* nfs_revalidate_mapping_protected - Revalidate the pagecache
* @inode - pointer to host inode
* @mapping - pointer to mapping
*
* Differs from nfs_revalidate_mapping() in that it grabs the inode->i_mutex
* while invalidating the mapping.
*/
int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping)
{
return __nfs_revalidate_mapping(inode, mapping, true);
}
static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
...@@ -1231,13 +1270,6 @@ static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fat ...@@ -1231,13 +1270,6 @@ static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fat
return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0;
} }
static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
{
if (!(fattr->valid & NFS_ATTR_FATTR_SIZE))
return 0;
return nfs_size_to_loff_t(fattr->size) > i_size_read(inode);
}
static atomic_long_t nfs_attr_generation_counter; static atomic_long_t nfs_attr_generation_counter;
static unsigned long nfs_read_attr_generation_counter(void) static unsigned long nfs_read_attr_generation_counter(void)
...@@ -1249,6 +1281,7 @@ unsigned long nfs_inc_attr_generation_counter(void) ...@@ -1249,6 +1281,7 @@ unsigned long nfs_inc_attr_generation_counter(void)
{ {
return atomic_long_inc_return(&nfs_attr_generation_counter); return atomic_long_inc_return(&nfs_attr_generation_counter);
} }
EXPORT_SYMBOL_GPL(nfs_inc_attr_generation_counter);
void nfs_fattr_init(struct nfs_fattr *fattr) void nfs_fattr_init(struct nfs_fattr *fattr)
{ {
...@@ -1260,6 +1293,22 @@ void nfs_fattr_init(struct nfs_fattr *fattr) ...@@ -1260,6 +1293,22 @@ void nfs_fattr_init(struct nfs_fattr *fattr)
} }
EXPORT_SYMBOL_GPL(nfs_fattr_init); EXPORT_SYMBOL_GPL(nfs_fattr_init);
/**
* nfs_fattr_set_barrier
* @fattr: attributes
*
* Used to set a barrier after an attribute was updated. This
* barrier ensures that older attributes from RPC calls that may
* have raced with our update cannot clobber these new values.
* Note that you are still responsible for ensuring that other
* operations which change the attribute on the server do not
* collide.
*/
void nfs_fattr_set_barrier(struct nfs_fattr *fattr)
{
fattr->gencount = nfs_inc_attr_generation_counter();
}
struct nfs_fattr *nfs_alloc_fattr(void) struct nfs_fattr *nfs_alloc_fattr(void)
{ {
struct nfs_fattr *fattr; struct nfs_fattr *fattr;
...@@ -1370,7 +1419,6 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n ...@@ -1370,7 +1419,6 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n
return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 ||
nfs_ctime_need_update(inode, fattr) || nfs_ctime_need_update(inode, fattr) ||
nfs_size_need_update(inode, fattr) ||
((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
} }
...@@ -1460,6 +1508,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1460,6 +1508,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
int status; int status;
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
nfs_fattr_set_barrier(fattr);
status = nfs_post_op_update_inode_locked(inode, fattr); status = nfs_post_op_update_inode_locked(inode, fattr);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
...@@ -1468,7 +1517,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1468,7 +1517,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); EXPORT_SYMBOL_GPL(nfs_post_op_update_inode);
/** /**
* nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache * nfs_post_op_update_inode_force_wcc_locked - update the inode attribute cache
* @inode - pointer to inode * @inode - pointer to inode
* @fattr - updated attributes * @fattr - updated attributes
* *
...@@ -1478,11 +1527,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); ...@@ -1478,11 +1527,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode);
* *
* This function is mainly designed to be used by the ->write_done() functions. * This function is mainly designed to be used by the ->write_done() functions.
*/ */
int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr)
{ {
int status; int status;
spin_lock(&inode->i_lock);
/* Don't do a WCC update if these attributes are already stale */ /* Don't do a WCC update if these attributes are already stale */
if ((fattr->valid & NFS_ATTR_FATTR) == 0 || if ((fattr->valid & NFS_ATTR_FATTR) == 0 ||
!nfs_inode_attrs_need_update(inode, fattr)) { !nfs_inode_attrs_need_update(inode, fattr)) {
...@@ -1514,6 +1562,27 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa ...@@ -1514,6 +1562,27 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
} }
out_noforce: out_noforce:
status = nfs_post_op_update_inode_locked(inode, fattr); status = nfs_post_op_update_inode_locked(inode, fattr);
return status;
}
/**
* nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache
* @inode - pointer to inode
* @fattr - updated attributes
*
* After an operation that has changed the inode metadata, mark the
* attribute cache as being invalid, then try to update it. Fake up
* weak cache consistency data, if none exist.
*
* This function is mainly designed to be used by the ->write_done() functions.
*/
int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr)
{
int status;
spin_lock(&inode->i_lock);
nfs_fattr_set_barrier(fattr);
status = nfs_post_op_update_inode_force_wcc_locked(inode, fattr);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
return status; return status;
} }
...@@ -1715,6 +1784,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1715,6 +1784,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
nfsi->attrtimeo_timestamp = now; nfsi->attrtimeo_timestamp = now;
/* Set barrier to be more recent than all outstanding updates */
nfsi->attr_gencount = nfs_inc_attr_generation_counter(); nfsi->attr_gencount = nfs_inc_attr_generation_counter();
} else { } else {
if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
...@@ -1722,6 +1792,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1722,6 +1792,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
nfsi->attrtimeo_timestamp = now; nfsi->attrtimeo_timestamp = now;
} }
/* Set the barrier to be more recent than this fattr */
if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0)
nfsi->attr_gencount = fattr->gencount;
} }
invalid &= ~NFS_INO_INVALID_ATTR; invalid &= ~NFS_INO_INVALID_ATTR;
/* Don't invalidate the data if we were to blame */ /* Don't invalidate the data if we were to blame */
......
...@@ -459,6 +459,7 @@ void nfs_mark_request_commit(struct nfs_page *req, ...@@ -459,6 +459,7 @@ void nfs_mark_request_commit(struct nfs_page *req,
struct nfs_commit_info *cinfo, struct nfs_commit_info *cinfo,
u32 ds_commit_idx); u32 ds_commit_idx);
int nfs_write_need_commit(struct nfs_pgio_header *); int nfs_write_need_commit(struct nfs_pgio_header *);
void nfs_writeback_update_inode(struct nfs_pgio_header *hdr);
int nfs_generic_commit_list(struct inode *inode, struct list_head *head, int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
int how, struct nfs_commit_info *cinfo); int how, struct nfs_commit_info *cinfo);
void nfs_retry_commit(struct list_head *page_list, void nfs_retry_commit(struct list_head *page_list,
......
...@@ -138,7 +138,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -138,7 +138,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
nfs_fattr_init(fattr); nfs_fattr_init(fattr);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
if (status == 0) if (status == 0)
nfs_setattr_update_inode(inode, sattr); nfs_setattr_update_inode(inode, sattr, fattr);
dprintk("NFS reply setattr: %d\n", status); dprintk("NFS reply setattr: %d\n", status);
return status; return status;
} }
...@@ -834,7 +834,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) ...@@ -834,7 +834,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
if (nfs3_async_handle_jukebox(task, inode)) if (nfs3_async_handle_jukebox(task, inode))
return -EAGAIN; return -EAGAIN;
if (task->tk_status >= 0) if (task->tk_status >= 0)
nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); nfs_writeback_update_inode(hdr);
return 0; return 0;
} }
......
...@@ -1987,6 +1987,11 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, ...@@ -1987,6 +1987,11 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
if (entry->fattr->valid & NFS_ATTR_FATTR_V3) if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
if (entry->fattr->fileid != entry->ino) {
entry->fattr->mounted_on_fileid = entry->ino;
entry->fattr->valid |= NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
}
/* In fact, a post_op_fh3: */ /* In fact, a post_op_fh3: */
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL)) if (unlikely(p == NULL))
......
...@@ -621,6 +621,9 @@ int nfs41_walk_client_list(struct nfs_client *new, ...@@ -621,6 +621,9 @@ int nfs41_walk_client_list(struct nfs_client *new,
spin_lock(&nn->nfs_client_lock); spin_lock(&nn->nfs_client_lock);
list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
if (pos == new)
goto found;
if (pos->rpc_ops != new->rpc_ops) if (pos->rpc_ops != new->rpc_ops)
continue; continue;
...@@ -639,10 +642,6 @@ int nfs41_walk_client_list(struct nfs_client *new, ...@@ -639,10 +642,6 @@ int nfs41_walk_client_list(struct nfs_client *new,
prev = pos; prev = pos;
status = nfs_wait_client_init_complete(pos); status = nfs_wait_client_init_complete(pos);
if (pos->cl_cons_state == NFS_CS_SESSION_INITING) {
nfs4_schedule_lease_recovery(pos);
status = nfs4_wait_clnt_recover(pos);
}
spin_lock(&nn->nfs_client_lock); spin_lock(&nn->nfs_client_lock);
if (status < 0) if (status < 0)
break; break;
...@@ -668,7 +667,7 @@ int nfs41_walk_client_list(struct nfs_client *new, ...@@ -668,7 +667,7 @@ int nfs41_walk_client_list(struct nfs_client *new,
*/ */
if (!nfs4_match_client_owner_id(pos, new)) if (!nfs4_match_client_owner_id(pos, new))
continue; continue;
found:
atomic_inc(&pos->cl_count); atomic_inc(&pos->cl_count);
*result = pos; *result = pos;
status = 0; status = 0;
......
...@@ -901,6 +901,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) ...@@ -901,6 +901,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
if (!cinfo->atomic || cinfo->before != dir->i_version) if (!cinfo->atomic || cinfo->before != dir->i_version)
nfs_force_lookup_revalidate(dir); nfs_force_lookup_revalidate(dir);
dir->i_version = cinfo->after; dir->i_version = cinfo->after;
nfsi->attr_gencount = nfs_inc_attr_generation_counter();
nfs_fscache_invalidate(dir); nfs_fscache_invalidate(dir);
spin_unlock(&dir->i_lock); spin_unlock(&dir->i_lock);
} }
...@@ -1552,6 +1553,9 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod ...@@ -1552,6 +1553,9 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod
opendata->o_arg.open_flags = 0; opendata->o_arg.open_flags = 0;
opendata->o_arg.fmode = fmode; opendata->o_arg.fmode = fmode;
opendata->o_arg.share_access = nfs4_map_atomic_open_share(
NFS_SB(opendata->dentry->d_sb),
fmode, 0);
memset(&opendata->o_res, 0, sizeof(opendata->o_res)); memset(&opendata->o_res, 0, sizeof(opendata->o_res));
memset(&opendata->c_res, 0, sizeof(opendata->c_res)); memset(&opendata->c_res, 0, sizeof(opendata->c_res));
nfs4_init_opendata_res(opendata); nfs4_init_opendata_res(opendata);
...@@ -2413,8 +2417,8 @@ static int _nfs4_do_open(struct inode *dir, ...@@ -2413,8 +2417,8 @@ static int _nfs4_do_open(struct inode *dir,
opendata->o_res.f_attr, sattr, opendata->o_res.f_attr, sattr,
state, label, olabel); state, label, olabel);
if (status == 0) { if (status == 0) {
nfs_setattr_update_inode(state->inode, sattr); nfs_setattr_update_inode(state->inode, sattr,
nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); opendata->o_res.f_attr);
nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
} }
} }
...@@ -2651,7 +2655,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) ...@@ -2651,7 +2655,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
if (!nfs4_stateid_match(&calldata->arg.stateid, if (!nfs4_stateid_match(&calldata->arg.stateid,
&state->stateid)) { &state->open_stateid)) {
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
goto out_release; goto out_release;
} }
...@@ -2687,7 +2691,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) ...@@ -2687,7 +2691,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
nfs4_stateid_copy(&calldata->arg.stateid, &state->stateid); nfs4_stateid_copy(&calldata->arg.stateid, &state->open_stateid);
/* Calculate the change in open mode */ /* Calculate the change in open mode */
calldata->arg.fmode = 0; calldata->arg.fmode = 0;
if (state->n_rdwr == 0) { if (state->n_rdwr == 0) {
...@@ -3288,7 +3292,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -3288,7 +3292,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label);
if (status == 0) { if (status == 0) {
nfs_setattr_update_inode(inode, sattr); nfs_setattr_update_inode(inode, sattr, fattr);
nfs_setsecurity(inode, fattr, label); nfs_setsecurity(inode, fattr, label);
} }
nfs4_label_free(label); nfs4_label_free(label);
...@@ -4234,7 +4238,7 @@ static int nfs4_write_done_cb(struct rpc_task *task, ...@@ -4234,7 +4238,7 @@ static int nfs4_write_done_cb(struct rpc_task *task,
} }
if (task->tk_status >= 0) { if (task->tk_status >= 0) {
renew_lease(NFS_SERVER(inode), hdr->timestamp); renew_lease(NFS_SERVER(inode), hdr->timestamp);
nfs_post_op_update_inode_force_wcc(inode, &hdr->fattr); nfs_writeback_update_inode(hdr);
} }
return 0; return 0;
} }
...@@ -6893,9 +6897,13 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, ...@@ -6893,9 +6897,13 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
if (status == 0) { if (status == 0) {
clp->cl_clientid = res.clientid; clp->cl_clientid = res.clientid;
clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); clp->cl_exchange_flags = res.flags;
if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) /* Client ID is not confirmed */
if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) {
clear_bit(NFS4_SESSION_ESTABLISHED,
&clp->cl_session->session_state);
clp->cl_seqid = res.seqid; clp->cl_seqid = res.seqid;
}
kfree(clp->cl_serverowner); kfree(clp->cl_serverowner);
clp->cl_serverowner = res.server_owner; clp->cl_serverowner = res.server_owner;
...@@ -7227,6 +7235,9 @@ static void nfs4_update_session(struct nfs4_session *session, ...@@ -7227,6 +7235,9 @@ static void nfs4_update_session(struct nfs4_session *session,
struct nfs41_create_session_res *res) struct nfs41_create_session_res *res)
{ {
nfs4_copy_sessionid(&session->sess_id, &res->sessionid); nfs4_copy_sessionid(&session->sess_id, &res->sessionid);
/* Mark client id and session as being confirmed */
session->clp->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R;
set_bit(NFS4_SESSION_ESTABLISHED, &session->session_state);
session->flags = res->flags; session->flags = res->flags;
memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs)); memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
if (res->flags & SESSION4_BACK_CHAN) if (res->flags & SESSION4_BACK_CHAN)
...@@ -7322,8 +7333,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, ...@@ -7322,8 +7333,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session,
dprintk("--> nfs4_proc_destroy_session\n"); dprintk("--> nfs4_proc_destroy_session\n");
/* session is still being setup */ /* session is still being setup */
if (session->clp->cl_cons_state != NFS_CS_READY) if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state))
return status; return 0;
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
trace_nfs4_destroy_session(session->clp, status); trace_nfs4_destroy_session(session->clp, status);
......
...@@ -70,6 +70,7 @@ struct nfs4_session { ...@@ -70,6 +70,7 @@ struct nfs4_session {
enum nfs4_session_state { enum nfs4_session_state {
NFS4_SESSION_INITING, NFS4_SESSION_INITING,
NFS4_SESSION_ESTABLISHED,
}; };
extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
......
...@@ -346,9 +346,23 @@ int nfs41_discover_server_trunking(struct nfs_client *clp, ...@@ -346,9 +346,23 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
status = nfs4_proc_exchange_id(clp, cred); status = nfs4_proc_exchange_id(clp, cred);
if (status != NFS4_OK) if (status != NFS4_OK)
return status; return status;
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
return nfs41_walk_client_list(clp, result, cred); status = nfs41_walk_client_list(clp, result, cred);
if (status < 0)
return status;
if (clp != *result)
return 0;
/* Purge state if the client id was established in a prior instance */
if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R)
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
else
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
nfs4_schedule_state_manager(clp);
status = nfs_wait_client_init_complete(clp);
if (status < 0)
nfs_put_client(clp);
return status;
} }
#endif /* CONFIG_NFS_V4_1 */ #endif /* CONFIG_NFS_V4_1 */
......
...@@ -139,7 +139,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -139,7 +139,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
nfs_fattr_init(fattr); nfs_fattr_init(fattr);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
if (status == 0) if (status == 0)
nfs_setattr_update_inode(inode, sattr); nfs_setattr_update_inode(inode, sattr, fattr);
dprintk("NFS reply setattr: %d\n", status); dprintk("NFS reply setattr: %d\n", status);
return status; return status;
} }
...@@ -609,10 +609,8 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task, ...@@ -609,10 +609,8 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task,
static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{ {
struct inode *inode = hdr->inode;
if (task->tk_status >= 0) if (task->tk_status >= 0)
nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); nfs_writeback_update_inode(hdr);
return 0; return 0;
} }
......
...@@ -1377,6 +1377,36 @@ static int nfs_should_remove_suid(const struct inode *inode) ...@@ -1377,6 +1377,36 @@ static int nfs_should_remove_suid(const struct inode *inode)
return 0; return 0;
} }
static void nfs_writeback_check_extend(struct nfs_pgio_header *hdr,
struct nfs_fattr *fattr)
{
struct nfs_pgio_args *argp = &hdr->args;
struct nfs_pgio_res *resp = &hdr->res;
if (!(fattr->valid & NFS_ATTR_FATTR_SIZE))
return;
if (argp->offset + resp->count != fattr->size)
return;
if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode))
return;
/* Set attribute barrier */
nfs_fattr_set_barrier(fattr);
}
void nfs_writeback_update_inode(struct nfs_pgio_header *hdr)
{
struct nfs_fattr *fattr = hdr->res.fattr;
struct inode *inode = hdr->inode;
if (fattr == NULL)
return;
spin_lock(&inode->i_lock);
nfs_writeback_check_extend(hdr, fattr);
nfs_post_op_update_inode_force_wcc_locked(inode, fattr);
spin_unlock(&inode->i_lock);
}
EXPORT_SYMBOL_GPL(nfs_writeback_update_inode);
/* /*
* This function is called when the WRITE call is complete. * This function is called when the WRITE call is complete.
*/ */
......
...@@ -343,6 +343,7 @@ extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, ...@@ -343,6 +343,7 @@ extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
extern void nfs_access_set_mask(struct nfs_access_entry *, u32); extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
...@@ -355,8 +356,9 @@ extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); ...@@ -355,8 +356,9 @@ extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode); extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
extern int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping);
extern int nfs_setattr(struct dentry *, struct iattr *); extern int nfs_setattr(struct dentry *, struct iattr *);
extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, struct nfs_fattr *);
extern void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, extern void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
struct nfs4_label *label); struct nfs4_label *label);
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
...@@ -369,6 +371,7 @@ extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ct ...@@ -369,6 +371,7 @@ extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ct
extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
extern u64 nfs_compat_user_ino64(u64 fileid); extern u64 nfs_compat_user_ino64(u64 fileid);
extern void nfs_fattr_init(struct nfs_fattr *fattr); extern void nfs_fattr_init(struct nfs_fattr *fattr);
extern void nfs_fattr_set_barrier(struct nfs_fattr *fattr);
extern unsigned long nfs_inc_attr_generation_counter(void); extern unsigned long nfs_inc_attr_generation_counter(void);
extern struct nfs_fattr *nfs_alloc_fattr(void); extern struct nfs_fattr *nfs_alloc_fattr(void);
......
...@@ -738,8 +738,9 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep) ...@@ -738,8 +738,9 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
struct rpc_xprt *xprt = rep->rr_xprt; struct rpc_xprt *xprt = rep->rr_xprt;
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
__be32 *iptr; __be32 *iptr;
int credits, rdmalen, status; int rdmalen, status;
unsigned long cwnd; unsigned long cwnd;
u32 credits;
/* Check status. If bad, signal disconnect and return rep to pool */ /* Check status. If bad, signal disconnect and return rep to pool */
if (rep->rr_len == ~0U) { if (rep->rr_len == ~0U) {
......
...@@ -285,7 +285,7 @@ rpcr_to_rdmar(struct rpc_rqst *rqst) ...@@ -285,7 +285,7 @@ rpcr_to_rdmar(struct rpc_rqst *rqst)
*/ */
struct rpcrdma_buffer { struct rpcrdma_buffer {
spinlock_t rb_lock; /* protects indexes */ spinlock_t rb_lock; /* protects indexes */
int rb_max_requests;/* client max requests */ u32 rb_max_requests;/* client max requests */
struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */
struct list_head rb_all; struct list_head rb_all;
int rb_send_index; int rb_send_index;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment