Commit 43df7110 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

NFSv4: Add CB_GETATTR support for delegated attributes



When the client holds an attribute delegation, the server may retrieve
all the timestamps through a CB_GETATTR callback.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarLance Shelton <lance.shelton@hammerspace.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 90f9ae74
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -46,14 +46,15 @@ struct cb_compound_hdr_res {

struct cb_getattrargs {
	struct nfs_fh fh;
	uint32_t bitmap[2];
	uint32_t bitmap[3];
};

struct cb_getattrres {
	__be32 status;
	uint32_t bitmap[2];
	uint32_t bitmap[3];
	uint64_t size;
	uint64_t change_attr;
	struct timespec64 atime;
	struct timespec64 ctime;
	struct timespec64 mtime;
};
+9 −5
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ __be32 nfs4_callback_getattr(void *argp, void *resp,
	if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
		goto out;

	res->bitmap[0] = res->bitmap[1] = 0;
	memset(res->bitmap, 0, sizeof(res->bitmap));
	res->status = htonl(NFS4ERR_BADHANDLE);

	dprintk_rcu("NFS: GETATTR callback request from %s\n",
@@ -59,12 +59,16 @@ __be32 nfs4_callback_getattr(void *argp, void *resp,
	res->change_attr = delegation->change_attr;
	if (nfs_have_writebacks(inode))
		res->change_attr++;
	res->atime = inode_get_atime(inode);
	res->ctime = inode_get_ctime(inode);
	res->mtime = inode_get_mtime(inode);
	res->bitmap[0] = (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE) &
			 args->bitmap[0];
	res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
		args->bitmap[1];
	res->bitmap[1] = (FATTR4_WORD1_TIME_ACCESS |
			  FATTR4_WORD1_TIME_METADATA |
			  FATTR4_WORD1_TIME_MODIFY) & args->bitmap[1];
	res->bitmap[2] = (FATTR4_WORD2_TIME_DELEG_ACCESS |
			  FATTR4_WORD2_TIME_DELEG_MODIFY) & args->bitmap[2];
	res->status = 0;
out_iput:
	rcu_read_unlock();
+37 −2
Original line number Diff line number Diff line
@@ -25,8 +25,9 @@
#define CB_OP_GETATTR_BITMAP_MAXSZ	(4 * 4) // bitmap length, 3 bitmaps
#define CB_OP_GETATTR_RES_MAXSZ		(CB_OP_HDR_RES_MAXSZ + \
					 CB_OP_GETATTR_BITMAP_MAXSZ + \
					 /* change, size, ctime, mtime */\
					 (2 + 2 + 3 + 3) * 4)
					 /* change, size, atime, ctime,
					  * mtime, deleg_atime, deleg_mtime */\
					 (2 + 2 + 3 + 3 + 3 + 3 + 3) * 4)
#define CB_OP_RECALL_RES_MAXSZ		(CB_OP_HDR_RES_MAXSZ)

#if defined(CONFIG_NFS_V4_1)
@@ -635,6 +636,13 @@ static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec64 *
	return 0;
}

static __be32 encode_attr_atime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec64 *time)
{
	if (!(bitmap[1] & FATTR4_WORD1_TIME_ACCESS))
		return 0;
	return encode_attr_time(xdr,time);
}

static __be32 encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec64 *time)
{
	if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA))
@@ -649,6 +657,24 @@ static __be32 encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap,
	return encode_attr_time(xdr,time);
}

static __be32 encode_attr_delegatime(struct xdr_stream *xdr,
				     const uint32_t *bitmap,
				     const struct timespec64 *time)
{
	if (!(bitmap[2] & FATTR4_WORD2_TIME_DELEG_ACCESS))
		return 0;
	return encode_attr_time(xdr,time);
}

static __be32 encode_attr_delegmtime(struct xdr_stream *xdr,
				     const uint32_t *bitmap,
				     const struct timespec64 *time)
{
	if (!(bitmap[2] & FATTR4_WORD2_TIME_DELEG_MODIFY))
		return 0;
	return encode_attr_time(xdr,time);
}

static __be32 encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr)
{
	__be32 status;
@@ -697,12 +723,21 @@ static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
	if (unlikely(status != 0))
		goto out;
	status = encode_attr_size(xdr, res->bitmap, res->size);
	if (unlikely(status != 0))
		goto out;
	status = encode_attr_atime(xdr, res->bitmap, &res->atime);
	if (unlikely(status != 0))
		goto out;
	status = encode_attr_ctime(xdr, res->bitmap, &res->ctime);
	if (unlikely(status != 0))
		goto out;
	status = encode_attr_mtime(xdr, res->bitmap, &res->mtime);
	if (unlikely(status != 0))
		goto out;
	status = encode_attr_delegatime(xdr, res->bitmap, &res->atime);
	if (unlikely(status != 0))
		goto out;
	status = encode_attr_delegmtime(xdr, res->bitmap, &res->mtime);
	*savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1)));
out:
	return status;