1 /* 2 * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com> 3 */ 4 #include <linux/sunrpc/svc.h> 5 #include <linux/nfs4.h> 6 7 #include "nfsd.h" 8 #include "flexfilelayoutxdr.h" 9 10 #define NFSDDBG_FACILITY NFSDDBG_PNFS 11 12 struct ff_idmap { 13 char buf[11]; 14 int len; 15 }; 16 17 __be32 18 nfsd4_ff_encode_layoutget(struct xdr_stream *xdr, 19 struct nfsd4_layoutget *lgp) 20 { 21 struct pnfs_ff_layout *fl = lgp->lg_content; 22 int len, mirror_len, ds_len, fh_len; 23 __be32 *p; 24 25 /* 26 * Unlike nfsd4_encode_user, we know these will 27 * always be stringified. 28 */ 29 struct ff_idmap uid; 30 struct ff_idmap gid; 31 32 fh_len = 4 + fl->fh.size; 33 34 uid.len = sprintf(uid.buf, "%u", from_kuid(&init_user_ns, fl->uid)); 35 gid.len = sprintf(gid.buf, "%u", from_kgid(&init_user_ns, fl->gid)); 36 37 /* 8 + len for recording the length, name, and padding */ 38 ds_len = 20 + sizeof(stateid_opaque_t) + 4 + fh_len + 39 8 + uid.len + 8 + gid.len; 40 41 mirror_len = 4 + ds_len; 42 43 /* The layout segment */ 44 len = 20 + mirror_len; 45 46 p = xdr_reserve_space(xdr, sizeof(__be32) + len); 47 if (!p) 48 return nfserr_toosmall; 49 50 *p++ = cpu_to_be32(len); 51 p = xdr_encode_hyper(p, 0); /* stripe unit of 1 */ 52 53 *p++ = cpu_to_be32(1); /* single mirror */ 54 *p++ = cpu_to_be32(1); /* single data server */ 55 56 p = xdr_encode_opaque_fixed(p, &fl->deviceid, 57 sizeof(struct nfsd4_deviceid)); 58 59 *p++ = cpu_to_be32(1); /* efficiency */ 60 61 *p++ = cpu_to_be32(fl->stateid.si_generation); 62 p = xdr_encode_opaque_fixed(p, &fl->stateid.si_opaque, 63 sizeof(stateid_opaque_t)); 64 65 *p++ = cpu_to_be32(1); /* single file handle */ 66 p = xdr_encode_opaque(p, fl->fh.data, fl->fh.size); 67 68 p = xdr_encode_opaque(p, uid.buf, uid.len); 69 p = xdr_encode_opaque(p, gid.buf, gid.len); 70 71 *p++ = cpu_to_be32(fl->flags); 72 *p++ = cpu_to_be32(0); /* No stats collect hint */ 73 74 return 0; 75 } 76 77 __be32 78 nfsd4_ff_encode_getdeviceinfo(struct xdr_stream *xdr, 79 struct nfsd4_getdeviceinfo *gdp) 80 { 81 struct pnfs_ff_device_addr *da = gdp->gd_device; 82 int len; 83 int ver_len; 84 int addr_len; 85 __be32 *p; 86 87 /* len + padding for two strings */ 88 addr_len = 16 + da->netaddr.netid_len + da->netaddr.addr_len; 89 ver_len = 20; 90 91 len = 4 + ver_len + 4 + addr_len; 92 93 p = xdr_reserve_space(xdr, len + sizeof(__be32)); 94 if (!p) 95 return nfserr_resource; 96 97 /* 98 * Fill in the overall length and number of volumes at the beginning 99 * of the layout. 100 */ 101 *p++ = cpu_to_be32(len); 102 *p++ = cpu_to_be32(1); /* 1 netaddr */ 103 p = xdr_encode_opaque(p, da->netaddr.netid, da->netaddr.netid_len); 104 p = xdr_encode_opaque(p, da->netaddr.addr, da->netaddr.addr_len); 105 106 *p++ = cpu_to_be32(1); /* 1 versions */ 107 108 *p++ = cpu_to_be32(da->version); 109 *p++ = cpu_to_be32(da->minor_version); 110 *p++ = cpu_to_be32(da->rsize); 111 *p++ = cpu_to_be32(da->wsize); 112 *p++ = cpu_to_be32(da->tightly_coupled); 113 114 return 0; 115 } 116