aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2014-01-13 12:08:11 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-01-13 12:08:11 -0500
commitd8c951c313ed1d7144b55c0d56f7c53220044dda (patch)
tree51d2a904da45349403b0db80fb9f8812967ec5dd
parent16a6ddc70920a0686dbf90e092a539c1a4fd7b77 (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.c19
-rw-r--r--fs/nfs/nfs4proc.c5
-rw-r--r--fs/nfs/pnfs.h16
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 */
1290static 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
1286static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) 1300static 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
362static inline bool
363pnfs_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
362static inline int pnfs_return_layout(struct inode *ino) 371static 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
527static inline bool
528pnfs_layoutcommit_outstanding(struct inode *inode)
529{
530 return false;
531}
532
533
518static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) 534static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)
519{ 535{
520 return NULL; 536 return NULL;