]>
Commit | Line | Data |
---|---|---|
9b9960a0 TH |
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 | } |