Commit d8c951c3 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4.1: Don't trust attributes if a pNFS LAYOUTCOMMIT is outstanding

If a LAYOUTCOMMIT is outstanding, then chances are that the metadata
server may still be returning incorrect values for the change attribute,
ctime, mtime and/or size.
Just ignore those attributes for now, and wait for the LAYOUTCOMMIT
rpc call to finish.
Reported-by: default avatarshaobingqing <shaobingqing@bwstor.com.cn>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 16a6ddc7
...@@ -1283,12 +1283,28 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n ...@@ -1283,12 +1283,28 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n
((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
} }
/*
* Don't trust the change_attribute, mtime, ctime or size if
* a pnfs LAYOUTCOMMIT is outstanding
*/
static void nfs_inode_attrs_handle_layoutcommit(struct inode *inode,
struct nfs_fattr *fattr)
{
if (pnfs_layoutcommit_outstanding(inode))
fattr->valid &= ~(NFS_ATTR_FATTR_CHANGE |
NFS_ATTR_FATTR_MTIME |
NFS_ATTR_FATTR_CTIME |
NFS_ATTR_FATTR_SIZE);
}
static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
{ {
int ret; int ret;
trace_nfs_refresh_inode_enter(inode); trace_nfs_refresh_inode_enter(inode);
nfs_inode_attrs_handle_layoutcommit(inode, fattr);
if (nfs_inode_attrs_need_update(inode, fattr)) if (nfs_inode_attrs_need_update(inode, fattr))
ret = nfs_update_inode(inode, fattr); ret = nfs_update_inode(inode, fattr);
else else
...@@ -1518,8 +1534,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1518,8 +1534,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (new_isize != cur_isize) { if (new_isize != cur_isize) {
/* Do we perhaps have any outstanding writes, or has /* Do we perhaps have any outstanding writes, or has
* the file grown beyond our last write? */ * the file grown beyond our last write? */
if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) || if ((nfsi->npages == 0) || new_isize > cur_isize) {
new_isize > cur_isize) {
i_size_write(inode, new_isize); i_size_write(inode, new_isize);
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
} }
......
...@@ -7780,10 +7780,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) ...@@ -7780,10 +7780,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
case -NFS4ERR_BADLAYOUT: /* no layout */ case -NFS4ERR_BADLAYOUT: /* no layout */
case -NFS4ERR_GRACE: /* loca_recalim always false */ case -NFS4ERR_GRACE: /* loca_recalim always false */
task->tk_status = 0; task->tk_status = 0;
break;
case 0: case 0:
nfs_post_op_update_inode_force_wcc(data->args.inode,
data->res.fattr);
break; break;
default: default:
if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
...@@ -7798,6 +7795,8 @@ static void nfs4_layoutcommit_release(void *calldata) ...@@ -7798,6 +7795,8 @@ static void nfs4_layoutcommit_release(void *calldata)
struct nfs4_layoutcommit_data *data = calldata; struct nfs4_layoutcommit_data *data = calldata;
pnfs_cleanup_layoutcommit(data); pnfs_cleanup_layoutcommit(data);
nfs_post_op_update_inode_force_wcc(data->args.inode,
data->res.fattr);
put_rpccred(data->cred); put_rpccred(data->cred);
kfree(data); kfree(data);
} }
......
...@@ -359,6 +359,15 @@ pnfs_ld_layoutret_on_setattr(struct inode *inode) ...@@ -359,6 +359,15 @@ pnfs_ld_layoutret_on_setattr(struct inode *inode)
PNFS_LAYOUTRET_ON_SETATTR; PNFS_LAYOUTRET_ON_SETATTR;
} }
static inline bool
pnfs_layoutcommit_outstanding(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
return test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags) != 0 ||
test_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags) != 0;
}
static inline int pnfs_return_layout(struct inode *ino) static inline int pnfs_return_layout(struct inode *ino)
{ {
struct nfs_inode *nfsi = NFS_I(ino); struct nfs_inode *nfsi = NFS_I(ino);
...@@ -515,6 +524,13 @@ pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, ...@@ -515,6 +524,13 @@ pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src,
return false; return false;
} }
static inline bool
pnfs_layoutcommit_outstanding(struct inode *inode)
{
return false;
}
static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)
{ {
return NULL; return NULL;
......
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