diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-01-13 12:08:11 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-01-13 12:08:11 -0500 |
commit | d8c951c313ed1d7144b55c0d56f7c53220044dda (patch) | |
tree | 51d2a904da45349403b0db80fb9f8812967ec5dd | |
parent | 16a6ddc70920a0686dbf90e092a539c1a4fd7b77 (diff) |
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: shaobingqing <shaobingqing@bwstor.com.cn>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/inode.c | 19 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 5 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 16 |
3 files changed, 35 insertions, 5 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 5feec233895d..c63e15224466 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1283,12 +1283,28 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n | |||
1283 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); | 1283 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | /* | ||
1287 | * Don't trust the change_attribute, mtime, ctime or size if | ||
1288 | * a pnfs LAYOUTCOMMIT is outstanding | ||
1289 | */ | ||
1290 | static void nfs_inode_attrs_handle_layoutcommit(struct inode *inode, | ||
1291 | struct nfs_fattr *fattr) | ||
1292 | { | ||
1293 | if (pnfs_layoutcommit_outstanding(inode)) | ||
1294 | fattr->valid &= ~(NFS_ATTR_FATTR_CHANGE | | ||
1295 | NFS_ATTR_FATTR_MTIME | | ||
1296 | NFS_ATTR_FATTR_CTIME | | ||
1297 | NFS_ATTR_FATTR_SIZE); | ||
1298 | } | ||
1299 | |||
1286 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | 1300 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) |
1287 | { | 1301 | { |
1288 | int ret; | 1302 | int ret; |
1289 | 1303 | ||
1290 | trace_nfs_refresh_inode_enter(inode); | 1304 | trace_nfs_refresh_inode_enter(inode); |
1291 | 1305 | ||
1306 | nfs_inode_attrs_handle_layoutcommit(inode, fattr); | ||
1307 | |||
1292 | if (nfs_inode_attrs_need_update(inode, fattr)) | 1308 | if (nfs_inode_attrs_need_update(inode, fattr)) |
1293 | ret = nfs_update_inode(inode, fattr); | 1309 | ret = nfs_update_inode(inode, fattr); |
1294 | else | 1310 | else |
@@ -1518,8 +1534,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1518 | if (new_isize != cur_isize) { | 1534 | if (new_isize != cur_isize) { |
1519 | /* Do we perhaps have any outstanding writes, or has | 1535 | /* Do we perhaps have any outstanding writes, or has |
1520 | * the file grown beyond our last write? */ | 1536 | * the file grown beyond our last write? */ |
1521 | if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) || | 1537 | if ((nfsi->npages == 0) || new_isize > cur_isize) { |
1522 | new_isize > cur_isize) { | ||
1523 | i_size_write(inode, new_isize); | 1538 | i_size_write(inode, new_isize); |
1524 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1539 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1525 | } | 1540 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 15052b81df42..f4908eb40a21 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -7780,10 +7780,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
7780 | case -NFS4ERR_BADLAYOUT: /* no layout */ | 7780 | case -NFS4ERR_BADLAYOUT: /* no layout */ |
7781 | case -NFS4ERR_GRACE: /* loca_recalim always false */ | 7781 | case -NFS4ERR_GRACE: /* loca_recalim always false */ |
7782 | task->tk_status = 0; | 7782 | task->tk_status = 0; |
7783 | break; | ||
7784 | case 0: | 7783 | case 0: |
7785 | nfs_post_op_update_inode_force_wcc(data->args.inode, | ||
7786 | data->res.fattr); | ||
7787 | break; | 7784 | break; |
7788 | default: | 7785 | default: |
7789 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | 7786 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { |
@@ -7798,6 +7795,8 @@ static void nfs4_layoutcommit_release(void *calldata) | |||
7798 | struct nfs4_layoutcommit_data *data = calldata; | 7795 | struct nfs4_layoutcommit_data *data = calldata; |
7799 | 7796 | ||
7800 | pnfs_cleanup_layoutcommit(data); | 7797 | pnfs_cleanup_layoutcommit(data); |
7798 | nfs_post_op_update_inode_force_wcc(data->args.inode, | ||
7799 | data->res.fattr); | ||
7801 | put_rpccred(data->cred); | 7800 | put_rpccred(data->cred); |
7802 | kfree(data); | 7801 | kfree(data); |
7803 | } | 7802 | } |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index a4f41810a7f4..023793909778 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -359,6 +359,15 @@ pnfs_ld_layoutret_on_setattr(struct inode *inode) | |||
359 | PNFS_LAYOUTRET_ON_SETATTR; | 359 | PNFS_LAYOUTRET_ON_SETATTR; |
360 | } | 360 | } |
361 | 361 | ||
362 | static inline bool | ||
363 | pnfs_layoutcommit_outstanding(struct inode *inode) | ||
364 | { | ||
365 | struct nfs_inode *nfsi = NFS_I(inode); | ||
366 | |||
367 | return test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags) != 0 || | ||
368 | test_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags) != 0; | ||
369 | } | ||
370 | |||
362 | static inline int pnfs_return_layout(struct inode *ino) | 371 | static inline int pnfs_return_layout(struct inode *ino) |
363 | { | 372 | { |
364 | struct nfs_inode *nfsi = NFS_I(ino); | 373 | struct nfs_inode *nfsi = NFS_I(ino); |
@@ -515,6 +524,13 @@ pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, | |||
515 | return false; | 524 | return false; |
516 | } | 525 | } |
517 | 526 | ||
527 | static inline bool | ||
528 | pnfs_layoutcommit_outstanding(struct inode *inode) | ||
529 | { | ||
530 | return false; | ||
531 | } | ||
532 | |||
533 | |||
518 | static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) | 534 | static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) |
519 | { | 535 | { |
520 | return NULL; | 536 | return NULL; |