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