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>
This commit is contained in:
		
							parent
							
								
									16a6ddc709
								
							
						
					
					
						commit
						d8c951c313
					
				| @ -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); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	trace_nfs_refresh_inode_enter(inode); | ||||
| 
 | ||||
| 	nfs_inode_attrs_handle_layoutcommit(inode, fattr); | ||||
| 
 | ||||
| 	if (nfs_inode_attrs_need_update(inode, fattr)) | ||||
| 		ret = nfs_update_inode(inode, fattr); | ||||
| 	else | ||||
| @ -1518,8 +1534,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | ||||
| 		if (new_isize != cur_isize) { | ||||
| 			/* Do we perhaps have any outstanding writes, or has
 | ||||
| 			 * the file grown beyond our last write? */ | ||||
| 			if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) || | ||||
| 			     new_isize > cur_isize) { | ||||
| 			if ((nfsi->npages == 0) || new_isize > cur_isize) { | ||||
| 				i_size_write(inode, new_isize); | ||||
| 				invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||||
| 			} | ||||
|  | ||||
| @ -7780,10 +7780,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | ||||
| 	case -NFS4ERR_BADLAYOUT:     /* no layout */ | ||||
| 	case -NFS4ERR_GRACE:	    /* loca_recalim always false */ | ||||
| 		task->tk_status = 0; | ||||
| 		break; | ||||
| 	case 0: | ||||
| 		nfs_post_op_update_inode_force_wcc(data->args.inode, | ||||
| 						   data->res.fattr); | ||||
| 		break; | ||||
| 	default: | ||||
| 		if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | ||||
| @ -7798,6 +7795,8 @@ static void nfs4_layoutcommit_release(void *calldata) | ||||
| 	struct nfs4_layoutcommit_data *data = calldata; | ||||
| 
 | ||||
| 	pnfs_cleanup_layoutcommit(data); | ||||
| 	nfs_post_op_update_inode_force_wcc(data->args.inode, | ||||
| 					   data->res.fattr); | ||||
| 	put_rpccred(data->cred); | ||||
| 	kfree(data); | ||||
| } | ||||
|  | ||||
| @ -359,6 +359,15 @@ pnfs_ld_layoutret_on_setattr(struct inode *inode) | ||||
| 		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) | ||||
| { | ||||
| 	struct nfs_inode *nfsi = NFS_I(ino); | ||||
| @ -515,6 +524,13 @@ pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static inline bool | ||||
| pnfs_layoutcommit_outstanding(struct inode *inode) | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) | ||||
| { | ||||
| 	return NULL; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user