Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8c951c3 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -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;
			}
+2 −3
Original line number Diff line number Diff line
@@ -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);
}
+16 −0
Original line number Diff line number Diff line
@@ -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;