@@ -2946,6 +2946,10 @@ struct nfsd4_fattr_args {
struct kstat stat;
struct kstatfs statfs;
struct nfs4_acl *acl;
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+ void *context;
+ int contextlen;
+#endif
u32 rdattr_err;
bool contextsupport;
bool ignore_crossmnt;
@@ -3421,6 +3425,14 @@ static __be32 nfsd4_encode_fattr4_layout_types(struct xdr_stream *xdr,
return nfsd4_encode_layout_types(xdr, args->exp->ex_layout_types);
}
+static __be32 nfsd4_encode_fattr4_layout_blksize(struct xdr_stream *xdr,
+ struct nfsd4_fattr_args *args)
+{
+ if (xdr_stream_encode_u32(xdr, args->stat.blksize) < 0)
+ return nfserr_resource;
+ return nfs_ok;
+}
+
#endif
static const nfsd4_enc_attr nfsd4_enc_fattr4_word1_ops[] = {
@@ -3462,6 +3474,84 @@ static const nfsd4_enc_attr nfsd4_enc_fattr4_word1_ops[] = {
[31] = nfsd4_encode_fattr4__noop, /* layout hint */
};
+static __be32 nfsd4_encode_fattr4_suppattr_exclcreat(struct xdr_stream *xdr,
+ struct nfsd4_fattr_args *args)
+{
+ struct nfsd4_compoundres *resp = args->rqstp->rq_resp;
+ u32 minorversion = resp->cstate.minorversion;
+ u32 supp[3];
+
+ memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
+ supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
+ supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
+ supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
+
+ return nfsd4_encode_bitmap(xdr, supp[0], supp[1], supp[2]);
+}
+
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+static __be32 nfsd4_encode_fattr4_sec_label(struct xdr_stream *xdr,
+ struct nfsd4_fattr_args *args)
+{
+ return nfsd4_encode_security_label(xdr, args->rqstp,
+ args->context, args->contextlen);
+}
+#endif
+
+static __be32 nfsd4_encode_fattr4_xattr_support(struct xdr_stream *xdr,
+ struct nfsd4_fattr_args *args)
+{
+ int err = xattr_supports_user_prefix(d_inode(args->dentry));
+
+ if (xdr_stream_encode_bool(xdr, err == 0) < 0)
+ return nfserr_resource;
+ return nfs_ok;
+}
+
+static const nfsd4_enc_attr nfsd4_enc_fattr4_word2_ops[] = {
+#ifdef CONFIG_NFSD_PNFS
+ [0] = nfsd4_encode_fattr4_layout_types,
+ [1] = nfsd4_encode_fattr4_layout_blksize,
+#else
+ [0] = nfsd4_encode_fattr4__noop,
+ [1] = nfsd4_encode_fattr4__noop,
+#endif
+ [2] = nfsd4_encode_fattr4__noop, /* layout alignment */
+ [3] = nfsd4_encode_fattr4__noop, /* fslocations info */
+ [4] = nfsd4_encode_fattr4__noop, /* mds threshold */
+ [5] = nfsd4_encode_fattr4__noop, /* retention get */
+ [6] = nfsd4_encode_fattr4__noop, /* retention set */
+ [7] = nfsd4_encode_fattr4__noop, /* retentevt get */
+ [8] = nfsd4_encode_fattr4__noop, /* retentevt set */
+ [9] = nfsd4_encode_fattr4__noop, /* retention hold */
+ [10] = nfsd4_encode_fattr4__noop, /* mode set mask */
+ [11] = nfsd4_encode_fattr4_suppattr_exclcreat,
+ [12] = nfsd4_encode_fattr4__noop, /* fs charset cap */
+ [13] = nfsd4_encode_fattr4__noop, /* clone blksize */
+ [14] = nfsd4_encode_fattr4__noop, /* space freed */
+ [15] = nfsd4_encode_fattr4__noop, /* change attr type */
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+ [16] = nfsd4_encode_fattr4_sec_label,
+#else
+ [16] = nfsd4_encode_fattr4__noop,
+#endif
+ [17] = nfsd4_encode_fattr4__noop, /* mode_umask */
+ [18] = nfsd4_encode_fattr4_xattr_support,
+ [19] = nfsd4_encode_fattr4__noop, /* reserved */
+ [20] = nfsd4_encode_fattr4__noop, /* reserved */
+ [21] = nfsd4_encode_fattr4__noop, /* reserved */
+ [22] = nfsd4_encode_fattr4__noop, /* reserved */
+ [23] = nfsd4_encode_fattr4__noop, /* reserved */
+ [24] = nfsd4_encode_fattr4__noop, /* reserved */
+ [25] = nfsd4_encode_fattr4__noop, /* reserved */
+ [26] = nfsd4_encode_fattr4__noop, /* reserved */
+ [27] = nfsd4_encode_fattr4__noop, /* reserved */
+ [28] = nfsd4_encode_fattr4__noop, /* reserved */
+ [29] = nfsd4_encode_fattr4__noop, /* reserved */
+ [30] = nfsd4_encode_fattr4__noop, /* reserved */
+ [31] = nfsd4_encode_fattr4__noop, /* reserved */
+};
+
/*
* Note: @fhp can be NULL; in this case, we might have to compose the filehandle
* ourselves.
@@ -3478,12 +3568,6 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
u32 bmval2 = bmval[2];
struct svc_fh *tempfh = NULL;
int starting_len = xdr->buf->len;
-#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- void *context = NULL;
- int contextlen;
-#endif
- struct nfsd4_compoundres *resp = rqstp->rq_resp;
- u32 minorversion = resp->cstate.minorversion;
int err, i, attrlen_offset;
__be32 status, *attrlen_p;
struct path path = {
@@ -3491,7 +3575,6 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
.dentry = dentry,
};
unsigned long mask;
- __be32 *p;
args.rqstp = rqstp;
args.fhp = fhp;
@@ -3552,11 +3635,12 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
args.contextsupport = false;
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+ args.context = NULL;
if ((bmval2 & FATTR4_WORD2_SECURITY_LABEL) ||
bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
err = security_inode_getsecctx(d_inode(dentry),
- &context, &contextlen);
+ &args.context, &args.contextlen);
else
err = -EOPNOTSUPP;
args.contextsupport = (err == 0);
@@ -3592,48 +3676,13 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
goto out;
}
-#ifdef CONFIG_NFSD_PNFS
- if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
- status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
- if (status)
- goto out;
- }
-
- if (bmval2 & FATTR4_WORD2_LAYOUT_BLKSIZE) {
- p = xdr_reserve_space(xdr, 4);
- if (!p)
- goto out_resource;
- *p++ = cpu_to_be32(args.stat.blksize);
- }
-#endif /* CONFIG_NFSD_PNFS */
- if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
- u32 supp[3];
-
- memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
- supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
- supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
- supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
-
- status = nfsd4_encode_bitmap(xdr, supp[0], supp[1], supp[2]);
- if (status)
- goto out;
- }
-
-#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
- status = nfsd4_encode_security_label(xdr, rqstp, context,
- contextlen);
- if (status)
- goto out;
- }
-#endif
-
- if (bmval2 & FATTR4_WORD2_XATTR_SUPPORT) {
- p = xdr_reserve_space(xdr, 4);
- if (!p)
- goto out_resource;
- err = xattr_supports_user_prefix(d_inode(dentry));
- *p++ = cpu_to_be32(err == 0);
+ if (bmval2) {
+ mask = bmval2;
+ for_each_set_bit(i, &mask, 32) {
+ status = nfsd4_enc_fattr4_word2_ops[i](xdr, &args);
+ if (status)
+ goto out;
+ }
}
*attrlen_p = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT);
@@ -3641,8 +3690,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
out:
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- if (context)
- security_release_secctx(context, contextlen);
+ if (args.context)
+ security_release_secctx(args.context, args.contextlen);
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(args.acl);
if (tempfh) {