Commit a613fa168afc19179a7547fbba45644c5b6912bf
1 parent
080b794ce5
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
SUNRPC: constify the rpc_program
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 17 changed files with 54 additions and 54 deletions Inline Diff
- fs/lockd/clnt4xdr.c
- fs/lockd/clntxdr.c
- fs/lockd/mon.c
- fs/nfs/client.c
- fs/nfs/internal.h
- fs/nfs/mount_clnt.c
- fs/nfs/nfs2xdr.c
- fs/nfs/nfs3xdr.c
- fs/nfs/nfs4xdr.c
- fs/nfsd/nfs4callback.c
- include/linux/lockd/lockd.h
- include/linux/lockd/xdr4.h
- include/linux/nfs_xdr.h
- include/linux/sunrpc/clnt.h
- include/linux/sunrpc/stats.h
- net/sunrpc/clnt.c
- net/sunrpc/rpcb_clnt.c
fs/lockd/clnt4xdr.c
1 | /* | 1 | /* |
2 | * linux/fs/lockd/clnt4xdr.c | 2 | * linux/fs/lockd/clnt4xdr.c |
3 | * | 3 | * |
4 | * XDR functions to encode/decode NLM version 4 RPC arguments and results. | 4 | * XDR functions to encode/decode NLM version 4 RPC arguments and results. |
5 | * | 5 | * |
6 | * NLM client-side only. | 6 | * NLM client-side only. |
7 | * | 7 | * |
8 | * Copyright (C) 2010, Oracle. All rights reserved. | 8 | * Copyright (C) 2010, Oracle. All rights reserved. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/sunrpc/xdr.h> | 12 | #include <linux/sunrpc/xdr.h> |
13 | #include <linux/sunrpc/clnt.h> | 13 | #include <linux/sunrpc/clnt.h> |
14 | #include <linux/sunrpc/stats.h> | 14 | #include <linux/sunrpc/stats.h> |
15 | #include <linux/lockd/lockd.h> | 15 | #include <linux/lockd/lockd.h> |
16 | 16 | ||
17 | #define NLMDBG_FACILITY NLMDBG_XDR | 17 | #define NLMDBG_FACILITY NLMDBG_XDR |
18 | 18 | ||
19 | #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) | 19 | #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) |
20 | # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" | 20 | # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | #if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) | 23 | #if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) |
24 | # error "NLM host name cannot be larger than NLM's maximum string length!" | 24 | # error "NLM host name cannot be larger than NLM's maximum string length!" |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Declare the space requirements for NLM arguments and replies as | 28 | * Declare the space requirements for NLM arguments and replies as |
29 | * number of 32bit-words | 29 | * number of 32bit-words |
30 | */ | 30 | */ |
31 | #define NLM4_void_sz (0) | 31 | #define NLM4_void_sz (0) |
32 | #define NLM4_cookie_sz (1+(NLM_MAXCOOKIELEN>>2)) | 32 | #define NLM4_cookie_sz (1+(NLM_MAXCOOKIELEN>>2)) |
33 | #define NLM4_caller_sz (1+(NLMCLNT_OHSIZE>>2)) | 33 | #define NLM4_caller_sz (1+(NLMCLNT_OHSIZE>>2)) |
34 | #define NLM4_owner_sz (1+(NLMCLNT_OHSIZE>>2)) | 34 | #define NLM4_owner_sz (1+(NLMCLNT_OHSIZE>>2)) |
35 | #define NLM4_fhandle_sz (1+(NFS3_FHSIZE>>2)) | 35 | #define NLM4_fhandle_sz (1+(NFS3_FHSIZE>>2)) |
36 | #define NLM4_lock_sz (5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz) | 36 | #define NLM4_lock_sz (5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz) |
37 | #define NLM4_holder_sz (6+NLM4_owner_sz) | 37 | #define NLM4_holder_sz (6+NLM4_owner_sz) |
38 | 38 | ||
39 | #define NLM4_testargs_sz (NLM4_cookie_sz+1+NLM4_lock_sz) | 39 | #define NLM4_testargs_sz (NLM4_cookie_sz+1+NLM4_lock_sz) |
40 | #define NLM4_lockargs_sz (NLM4_cookie_sz+4+NLM4_lock_sz) | 40 | #define NLM4_lockargs_sz (NLM4_cookie_sz+4+NLM4_lock_sz) |
41 | #define NLM4_cancargs_sz (NLM4_cookie_sz+2+NLM4_lock_sz) | 41 | #define NLM4_cancargs_sz (NLM4_cookie_sz+2+NLM4_lock_sz) |
42 | #define NLM4_unlockargs_sz (NLM4_cookie_sz+NLM4_lock_sz) | 42 | #define NLM4_unlockargs_sz (NLM4_cookie_sz+NLM4_lock_sz) |
43 | 43 | ||
44 | #define NLM4_testres_sz (NLM4_cookie_sz+1+NLM4_holder_sz) | 44 | #define NLM4_testres_sz (NLM4_cookie_sz+1+NLM4_holder_sz) |
45 | #define NLM4_res_sz (NLM4_cookie_sz+1) | 45 | #define NLM4_res_sz (NLM4_cookie_sz+1) |
46 | #define NLM4_norep_sz (0) | 46 | #define NLM4_norep_sz (0) |
47 | 47 | ||
48 | 48 | ||
49 | static s64 loff_t_to_s64(loff_t offset) | 49 | static s64 loff_t_to_s64(loff_t offset) |
50 | { | 50 | { |
51 | s64 res; | 51 | s64 res; |
52 | 52 | ||
53 | if (offset >= NLM4_OFFSET_MAX) | 53 | if (offset >= NLM4_OFFSET_MAX) |
54 | res = NLM4_OFFSET_MAX; | 54 | res = NLM4_OFFSET_MAX; |
55 | else if (offset <= -NLM4_OFFSET_MAX) | 55 | else if (offset <= -NLM4_OFFSET_MAX) |
56 | res = -NLM4_OFFSET_MAX; | 56 | res = -NLM4_OFFSET_MAX; |
57 | else | 57 | else |
58 | res = offset; | 58 | res = offset; |
59 | return res; | 59 | return res; |
60 | } | 60 | } |
61 | 61 | ||
62 | static void nlm4_compute_offsets(const struct nlm_lock *lock, | 62 | static void nlm4_compute_offsets(const struct nlm_lock *lock, |
63 | u64 *l_offset, u64 *l_len) | 63 | u64 *l_offset, u64 *l_len) |
64 | { | 64 | { |
65 | const struct file_lock *fl = &lock->fl; | 65 | const struct file_lock *fl = &lock->fl; |
66 | 66 | ||
67 | BUG_ON(fl->fl_start > NLM4_OFFSET_MAX); | 67 | BUG_ON(fl->fl_start > NLM4_OFFSET_MAX); |
68 | BUG_ON(fl->fl_end > NLM4_OFFSET_MAX && | 68 | BUG_ON(fl->fl_end > NLM4_OFFSET_MAX && |
69 | fl->fl_end != OFFSET_MAX); | 69 | fl->fl_end != OFFSET_MAX); |
70 | 70 | ||
71 | *l_offset = loff_t_to_s64(fl->fl_start); | 71 | *l_offset = loff_t_to_s64(fl->fl_start); |
72 | if (fl->fl_end == OFFSET_MAX) | 72 | if (fl->fl_end == OFFSET_MAX) |
73 | *l_len = 0; | 73 | *l_len = 0; |
74 | else | 74 | else |
75 | *l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); | 75 | *l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); |
76 | } | 76 | } |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Handle decode buffer overflows out-of-line. | 79 | * Handle decode buffer overflows out-of-line. |
80 | */ | 80 | */ |
81 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 81 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
82 | { | 82 | { |
83 | dprintk("lockd: %s prematurely hit the end of our receive buffer. " | 83 | dprintk("lockd: %s prematurely hit the end of our receive buffer. " |
84 | "Remaining buffer length is %tu words.\n", | 84 | "Remaining buffer length is %tu words.\n", |
85 | func, xdr->end - xdr->p); | 85 | func, xdr->end - xdr->p); |
86 | } | 86 | } |
87 | 87 | ||
88 | 88 | ||
89 | /* | 89 | /* |
90 | * Encode/decode NLMv4 basic data types | 90 | * Encode/decode NLMv4 basic data types |
91 | * | 91 | * |
92 | * Basic NLMv4 data types are defined in Appendix II, section 6.1.4 | 92 | * Basic NLMv4 data types are defined in Appendix II, section 6.1.4 |
93 | * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter | 93 | * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter |
94 | * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W". | 94 | * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W". |
95 | * | 95 | * |
96 | * Not all basic data types have their own encoding and decoding | 96 | * Not all basic data types have their own encoding and decoding |
97 | * functions. For run-time efficiency, some data types are encoded | 97 | * functions. For run-time efficiency, some data types are encoded |
98 | * or decoded inline. | 98 | * or decoded inline. |
99 | */ | 99 | */ |
100 | 100 | ||
101 | static void encode_bool(struct xdr_stream *xdr, const int value) | 101 | static void encode_bool(struct xdr_stream *xdr, const int value) |
102 | { | 102 | { |
103 | __be32 *p; | 103 | __be32 *p; |
104 | 104 | ||
105 | p = xdr_reserve_space(xdr, 4); | 105 | p = xdr_reserve_space(xdr, 4); |
106 | *p = value ? xdr_one : xdr_zero; | 106 | *p = value ? xdr_one : xdr_zero; |
107 | } | 107 | } |
108 | 108 | ||
109 | static void encode_int32(struct xdr_stream *xdr, const s32 value) | 109 | static void encode_int32(struct xdr_stream *xdr, const s32 value) |
110 | { | 110 | { |
111 | __be32 *p; | 111 | __be32 *p; |
112 | 112 | ||
113 | p = xdr_reserve_space(xdr, 4); | 113 | p = xdr_reserve_space(xdr, 4); |
114 | *p = cpu_to_be32(value); | 114 | *p = cpu_to_be32(value); |
115 | } | 115 | } |
116 | 116 | ||
117 | /* | 117 | /* |
118 | * typedef opaque netobj<MAXNETOBJ_SZ> | 118 | * typedef opaque netobj<MAXNETOBJ_SZ> |
119 | */ | 119 | */ |
120 | static void encode_netobj(struct xdr_stream *xdr, | 120 | static void encode_netobj(struct xdr_stream *xdr, |
121 | const u8 *data, const unsigned int length) | 121 | const u8 *data, const unsigned int length) |
122 | { | 122 | { |
123 | __be32 *p; | 123 | __be32 *p; |
124 | 124 | ||
125 | BUG_ON(length > XDR_MAX_NETOBJ); | 125 | BUG_ON(length > XDR_MAX_NETOBJ); |
126 | p = xdr_reserve_space(xdr, 4 + length); | 126 | p = xdr_reserve_space(xdr, 4 + length); |
127 | xdr_encode_opaque(p, data, length); | 127 | xdr_encode_opaque(p, data, length); |
128 | } | 128 | } |
129 | 129 | ||
130 | static int decode_netobj(struct xdr_stream *xdr, | 130 | static int decode_netobj(struct xdr_stream *xdr, |
131 | struct xdr_netobj *obj) | 131 | struct xdr_netobj *obj) |
132 | { | 132 | { |
133 | u32 length; | 133 | u32 length; |
134 | __be32 *p; | 134 | __be32 *p; |
135 | 135 | ||
136 | p = xdr_inline_decode(xdr, 4); | 136 | p = xdr_inline_decode(xdr, 4); |
137 | if (unlikely(p == NULL)) | 137 | if (unlikely(p == NULL)) |
138 | goto out_overflow; | 138 | goto out_overflow; |
139 | length = be32_to_cpup(p++); | 139 | length = be32_to_cpup(p++); |
140 | if (unlikely(length > XDR_MAX_NETOBJ)) | 140 | if (unlikely(length > XDR_MAX_NETOBJ)) |
141 | goto out_size; | 141 | goto out_size; |
142 | obj->len = length; | 142 | obj->len = length; |
143 | obj->data = (u8 *)p; | 143 | obj->data = (u8 *)p; |
144 | return 0; | 144 | return 0; |
145 | out_size: | 145 | out_size: |
146 | dprintk("NFS: returned netobj was too long: %u\n", length); | 146 | dprintk("NFS: returned netobj was too long: %u\n", length); |
147 | return -EIO; | 147 | return -EIO; |
148 | out_overflow: | 148 | out_overflow: |
149 | print_overflow_msg(__func__, xdr); | 149 | print_overflow_msg(__func__, xdr); |
150 | return -EIO; | 150 | return -EIO; |
151 | } | 151 | } |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * netobj cookie; | 154 | * netobj cookie; |
155 | */ | 155 | */ |
156 | static void encode_cookie(struct xdr_stream *xdr, | 156 | static void encode_cookie(struct xdr_stream *xdr, |
157 | const struct nlm_cookie *cookie) | 157 | const struct nlm_cookie *cookie) |
158 | { | 158 | { |
159 | BUG_ON(cookie->len > NLM_MAXCOOKIELEN); | 159 | BUG_ON(cookie->len > NLM_MAXCOOKIELEN); |
160 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); | 160 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); |
161 | } | 161 | } |
162 | 162 | ||
163 | static int decode_cookie(struct xdr_stream *xdr, | 163 | static int decode_cookie(struct xdr_stream *xdr, |
164 | struct nlm_cookie *cookie) | 164 | struct nlm_cookie *cookie) |
165 | { | 165 | { |
166 | u32 length; | 166 | u32 length; |
167 | __be32 *p; | 167 | __be32 *p; |
168 | 168 | ||
169 | p = xdr_inline_decode(xdr, 4); | 169 | p = xdr_inline_decode(xdr, 4); |
170 | if (unlikely(p == NULL)) | 170 | if (unlikely(p == NULL)) |
171 | goto out_overflow; | 171 | goto out_overflow; |
172 | length = be32_to_cpup(p++); | 172 | length = be32_to_cpup(p++); |
173 | /* apparently HPUX can return empty cookies */ | 173 | /* apparently HPUX can return empty cookies */ |
174 | if (length == 0) | 174 | if (length == 0) |
175 | goto out_hpux; | 175 | goto out_hpux; |
176 | if (length > NLM_MAXCOOKIELEN) | 176 | if (length > NLM_MAXCOOKIELEN) |
177 | goto out_size; | 177 | goto out_size; |
178 | p = xdr_inline_decode(xdr, length); | 178 | p = xdr_inline_decode(xdr, length); |
179 | if (unlikely(p == NULL)) | 179 | if (unlikely(p == NULL)) |
180 | goto out_overflow; | 180 | goto out_overflow; |
181 | cookie->len = length; | 181 | cookie->len = length; |
182 | memcpy(cookie->data, p, length); | 182 | memcpy(cookie->data, p, length); |
183 | return 0; | 183 | return 0; |
184 | out_hpux: | 184 | out_hpux: |
185 | cookie->len = 4; | 185 | cookie->len = 4; |
186 | memset(cookie->data, 0, 4); | 186 | memset(cookie->data, 0, 4); |
187 | return 0; | 187 | return 0; |
188 | out_size: | 188 | out_size: |
189 | dprintk("NFS: returned cookie was too long: %u\n", length); | 189 | dprintk("NFS: returned cookie was too long: %u\n", length); |
190 | return -EIO; | 190 | return -EIO; |
191 | out_overflow: | 191 | out_overflow: |
192 | print_overflow_msg(__func__, xdr); | 192 | print_overflow_msg(__func__, xdr); |
193 | return -EIO; | 193 | return -EIO; |
194 | } | 194 | } |
195 | 195 | ||
196 | /* | 196 | /* |
197 | * netobj fh; | 197 | * netobj fh; |
198 | */ | 198 | */ |
199 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) | 199 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) |
200 | { | 200 | { |
201 | BUG_ON(fh->size > NFS3_FHSIZE); | 201 | BUG_ON(fh->size > NFS3_FHSIZE); |
202 | encode_netobj(xdr, (u8 *)&fh->data, fh->size); | 202 | encode_netobj(xdr, (u8 *)&fh->data, fh->size); |
203 | } | 203 | } |
204 | 204 | ||
205 | /* | 205 | /* |
206 | * enum nlm4_stats { | 206 | * enum nlm4_stats { |
207 | * NLM4_GRANTED = 0, | 207 | * NLM4_GRANTED = 0, |
208 | * NLM4_DENIED = 1, | 208 | * NLM4_DENIED = 1, |
209 | * NLM4_DENIED_NOLOCKS = 2, | 209 | * NLM4_DENIED_NOLOCKS = 2, |
210 | * NLM4_BLOCKED = 3, | 210 | * NLM4_BLOCKED = 3, |
211 | * NLM4_DENIED_GRACE_PERIOD = 4, | 211 | * NLM4_DENIED_GRACE_PERIOD = 4, |
212 | * NLM4_DEADLCK = 5, | 212 | * NLM4_DEADLCK = 5, |
213 | * NLM4_ROFS = 6, | 213 | * NLM4_ROFS = 6, |
214 | * NLM4_STALE_FH = 7, | 214 | * NLM4_STALE_FH = 7, |
215 | * NLM4_FBIG = 8, | 215 | * NLM4_FBIG = 8, |
216 | * NLM4_FAILED = 9 | 216 | * NLM4_FAILED = 9 |
217 | * }; | 217 | * }; |
218 | * | 218 | * |
219 | * struct nlm4_stat { | 219 | * struct nlm4_stat { |
220 | * nlm4_stats stat; | 220 | * nlm4_stats stat; |
221 | * }; | 221 | * }; |
222 | * | 222 | * |
223 | * NB: we don't swap bytes for the NLM status values. The upper | 223 | * NB: we don't swap bytes for the NLM status values. The upper |
224 | * layers deal directly with the status value in network byte | 224 | * layers deal directly with the status value in network byte |
225 | * order. | 225 | * order. |
226 | */ | 226 | */ |
227 | static void encode_nlm4_stat(struct xdr_stream *xdr, | 227 | static void encode_nlm4_stat(struct xdr_stream *xdr, |
228 | const __be32 stat) | 228 | const __be32 stat) |
229 | { | 229 | { |
230 | __be32 *p; | 230 | __be32 *p; |
231 | 231 | ||
232 | BUG_ON(be32_to_cpu(stat) > NLM_FAILED); | 232 | BUG_ON(be32_to_cpu(stat) > NLM_FAILED); |
233 | p = xdr_reserve_space(xdr, 4); | 233 | p = xdr_reserve_space(xdr, 4); |
234 | *p = stat; | 234 | *p = stat; |
235 | } | 235 | } |
236 | 236 | ||
237 | static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat) | 237 | static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat) |
238 | { | 238 | { |
239 | __be32 *p; | 239 | __be32 *p; |
240 | 240 | ||
241 | p = xdr_inline_decode(xdr, 4); | 241 | p = xdr_inline_decode(xdr, 4); |
242 | if (unlikely(p == NULL)) | 242 | if (unlikely(p == NULL)) |
243 | goto out_overflow; | 243 | goto out_overflow; |
244 | if (unlikely(*p > nlm4_failed)) | 244 | if (unlikely(*p > nlm4_failed)) |
245 | goto out_bad_xdr; | 245 | goto out_bad_xdr; |
246 | *stat = *p; | 246 | *stat = *p; |
247 | return 0; | 247 | return 0; |
248 | out_bad_xdr: | 248 | out_bad_xdr: |
249 | dprintk("%s: server returned invalid nlm4_stats value: %u\n", | 249 | dprintk("%s: server returned invalid nlm4_stats value: %u\n", |
250 | __func__, be32_to_cpup(p)); | 250 | __func__, be32_to_cpup(p)); |
251 | return -EIO; | 251 | return -EIO; |
252 | out_overflow: | 252 | out_overflow: |
253 | print_overflow_msg(__func__, xdr); | 253 | print_overflow_msg(__func__, xdr); |
254 | return -EIO; | 254 | return -EIO; |
255 | } | 255 | } |
256 | 256 | ||
257 | /* | 257 | /* |
258 | * struct nlm4_holder { | 258 | * struct nlm4_holder { |
259 | * bool exclusive; | 259 | * bool exclusive; |
260 | * int32 svid; | 260 | * int32 svid; |
261 | * netobj oh; | 261 | * netobj oh; |
262 | * uint64 l_offset; | 262 | * uint64 l_offset; |
263 | * uint64 l_len; | 263 | * uint64 l_len; |
264 | * }; | 264 | * }; |
265 | */ | 265 | */ |
266 | static void encode_nlm4_holder(struct xdr_stream *xdr, | 266 | static void encode_nlm4_holder(struct xdr_stream *xdr, |
267 | const struct nlm_res *result) | 267 | const struct nlm_res *result) |
268 | { | 268 | { |
269 | const struct nlm_lock *lock = &result->lock; | 269 | const struct nlm_lock *lock = &result->lock; |
270 | u64 l_offset, l_len; | 270 | u64 l_offset, l_len; |
271 | __be32 *p; | 271 | __be32 *p; |
272 | 272 | ||
273 | encode_bool(xdr, lock->fl.fl_type == F_RDLCK); | 273 | encode_bool(xdr, lock->fl.fl_type == F_RDLCK); |
274 | encode_int32(xdr, lock->svid); | 274 | encode_int32(xdr, lock->svid); |
275 | encode_netobj(xdr, lock->oh.data, lock->oh.len); | 275 | encode_netobj(xdr, lock->oh.data, lock->oh.len); |
276 | 276 | ||
277 | p = xdr_reserve_space(xdr, 4 + 4); | 277 | p = xdr_reserve_space(xdr, 4 + 4); |
278 | nlm4_compute_offsets(lock, &l_offset, &l_len); | 278 | nlm4_compute_offsets(lock, &l_offset, &l_len); |
279 | p = xdr_encode_hyper(p, l_offset); | 279 | p = xdr_encode_hyper(p, l_offset); |
280 | xdr_encode_hyper(p, l_len); | 280 | xdr_encode_hyper(p, l_len); |
281 | } | 281 | } |
282 | 282 | ||
283 | static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) | 283 | static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) |
284 | { | 284 | { |
285 | struct nlm_lock *lock = &result->lock; | 285 | struct nlm_lock *lock = &result->lock; |
286 | struct file_lock *fl = &lock->fl; | 286 | struct file_lock *fl = &lock->fl; |
287 | u64 l_offset, l_len; | 287 | u64 l_offset, l_len; |
288 | u32 exclusive; | 288 | u32 exclusive; |
289 | int error; | 289 | int error; |
290 | __be32 *p; | 290 | __be32 *p; |
291 | s32 end; | 291 | s32 end; |
292 | 292 | ||
293 | memset(lock, 0, sizeof(*lock)); | 293 | memset(lock, 0, sizeof(*lock)); |
294 | locks_init_lock(fl); | 294 | locks_init_lock(fl); |
295 | 295 | ||
296 | p = xdr_inline_decode(xdr, 4 + 4); | 296 | p = xdr_inline_decode(xdr, 4 + 4); |
297 | if (unlikely(p == NULL)) | 297 | if (unlikely(p == NULL)) |
298 | goto out_overflow; | 298 | goto out_overflow; |
299 | exclusive = be32_to_cpup(p++); | 299 | exclusive = be32_to_cpup(p++); |
300 | lock->svid = be32_to_cpup(p); | 300 | lock->svid = be32_to_cpup(p); |
301 | fl->fl_pid = (pid_t)lock->svid; | 301 | fl->fl_pid = (pid_t)lock->svid; |
302 | 302 | ||
303 | error = decode_netobj(xdr, &lock->oh); | 303 | error = decode_netobj(xdr, &lock->oh); |
304 | if (unlikely(error)) | 304 | if (unlikely(error)) |
305 | goto out; | 305 | goto out; |
306 | 306 | ||
307 | p = xdr_inline_decode(xdr, 8 + 8); | 307 | p = xdr_inline_decode(xdr, 8 + 8); |
308 | if (unlikely(p == NULL)) | 308 | if (unlikely(p == NULL)) |
309 | goto out_overflow; | 309 | goto out_overflow; |
310 | 310 | ||
311 | fl->fl_flags = FL_POSIX; | 311 | fl->fl_flags = FL_POSIX; |
312 | fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; | 312 | fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; |
313 | p = xdr_decode_hyper(p, &l_offset); | 313 | p = xdr_decode_hyper(p, &l_offset); |
314 | xdr_decode_hyper(p, &l_len); | 314 | xdr_decode_hyper(p, &l_len); |
315 | end = l_offset + l_len - 1; | 315 | end = l_offset + l_len - 1; |
316 | 316 | ||
317 | fl->fl_start = (loff_t)l_offset; | 317 | fl->fl_start = (loff_t)l_offset; |
318 | if (l_len == 0 || end < 0) | 318 | if (l_len == 0 || end < 0) |
319 | fl->fl_end = OFFSET_MAX; | 319 | fl->fl_end = OFFSET_MAX; |
320 | else | 320 | else |
321 | fl->fl_end = (loff_t)end; | 321 | fl->fl_end = (loff_t)end; |
322 | error = 0; | 322 | error = 0; |
323 | out: | 323 | out: |
324 | return error; | 324 | return error; |
325 | out_overflow: | 325 | out_overflow: |
326 | print_overflow_msg(__func__, xdr); | 326 | print_overflow_msg(__func__, xdr); |
327 | return -EIO; | 327 | return -EIO; |
328 | } | 328 | } |
329 | 329 | ||
330 | /* | 330 | /* |
331 | * string caller_name<LM_MAXSTRLEN>; | 331 | * string caller_name<LM_MAXSTRLEN>; |
332 | */ | 332 | */ |
333 | static void encode_caller_name(struct xdr_stream *xdr, const char *name) | 333 | static void encode_caller_name(struct xdr_stream *xdr, const char *name) |
334 | { | 334 | { |
335 | /* NB: client-side does not set lock->len */ | 335 | /* NB: client-side does not set lock->len */ |
336 | u32 length = strlen(name); | 336 | u32 length = strlen(name); |
337 | __be32 *p; | 337 | __be32 *p; |
338 | 338 | ||
339 | BUG_ON(length > NLM_MAXSTRLEN); | 339 | BUG_ON(length > NLM_MAXSTRLEN); |
340 | p = xdr_reserve_space(xdr, 4 + length); | 340 | p = xdr_reserve_space(xdr, 4 + length); |
341 | xdr_encode_opaque(p, name, length); | 341 | xdr_encode_opaque(p, name, length); |
342 | } | 342 | } |
343 | 343 | ||
344 | /* | 344 | /* |
345 | * struct nlm4_lock { | 345 | * struct nlm4_lock { |
346 | * string caller_name<LM_MAXSTRLEN>; | 346 | * string caller_name<LM_MAXSTRLEN>; |
347 | * netobj fh; | 347 | * netobj fh; |
348 | * netobj oh; | 348 | * netobj oh; |
349 | * int32 svid; | 349 | * int32 svid; |
350 | * uint64 l_offset; | 350 | * uint64 l_offset; |
351 | * uint64 l_len; | 351 | * uint64 l_len; |
352 | * }; | 352 | * }; |
353 | */ | 353 | */ |
354 | static void encode_nlm4_lock(struct xdr_stream *xdr, | 354 | static void encode_nlm4_lock(struct xdr_stream *xdr, |
355 | const struct nlm_lock *lock) | 355 | const struct nlm_lock *lock) |
356 | { | 356 | { |
357 | u64 l_offset, l_len; | 357 | u64 l_offset, l_len; |
358 | __be32 *p; | 358 | __be32 *p; |
359 | 359 | ||
360 | encode_caller_name(xdr, lock->caller); | 360 | encode_caller_name(xdr, lock->caller); |
361 | encode_fh(xdr, &lock->fh); | 361 | encode_fh(xdr, &lock->fh); |
362 | encode_netobj(xdr, lock->oh.data, lock->oh.len); | 362 | encode_netobj(xdr, lock->oh.data, lock->oh.len); |
363 | 363 | ||
364 | p = xdr_reserve_space(xdr, 4 + 8 + 8); | 364 | p = xdr_reserve_space(xdr, 4 + 8 + 8); |
365 | *p++ = cpu_to_be32(lock->svid); | 365 | *p++ = cpu_to_be32(lock->svid); |
366 | 366 | ||
367 | nlm4_compute_offsets(lock, &l_offset, &l_len); | 367 | nlm4_compute_offsets(lock, &l_offset, &l_len); |
368 | p = xdr_encode_hyper(p, l_offset); | 368 | p = xdr_encode_hyper(p, l_offset); |
369 | xdr_encode_hyper(p, l_len); | 369 | xdr_encode_hyper(p, l_len); |
370 | } | 370 | } |
371 | 371 | ||
372 | 372 | ||
373 | /* | 373 | /* |
374 | * NLMv4 XDR encode functions | 374 | * NLMv4 XDR encode functions |
375 | * | 375 | * |
376 | * NLMv4 argument types are defined in Appendix II of RFC 1813: | 376 | * NLMv4 argument types are defined in Appendix II of RFC 1813: |
377 | * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's | 377 | * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's |
378 | * "Protocols for Interworking: XNFS, Version 3W". | 378 | * "Protocols for Interworking: XNFS, Version 3W". |
379 | */ | 379 | */ |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * struct nlm4_testargs { | 382 | * struct nlm4_testargs { |
383 | * netobj cookie; | 383 | * netobj cookie; |
384 | * bool exclusive; | 384 | * bool exclusive; |
385 | * struct nlm4_lock alock; | 385 | * struct nlm4_lock alock; |
386 | * }; | 386 | * }; |
387 | */ | 387 | */ |
388 | static void nlm4_xdr_enc_testargs(struct rpc_rqst *req, | 388 | static void nlm4_xdr_enc_testargs(struct rpc_rqst *req, |
389 | struct xdr_stream *xdr, | 389 | struct xdr_stream *xdr, |
390 | const struct nlm_args *args) | 390 | const struct nlm_args *args) |
391 | { | 391 | { |
392 | const struct nlm_lock *lock = &args->lock; | 392 | const struct nlm_lock *lock = &args->lock; |
393 | 393 | ||
394 | encode_cookie(xdr, &args->cookie); | 394 | encode_cookie(xdr, &args->cookie); |
395 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); | 395 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); |
396 | encode_nlm4_lock(xdr, lock); | 396 | encode_nlm4_lock(xdr, lock); |
397 | } | 397 | } |
398 | 398 | ||
399 | /* | 399 | /* |
400 | * struct nlm4_lockargs { | 400 | * struct nlm4_lockargs { |
401 | * netobj cookie; | 401 | * netobj cookie; |
402 | * bool block; | 402 | * bool block; |
403 | * bool exclusive; | 403 | * bool exclusive; |
404 | * struct nlm4_lock alock; | 404 | * struct nlm4_lock alock; |
405 | * bool reclaim; | 405 | * bool reclaim; |
406 | * int state; | 406 | * int state; |
407 | * }; | 407 | * }; |
408 | */ | 408 | */ |
409 | static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req, | 409 | static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req, |
410 | struct xdr_stream *xdr, | 410 | struct xdr_stream *xdr, |
411 | const struct nlm_args *args) | 411 | const struct nlm_args *args) |
412 | { | 412 | { |
413 | const struct nlm_lock *lock = &args->lock; | 413 | const struct nlm_lock *lock = &args->lock; |
414 | 414 | ||
415 | encode_cookie(xdr, &args->cookie); | 415 | encode_cookie(xdr, &args->cookie); |
416 | encode_bool(xdr, args->block); | 416 | encode_bool(xdr, args->block); |
417 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); | 417 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); |
418 | encode_nlm4_lock(xdr, lock); | 418 | encode_nlm4_lock(xdr, lock); |
419 | encode_bool(xdr, args->reclaim); | 419 | encode_bool(xdr, args->reclaim); |
420 | encode_int32(xdr, args->state); | 420 | encode_int32(xdr, args->state); |
421 | } | 421 | } |
422 | 422 | ||
423 | /* | 423 | /* |
424 | * struct nlm4_cancargs { | 424 | * struct nlm4_cancargs { |
425 | * netobj cookie; | 425 | * netobj cookie; |
426 | * bool block; | 426 | * bool block; |
427 | * bool exclusive; | 427 | * bool exclusive; |
428 | * struct nlm4_lock alock; | 428 | * struct nlm4_lock alock; |
429 | * }; | 429 | * }; |
430 | */ | 430 | */ |
431 | static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req, | 431 | static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req, |
432 | struct xdr_stream *xdr, | 432 | struct xdr_stream *xdr, |
433 | const struct nlm_args *args) | 433 | const struct nlm_args *args) |
434 | { | 434 | { |
435 | const struct nlm_lock *lock = &args->lock; | 435 | const struct nlm_lock *lock = &args->lock; |
436 | 436 | ||
437 | encode_cookie(xdr, &args->cookie); | 437 | encode_cookie(xdr, &args->cookie); |
438 | encode_bool(xdr, args->block); | 438 | encode_bool(xdr, args->block); |
439 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); | 439 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); |
440 | encode_nlm4_lock(xdr, lock); | 440 | encode_nlm4_lock(xdr, lock); |
441 | } | 441 | } |
442 | 442 | ||
443 | /* | 443 | /* |
444 | * struct nlm4_unlockargs { | 444 | * struct nlm4_unlockargs { |
445 | * netobj cookie; | 445 | * netobj cookie; |
446 | * struct nlm4_lock alock; | 446 | * struct nlm4_lock alock; |
447 | * }; | 447 | * }; |
448 | */ | 448 | */ |
449 | static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req, | 449 | static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req, |
450 | struct xdr_stream *xdr, | 450 | struct xdr_stream *xdr, |
451 | const struct nlm_args *args) | 451 | const struct nlm_args *args) |
452 | { | 452 | { |
453 | const struct nlm_lock *lock = &args->lock; | 453 | const struct nlm_lock *lock = &args->lock; |
454 | 454 | ||
455 | encode_cookie(xdr, &args->cookie); | 455 | encode_cookie(xdr, &args->cookie); |
456 | encode_nlm4_lock(xdr, lock); | 456 | encode_nlm4_lock(xdr, lock); |
457 | } | 457 | } |
458 | 458 | ||
459 | /* | 459 | /* |
460 | * struct nlm4_res { | 460 | * struct nlm4_res { |
461 | * netobj cookie; | 461 | * netobj cookie; |
462 | * nlm4_stat stat; | 462 | * nlm4_stat stat; |
463 | * }; | 463 | * }; |
464 | */ | 464 | */ |
465 | static void nlm4_xdr_enc_res(struct rpc_rqst *req, | 465 | static void nlm4_xdr_enc_res(struct rpc_rqst *req, |
466 | struct xdr_stream *xdr, | 466 | struct xdr_stream *xdr, |
467 | const struct nlm_res *result) | 467 | const struct nlm_res *result) |
468 | { | 468 | { |
469 | encode_cookie(xdr, &result->cookie); | 469 | encode_cookie(xdr, &result->cookie); |
470 | encode_nlm4_stat(xdr, result->status); | 470 | encode_nlm4_stat(xdr, result->status); |
471 | } | 471 | } |
472 | 472 | ||
473 | /* | 473 | /* |
474 | * union nlm4_testrply switch (nlm4_stats stat) { | 474 | * union nlm4_testrply switch (nlm4_stats stat) { |
475 | * case NLM4_DENIED: | 475 | * case NLM4_DENIED: |
476 | * struct nlm4_holder holder; | 476 | * struct nlm4_holder holder; |
477 | * default: | 477 | * default: |
478 | * void; | 478 | * void; |
479 | * }; | 479 | * }; |
480 | * | 480 | * |
481 | * struct nlm4_testres { | 481 | * struct nlm4_testres { |
482 | * netobj cookie; | 482 | * netobj cookie; |
483 | * nlm4_testrply test_stat; | 483 | * nlm4_testrply test_stat; |
484 | * }; | 484 | * }; |
485 | */ | 485 | */ |
486 | static void nlm4_xdr_enc_testres(struct rpc_rqst *req, | 486 | static void nlm4_xdr_enc_testres(struct rpc_rqst *req, |
487 | struct xdr_stream *xdr, | 487 | struct xdr_stream *xdr, |
488 | const struct nlm_res *result) | 488 | const struct nlm_res *result) |
489 | { | 489 | { |
490 | encode_cookie(xdr, &result->cookie); | 490 | encode_cookie(xdr, &result->cookie); |
491 | encode_nlm4_stat(xdr, result->status); | 491 | encode_nlm4_stat(xdr, result->status); |
492 | if (result->status == nlm_lck_denied) | 492 | if (result->status == nlm_lck_denied) |
493 | encode_nlm4_holder(xdr, result); | 493 | encode_nlm4_holder(xdr, result); |
494 | } | 494 | } |
495 | 495 | ||
496 | 496 | ||
497 | /* | 497 | /* |
498 | * NLMv4 XDR decode functions | 498 | * NLMv4 XDR decode functions |
499 | * | 499 | * |
500 | * NLMv4 argument types are defined in Appendix II of RFC 1813: | 500 | * NLMv4 argument types are defined in Appendix II of RFC 1813: |
501 | * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's | 501 | * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's |
502 | * "Protocols for Interworking: XNFS, Version 3W". | 502 | * "Protocols for Interworking: XNFS, Version 3W". |
503 | */ | 503 | */ |
504 | 504 | ||
505 | /* | 505 | /* |
506 | * union nlm4_testrply switch (nlm4_stats stat) { | 506 | * union nlm4_testrply switch (nlm4_stats stat) { |
507 | * case NLM4_DENIED: | 507 | * case NLM4_DENIED: |
508 | * struct nlm4_holder holder; | 508 | * struct nlm4_holder holder; |
509 | * default: | 509 | * default: |
510 | * void; | 510 | * void; |
511 | * }; | 511 | * }; |
512 | * | 512 | * |
513 | * struct nlm4_testres { | 513 | * struct nlm4_testres { |
514 | * netobj cookie; | 514 | * netobj cookie; |
515 | * nlm4_testrply test_stat; | 515 | * nlm4_testrply test_stat; |
516 | * }; | 516 | * }; |
517 | */ | 517 | */ |
518 | static int decode_nlm4_testrply(struct xdr_stream *xdr, | 518 | static int decode_nlm4_testrply(struct xdr_stream *xdr, |
519 | struct nlm_res *result) | 519 | struct nlm_res *result) |
520 | { | 520 | { |
521 | int error; | 521 | int error; |
522 | 522 | ||
523 | error = decode_nlm4_stat(xdr, &result->status); | 523 | error = decode_nlm4_stat(xdr, &result->status); |
524 | if (unlikely(error)) | 524 | if (unlikely(error)) |
525 | goto out; | 525 | goto out; |
526 | if (result->status == nlm_lck_denied) | 526 | if (result->status == nlm_lck_denied) |
527 | error = decode_nlm4_holder(xdr, result); | 527 | error = decode_nlm4_holder(xdr, result); |
528 | out: | 528 | out: |
529 | return error; | 529 | return error; |
530 | } | 530 | } |
531 | 531 | ||
532 | static int nlm4_xdr_dec_testres(struct rpc_rqst *req, | 532 | static int nlm4_xdr_dec_testres(struct rpc_rqst *req, |
533 | struct xdr_stream *xdr, | 533 | struct xdr_stream *xdr, |
534 | struct nlm_res *result) | 534 | struct nlm_res *result) |
535 | { | 535 | { |
536 | int error; | 536 | int error; |
537 | 537 | ||
538 | error = decode_cookie(xdr, &result->cookie); | 538 | error = decode_cookie(xdr, &result->cookie); |
539 | if (unlikely(error)) | 539 | if (unlikely(error)) |
540 | goto out; | 540 | goto out; |
541 | error = decode_nlm4_testrply(xdr, result); | 541 | error = decode_nlm4_testrply(xdr, result); |
542 | out: | 542 | out: |
543 | return error; | 543 | return error; |
544 | } | 544 | } |
545 | 545 | ||
546 | /* | 546 | /* |
547 | * struct nlm4_res { | 547 | * struct nlm4_res { |
548 | * netobj cookie; | 548 | * netobj cookie; |
549 | * nlm4_stat stat; | 549 | * nlm4_stat stat; |
550 | * }; | 550 | * }; |
551 | */ | 551 | */ |
552 | static int nlm4_xdr_dec_res(struct rpc_rqst *req, | 552 | static int nlm4_xdr_dec_res(struct rpc_rqst *req, |
553 | struct xdr_stream *xdr, | 553 | struct xdr_stream *xdr, |
554 | struct nlm_res *result) | 554 | struct nlm_res *result) |
555 | { | 555 | { |
556 | int error; | 556 | int error; |
557 | 557 | ||
558 | error = decode_cookie(xdr, &result->cookie); | 558 | error = decode_cookie(xdr, &result->cookie); |
559 | if (unlikely(error)) | 559 | if (unlikely(error)) |
560 | goto out; | 560 | goto out; |
561 | error = decode_nlm4_stat(xdr, &result->status); | 561 | error = decode_nlm4_stat(xdr, &result->status); |
562 | out: | 562 | out: |
563 | return error; | 563 | return error; |
564 | } | 564 | } |
565 | 565 | ||
566 | 566 | ||
567 | /* | 567 | /* |
568 | * For NLM, a void procedure really returns nothing | 568 | * For NLM, a void procedure really returns nothing |
569 | */ | 569 | */ |
570 | #define nlm4_xdr_dec_norep NULL | 570 | #define nlm4_xdr_dec_norep NULL |
571 | 571 | ||
572 | #define PROC(proc, argtype, restype) \ | 572 | #define PROC(proc, argtype, restype) \ |
573 | [NLMPROC_##proc] = { \ | 573 | [NLMPROC_##proc] = { \ |
574 | .p_proc = NLMPROC_##proc, \ | 574 | .p_proc = NLMPROC_##proc, \ |
575 | .p_encode = (kxdreproc_t)nlm4_xdr_enc_##argtype, \ | 575 | .p_encode = (kxdreproc_t)nlm4_xdr_enc_##argtype, \ |
576 | .p_decode = (kxdrdproc_t)nlm4_xdr_dec_##restype, \ | 576 | .p_decode = (kxdrdproc_t)nlm4_xdr_dec_##restype, \ |
577 | .p_arglen = NLM4_##argtype##_sz, \ | 577 | .p_arglen = NLM4_##argtype##_sz, \ |
578 | .p_replen = NLM4_##restype##_sz, \ | 578 | .p_replen = NLM4_##restype##_sz, \ |
579 | .p_statidx = NLMPROC_##proc, \ | 579 | .p_statidx = NLMPROC_##proc, \ |
580 | .p_name = #proc, \ | 580 | .p_name = #proc, \ |
581 | } | 581 | } |
582 | 582 | ||
583 | static struct rpc_procinfo nlm4_procedures[] = { | 583 | static struct rpc_procinfo nlm4_procedures[] = { |
584 | PROC(TEST, testargs, testres), | 584 | PROC(TEST, testargs, testres), |
585 | PROC(LOCK, lockargs, res), | 585 | PROC(LOCK, lockargs, res), |
586 | PROC(CANCEL, cancargs, res), | 586 | PROC(CANCEL, cancargs, res), |
587 | PROC(UNLOCK, unlockargs, res), | 587 | PROC(UNLOCK, unlockargs, res), |
588 | PROC(GRANTED, testargs, res), | 588 | PROC(GRANTED, testargs, res), |
589 | PROC(TEST_MSG, testargs, norep), | 589 | PROC(TEST_MSG, testargs, norep), |
590 | PROC(LOCK_MSG, lockargs, norep), | 590 | PROC(LOCK_MSG, lockargs, norep), |
591 | PROC(CANCEL_MSG, cancargs, norep), | 591 | PROC(CANCEL_MSG, cancargs, norep), |
592 | PROC(UNLOCK_MSG, unlockargs, norep), | 592 | PROC(UNLOCK_MSG, unlockargs, norep), |
593 | PROC(GRANTED_MSG, testargs, norep), | 593 | PROC(GRANTED_MSG, testargs, norep), |
594 | PROC(TEST_RES, testres, norep), | 594 | PROC(TEST_RES, testres, norep), |
595 | PROC(LOCK_RES, res, norep), | 595 | PROC(LOCK_RES, res, norep), |
596 | PROC(CANCEL_RES, res, norep), | 596 | PROC(CANCEL_RES, res, norep), |
597 | PROC(UNLOCK_RES, res, norep), | 597 | PROC(UNLOCK_RES, res, norep), |
598 | PROC(GRANTED_RES, res, norep), | 598 | PROC(GRANTED_RES, res, norep), |
599 | }; | 599 | }; |
600 | 600 | ||
601 | struct rpc_version nlm_version4 = { | 601 | const struct rpc_version nlm_version4 = { |
602 | .number = 4, | 602 | .number = 4, |
603 | .nrprocs = ARRAY_SIZE(nlm4_procedures), | 603 | .nrprocs = ARRAY_SIZE(nlm4_procedures), |
604 | .procs = nlm4_procedures, | 604 | .procs = nlm4_procedures, |
605 | }; | 605 | }; |
606 | 606 |
fs/lockd/clntxdr.c
1 | /* | 1 | /* |
2 | * linux/fs/lockd/clntxdr.c | 2 | * linux/fs/lockd/clntxdr.c |
3 | * | 3 | * |
4 | * XDR functions to encode/decode NLM version 3 RPC arguments and results. | 4 | * XDR functions to encode/decode NLM version 3 RPC arguments and results. |
5 | * NLM version 3 is backwards compatible with NLM versions 1 and 2. | 5 | * NLM version 3 is backwards compatible with NLM versions 1 and 2. |
6 | * | 6 | * |
7 | * NLM client-side only. | 7 | * NLM client-side only. |
8 | * | 8 | * |
9 | * Copyright (C) 2010, Oracle. All rights reserved. | 9 | * Copyright (C) 2010, Oracle. All rights reserved. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/sunrpc/xdr.h> | 13 | #include <linux/sunrpc/xdr.h> |
14 | #include <linux/sunrpc/clnt.h> | 14 | #include <linux/sunrpc/clnt.h> |
15 | #include <linux/sunrpc/stats.h> | 15 | #include <linux/sunrpc/stats.h> |
16 | #include <linux/lockd/lockd.h> | 16 | #include <linux/lockd/lockd.h> |
17 | 17 | ||
18 | #define NLMDBG_FACILITY NLMDBG_XDR | 18 | #define NLMDBG_FACILITY NLMDBG_XDR |
19 | 19 | ||
20 | #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) | 20 | #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) |
21 | # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" | 21 | # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * Declare the space requirements for NLM arguments and replies as | 25 | * Declare the space requirements for NLM arguments and replies as |
26 | * number of 32bit-words | 26 | * number of 32bit-words |
27 | */ | 27 | */ |
28 | #define NLM_cookie_sz (1+(NLM_MAXCOOKIELEN>>2)) | 28 | #define NLM_cookie_sz (1+(NLM_MAXCOOKIELEN>>2)) |
29 | #define NLM_caller_sz (1+(NLMCLNT_OHSIZE>>2)) | 29 | #define NLM_caller_sz (1+(NLMCLNT_OHSIZE>>2)) |
30 | #define NLM_owner_sz (1+(NLMCLNT_OHSIZE>>2)) | 30 | #define NLM_owner_sz (1+(NLMCLNT_OHSIZE>>2)) |
31 | #define NLM_fhandle_sz (1+(NFS2_FHSIZE>>2)) | 31 | #define NLM_fhandle_sz (1+(NFS2_FHSIZE>>2)) |
32 | #define NLM_lock_sz (3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz) | 32 | #define NLM_lock_sz (3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz) |
33 | #define NLM_holder_sz (4+NLM_owner_sz) | 33 | #define NLM_holder_sz (4+NLM_owner_sz) |
34 | 34 | ||
35 | #define NLM_testargs_sz (NLM_cookie_sz+1+NLM_lock_sz) | 35 | #define NLM_testargs_sz (NLM_cookie_sz+1+NLM_lock_sz) |
36 | #define NLM_lockargs_sz (NLM_cookie_sz+4+NLM_lock_sz) | 36 | #define NLM_lockargs_sz (NLM_cookie_sz+4+NLM_lock_sz) |
37 | #define NLM_cancargs_sz (NLM_cookie_sz+2+NLM_lock_sz) | 37 | #define NLM_cancargs_sz (NLM_cookie_sz+2+NLM_lock_sz) |
38 | #define NLM_unlockargs_sz (NLM_cookie_sz+NLM_lock_sz) | 38 | #define NLM_unlockargs_sz (NLM_cookie_sz+NLM_lock_sz) |
39 | 39 | ||
40 | #define NLM_testres_sz (NLM_cookie_sz+1+NLM_holder_sz) | 40 | #define NLM_testres_sz (NLM_cookie_sz+1+NLM_holder_sz) |
41 | #define NLM_res_sz (NLM_cookie_sz+1) | 41 | #define NLM_res_sz (NLM_cookie_sz+1) |
42 | #define NLM_norep_sz (0) | 42 | #define NLM_norep_sz (0) |
43 | 43 | ||
44 | 44 | ||
45 | static s32 loff_t_to_s32(loff_t offset) | 45 | static s32 loff_t_to_s32(loff_t offset) |
46 | { | 46 | { |
47 | s32 res; | 47 | s32 res; |
48 | 48 | ||
49 | if (offset >= NLM_OFFSET_MAX) | 49 | if (offset >= NLM_OFFSET_MAX) |
50 | res = NLM_OFFSET_MAX; | 50 | res = NLM_OFFSET_MAX; |
51 | else if (offset <= -NLM_OFFSET_MAX) | 51 | else if (offset <= -NLM_OFFSET_MAX) |
52 | res = -NLM_OFFSET_MAX; | 52 | res = -NLM_OFFSET_MAX; |
53 | else | 53 | else |
54 | res = offset; | 54 | res = offset; |
55 | return res; | 55 | return res; |
56 | } | 56 | } |
57 | 57 | ||
58 | static void nlm_compute_offsets(const struct nlm_lock *lock, | 58 | static void nlm_compute_offsets(const struct nlm_lock *lock, |
59 | u32 *l_offset, u32 *l_len) | 59 | u32 *l_offset, u32 *l_len) |
60 | { | 60 | { |
61 | const struct file_lock *fl = &lock->fl; | 61 | const struct file_lock *fl = &lock->fl; |
62 | 62 | ||
63 | BUG_ON(fl->fl_start > NLM_OFFSET_MAX); | 63 | BUG_ON(fl->fl_start > NLM_OFFSET_MAX); |
64 | BUG_ON(fl->fl_end > NLM_OFFSET_MAX && | 64 | BUG_ON(fl->fl_end > NLM_OFFSET_MAX && |
65 | fl->fl_end != OFFSET_MAX); | 65 | fl->fl_end != OFFSET_MAX); |
66 | 66 | ||
67 | *l_offset = loff_t_to_s32(fl->fl_start); | 67 | *l_offset = loff_t_to_s32(fl->fl_start); |
68 | if (fl->fl_end == OFFSET_MAX) | 68 | if (fl->fl_end == OFFSET_MAX) |
69 | *l_len = 0; | 69 | *l_len = 0; |
70 | else | 70 | else |
71 | *l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); | 71 | *l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); |
72 | } | 72 | } |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * Handle decode buffer overflows out-of-line. | 75 | * Handle decode buffer overflows out-of-line. |
76 | */ | 76 | */ |
77 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 77 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
78 | { | 78 | { |
79 | dprintk("lockd: %s prematurely hit the end of our receive buffer. " | 79 | dprintk("lockd: %s prematurely hit the end of our receive buffer. " |
80 | "Remaining buffer length is %tu words.\n", | 80 | "Remaining buffer length is %tu words.\n", |
81 | func, xdr->end - xdr->p); | 81 | func, xdr->end - xdr->p); |
82 | } | 82 | } |
83 | 83 | ||
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Encode/decode NLMv3 basic data types | 86 | * Encode/decode NLMv3 basic data types |
87 | * | 87 | * |
88 | * Basic NLMv3 data types are not defined in an IETF standards | 88 | * Basic NLMv3 data types are not defined in an IETF standards |
89 | * document. X/Open has a description of these data types that | 89 | * document. X/Open has a description of these data types that |
90 | * is useful. See Chapter 10 of "Protocols for Interworking: | 90 | * is useful. See Chapter 10 of "Protocols for Interworking: |
91 | * XNFS, Version 3W". | 91 | * XNFS, Version 3W". |
92 | * | 92 | * |
93 | * Not all basic data types have their own encoding and decoding | 93 | * Not all basic data types have their own encoding and decoding |
94 | * functions. For run-time efficiency, some data types are encoded | 94 | * functions. For run-time efficiency, some data types are encoded |
95 | * or decoded inline. | 95 | * or decoded inline. |
96 | */ | 96 | */ |
97 | 97 | ||
98 | static void encode_bool(struct xdr_stream *xdr, const int value) | 98 | static void encode_bool(struct xdr_stream *xdr, const int value) |
99 | { | 99 | { |
100 | __be32 *p; | 100 | __be32 *p; |
101 | 101 | ||
102 | p = xdr_reserve_space(xdr, 4); | 102 | p = xdr_reserve_space(xdr, 4); |
103 | *p = value ? xdr_one : xdr_zero; | 103 | *p = value ? xdr_one : xdr_zero; |
104 | } | 104 | } |
105 | 105 | ||
106 | static void encode_int32(struct xdr_stream *xdr, const s32 value) | 106 | static void encode_int32(struct xdr_stream *xdr, const s32 value) |
107 | { | 107 | { |
108 | __be32 *p; | 108 | __be32 *p; |
109 | 109 | ||
110 | p = xdr_reserve_space(xdr, 4); | 110 | p = xdr_reserve_space(xdr, 4); |
111 | *p = cpu_to_be32(value); | 111 | *p = cpu_to_be32(value); |
112 | } | 112 | } |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * typedef opaque netobj<MAXNETOBJ_SZ> | 115 | * typedef opaque netobj<MAXNETOBJ_SZ> |
116 | */ | 116 | */ |
117 | static void encode_netobj(struct xdr_stream *xdr, | 117 | static void encode_netobj(struct xdr_stream *xdr, |
118 | const u8 *data, const unsigned int length) | 118 | const u8 *data, const unsigned int length) |
119 | { | 119 | { |
120 | __be32 *p; | 120 | __be32 *p; |
121 | 121 | ||
122 | BUG_ON(length > XDR_MAX_NETOBJ); | 122 | BUG_ON(length > XDR_MAX_NETOBJ); |
123 | p = xdr_reserve_space(xdr, 4 + length); | 123 | p = xdr_reserve_space(xdr, 4 + length); |
124 | xdr_encode_opaque(p, data, length); | 124 | xdr_encode_opaque(p, data, length); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int decode_netobj(struct xdr_stream *xdr, | 127 | static int decode_netobj(struct xdr_stream *xdr, |
128 | struct xdr_netobj *obj) | 128 | struct xdr_netobj *obj) |
129 | { | 129 | { |
130 | u32 length; | 130 | u32 length; |
131 | __be32 *p; | 131 | __be32 *p; |
132 | 132 | ||
133 | p = xdr_inline_decode(xdr, 4); | 133 | p = xdr_inline_decode(xdr, 4); |
134 | if (unlikely(p == NULL)) | 134 | if (unlikely(p == NULL)) |
135 | goto out_overflow; | 135 | goto out_overflow; |
136 | length = be32_to_cpup(p++); | 136 | length = be32_to_cpup(p++); |
137 | if (unlikely(length > XDR_MAX_NETOBJ)) | 137 | if (unlikely(length > XDR_MAX_NETOBJ)) |
138 | goto out_size; | 138 | goto out_size; |
139 | obj->len = length; | 139 | obj->len = length; |
140 | obj->data = (u8 *)p; | 140 | obj->data = (u8 *)p; |
141 | return 0; | 141 | return 0; |
142 | out_size: | 142 | out_size: |
143 | dprintk("NFS: returned netobj was too long: %u\n", length); | 143 | dprintk("NFS: returned netobj was too long: %u\n", length); |
144 | return -EIO; | 144 | return -EIO; |
145 | out_overflow: | 145 | out_overflow: |
146 | print_overflow_msg(__func__, xdr); | 146 | print_overflow_msg(__func__, xdr); |
147 | return -EIO; | 147 | return -EIO; |
148 | } | 148 | } |
149 | 149 | ||
150 | /* | 150 | /* |
151 | * netobj cookie; | 151 | * netobj cookie; |
152 | */ | 152 | */ |
153 | static void encode_cookie(struct xdr_stream *xdr, | 153 | static void encode_cookie(struct xdr_stream *xdr, |
154 | const struct nlm_cookie *cookie) | 154 | const struct nlm_cookie *cookie) |
155 | { | 155 | { |
156 | BUG_ON(cookie->len > NLM_MAXCOOKIELEN); | 156 | BUG_ON(cookie->len > NLM_MAXCOOKIELEN); |
157 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); | 157 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); |
158 | } | 158 | } |
159 | 159 | ||
160 | static int decode_cookie(struct xdr_stream *xdr, | 160 | static int decode_cookie(struct xdr_stream *xdr, |
161 | struct nlm_cookie *cookie) | 161 | struct nlm_cookie *cookie) |
162 | { | 162 | { |
163 | u32 length; | 163 | u32 length; |
164 | __be32 *p; | 164 | __be32 *p; |
165 | 165 | ||
166 | p = xdr_inline_decode(xdr, 4); | 166 | p = xdr_inline_decode(xdr, 4); |
167 | if (unlikely(p == NULL)) | 167 | if (unlikely(p == NULL)) |
168 | goto out_overflow; | 168 | goto out_overflow; |
169 | length = be32_to_cpup(p++); | 169 | length = be32_to_cpup(p++); |
170 | /* apparently HPUX can return empty cookies */ | 170 | /* apparently HPUX can return empty cookies */ |
171 | if (length == 0) | 171 | if (length == 0) |
172 | goto out_hpux; | 172 | goto out_hpux; |
173 | if (length > NLM_MAXCOOKIELEN) | 173 | if (length > NLM_MAXCOOKIELEN) |
174 | goto out_size; | 174 | goto out_size; |
175 | p = xdr_inline_decode(xdr, length); | 175 | p = xdr_inline_decode(xdr, length); |
176 | if (unlikely(p == NULL)) | 176 | if (unlikely(p == NULL)) |
177 | goto out_overflow; | 177 | goto out_overflow; |
178 | cookie->len = length; | 178 | cookie->len = length; |
179 | memcpy(cookie->data, p, length); | 179 | memcpy(cookie->data, p, length); |
180 | return 0; | 180 | return 0; |
181 | out_hpux: | 181 | out_hpux: |
182 | cookie->len = 4; | 182 | cookie->len = 4; |
183 | memset(cookie->data, 0, 4); | 183 | memset(cookie->data, 0, 4); |
184 | return 0; | 184 | return 0; |
185 | out_size: | 185 | out_size: |
186 | dprintk("NFS: returned cookie was too long: %u\n", length); | 186 | dprintk("NFS: returned cookie was too long: %u\n", length); |
187 | return -EIO; | 187 | return -EIO; |
188 | out_overflow: | 188 | out_overflow: |
189 | print_overflow_msg(__func__, xdr); | 189 | print_overflow_msg(__func__, xdr); |
190 | return -EIO; | 190 | return -EIO; |
191 | } | 191 | } |
192 | 192 | ||
193 | /* | 193 | /* |
194 | * netobj fh; | 194 | * netobj fh; |
195 | */ | 195 | */ |
196 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) | 196 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) |
197 | { | 197 | { |
198 | BUG_ON(fh->size != NFS2_FHSIZE); | 198 | BUG_ON(fh->size != NFS2_FHSIZE); |
199 | encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE); | 199 | encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE); |
200 | } | 200 | } |
201 | 201 | ||
202 | /* | 202 | /* |
203 | * enum nlm_stats { | 203 | * enum nlm_stats { |
204 | * LCK_GRANTED = 0, | 204 | * LCK_GRANTED = 0, |
205 | * LCK_DENIED = 1, | 205 | * LCK_DENIED = 1, |
206 | * LCK_DENIED_NOLOCKS = 2, | 206 | * LCK_DENIED_NOLOCKS = 2, |
207 | * LCK_BLOCKED = 3, | 207 | * LCK_BLOCKED = 3, |
208 | * LCK_DENIED_GRACE_PERIOD = 4 | 208 | * LCK_DENIED_GRACE_PERIOD = 4 |
209 | * }; | 209 | * }; |
210 | * | 210 | * |
211 | * | 211 | * |
212 | * struct nlm_stat { | 212 | * struct nlm_stat { |
213 | * nlm_stats stat; | 213 | * nlm_stats stat; |
214 | * }; | 214 | * }; |
215 | * | 215 | * |
216 | * NB: we don't swap bytes for the NLM status values. The upper | 216 | * NB: we don't swap bytes for the NLM status values. The upper |
217 | * layers deal directly with the status value in network byte | 217 | * layers deal directly with the status value in network byte |
218 | * order. | 218 | * order. |
219 | */ | 219 | */ |
220 | 220 | ||
221 | static void encode_nlm_stat(struct xdr_stream *xdr, | 221 | static void encode_nlm_stat(struct xdr_stream *xdr, |
222 | const __be32 stat) | 222 | const __be32 stat) |
223 | { | 223 | { |
224 | __be32 *p; | 224 | __be32 *p; |
225 | 225 | ||
226 | BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); | 226 | BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); |
227 | p = xdr_reserve_space(xdr, 4); | 227 | p = xdr_reserve_space(xdr, 4); |
228 | *p = stat; | 228 | *p = stat; |
229 | } | 229 | } |
230 | 230 | ||
231 | static int decode_nlm_stat(struct xdr_stream *xdr, | 231 | static int decode_nlm_stat(struct xdr_stream *xdr, |
232 | __be32 *stat) | 232 | __be32 *stat) |
233 | { | 233 | { |
234 | __be32 *p; | 234 | __be32 *p; |
235 | 235 | ||
236 | p = xdr_inline_decode(xdr, 4); | 236 | p = xdr_inline_decode(xdr, 4); |
237 | if (unlikely(p == NULL)) | 237 | if (unlikely(p == NULL)) |
238 | goto out_overflow; | 238 | goto out_overflow; |
239 | if (unlikely(*p > nlm_lck_denied_grace_period)) | 239 | if (unlikely(*p > nlm_lck_denied_grace_period)) |
240 | goto out_enum; | 240 | goto out_enum; |
241 | *stat = *p; | 241 | *stat = *p; |
242 | return 0; | 242 | return 0; |
243 | out_enum: | 243 | out_enum: |
244 | dprintk("%s: server returned invalid nlm_stats value: %u\n", | 244 | dprintk("%s: server returned invalid nlm_stats value: %u\n", |
245 | __func__, be32_to_cpup(p)); | 245 | __func__, be32_to_cpup(p)); |
246 | return -EIO; | 246 | return -EIO; |
247 | out_overflow: | 247 | out_overflow: |
248 | print_overflow_msg(__func__, xdr); | 248 | print_overflow_msg(__func__, xdr); |
249 | return -EIO; | 249 | return -EIO; |
250 | } | 250 | } |
251 | 251 | ||
252 | /* | 252 | /* |
253 | * struct nlm_holder { | 253 | * struct nlm_holder { |
254 | * bool exclusive; | 254 | * bool exclusive; |
255 | * int uppid; | 255 | * int uppid; |
256 | * netobj oh; | 256 | * netobj oh; |
257 | * unsigned l_offset; | 257 | * unsigned l_offset; |
258 | * unsigned l_len; | 258 | * unsigned l_len; |
259 | * }; | 259 | * }; |
260 | */ | 260 | */ |
261 | static void encode_nlm_holder(struct xdr_stream *xdr, | 261 | static void encode_nlm_holder(struct xdr_stream *xdr, |
262 | const struct nlm_res *result) | 262 | const struct nlm_res *result) |
263 | { | 263 | { |
264 | const struct nlm_lock *lock = &result->lock; | 264 | const struct nlm_lock *lock = &result->lock; |
265 | u32 l_offset, l_len; | 265 | u32 l_offset, l_len; |
266 | __be32 *p; | 266 | __be32 *p; |
267 | 267 | ||
268 | encode_bool(xdr, lock->fl.fl_type == F_RDLCK); | 268 | encode_bool(xdr, lock->fl.fl_type == F_RDLCK); |
269 | encode_int32(xdr, lock->svid); | 269 | encode_int32(xdr, lock->svid); |
270 | encode_netobj(xdr, lock->oh.data, lock->oh.len); | 270 | encode_netobj(xdr, lock->oh.data, lock->oh.len); |
271 | 271 | ||
272 | p = xdr_reserve_space(xdr, 4 + 4); | 272 | p = xdr_reserve_space(xdr, 4 + 4); |
273 | nlm_compute_offsets(lock, &l_offset, &l_len); | 273 | nlm_compute_offsets(lock, &l_offset, &l_len); |
274 | *p++ = cpu_to_be32(l_offset); | 274 | *p++ = cpu_to_be32(l_offset); |
275 | *p = cpu_to_be32(l_len); | 275 | *p = cpu_to_be32(l_len); |
276 | } | 276 | } |
277 | 277 | ||
278 | static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result) | 278 | static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result) |
279 | { | 279 | { |
280 | struct nlm_lock *lock = &result->lock; | 280 | struct nlm_lock *lock = &result->lock; |
281 | struct file_lock *fl = &lock->fl; | 281 | struct file_lock *fl = &lock->fl; |
282 | u32 exclusive, l_offset, l_len; | 282 | u32 exclusive, l_offset, l_len; |
283 | int error; | 283 | int error; |
284 | __be32 *p; | 284 | __be32 *p; |
285 | s32 end; | 285 | s32 end; |
286 | 286 | ||
287 | memset(lock, 0, sizeof(*lock)); | 287 | memset(lock, 0, sizeof(*lock)); |
288 | locks_init_lock(fl); | 288 | locks_init_lock(fl); |
289 | 289 | ||
290 | p = xdr_inline_decode(xdr, 4 + 4); | 290 | p = xdr_inline_decode(xdr, 4 + 4); |
291 | if (unlikely(p == NULL)) | 291 | if (unlikely(p == NULL)) |
292 | goto out_overflow; | 292 | goto out_overflow; |
293 | exclusive = be32_to_cpup(p++); | 293 | exclusive = be32_to_cpup(p++); |
294 | lock->svid = be32_to_cpup(p); | 294 | lock->svid = be32_to_cpup(p); |
295 | fl->fl_pid = (pid_t)lock->svid; | 295 | fl->fl_pid = (pid_t)lock->svid; |
296 | 296 | ||
297 | error = decode_netobj(xdr, &lock->oh); | 297 | error = decode_netobj(xdr, &lock->oh); |
298 | if (unlikely(error)) | 298 | if (unlikely(error)) |
299 | goto out; | 299 | goto out; |
300 | 300 | ||
301 | p = xdr_inline_decode(xdr, 4 + 4); | 301 | p = xdr_inline_decode(xdr, 4 + 4); |
302 | if (unlikely(p == NULL)) | 302 | if (unlikely(p == NULL)) |
303 | goto out_overflow; | 303 | goto out_overflow; |
304 | 304 | ||
305 | fl->fl_flags = FL_POSIX; | 305 | fl->fl_flags = FL_POSIX; |
306 | fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; | 306 | fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; |
307 | l_offset = be32_to_cpup(p++); | 307 | l_offset = be32_to_cpup(p++); |
308 | l_len = be32_to_cpup(p); | 308 | l_len = be32_to_cpup(p); |
309 | end = l_offset + l_len - 1; | 309 | end = l_offset + l_len - 1; |
310 | 310 | ||
311 | fl->fl_start = (loff_t)l_offset; | 311 | fl->fl_start = (loff_t)l_offset; |
312 | if (l_len == 0 || end < 0) | 312 | if (l_len == 0 || end < 0) |
313 | fl->fl_end = OFFSET_MAX; | 313 | fl->fl_end = OFFSET_MAX; |
314 | else | 314 | else |
315 | fl->fl_end = (loff_t)end; | 315 | fl->fl_end = (loff_t)end; |
316 | error = 0; | 316 | error = 0; |
317 | out: | 317 | out: |
318 | return error; | 318 | return error; |
319 | out_overflow: | 319 | out_overflow: |
320 | print_overflow_msg(__func__, xdr); | 320 | print_overflow_msg(__func__, xdr); |
321 | return -EIO; | 321 | return -EIO; |
322 | } | 322 | } |
323 | 323 | ||
324 | /* | 324 | /* |
325 | * string caller_name<LM_MAXSTRLEN>; | 325 | * string caller_name<LM_MAXSTRLEN>; |
326 | */ | 326 | */ |
327 | static void encode_caller_name(struct xdr_stream *xdr, const char *name) | 327 | static void encode_caller_name(struct xdr_stream *xdr, const char *name) |
328 | { | 328 | { |
329 | /* NB: client-side does not set lock->len */ | 329 | /* NB: client-side does not set lock->len */ |
330 | u32 length = strlen(name); | 330 | u32 length = strlen(name); |
331 | __be32 *p; | 331 | __be32 *p; |
332 | 332 | ||
333 | BUG_ON(length > NLM_MAXSTRLEN); | 333 | BUG_ON(length > NLM_MAXSTRLEN); |
334 | p = xdr_reserve_space(xdr, 4 + length); | 334 | p = xdr_reserve_space(xdr, 4 + length); |
335 | xdr_encode_opaque(p, name, length); | 335 | xdr_encode_opaque(p, name, length); |
336 | } | 336 | } |
337 | 337 | ||
338 | /* | 338 | /* |
339 | * struct nlm_lock { | 339 | * struct nlm_lock { |
340 | * string caller_name<LM_MAXSTRLEN>; | 340 | * string caller_name<LM_MAXSTRLEN>; |
341 | * netobj fh; | 341 | * netobj fh; |
342 | * netobj oh; | 342 | * netobj oh; |
343 | * int uppid; | 343 | * int uppid; |
344 | * unsigned l_offset; | 344 | * unsigned l_offset; |
345 | * unsigned l_len; | 345 | * unsigned l_len; |
346 | * }; | 346 | * }; |
347 | */ | 347 | */ |
348 | static void encode_nlm_lock(struct xdr_stream *xdr, | 348 | static void encode_nlm_lock(struct xdr_stream *xdr, |
349 | const struct nlm_lock *lock) | 349 | const struct nlm_lock *lock) |
350 | { | 350 | { |
351 | u32 l_offset, l_len; | 351 | u32 l_offset, l_len; |
352 | __be32 *p; | 352 | __be32 *p; |
353 | 353 | ||
354 | encode_caller_name(xdr, lock->caller); | 354 | encode_caller_name(xdr, lock->caller); |
355 | encode_fh(xdr, &lock->fh); | 355 | encode_fh(xdr, &lock->fh); |
356 | encode_netobj(xdr, lock->oh.data, lock->oh.len); | 356 | encode_netobj(xdr, lock->oh.data, lock->oh.len); |
357 | 357 | ||
358 | p = xdr_reserve_space(xdr, 4 + 4 + 4); | 358 | p = xdr_reserve_space(xdr, 4 + 4 + 4); |
359 | *p++ = cpu_to_be32(lock->svid); | 359 | *p++ = cpu_to_be32(lock->svid); |
360 | 360 | ||
361 | nlm_compute_offsets(lock, &l_offset, &l_len); | 361 | nlm_compute_offsets(lock, &l_offset, &l_len); |
362 | *p++ = cpu_to_be32(l_offset); | 362 | *p++ = cpu_to_be32(l_offset); |
363 | *p = cpu_to_be32(l_len); | 363 | *p = cpu_to_be32(l_len); |
364 | } | 364 | } |
365 | 365 | ||
366 | 366 | ||
367 | /* | 367 | /* |
368 | * NLMv3 XDR encode functions | 368 | * NLMv3 XDR encode functions |
369 | * | 369 | * |
370 | * NLMv3 argument types are defined in Chapter 10 of The Open Group's | 370 | * NLMv3 argument types are defined in Chapter 10 of The Open Group's |
371 | * "Protocols for Interworking: XNFS, Version 3W". | 371 | * "Protocols for Interworking: XNFS, Version 3W". |
372 | */ | 372 | */ |
373 | 373 | ||
374 | /* | 374 | /* |
375 | * struct nlm_testargs { | 375 | * struct nlm_testargs { |
376 | * netobj cookie; | 376 | * netobj cookie; |
377 | * bool exclusive; | 377 | * bool exclusive; |
378 | * struct nlm_lock alock; | 378 | * struct nlm_lock alock; |
379 | * }; | 379 | * }; |
380 | */ | 380 | */ |
381 | static void nlm_xdr_enc_testargs(struct rpc_rqst *req, | 381 | static void nlm_xdr_enc_testargs(struct rpc_rqst *req, |
382 | struct xdr_stream *xdr, | 382 | struct xdr_stream *xdr, |
383 | const struct nlm_args *args) | 383 | const struct nlm_args *args) |
384 | { | 384 | { |
385 | const struct nlm_lock *lock = &args->lock; | 385 | const struct nlm_lock *lock = &args->lock; |
386 | 386 | ||
387 | encode_cookie(xdr, &args->cookie); | 387 | encode_cookie(xdr, &args->cookie); |
388 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); | 388 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); |
389 | encode_nlm_lock(xdr, lock); | 389 | encode_nlm_lock(xdr, lock); |
390 | } | 390 | } |
391 | 391 | ||
392 | /* | 392 | /* |
393 | * struct nlm_lockargs { | 393 | * struct nlm_lockargs { |
394 | * netobj cookie; | 394 | * netobj cookie; |
395 | * bool block; | 395 | * bool block; |
396 | * bool exclusive; | 396 | * bool exclusive; |
397 | * struct nlm_lock alock; | 397 | * struct nlm_lock alock; |
398 | * bool reclaim; | 398 | * bool reclaim; |
399 | * int state; | 399 | * int state; |
400 | * }; | 400 | * }; |
401 | */ | 401 | */ |
402 | static void nlm_xdr_enc_lockargs(struct rpc_rqst *req, | 402 | static void nlm_xdr_enc_lockargs(struct rpc_rqst *req, |
403 | struct xdr_stream *xdr, | 403 | struct xdr_stream *xdr, |
404 | const struct nlm_args *args) | 404 | const struct nlm_args *args) |
405 | { | 405 | { |
406 | const struct nlm_lock *lock = &args->lock; | 406 | const struct nlm_lock *lock = &args->lock; |
407 | 407 | ||
408 | encode_cookie(xdr, &args->cookie); | 408 | encode_cookie(xdr, &args->cookie); |
409 | encode_bool(xdr, args->block); | 409 | encode_bool(xdr, args->block); |
410 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); | 410 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); |
411 | encode_nlm_lock(xdr, lock); | 411 | encode_nlm_lock(xdr, lock); |
412 | encode_bool(xdr, args->reclaim); | 412 | encode_bool(xdr, args->reclaim); |
413 | encode_int32(xdr, args->state); | 413 | encode_int32(xdr, args->state); |
414 | } | 414 | } |
415 | 415 | ||
416 | /* | 416 | /* |
417 | * struct nlm_cancargs { | 417 | * struct nlm_cancargs { |
418 | * netobj cookie; | 418 | * netobj cookie; |
419 | * bool block; | 419 | * bool block; |
420 | * bool exclusive; | 420 | * bool exclusive; |
421 | * struct nlm_lock alock; | 421 | * struct nlm_lock alock; |
422 | * }; | 422 | * }; |
423 | */ | 423 | */ |
424 | static void nlm_xdr_enc_cancargs(struct rpc_rqst *req, | 424 | static void nlm_xdr_enc_cancargs(struct rpc_rqst *req, |
425 | struct xdr_stream *xdr, | 425 | struct xdr_stream *xdr, |
426 | const struct nlm_args *args) | 426 | const struct nlm_args *args) |
427 | { | 427 | { |
428 | const struct nlm_lock *lock = &args->lock; | 428 | const struct nlm_lock *lock = &args->lock; |
429 | 429 | ||
430 | encode_cookie(xdr, &args->cookie); | 430 | encode_cookie(xdr, &args->cookie); |
431 | encode_bool(xdr, args->block); | 431 | encode_bool(xdr, args->block); |
432 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); | 432 | encode_bool(xdr, lock->fl.fl_type == F_WRLCK); |
433 | encode_nlm_lock(xdr, lock); | 433 | encode_nlm_lock(xdr, lock); |
434 | } | 434 | } |
435 | 435 | ||
436 | /* | 436 | /* |
437 | * struct nlm_unlockargs { | 437 | * struct nlm_unlockargs { |
438 | * netobj cookie; | 438 | * netobj cookie; |
439 | * struct nlm_lock alock; | 439 | * struct nlm_lock alock; |
440 | * }; | 440 | * }; |
441 | */ | 441 | */ |
442 | static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req, | 442 | static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req, |
443 | struct xdr_stream *xdr, | 443 | struct xdr_stream *xdr, |
444 | const struct nlm_args *args) | 444 | const struct nlm_args *args) |
445 | { | 445 | { |
446 | const struct nlm_lock *lock = &args->lock; | 446 | const struct nlm_lock *lock = &args->lock; |
447 | 447 | ||
448 | encode_cookie(xdr, &args->cookie); | 448 | encode_cookie(xdr, &args->cookie); |
449 | encode_nlm_lock(xdr, lock); | 449 | encode_nlm_lock(xdr, lock); |
450 | } | 450 | } |
451 | 451 | ||
452 | /* | 452 | /* |
453 | * struct nlm_res { | 453 | * struct nlm_res { |
454 | * netobj cookie; | 454 | * netobj cookie; |
455 | * nlm_stat stat; | 455 | * nlm_stat stat; |
456 | * }; | 456 | * }; |
457 | */ | 457 | */ |
458 | static void nlm_xdr_enc_res(struct rpc_rqst *req, | 458 | static void nlm_xdr_enc_res(struct rpc_rqst *req, |
459 | struct xdr_stream *xdr, | 459 | struct xdr_stream *xdr, |
460 | const struct nlm_res *result) | 460 | const struct nlm_res *result) |
461 | { | 461 | { |
462 | encode_cookie(xdr, &result->cookie); | 462 | encode_cookie(xdr, &result->cookie); |
463 | encode_nlm_stat(xdr, result->status); | 463 | encode_nlm_stat(xdr, result->status); |
464 | } | 464 | } |
465 | 465 | ||
466 | /* | 466 | /* |
467 | * union nlm_testrply switch (nlm_stats stat) { | 467 | * union nlm_testrply switch (nlm_stats stat) { |
468 | * case LCK_DENIED: | 468 | * case LCK_DENIED: |
469 | * struct nlm_holder holder; | 469 | * struct nlm_holder holder; |
470 | * default: | 470 | * default: |
471 | * void; | 471 | * void; |
472 | * }; | 472 | * }; |
473 | * | 473 | * |
474 | * struct nlm_testres { | 474 | * struct nlm_testres { |
475 | * netobj cookie; | 475 | * netobj cookie; |
476 | * nlm_testrply test_stat; | 476 | * nlm_testrply test_stat; |
477 | * }; | 477 | * }; |
478 | */ | 478 | */ |
479 | static void encode_nlm_testrply(struct xdr_stream *xdr, | 479 | static void encode_nlm_testrply(struct xdr_stream *xdr, |
480 | const struct nlm_res *result) | 480 | const struct nlm_res *result) |
481 | { | 481 | { |
482 | if (result->status == nlm_lck_denied) | 482 | if (result->status == nlm_lck_denied) |
483 | encode_nlm_holder(xdr, result); | 483 | encode_nlm_holder(xdr, result); |
484 | } | 484 | } |
485 | 485 | ||
486 | static void nlm_xdr_enc_testres(struct rpc_rqst *req, | 486 | static void nlm_xdr_enc_testres(struct rpc_rqst *req, |
487 | struct xdr_stream *xdr, | 487 | struct xdr_stream *xdr, |
488 | const struct nlm_res *result) | 488 | const struct nlm_res *result) |
489 | { | 489 | { |
490 | encode_cookie(xdr, &result->cookie); | 490 | encode_cookie(xdr, &result->cookie); |
491 | encode_nlm_stat(xdr, result->status); | 491 | encode_nlm_stat(xdr, result->status); |
492 | encode_nlm_testrply(xdr, result); | 492 | encode_nlm_testrply(xdr, result); |
493 | } | 493 | } |
494 | 494 | ||
495 | 495 | ||
496 | /* | 496 | /* |
497 | * NLMv3 XDR decode functions | 497 | * NLMv3 XDR decode functions |
498 | * | 498 | * |
499 | * NLMv3 result types are defined in Chapter 10 of The Open Group's | 499 | * NLMv3 result types are defined in Chapter 10 of The Open Group's |
500 | * "Protocols for Interworking: XNFS, Version 3W". | 500 | * "Protocols for Interworking: XNFS, Version 3W". |
501 | */ | 501 | */ |
502 | 502 | ||
503 | /* | 503 | /* |
504 | * union nlm_testrply switch (nlm_stats stat) { | 504 | * union nlm_testrply switch (nlm_stats stat) { |
505 | * case LCK_DENIED: | 505 | * case LCK_DENIED: |
506 | * struct nlm_holder holder; | 506 | * struct nlm_holder holder; |
507 | * default: | 507 | * default: |
508 | * void; | 508 | * void; |
509 | * }; | 509 | * }; |
510 | * | 510 | * |
511 | * struct nlm_testres { | 511 | * struct nlm_testres { |
512 | * netobj cookie; | 512 | * netobj cookie; |
513 | * nlm_testrply test_stat; | 513 | * nlm_testrply test_stat; |
514 | * }; | 514 | * }; |
515 | */ | 515 | */ |
516 | static int decode_nlm_testrply(struct xdr_stream *xdr, | 516 | static int decode_nlm_testrply(struct xdr_stream *xdr, |
517 | struct nlm_res *result) | 517 | struct nlm_res *result) |
518 | { | 518 | { |
519 | int error; | 519 | int error; |
520 | 520 | ||
521 | error = decode_nlm_stat(xdr, &result->status); | 521 | error = decode_nlm_stat(xdr, &result->status); |
522 | if (unlikely(error)) | 522 | if (unlikely(error)) |
523 | goto out; | 523 | goto out; |
524 | if (result->status == nlm_lck_denied) | 524 | if (result->status == nlm_lck_denied) |
525 | error = decode_nlm_holder(xdr, result); | 525 | error = decode_nlm_holder(xdr, result); |
526 | out: | 526 | out: |
527 | return error; | 527 | return error; |
528 | } | 528 | } |
529 | 529 | ||
530 | static int nlm_xdr_dec_testres(struct rpc_rqst *req, | 530 | static int nlm_xdr_dec_testres(struct rpc_rqst *req, |
531 | struct xdr_stream *xdr, | 531 | struct xdr_stream *xdr, |
532 | struct nlm_res *result) | 532 | struct nlm_res *result) |
533 | { | 533 | { |
534 | int error; | 534 | int error; |
535 | 535 | ||
536 | error = decode_cookie(xdr, &result->cookie); | 536 | error = decode_cookie(xdr, &result->cookie); |
537 | if (unlikely(error)) | 537 | if (unlikely(error)) |
538 | goto out; | 538 | goto out; |
539 | error = decode_nlm_testrply(xdr, result); | 539 | error = decode_nlm_testrply(xdr, result); |
540 | out: | 540 | out: |
541 | return error; | 541 | return error; |
542 | } | 542 | } |
543 | 543 | ||
544 | /* | 544 | /* |
545 | * struct nlm_res { | 545 | * struct nlm_res { |
546 | * netobj cookie; | 546 | * netobj cookie; |
547 | * nlm_stat stat; | 547 | * nlm_stat stat; |
548 | * }; | 548 | * }; |
549 | */ | 549 | */ |
550 | static int nlm_xdr_dec_res(struct rpc_rqst *req, | 550 | static int nlm_xdr_dec_res(struct rpc_rqst *req, |
551 | struct xdr_stream *xdr, | 551 | struct xdr_stream *xdr, |
552 | struct nlm_res *result) | 552 | struct nlm_res *result) |
553 | { | 553 | { |
554 | int error; | 554 | int error; |
555 | 555 | ||
556 | error = decode_cookie(xdr, &result->cookie); | 556 | error = decode_cookie(xdr, &result->cookie); |
557 | if (unlikely(error)) | 557 | if (unlikely(error)) |
558 | goto out; | 558 | goto out; |
559 | error = decode_nlm_stat(xdr, &result->status); | 559 | error = decode_nlm_stat(xdr, &result->status); |
560 | out: | 560 | out: |
561 | return error; | 561 | return error; |
562 | } | 562 | } |
563 | 563 | ||
564 | 564 | ||
565 | /* | 565 | /* |
566 | * For NLM, a void procedure really returns nothing | 566 | * For NLM, a void procedure really returns nothing |
567 | */ | 567 | */ |
568 | #define nlm_xdr_dec_norep NULL | 568 | #define nlm_xdr_dec_norep NULL |
569 | 569 | ||
570 | #define PROC(proc, argtype, restype) \ | 570 | #define PROC(proc, argtype, restype) \ |
571 | [NLMPROC_##proc] = { \ | 571 | [NLMPROC_##proc] = { \ |
572 | .p_proc = NLMPROC_##proc, \ | 572 | .p_proc = NLMPROC_##proc, \ |
573 | .p_encode = (kxdreproc_t)nlm_xdr_enc_##argtype, \ | 573 | .p_encode = (kxdreproc_t)nlm_xdr_enc_##argtype, \ |
574 | .p_decode = (kxdrdproc_t)nlm_xdr_dec_##restype, \ | 574 | .p_decode = (kxdrdproc_t)nlm_xdr_dec_##restype, \ |
575 | .p_arglen = NLM_##argtype##_sz, \ | 575 | .p_arglen = NLM_##argtype##_sz, \ |
576 | .p_replen = NLM_##restype##_sz, \ | 576 | .p_replen = NLM_##restype##_sz, \ |
577 | .p_statidx = NLMPROC_##proc, \ | 577 | .p_statidx = NLMPROC_##proc, \ |
578 | .p_name = #proc, \ | 578 | .p_name = #proc, \ |
579 | } | 579 | } |
580 | 580 | ||
581 | static struct rpc_procinfo nlm_procedures[] = { | 581 | static struct rpc_procinfo nlm_procedures[] = { |
582 | PROC(TEST, testargs, testres), | 582 | PROC(TEST, testargs, testres), |
583 | PROC(LOCK, lockargs, res), | 583 | PROC(LOCK, lockargs, res), |
584 | PROC(CANCEL, cancargs, res), | 584 | PROC(CANCEL, cancargs, res), |
585 | PROC(UNLOCK, unlockargs, res), | 585 | PROC(UNLOCK, unlockargs, res), |
586 | PROC(GRANTED, testargs, res), | 586 | PROC(GRANTED, testargs, res), |
587 | PROC(TEST_MSG, testargs, norep), | 587 | PROC(TEST_MSG, testargs, norep), |
588 | PROC(LOCK_MSG, lockargs, norep), | 588 | PROC(LOCK_MSG, lockargs, norep), |
589 | PROC(CANCEL_MSG, cancargs, norep), | 589 | PROC(CANCEL_MSG, cancargs, norep), |
590 | PROC(UNLOCK_MSG, unlockargs, norep), | 590 | PROC(UNLOCK_MSG, unlockargs, norep), |
591 | PROC(GRANTED_MSG, testargs, norep), | 591 | PROC(GRANTED_MSG, testargs, norep), |
592 | PROC(TEST_RES, testres, norep), | 592 | PROC(TEST_RES, testres, norep), |
593 | PROC(LOCK_RES, res, norep), | 593 | PROC(LOCK_RES, res, norep), |
594 | PROC(CANCEL_RES, res, norep), | 594 | PROC(CANCEL_RES, res, norep), |
595 | PROC(UNLOCK_RES, res, norep), | 595 | PROC(UNLOCK_RES, res, norep), |
596 | PROC(GRANTED_RES, res, norep), | 596 | PROC(GRANTED_RES, res, norep), |
597 | }; | 597 | }; |
598 | 598 | ||
599 | static struct rpc_version nlm_version1 = { | 599 | static const struct rpc_version nlm_version1 = { |
600 | .number = 1, | 600 | .number = 1, |
601 | .nrprocs = ARRAY_SIZE(nlm_procedures), | 601 | .nrprocs = ARRAY_SIZE(nlm_procedures), |
602 | .procs = nlm_procedures, | 602 | .procs = nlm_procedures, |
603 | }; | 603 | }; |
604 | 604 | ||
605 | static struct rpc_version nlm_version3 = { | 605 | static const struct rpc_version nlm_version3 = { |
606 | .number = 3, | 606 | .number = 3, |
607 | .nrprocs = ARRAY_SIZE(nlm_procedures), | 607 | .nrprocs = ARRAY_SIZE(nlm_procedures), |
608 | .procs = nlm_procedures, | 608 | .procs = nlm_procedures, |
609 | }; | 609 | }; |
610 | 610 | ||
611 | static struct rpc_version *nlm_versions[] = { | 611 | static const struct rpc_version *nlm_versions[] = { |
612 | [1] = &nlm_version1, | 612 | [1] = &nlm_version1, |
613 | [3] = &nlm_version3, | 613 | [3] = &nlm_version3, |
614 | #ifdef CONFIG_LOCKD_V4 | 614 | #ifdef CONFIG_LOCKD_V4 |
615 | [4] = &nlm_version4, | 615 | [4] = &nlm_version4, |
616 | #endif | 616 | #endif |
617 | }; | 617 | }; |
618 | 618 | ||
619 | static struct rpc_stat nlm_rpc_stats; | 619 | static struct rpc_stat nlm_rpc_stats; |
620 | 620 | ||
621 | struct rpc_program nlm_program = { | 621 | const struct rpc_program nlm_program = { |
622 | .name = "lockd", | 622 | .name = "lockd", |
623 | .number = NLM_PROGRAM, | 623 | .number = NLM_PROGRAM, |
624 | .nrvers = ARRAY_SIZE(nlm_versions), | 624 | .nrvers = ARRAY_SIZE(nlm_versions), |
625 | .version = nlm_versions, | 625 | .version = nlm_versions, |
626 | .stats = &nlm_rpc_stats, | 626 | .stats = &nlm_rpc_stats, |
627 | }; | 627 | }; |
628 | 628 |
fs/lockd/mon.c
1 | /* | 1 | /* |
2 | * linux/fs/lockd/mon.c | 2 | * linux/fs/lockd/mon.c |
3 | * | 3 | * |
4 | * The kernel statd client. | 4 | * The kernel statd client. |
5 | * | 5 | * |
6 | * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/utsname.h> | 10 | #include <linux/utsname.h> |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/ktime.h> | 12 | #include <linux/ktime.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | 14 | ||
15 | #include <linux/sunrpc/clnt.h> | 15 | #include <linux/sunrpc/clnt.h> |
16 | #include <linux/sunrpc/xprtsock.h> | 16 | #include <linux/sunrpc/xprtsock.h> |
17 | #include <linux/sunrpc/svc.h> | 17 | #include <linux/sunrpc/svc.h> |
18 | #include <linux/lockd/lockd.h> | 18 | #include <linux/lockd/lockd.h> |
19 | 19 | ||
20 | #include <asm/unaligned.h> | 20 | #include <asm/unaligned.h> |
21 | 21 | ||
22 | #define NLMDBG_FACILITY NLMDBG_MONITOR | 22 | #define NLMDBG_FACILITY NLMDBG_MONITOR |
23 | #define NSM_PROGRAM 100024 | 23 | #define NSM_PROGRAM 100024 |
24 | #define NSM_VERSION 1 | 24 | #define NSM_VERSION 1 |
25 | 25 | ||
26 | enum { | 26 | enum { |
27 | NSMPROC_NULL, | 27 | NSMPROC_NULL, |
28 | NSMPROC_STAT, | 28 | NSMPROC_STAT, |
29 | NSMPROC_MON, | 29 | NSMPROC_MON, |
30 | NSMPROC_UNMON, | 30 | NSMPROC_UNMON, |
31 | NSMPROC_UNMON_ALL, | 31 | NSMPROC_UNMON_ALL, |
32 | NSMPROC_SIMU_CRASH, | 32 | NSMPROC_SIMU_CRASH, |
33 | NSMPROC_NOTIFY, | 33 | NSMPROC_NOTIFY, |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct nsm_args { | 36 | struct nsm_args { |
37 | struct nsm_private *priv; | 37 | struct nsm_private *priv; |
38 | u32 prog; /* RPC callback info */ | 38 | u32 prog; /* RPC callback info */ |
39 | u32 vers; | 39 | u32 vers; |
40 | u32 proc; | 40 | u32 proc; |
41 | 41 | ||
42 | char *mon_name; | 42 | char *mon_name; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct nsm_res { | 45 | struct nsm_res { |
46 | u32 status; | 46 | u32 status; |
47 | u32 state; | 47 | u32 state; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | static struct rpc_program nsm_program; | 50 | static const struct rpc_program nsm_program; |
51 | static LIST_HEAD(nsm_handles); | 51 | static LIST_HEAD(nsm_handles); |
52 | static DEFINE_SPINLOCK(nsm_lock); | 52 | static DEFINE_SPINLOCK(nsm_lock); |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * Local NSM state | 55 | * Local NSM state |
56 | */ | 56 | */ |
57 | u32 __read_mostly nsm_local_state; | 57 | u32 __read_mostly nsm_local_state; |
58 | bool __read_mostly nsm_use_hostnames; | 58 | bool __read_mostly nsm_use_hostnames; |
59 | 59 | ||
60 | static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm) | 60 | static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm) |
61 | { | 61 | { |
62 | return (struct sockaddr *)&nsm->sm_addr; | 62 | return (struct sockaddr *)&nsm->sm_addr; |
63 | } | 63 | } |
64 | 64 | ||
65 | static struct rpc_clnt *nsm_create(void) | 65 | static struct rpc_clnt *nsm_create(void) |
66 | { | 66 | { |
67 | struct sockaddr_in sin = { | 67 | struct sockaddr_in sin = { |
68 | .sin_family = AF_INET, | 68 | .sin_family = AF_INET, |
69 | .sin_addr.s_addr = htonl(INADDR_LOOPBACK), | 69 | .sin_addr.s_addr = htonl(INADDR_LOOPBACK), |
70 | }; | 70 | }; |
71 | struct rpc_create_args args = { | 71 | struct rpc_create_args args = { |
72 | .net = &init_net, | 72 | .net = &init_net, |
73 | .protocol = XPRT_TRANSPORT_UDP, | 73 | .protocol = XPRT_TRANSPORT_UDP, |
74 | .address = (struct sockaddr *)&sin, | 74 | .address = (struct sockaddr *)&sin, |
75 | .addrsize = sizeof(sin), | 75 | .addrsize = sizeof(sin), |
76 | .servername = "rpc.statd", | 76 | .servername = "rpc.statd", |
77 | .program = &nsm_program, | 77 | .program = &nsm_program, |
78 | .version = NSM_VERSION, | 78 | .version = NSM_VERSION, |
79 | .authflavor = RPC_AUTH_NULL, | 79 | .authflavor = RPC_AUTH_NULL, |
80 | .flags = RPC_CLNT_CREATE_NOPING, | 80 | .flags = RPC_CLNT_CREATE_NOPING, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | return rpc_create(&args); | 83 | return rpc_create(&args); |
84 | } | 84 | } |
85 | 85 | ||
86 | static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) | 86 | static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) |
87 | { | 87 | { |
88 | struct rpc_clnt *clnt; | 88 | struct rpc_clnt *clnt; |
89 | int status; | 89 | int status; |
90 | struct nsm_args args = { | 90 | struct nsm_args args = { |
91 | .priv = &nsm->sm_priv, | 91 | .priv = &nsm->sm_priv, |
92 | .prog = NLM_PROGRAM, | 92 | .prog = NLM_PROGRAM, |
93 | .vers = 3, | 93 | .vers = 3, |
94 | .proc = NLMPROC_NSM_NOTIFY, | 94 | .proc = NLMPROC_NSM_NOTIFY, |
95 | .mon_name = nsm->sm_mon_name, | 95 | .mon_name = nsm->sm_mon_name, |
96 | }; | 96 | }; |
97 | struct rpc_message msg = { | 97 | struct rpc_message msg = { |
98 | .rpc_argp = &args, | 98 | .rpc_argp = &args, |
99 | .rpc_resp = res, | 99 | .rpc_resp = res, |
100 | }; | 100 | }; |
101 | 101 | ||
102 | clnt = nsm_create(); | 102 | clnt = nsm_create(); |
103 | if (IS_ERR(clnt)) { | 103 | if (IS_ERR(clnt)) { |
104 | status = PTR_ERR(clnt); | 104 | status = PTR_ERR(clnt); |
105 | dprintk("lockd: failed to create NSM upcall transport, " | 105 | dprintk("lockd: failed to create NSM upcall transport, " |
106 | "status=%d\n", status); | 106 | "status=%d\n", status); |
107 | goto out; | 107 | goto out; |
108 | } | 108 | } |
109 | 109 | ||
110 | memset(res, 0, sizeof(*res)); | 110 | memset(res, 0, sizeof(*res)); |
111 | 111 | ||
112 | msg.rpc_proc = &clnt->cl_procinfo[proc]; | 112 | msg.rpc_proc = &clnt->cl_procinfo[proc]; |
113 | status = rpc_call_sync(clnt, &msg, 0); | 113 | status = rpc_call_sync(clnt, &msg, 0); |
114 | if (status < 0) | 114 | if (status < 0) |
115 | dprintk("lockd: NSM upcall RPC failed, status=%d\n", | 115 | dprintk("lockd: NSM upcall RPC failed, status=%d\n", |
116 | status); | 116 | status); |
117 | else | 117 | else |
118 | status = 0; | 118 | status = 0; |
119 | rpc_shutdown_client(clnt); | 119 | rpc_shutdown_client(clnt); |
120 | out: | 120 | out: |
121 | return status; | 121 | return status; |
122 | } | 122 | } |
123 | 123 | ||
124 | /** | 124 | /** |
125 | * nsm_monitor - Notify a peer in case we reboot | 125 | * nsm_monitor - Notify a peer in case we reboot |
126 | * @host: pointer to nlm_host of peer to notify | 126 | * @host: pointer to nlm_host of peer to notify |
127 | * | 127 | * |
128 | * If this peer is not already monitored, this function sends an | 128 | * If this peer is not already monitored, this function sends an |
129 | * upcall to the local rpc.statd to record the name/address of | 129 | * upcall to the local rpc.statd to record the name/address of |
130 | * the peer to notify in case we reboot. | 130 | * the peer to notify in case we reboot. |
131 | * | 131 | * |
132 | * Returns zero if the peer is monitored by the local rpc.statd; | 132 | * Returns zero if the peer is monitored by the local rpc.statd; |
133 | * otherwise a negative errno value is returned. | 133 | * otherwise a negative errno value is returned. |
134 | */ | 134 | */ |
135 | int nsm_monitor(const struct nlm_host *host) | 135 | int nsm_monitor(const struct nlm_host *host) |
136 | { | 136 | { |
137 | struct nsm_handle *nsm = host->h_nsmhandle; | 137 | struct nsm_handle *nsm = host->h_nsmhandle; |
138 | struct nsm_res res; | 138 | struct nsm_res res; |
139 | int status; | 139 | int status; |
140 | 140 | ||
141 | dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); | 141 | dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); |
142 | 142 | ||
143 | if (nsm->sm_monitored) | 143 | if (nsm->sm_monitored) |
144 | return 0; | 144 | return 0; |
145 | 145 | ||
146 | /* | 146 | /* |
147 | * Choose whether to record the caller_name or IP address of | 147 | * Choose whether to record the caller_name or IP address of |
148 | * this peer in the local rpc.statd's database. | 148 | * this peer in the local rpc.statd's database. |
149 | */ | 149 | */ |
150 | nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; | 150 | nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; |
151 | 151 | ||
152 | status = nsm_mon_unmon(nsm, NSMPROC_MON, &res); | 152 | status = nsm_mon_unmon(nsm, NSMPROC_MON, &res); |
153 | if (unlikely(res.status != 0)) | 153 | if (unlikely(res.status != 0)) |
154 | status = -EIO; | 154 | status = -EIO; |
155 | if (unlikely(status < 0)) { | 155 | if (unlikely(status < 0)) { |
156 | printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); | 156 | printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); |
157 | return status; | 157 | return status; |
158 | } | 158 | } |
159 | 159 | ||
160 | nsm->sm_monitored = 1; | 160 | nsm->sm_monitored = 1; |
161 | if (unlikely(nsm_local_state != res.state)) { | 161 | if (unlikely(nsm_local_state != res.state)) { |
162 | nsm_local_state = res.state; | 162 | nsm_local_state = res.state; |
163 | dprintk("lockd: NSM state changed to %d\n", nsm_local_state); | 163 | dprintk("lockd: NSM state changed to %d\n", nsm_local_state); |
164 | } | 164 | } |
165 | return 0; | 165 | return 0; |
166 | } | 166 | } |
167 | 167 | ||
168 | /** | 168 | /** |
169 | * nsm_unmonitor - Unregister peer notification | 169 | * nsm_unmonitor - Unregister peer notification |
170 | * @host: pointer to nlm_host of peer to stop monitoring | 170 | * @host: pointer to nlm_host of peer to stop monitoring |
171 | * | 171 | * |
172 | * If this peer is monitored, this function sends an upcall to | 172 | * If this peer is monitored, this function sends an upcall to |
173 | * tell the local rpc.statd not to send this peer a notification | 173 | * tell the local rpc.statd not to send this peer a notification |
174 | * when we reboot. | 174 | * when we reboot. |
175 | */ | 175 | */ |
176 | void nsm_unmonitor(const struct nlm_host *host) | 176 | void nsm_unmonitor(const struct nlm_host *host) |
177 | { | 177 | { |
178 | struct nsm_handle *nsm = host->h_nsmhandle; | 178 | struct nsm_handle *nsm = host->h_nsmhandle; |
179 | struct nsm_res res; | 179 | struct nsm_res res; |
180 | int status; | 180 | int status; |
181 | 181 | ||
182 | if (atomic_read(&nsm->sm_count) == 1 | 182 | if (atomic_read(&nsm->sm_count) == 1 |
183 | && nsm->sm_monitored && !nsm->sm_sticky) { | 183 | && nsm->sm_monitored && !nsm->sm_sticky) { |
184 | dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); | 184 | dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); |
185 | 185 | ||
186 | status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res); | 186 | status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res); |
187 | if (res.status != 0) | 187 | if (res.status != 0) |
188 | status = -EIO; | 188 | status = -EIO; |
189 | if (status < 0) | 189 | if (status < 0) |
190 | printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", | 190 | printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", |
191 | nsm->sm_name); | 191 | nsm->sm_name); |
192 | else | 192 | else |
193 | nsm->sm_monitored = 0; | 193 | nsm->sm_monitored = 0; |
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
197 | static struct nsm_handle *nsm_lookup_hostname(const char *hostname, | 197 | static struct nsm_handle *nsm_lookup_hostname(const char *hostname, |
198 | const size_t len) | 198 | const size_t len) |
199 | { | 199 | { |
200 | struct nsm_handle *nsm; | 200 | struct nsm_handle *nsm; |
201 | 201 | ||
202 | list_for_each_entry(nsm, &nsm_handles, sm_link) | 202 | list_for_each_entry(nsm, &nsm_handles, sm_link) |
203 | if (strlen(nsm->sm_name) == len && | 203 | if (strlen(nsm->sm_name) == len && |
204 | memcmp(nsm->sm_name, hostname, len) == 0) | 204 | memcmp(nsm->sm_name, hostname, len) == 0) |
205 | return nsm; | 205 | return nsm; |
206 | return NULL; | 206 | return NULL; |
207 | } | 207 | } |
208 | 208 | ||
209 | static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap) | 209 | static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap) |
210 | { | 210 | { |
211 | struct nsm_handle *nsm; | 211 | struct nsm_handle *nsm; |
212 | 212 | ||
213 | list_for_each_entry(nsm, &nsm_handles, sm_link) | 213 | list_for_each_entry(nsm, &nsm_handles, sm_link) |
214 | if (rpc_cmp_addr(nsm_addr(nsm), sap)) | 214 | if (rpc_cmp_addr(nsm_addr(nsm), sap)) |
215 | return nsm; | 215 | return nsm; |
216 | return NULL; | 216 | return NULL; |
217 | } | 217 | } |
218 | 218 | ||
219 | static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv) | 219 | static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv) |
220 | { | 220 | { |
221 | struct nsm_handle *nsm; | 221 | struct nsm_handle *nsm; |
222 | 222 | ||
223 | list_for_each_entry(nsm, &nsm_handles, sm_link) | 223 | list_for_each_entry(nsm, &nsm_handles, sm_link) |
224 | if (memcmp(nsm->sm_priv.data, priv->data, | 224 | if (memcmp(nsm->sm_priv.data, priv->data, |
225 | sizeof(priv->data)) == 0) | 225 | sizeof(priv->data)) == 0) |
226 | return nsm; | 226 | return nsm; |
227 | return NULL; | 227 | return NULL; |
228 | } | 228 | } |
229 | 229 | ||
230 | /* | 230 | /* |
231 | * Construct a unique cookie to match this nsm_handle to this monitored | 231 | * Construct a unique cookie to match this nsm_handle to this monitored |
232 | * host. It is passed to the local rpc.statd via NSMPROC_MON, and | 232 | * host. It is passed to the local rpc.statd via NSMPROC_MON, and |
233 | * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these | 233 | * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these |
234 | * requests. | 234 | * requests. |
235 | * | 235 | * |
236 | * The NSM protocol requires that these cookies be unique while the | 236 | * The NSM protocol requires that these cookies be unique while the |
237 | * system is running. We prefer a stronger requirement of making them | 237 | * system is running. We prefer a stronger requirement of making them |
238 | * unique across reboots. If user space bugs cause a stale cookie to | 238 | * unique across reboots. If user space bugs cause a stale cookie to |
239 | * be sent to the kernel, it could cause the wrong host to lose its | 239 | * be sent to the kernel, it could cause the wrong host to lose its |
240 | * lock state if cookies were not unique across reboots. | 240 | * lock state if cookies were not unique across reboots. |
241 | * | 241 | * |
242 | * The cookies are exposed only to local user space via loopback. They | 242 | * The cookies are exposed only to local user space via loopback. They |
243 | * do not appear on the physical network. If we want greater security | 243 | * do not appear on the physical network. If we want greater security |
244 | * for some reason, nsm_init_private() could perform a one-way hash to | 244 | * for some reason, nsm_init_private() could perform a one-way hash to |
245 | * obscure the contents of the cookie. | 245 | * obscure the contents of the cookie. |
246 | */ | 246 | */ |
247 | static void nsm_init_private(struct nsm_handle *nsm) | 247 | static void nsm_init_private(struct nsm_handle *nsm) |
248 | { | 248 | { |
249 | u64 *p = (u64 *)&nsm->sm_priv.data; | 249 | u64 *p = (u64 *)&nsm->sm_priv.data; |
250 | struct timespec ts; | 250 | struct timespec ts; |
251 | s64 ns; | 251 | s64 ns; |
252 | 252 | ||
253 | ktime_get_ts(&ts); | 253 | ktime_get_ts(&ts); |
254 | ns = timespec_to_ns(&ts); | 254 | ns = timespec_to_ns(&ts); |
255 | put_unaligned(ns, p); | 255 | put_unaligned(ns, p); |
256 | put_unaligned((unsigned long)nsm, p + 1); | 256 | put_unaligned((unsigned long)nsm, p + 1); |
257 | } | 257 | } |
258 | 258 | ||
259 | static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap, | 259 | static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap, |
260 | const size_t salen, | 260 | const size_t salen, |
261 | const char *hostname, | 261 | const char *hostname, |
262 | const size_t hostname_len) | 262 | const size_t hostname_len) |
263 | { | 263 | { |
264 | struct nsm_handle *new; | 264 | struct nsm_handle *new; |
265 | 265 | ||
266 | new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL); | 266 | new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL); |
267 | if (unlikely(new == NULL)) | 267 | if (unlikely(new == NULL)) |
268 | return NULL; | 268 | return NULL; |
269 | 269 | ||
270 | atomic_set(&new->sm_count, 1); | 270 | atomic_set(&new->sm_count, 1); |
271 | new->sm_name = (char *)(new + 1); | 271 | new->sm_name = (char *)(new + 1); |
272 | memcpy(nsm_addr(new), sap, salen); | 272 | memcpy(nsm_addr(new), sap, salen); |
273 | new->sm_addrlen = salen; | 273 | new->sm_addrlen = salen; |
274 | nsm_init_private(new); | 274 | nsm_init_private(new); |
275 | 275 | ||
276 | if (rpc_ntop(nsm_addr(new), new->sm_addrbuf, | 276 | if (rpc_ntop(nsm_addr(new), new->sm_addrbuf, |
277 | sizeof(new->sm_addrbuf)) == 0) | 277 | sizeof(new->sm_addrbuf)) == 0) |
278 | (void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf), | 278 | (void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf), |
279 | "unsupported address family"); | 279 | "unsupported address family"); |
280 | memcpy(new->sm_name, hostname, hostname_len); | 280 | memcpy(new->sm_name, hostname, hostname_len); |
281 | new->sm_name[hostname_len] = '\0'; | 281 | new->sm_name[hostname_len] = '\0'; |
282 | 282 | ||
283 | return new; | 283 | return new; |
284 | } | 284 | } |
285 | 285 | ||
286 | /** | 286 | /** |
287 | * nsm_get_handle - Find or create a cached nsm_handle | 287 | * nsm_get_handle - Find or create a cached nsm_handle |
288 | * @sap: pointer to socket address of handle to find | 288 | * @sap: pointer to socket address of handle to find |
289 | * @salen: length of socket address | 289 | * @salen: length of socket address |
290 | * @hostname: pointer to C string containing hostname to find | 290 | * @hostname: pointer to C string containing hostname to find |
291 | * @hostname_len: length of C string | 291 | * @hostname_len: length of C string |
292 | * | 292 | * |
293 | * Behavior is modulated by the global nsm_use_hostnames variable. | 293 | * Behavior is modulated by the global nsm_use_hostnames variable. |
294 | * | 294 | * |
295 | * Returns a cached nsm_handle after bumping its ref count, or | 295 | * Returns a cached nsm_handle after bumping its ref count, or |
296 | * returns a fresh nsm_handle if a handle that matches @sap and/or | 296 | * returns a fresh nsm_handle if a handle that matches @sap and/or |
297 | * @hostname cannot be found in the handle cache. Returns NULL if | 297 | * @hostname cannot be found in the handle cache. Returns NULL if |
298 | * an error occurs. | 298 | * an error occurs. |
299 | */ | 299 | */ |
300 | struct nsm_handle *nsm_get_handle(const struct sockaddr *sap, | 300 | struct nsm_handle *nsm_get_handle(const struct sockaddr *sap, |
301 | const size_t salen, const char *hostname, | 301 | const size_t salen, const char *hostname, |
302 | const size_t hostname_len) | 302 | const size_t hostname_len) |
303 | { | 303 | { |
304 | struct nsm_handle *cached, *new = NULL; | 304 | struct nsm_handle *cached, *new = NULL; |
305 | 305 | ||
306 | if (hostname && memchr(hostname, '/', hostname_len) != NULL) { | 306 | if (hostname && memchr(hostname, '/', hostname_len) != NULL) { |
307 | if (printk_ratelimit()) { | 307 | if (printk_ratelimit()) { |
308 | printk(KERN_WARNING "Invalid hostname \"%.*s\" " | 308 | printk(KERN_WARNING "Invalid hostname \"%.*s\" " |
309 | "in NFS lock request\n", | 309 | "in NFS lock request\n", |
310 | (int)hostname_len, hostname); | 310 | (int)hostname_len, hostname); |
311 | } | 311 | } |
312 | return NULL; | 312 | return NULL; |
313 | } | 313 | } |
314 | 314 | ||
315 | retry: | 315 | retry: |
316 | spin_lock(&nsm_lock); | 316 | spin_lock(&nsm_lock); |
317 | 317 | ||
318 | if (nsm_use_hostnames && hostname != NULL) | 318 | if (nsm_use_hostnames && hostname != NULL) |
319 | cached = nsm_lookup_hostname(hostname, hostname_len); | 319 | cached = nsm_lookup_hostname(hostname, hostname_len); |
320 | else | 320 | else |
321 | cached = nsm_lookup_addr(sap); | 321 | cached = nsm_lookup_addr(sap); |
322 | 322 | ||
323 | if (cached != NULL) { | 323 | if (cached != NULL) { |
324 | atomic_inc(&cached->sm_count); | 324 | atomic_inc(&cached->sm_count); |
325 | spin_unlock(&nsm_lock); | 325 | spin_unlock(&nsm_lock); |
326 | kfree(new); | 326 | kfree(new); |
327 | dprintk("lockd: found nsm_handle for %s (%s), " | 327 | dprintk("lockd: found nsm_handle for %s (%s), " |
328 | "cnt %d\n", cached->sm_name, | 328 | "cnt %d\n", cached->sm_name, |
329 | cached->sm_addrbuf, | 329 | cached->sm_addrbuf, |
330 | atomic_read(&cached->sm_count)); | 330 | atomic_read(&cached->sm_count)); |
331 | return cached; | 331 | return cached; |
332 | } | 332 | } |
333 | 333 | ||
334 | if (new != NULL) { | 334 | if (new != NULL) { |
335 | list_add(&new->sm_link, &nsm_handles); | 335 | list_add(&new->sm_link, &nsm_handles); |
336 | spin_unlock(&nsm_lock); | 336 | spin_unlock(&nsm_lock); |
337 | dprintk("lockd: created nsm_handle for %s (%s)\n", | 337 | dprintk("lockd: created nsm_handle for %s (%s)\n", |
338 | new->sm_name, new->sm_addrbuf); | 338 | new->sm_name, new->sm_addrbuf); |
339 | return new; | 339 | return new; |
340 | } | 340 | } |
341 | 341 | ||
342 | spin_unlock(&nsm_lock); | 342 | spin_unlock(&nsm_lock); |
343 | 343 | ||
344 | new = nsm_create_handle(sap, salen, hostname, hostname_len); | 344 | new = nsm_create_handle(sap, salen, hostname, hostname_len); |
345 | if (unlikely(new == NULL)) | 345 | if (unlikely(new == NULL)) |
346 | return NULL; | 346 | return NULL; |
347 | goto retry; | 347 | goto retry; |
348 | } | 348 | } |
349 | 349 | ||
350 | /** | 350 | /** |
351 | * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle | 351 | * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle |
352 | * @info: pointer to NLMPROC_SM_NOTIFY arguments | 352 | * @info: pointer to NLMPROC_SM_NOTIFY arguments |
353 | * | 353 | * |
354 | * Returns a matching nsm_handle if found in the nsm cache. The returned | 354 | * Returns a matching nsm_handle if found in the nsm cache. The returned |
355 | * nsm_handle's reference count is bumped. Otherwise returns NULL if some | 355 | * nsm_handle's reference count is bumped. Otherwise returns NULL if some |
356 | * error occurred. | 356 | * error occurred. |
357 | */ | 357 | */ |
358 | struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info) | 358 | struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info) |
359 | { | 359 | { |
360 | struct nsm_handle *cached; | 360 | struct nsm_handle *cached; |
361 | 361 | ||
362 | spin_lock(&nsm_lock); | 362 | spin_lock(&nsm_lock); |
363 | 363 | ||
364 | cached = nsm_lookup_priv(&info->priv); | 364 | cached = nsm_lookup_priv(&info->priv); |
365 | if (unlikely(cached == NULL)) { | 365 | if (unlikely(cached == NULL)) { |
366 | spin_unlock(&nsm_lock); | 366 | spin_unlock(&nsm_lock); |
367 | dprintk("lockd: never saw rebooted peer '%.*s' before\n", | 367 | dprintk("lockd: never saw rebooted peer '%.*s' before\n", |
368 | info->len, info->mon); | 368 | info->len, info->mon); |
369 | return cached; | 369 | return cached; |
370 | } | 370 | } |
371 | 371 | ||
372 | atomic_inc(&cached->sm_count); | 372 | atomic_inc(&cached->sm_count); |
373 | spin_unlock(&nsm_lock); | 373 | spin_unlock(&nsm_lock); |
374 | 374 | ||
375 | dprintk("lockd: host %s (%s) rebooted, cnt %d\n", | 375 | dprintk("lockd: host %s (%s) rebooted, cnt %d\n", |
376 | cached->sm_name, cached->sm_addrbuf, | 376 | cached->sm_name, cached->sm_addrbuf, |
377 | atomic_read(&cached->sm_count)); | 377 | atomic_read(&cached->sm_count)); |
378 | return cached; | 378 | return cached; |
379 | } | 379 | } |
380 | 380 | ||
381 | /** | 381 | /** |
382 | * nsm_release - Release an NSM handle | 382 | * nsm_release - Release an NSM handle |
383 | * @nsm: pointer to handle to be released | 383 | * @nsm: pointer to handle to be released |
384 | * | 384 | * |
385 | */ | 385 | */ |
386 | void nsm_release(struct nsm_handle *nsm) | 386 | void nsm_release(struct nsm_handle *nsm) |
387 | { | 387 | { |
388 | if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { | 388 | if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { |
389 | list_del(&nsm->sm_link); | 389 | list_del(&nsm->sm_link); |
390 | spin_unlock(&nsm_lock); | 390 | spin_unlock(&nsm_lock); |
391 | dprintk("lockd: destroyed nsm_handle for %s (%s)\n", | 391 | dprintk("lockd: destroyed nsm_handle for %s (%s)\n", |
392 | nsm->sm_name, nsm->sm_addrbuf); | 392 | nsm->sm_name, nsm->sm_addrbuf); |
393 | kfree(nsm); | 393 | kfree(nsm); |
394 | } | 394 | } |
395 | } | 395 | } |
396 | 396 | ||
397 | /* | 397 | /* |
398 | * XDR functions for NSM. | 398 | * XDR functions for NSM. |
399 | * | 399 | * |
400 | * See http://www.opengroup.org/ for details on the Network | 400 | * See http://www.opengroup.org/ for details on the Network |
401 | * Status Monitor wire protocol. | 401 | * Status Monitor wire protocol. |
402 | */ | 402 | */ |
403 | 403 | ||
404 | static void encode_nsm_string(struct xdr_stream *xdr, const char *string) | 404 | static void encode_nsm_string(struct xdr_stream *xdr, const char *string) |
405 | { | 405 | { |
406 | const u32 len = strlen(string); | 406 | const u32 len = strlen(string); |
407 | __be32 *p; | 407 | __be32 *p; |
408 | 408 | ||
409 | BUG_ON(len > SM_MAXSTRLEN); | 409 | BUG_ON(len > SM_MAXSTRLEN); |
410 | p = xdr_reserve_space(xdr, 4 + len); | 410 | p = xdr_reserve_space(xdr, 4 + len); |
411 | xdr_encode_opaque(p, string, len); | 411 | xdr_encode_opaque(p, string, len); |
412 | } | 412 | } |
413 | 413 | ||
414 | /* | 414 | /* |
415 | * "mon_name" specifies the host to be monitored. | 415 | * "mon_name" specifies the host to be monitored. |
416 | */ | 416 | */ |
417 | static void encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp) | 417 | static void encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp) |
418 | { | 418 | { |
419 | encode_nsm_string(xdr, argp->mon_name); | 419 | encode_nsm_string(xdr, argp->mon_name); |
420 | } | 420 | } |
421 | 421 | ||
422 | /* | 422 | /* |
423 | * The "my_id" argument specifies the hostname and RPC procedure | 423 | * The "my_id" argument specifies the hostname and RPC procedure |
424 | * to be called when the status manager receives notification | 424 | * to be called when the status manager receives notification |
425 | * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name" | 425 | * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name" |
426 | * has changed. | 426 | * has changed. |
427 | */ | 427 | */ |
428 | static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp) | 428 | static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp) |
429 | { | 429 | { |
430 | __be32 *p; | 430 | __be32 *p; |
431 | 431 | ||
432 | encode_nsm_string(xdr, utsname()->nodename); | 432 | encode_nsm_string(xdr, utsname()->nodename); |
433 | p = xdr_reserve_space(xdr, 4 + 4 + 4); | 433 | p = xdr_reserve_space(xdr, 4 + 4 + 4); |
434 | *p++ = cpu_to_be32(argp->prog); | 434 | *p++ = cpu_to_be32(argp->prog); |
435 | *p++ = cpu_to_be32(argp->vers); | 435 | *p++ = cpu_to_be32(argp->vers); |
436 | *p = cpu_to_be32(argp->proc); | 436 | *p = cpu_to_be32(argp->proc); |
437 | } | 437 | } |
438 | 438 | ||
439 | /* | 439 | /* |
440 | * The "mon_id" argument specifies the non-private arguments | 440 | * The "mon_id" argument specifies the non-private arguments |
441 | * of an NSMPROC_MON or NSMPROC_UNMON call. | 441 | * of an NSMPROC_MON or NSMPROC_UNMON call. |
442 | */ | 442 | */ |
443 | static void encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp) | 443 | static void encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp) |
444 | { | 444 | { |
445 | encode_mon_name(xdr, argp); | 445 | encode_mon_name(xdr, argp); |
446 | encode_my_id(xdr, argp); | 446 | encode_my_id(xdr, argp); |
447 | } | 447 | } |
448 | 448 | ||
449 | /* | 449 | /* |
450 | * The "priv" argument may contain private information required | 450 | * The "priv" argument may contain private information required |
451 | * by the NSMPROC_MON call. This information will be supplied in the | 451 | * by the NSMPROC_MON call. This information will be supplied in the |
452 | * NLMPROC_SM_NOTIFY call. | 452 | * NLMPROC_SM_NOTIFY call. |
453 | */ | 453 | */ |
454 | static void encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp) | 454 | static void encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp) |
455 | { | 455 | { |
456 | __be32 *p; | 456 | __be32 *p; |
457 | 457 | ||
458 | p = xdr_reserve_space(xdr, SM_PRIV_SIZE); | 458 | p = xdr_reserve_space(xdr, SM_PRIV_SIZE); |
459 | xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE); | 459 | xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE); |
460 | } | 460 | } |
461 | 461 | ||
462 | static void nsm_xdr_enc_mon(struct rpc_rqst *req, struct xdr_stream *xdr, | 462 | static void nsm_xdr_enc_mon(struct rpc_rqst *req, struct xdr_stream *xdr, |
463 | const struct nsm_args *argp) | 463 | const struct nsm_args *argp) |
464 | { | 464 | { |
465 | encode_mon_id(xdr, argp); | 465 | encode_mon_id(xdr, argp); |
466 | encode_priv(xdr, argp); | 466 | encode_priv(xdr, argp); |
467 | } | 467 | } |
468 | 468 | ||
469 | static void nsm_xdr_enc_unmon(struct rpc_rqst *req, struct xdr_stream *xdr, | 469 | static void nsm_xdr_enc_unmon(struct rpc_rqst *req, struct xdr_stream *xdr, |
470 | const struct nsm_args *argp) | 470 | const struct nsm_args *argp) |
471 | { | 471 | { |
472 | encode_mon_id(xdr, argp); | 472 | encode_mon_id(xdr, argp); |
473 | } | 473 | } |
474 | 474 | ||
475 | static int nsm_xdr_dec_stat_res(struct rpc_rqst *rqstp, | 475 | static int nsm_xdr_dec_stat_res(struct rpc_rqst *rqstp, |
476 | struct xdr_stream *xdr, | 476 | struct xdr_stream *xdr, |
477 | struct nsm_res *resp) | 477 | struct nsm_res *resp) |
478 | { | 478 | { |
479 | __be32 *p; | 479 | __be32 *p; |
480 | 480 | ||
481 | p = xdr_inline_decode(xdr, 4 + 4); | 481 | p = xdr_inline_decode(xdr, 4 + 4); |
482 | if (unlikely(p == NULL)) | 482 | if (unlikely(p == NULL)) |
483 | return -EIO; | 483 | return -EIO; |
484 | resp->status = be32_to_cpup(p++); | 484 | resp->status = be32_to_cpup(p++); |
485 | resp->state = be32_to_cpup(p); | 485 | resp->state = be32_to_cpup(p); |
486 | 486 | ||
487 | dprintk("lockd: %s status %d state %d\n", | 487 | dprintk("lockd: %s status %d state %d\n", |
488 | __func__, resp->status, resp->state); | 488 | __func__, resp->status, resp->state); |
489 | return 0; | 489 | return 0; |
490 | } | 490 | } |
491 | 491 | ||
492 | static int nsm_xdr_dec_stat(struct rpc_rqst *rqstp, | 492 | static int nsm_xdr_dec_stat(struct rpc_rqst *rqstp, |
493 | struct xdr_stream *xdr, | 493 | struct xdr_stream *xdr, |
494 | struct nsm_res *resp) | 494 | struct nsm_res *resp) |
495 | { | 495 | { |
496 | __be32 *p; | 496 | __be32 *p; |
497 | 497 | ||
498 | p = xdr_inline_decode(xdr, 4); | 498 | p = xdr_inline_decode(xdr, 4); |
499 | if (unlikely(p == NULL)) | 499 | if (unlikely(p == NULL)) |
500 | return -EIO; | 500 | return -EIO; |
501 | resp->state = be32_to_cpup(p); | 501 | resp->state = be32_to_cpup(p); |
502 | 502 | ||
503 | dprintk("lockd: %s state %d\n", __func__, resp->state); | 503 | dprintk("lockd: %s state %d\n", __func__, resp->state); |
504 | return 0; | 504 | return 0; |
505 | } | 505 | } |
506 | 506 | ||
507 | #define SM_my_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN)) | 507 | #define SM_my_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN)) |
508 | #define SM_my_id_sz (SM_my_name_sz+3) | 508 | #define SM_my_id_sz (SM_my_name_sz+3) |
509 | #define SM_mon_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN)) | 509 | #define SM_mon_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN)) |
510 | #define SM_mon_id_sz (SM_mon_name_sz+SM_my_id_sz) | 510 | #define SM_mon_id_sz (SM_mon_name_sz+SM_my_id_sz) |
511 | #define SM_priv_sz (XDR_QUADLEN(SM_PRIV_SIZE)) | 511 | #define SM_priv_sz (XDR_QUADLEN(SM_PRIV_SIZE)) |
512 | #define SM_mon_sz (SM_mon_id_sz+SM_priv_sz) | 512 | #define SM_mon_sz (SM_mon_id_sz+SM_priv_sz) |
513 | #define SM_monres_sz 2 | 513 | #define SM_monres_sz 2 |
514 | #define SM_unmonres_sz 1 | 514 | #define SM_unmonres_sz 1 |
515 | 515 | ||
516 | static struct rpc_procinfo nsm_procedures[] = { | 516 | static struct rpc_procinfo nsm_procedures[] = { |
517 | [NSMPROC_MON] = { | 517 | [NSMPROC_MON] = { |
518 | .p_proc = NSMPROC_MON, | 518 | .p_proc = NSMPROC_MON, |
519 | .p_encode = (kxdreproc_t)nsm_xdr_enc_mon, | 519 | .p_encode = (kxdreproc_t)nsm_xdr_enc_mon, |
520 | .p_decode = (kxdrdproc_t)nsm_xdr_dec_stat_res, | 520 | .p_decode = (kxdrdproc_t)nsm_xdr_dec_stat_res, |
521 | .p_arglen = SM_mon_sz, | 521 | .p_arglen = SM_mon_sz, |
522 | .p_replen = SM_monres_sz, | 522 | .p_replen = SM_monres_sz, |
523 | .p_statidx = NSMPROC_MON, | 523 | .p_statidx = NSMPROC_MON, |
524 | .p_name = "MONITOR", | 524 | .p_name = "MONITOR", |
525 | }, | 525 | }, |
526 | [NSMPROC_UNMON] = { | 526 | [NSMPROC_UNMON] = { |
527 | .p_proc = NSMPROC_UNMON, | 527 | .p_proc = NSMPROC_UNMON, |
528 | .p_encode = (kxdreproc_t)nsm_xdr_enc_unmon, | 528 | .p_encode = (kxdreproc_t)nsm_xdr_enc_unmon, |
529 | .p_decode = (kxdrdproc_t)nsm_xdr_dec_stat, | 529 | .p_decode = (kxdrdproc_t)nsm_xdr_dec_stat, |
530 | .p_arglen = SM_mon_id_sz, | 530 | .p_arglen = SM_mon_id_sz, |
531 | .p_replen = SM_unmonres_sz, | 531 | .p_replen = SM_unmonres_sz, |
532 | .p_statidx = NSMPROC_UNMON, | 532 | .p_statidx = NSMPROC_UNMON, |
533 | .p_name = "UNMONITOR", | 533 | .p_name = "UNMONITOR", |
534 | }, | 534 | }, |
535 | }; | 535 | }; |
536 | 536 | ||
537 | static struct rpc_version nsm_version1 = { | 537 | static const struct rpc_version nsm_version1 = { |
538 | .number = 1, | 538 | .number = 1, |
539 | .nrprocs = ARRAY_SIZE(nsm_procedures), | 539 | .nrprocs = ARRAY_SIZE(nsm_procedures), |
540 | .procs = nsm_procedures | 540 | .procs = nsm_procedures |
541 | }; | 541 | }; |
542 | 542 | ||
543 | static struct rpc_version * nsm_version[] = { | 543 | static const struct rpc_version *nsm_version[] = { |
544 | [1] = &nsm_version1, | 544 | [1] = &nsm_version1, |
545 | }; | 545 | }; |
546 | 546 | ||
547 | static struct rpc_stat nsm_stats; | 547 | static struct rpc_stat nsm_stats; |
548 | 548 | ||
549 | static struct rpc_program nsm_program = { | 549 | static const struct rpc_program nsm_program = { |
550 | .name = "statd", | 550 | .name = "statd", |
551 | .number = NSM_PROGRAM, | 551 | .number = NSM_PROGRAM, |
552 | .nrvers = ARRAY_SIZE(nsm_version), | 552 | .nrvers = ARRAY_SIZE(nsm_version), |
553 | .version = nsm_version, | 553 | .version = nsm_version, |
554 | .stats = &nsm_stats | 554 | .stats = &nsm_stats |
555 | }; | 555 | }; |
556 | 556 |
fs/nfs/client.c
1 | /* client.c: NFS client sharing and management code | 1 | /* client.c: NFS client sharing and management code |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/stat.h> | 20 | #include <linux/stat.h> |
21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
22 | #include <linux/unistd.h> | 22 | #include <linux/unistd.h> |
23 | #include <linux/sunrpc/clnt.h> | 23 | #include <linux/sunrpc/clnt.h> |
24 | #include <linux/sunrpc/stats.h> | 24 | #include <linux/sunrpc/stats.h> |
25 | #include <linux/sunrpc/metrics.h> | 25 | #include <linux/sunrpc/metrics.h> |
26 | #include <linux/sunrpc/xprtsock.h> | 26 | #include <linux/sunrpc/xprtsock.h> |
27 | #include <linux/sunrpc/xprtrdma.h> | 27 | #include <linux/sunrpc/xprtrdma.h> |
28 | #include <linux/nfs_fs.h> | 28 | #include <linux/nfs_fs.h> |
29 | #include <linux/nfs_mount.h> | 29 | #include <linux/nfs_mount.h> |
30 | #include <linux/nfs4_mount.h> | 30 | #include <linux/nfs4_mount.h> |
31 | #include <linux/lockd/bind.h> | 31 | #include <linux/lockd/bind.h> |
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #include <linux/mount.h> | 33 | #include <linux/mount.h> |
34 | #include <linux/nfs_idmap.h> | 34 | #include <linux/nfs_idmap.h> |
35 | #include <linux/vfs.h> | 35 | #include <linux/vfs.h> |
36 | #include <linux/inet.h> | 36 | #include <linux/inet.h> |
37 | #include <linux/in6.h> | 37 | #include <linux/in6.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <net/ipv6.h> | 39 | #include <net/ipv6.h> |
40 | #include <linux/nfs_xdr.h> | 40 | #include <linux/nfs_xdr.h> |
41 | #include <linux/sunrpc/bc_xprt.h> | 41 | #include <linux/sunrpc/bc_xprt.h> |
42 | 42 | ||
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | 44 | ||
45 | #include "nfs4_fs.h" | 45 | #include "nfs4_fs.h" |
46 | #include "callback.h" | 46 | #include "callback.h" |
47 | #include "delegation.h" | 47 | #include "delegation.h" |
48 | #include "iostat.h" | 48 | #include "iostat.h" |
49 | #include "internal.h" | 49 | #include "internal.h" |
50 | #include "fscache.h" | 50 | #include "fscache.h" |
51 | #include "pnfs.h" | 51 | #include "pnfs.h" |
52 | 52 | ||
53 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 53 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
54 | 54 | ||
55 | DEFINE_SPINLOCK(nfs_client_lock); | 55 | DEFINE_SPINLOCK(nfs_client_lock); |
56 | LIST_HEAD(nfs_client_list); | 56 | LIST_HEAD(nfs_client_list); |
57 | static LIST_HEAD(nfs_volume_list); | 57 | static LIST_HEAD(nfs_volume_list); |
58 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); | 58 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); |
59 | #ifdef CONFIG_NFS_V4 | 59 | #ifdef CONFIG_NFS_V4 |
60 | static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */ | 60 | static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */ |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * Get a unique NFSv4.0 callback identifier which will be used | 63 | * Get a unique NFSv4.0 callback identifier which will be used |
64 | * by the V4.0 callback service to lookup the nfs_client struct | 64 | * by the V4.0 callback service to lookup the nfs_client struct |
65 | */ | 65 | */ |
66 | static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) | 66 | static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) |
67 | { | 67 | { |
68 | int ret = 0; | 68 | int ret = 0; |
69 | 69 | ||
70 | if (clp->rpc_ops->version != 4 || minorversion != 0) | 70 | if (clp->rpc_ops->version != 4 || minorversion != 0) |
71 | return ret; | 71 | return ret; |
72 | retry: | 72 | retry: |
73 | if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL)) | 73 | if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL)) |
74 | return -ENOMEM; | 74 | return -ENOMEM; |
75 | spin_lock(&nfs_client_lock); | 75 | spin_lock(&nfs_client_lock); |
76 | ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident); | 76 | ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident); |
77 | spin_unlock(&nfs_client_lock); | 77 | spin_unlock(&nfs_client_lock); |
78 | if (ret == -EAGAIN) | 78 | if (ret == -EAGAIN) |
79 | goto retry; | 79 | goto retry; |
80 | return ret; | 80 | return ret; |
81 | } | 81 | } |
82 | #endif /* CONFIG_NFS_V4 */ | 82 | #endif /* CONFIG_NFS_V4 */ |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * Turn off NFSv4 uid/gid mapping when using AUTH_SYS | 85 | * Turn off NFSv4 uid/gid mapping when using AUTH_SYS |
86 | */ | 86 | */ |
87 | static bool nfs4_disable_idmapping = true; | 87 | static bool nfs4_disable_idmapping = true; |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * RPC cruft for NFS | 90 | * RPC cruft for NFS |
91 | */ | 91 | */ |
92 | static struct rpc_version *nfs_version[5] = { | 92 | static const struct rpc_version *nfs_version[5] = { |
93 | [2] = &nfs_version2, | 93 | [2] = &nfs_version2, |
94 | #ifdef CONFIG_NFS_V3 | 94 | #ifdef CONFIG_NFS_V3 |
95 | [3] = &nfs_version3, | 95 | [3] = &nfs_version3, |
96 | #endif | 96 | #endif |
97 | #ifdef CONFIG_NFS_V4 | 97 | #ifdef CONFIG_NFS_V4 |
98 | [4] = &nfs_version4, | 98 | [4] = &nfs_version4, |
99 | #endif | 99 | #endif |
100 | }; | 100 | }; |
101 | 101 | ||
102 | struct rpc_program nfs_program = { | 102 | const struct rpc_program nfs_program = { |
103 | .name = "nfs", | 103 | .name = "nfs", |
104 | .number = NFS_PROGRAM, | 104 | .number = NFS_PROGRAM, |
105 | .nrvers = ARRAY_SIZE(nfs_version), | 105 | .nrvers = ARRAY_SIZE(nfs_version), |
106 | .version = nfs_version, | 106 | .version = nfs_version, |
107 | .stats = &nfs_rpcstat, | 107 | .stats = &nfs_rpcstat, |
108 | .pipe_dir_name = NFS_PIPE_DIRNAME, | 108 | .pipe_dir_name = NFS_PIPE_DIRNAME, |
109 | }; | 109 | }; |
110 | 110 | ||
111 | struct rpc_stat nfs_rpcstat = { | 111 | struct rpc_stat nfs_rpcstat = { |
112 | .program = &nfs_program | 112 | .program = &nfs_program |
113 | }; | 113 | }; |
114 | 114 | ||
115 | 115 | ||
116 | #ifdef CONFIG_NFS_V3_ACL | 116 | #ifdef CONFIG_NFS_V3_ACL |
117 | static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; | 117 | static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; |
118 | static struct rpc_version * nfsacl_version[] = { | 118 | static const struct rpc_version *nfsacl_version[] = { |
119 | [3] = &nfsacl_version3, | 119 | [3] = &nfsacl_version3, |
120 | }; | 120 | }; |
121 | 121 | ||
122 | struct rpc_program nfsacl_program = { | 122 | const struct rpc_program nfsacl_program = { |
123 | .name = "nfsacl", | 123 | .name = "nfsacl", |
124 | .number = NFS_ACL_PROGRAM, | 124 | .number = NFS_ACL_PROGRAM, |
125 | .nrvers = ARRAY_SIZE(nfsacl_version), | 125 | .nrvers = ARRAY_SIZE(nfsacl_version), |
126 | .version = nfsacl_version, | 126 | .version = nfsacl_version, |
127 | .stats = &nfsacl_rpcstat, | 127 | .stats = &nfsacl_rpcstat, |
128 | }; | 128 | }; |
129 | #endif /* CONFIG_NFS_V3_ACL */ | 129 | #endif /* CONFIG_NFS_V3_ACL */ |
130 | 130 | ||
131 | struct nfs_client_initdata { | 131 | struct nfs_client_initdata { |
132 | const char *hostname; | 132 | const char *hostname; |
133 | const struct sockaddr *addr; | 133 | const struct sockaddr *addr; |
134 | size_t addrlen; | 134 | size_t addrlen; |
135 | const struct nfs_rpc_ops *rpc_ops; | 135 | const struct nfs_rpc_ops *rpc_ops; |
136 | int proto; | 136 | int proto; |
137 | u32 minorversion; | 137 | u32 minorversion; |
138 | struct net *net; | 138 | struct net *net; |
139 | }; | 139 | }; |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * Allocate a shared client record | 142 | * Allocate a shared client record |
143 | * | 143 | * |
144 | * Since these are allocated/deallocated very rarely, we don't | 144 | * Since these are allocated/deallocated very rarely, we don't |
145 | * bother putting them in a slab cache... | 145 | * bother putting them in a slab cache... |
146 | */ | 146 | */ |
147 | static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) | 147 | static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) |
148 | { | 148 | { |
149 | struct nfs_client *clp; | 149 | struct nfs_client *clp; |
150 | struct rpc_cred *cred; | 150 | struct rpc_cred *cred; |
151 | int err = -ENOMEM; | 151 | int err = -ENOMEM; |
152 | 152 | ||
153 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) | 153 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) |
154 | goto error_0; | 154 | goto error_0; |
155 | 155 | ||
156 | clp->rpc_ops = cl_init->rpc_ops; | 156 | clp->rpc_ops = cl_init->rpc_ops; |
157 | 157 | ||
158 | atomic_set(&clp->cl_count, 1); | 158 | atomic_set(&clp->cl_count, 1); |
159 | clp->cl_cons_state = NFS_CS_INITING; | 159 | clp->cl_cons_state = NFS_CS_INITING; |
160 | 160 | ||
161 | memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen); | 161 | memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen); |
162 | clp->cl_addrlen = cl_init->addrlen; | 162 | clp->cl_addrlen = cl_init->addrlen; |
163 | 163 | ||
164 | if (cl_init->hostname) { | 164 | if (cl_init->hostname) { |
165 | err = -ENOMEM; | 165 | err = -ENOMEM; |
166 | clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); | 166 | clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); |
167 | if (!clp->cl_hostname) | 167 | if (!clp->cl_hostname) |
168 | goto error_cleanup; | 168 | goto error_cleanup; |
169 | } | 169 | } |
170 | 170 | ||
171 | INIT_LIST_HEAD(&clp->cl_superblocks); | 171 | INIT_LIST_HEAD(&clp->cl_superblocks); |
172 | clp->cl_rpcclient = ERR_PTR(-EINVAL); | 172 | clp->cl_rpcclient = ERR_PTR(-EINVAL); |
173 | 173 | ||
174 | clp->cl_proto = cl_init->proto; | 174 | clp->cl_proto = cl_init->proto; |
175 | 175 | ||
176 | #ifdef CONFIG_NFS_V4 | 176 | #ifdef CONFIG_NFS_V4 |
177 | err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); | 177 | err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); |
178 | if (err) | 178 | if (err) |
179 | goto error_cleanup; | 179 | goto error_cleanup; |
180 | 180 | ||
181 | spin_lock_init(&clp->cl_lock); | 181 | spin_lock_init(&clp->cl_lock); |
182 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | 182 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); |
183 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | 183 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); |
184 | clp->cl_boot_time = CURRENT_TIME; | 184 | clp->cl_boot_time = CURRENT_TIME; |
185 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | 185 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; |
186 | clp->cl_minorversion = cl_init->minorversion; | 186 | clp->cl_minorversion = cl_init->minorversion; |
187 | clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; | 187 | clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; |
188 | #endif | 188 | #endif |
189 | cred = rpc_lookup_machine_cred("*"); | 189 | cred = rpc_lookup_machine_cred("*"); |
190 | if (!IS_ERR(cred)) | 190 | if (!IS_ERR(cred)) |
191 | clp->cl_machine_cred = cred; | 191 | clp->cl_machine_cred = cred; |
192 | nfs_fscache_get_client_cookie(clp); | 192 | nfs_fscache_get_client_cookie(clp); |
193 | clp->net = cl_init->net; | 193 | clp->net = cl_init->net; |
194 | 194 | ||
195 | return clp; | 195 | return clp; |
196 | 196 | ||
197 | error_cleanup: | 197 | error_cleanup: |
198 | kfree(clp); | 198 | kfree(clp); |
199 | error_0: | 199 | error_0: |
200 | return ERR_PTR(err); | 200 | return ERR_PTR(err); |
201 | } | 201 | } |
202 | 202 | ||
203 | #ifdef CONFIG_NFS_V4 | 203 | #ifdef CONFIG_NFS_V4 |
204 | #ifdef CONFIG_NFS_V4_1 | 204 | #ifdef CONFIG_NFS_V4_1 |
205 | static void nfs4_shutdown_session(struct nfs_client *clp) | 205 | static void nfs4_shutdown_session(struct nfs_client *clp) |
206 | { | 206 | { |
207 | if (nfs4_has_session(clp)) | 207 | if (nfs4_has_session(clp)) |
208 | nfs4_destroy_session(clp->cl_session); | 208 | nfs4_destroy_session(clp->cl_session); |
209 | } | 209 | } |
210 | #else /* CONFIG_NFS_V4_1 */ | 210 | #else /* CONFIG_NFS_V4_1 */ |
211 | static void nfs4_shutdown_session(struct nfs_client *clp) | 211 | static void nfs4_shutdown_session(struct nfs_client *clp) |
212 | { | 212 | { |
213 | } | 213 | } |
214 | #endif /* CONFIG_NFS_V4_1 */ | 214 | #endif /* CONFIG_NFS_V4_1 */ |
215 | 215 | ||
216 | /* | 216 | /* |
217 | * Destroy the NFS4 callback service | 217 | * Destroy the NFS4 callback service |
218 | */ | 218 | */ |
219 | static void nfs4_destroy_callback(struct nfs_client *clp) | 219 | static void nfs4_destroy_callback(struct nfs_client *clp) |
220 | { | 220 | { |
221 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) | 221 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) |
222 | nfs_callback_down(clp->cl_mvops->minor_version); | 222 | nfs_callback_down(clp->cl_mvops->minor_version); |
223 | } | 223 | } |
224 | 224 | ||
225 | static void nfs4_shutdown_client(struct nfs_client *clp) | 225 | static void nfs4_shutdown_client(struct nfs_client *clp) |
226 | { | 226 | { |
227 | if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) | 227 | if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) |
228 | nfs4_kill_renewd(clp); | 228 | nfs4_kill_renewd(clp); |
229 | nfs4_shutdown_session(clp); | 229 | nfs4_shutdown_session(clp); |
230 | nfs4_destroy_callback(clp); | 230 | nfs4_destroy_callback(clp); |
231 | if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) | 231 | if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) |
232 | nfs_idmap_delete(clp); | 232 | nfs_idmap_delete(clp); |
233 | 233 | ||
234 | rpc_destroy_wait_queue(&clp->cl_rpcwaitq); | 234 | rpc_destroy_wait_queue(&clp->cl_rpcwaitq); |
235 | } | 235 | } |
236 | 236 | ||
237 | /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ | 237 | /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ |
238 | void nfs_cleanup_cb_ident_idr(void) | 238 | void nfs_cleanup_cb_ident_idr(void) |
239 | { | 239 | { |
240 | idr_destroy(&cb_ident_idr); | 240 | idr_destroy(&cb_ident_idr); |
241 | } | 241 | } |
242 | 242 | ||
243 | /* nfs_client_lock held */ | 243 | /* nfs_client_lock held */ |
244 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) | 244 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) |
245 | { | 245 | { |
246 | if (clp->cl_cb_ident) | 246 | if (clp->cl_cb_ident) |
247 | idr_remove(&cb_ident_idr, clp->cl_cb_ident); | 247 | idr_remove(&cb_ident_idr, clp->cl_cb_ident); |
248 | } | 248 | } |
249 | 249 | ||
250 | static void pnfs_init_server(struct nfs_server *server) | 250 | static void pnfs_init_server(struct nfs_server *server) |
251 | { | 251 | { |
252 | rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC"); | 252 | rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC"); |
253 | } | 253 | } |
254 | 254 | ||
255 | static void nfs4_destroy_server(struct nfs_server *server) | 255 | static void nfs4_destroy_server(struct nfs_server *server) |
256 | { | 256 | { |
257 | nfs4_purge_state_owners(server); | 257 | nfs4_purge_state_owners(server); |
258 | } | 258 | } |
259 | 259 | ||
260 | #else | 260 | #else |
261 | static void nfs4_shutdown_client(struct nfs_client *clp) | 261 | static void nfs4_shutdown_client(struct nfs_client *clp) |
262 | { | 262 | { |
263 | } | 263 | } |
264 | 264 | ||
265 | void nfs_cleanup_cb_ident_idr(void) | 265 | void nfs_cleanup_cb_ident_idr(void) |
266 | { | 266 | { |
267 | } | 267 | } |
268 | 268 | ||
269 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) | 269 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) |
270 | { | 270 | { |
271 | } | 271 | } |
272 | 272 | ||
273 | static void pnfs_init_server(struct nfs_server *server) | 273 | static void pnfs_init_server(struct nfs_server *server) |
274 | { | 274 | { |
275 | } | 275 | } |
276 | 276 | ||
277 | #endif /* CONFIG_NFS_V4 */ | 277 | #endif /* CONFIG_NFS_V4 */ |
278 | 278 | ||
279 | /* | 279 | /* |
280 | * Destroy a shared client record | 280 | * Destroy a shared client record |
281 | */ | 281 | */ |
282 | static void nfs_free_client(struct nfs_client *clp) | 282 | static void nfs_free_client(struct nfs_client *clp) |
283 | { | 283 | { |
284 | dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); | 284 | dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); |
285 | 285 | ||
286 | nfs4_shutdown_client(clp); | 286 | nfs4_shutdown_client(clp); |
287 | 287 | ||
288 | nfs_fscache_release_client_cookie(clp); | 288 | nfs_fscache_release_client_cookie(clp); |
289 | 289 | ||
290 | /* -EIO all pending I/O */ | 290 | /* -EIO all pending I/O */ |
291 | if (!IS_ERR(clp->cl_rpcclient)) | 291 | if (!IS_ERR(clp->cl_rpcclient)) |
292 | rpc_shutdown_client(clp->cl_rpcclient); | 292 | rpc_shutdown_client(clp->cl_rpcclient); |
293 | 293 | ||
294 | if (clp->cl_machine_cred != NULL) | 294 | if (clp->cl_machine_cred != NULL) |
295 | put_rpccred(clp->cl_machine_cred); | 295 | put_rpccred(clp->cl_machine_cred); |
296 | 296 | ||
297 | nfs4_deviceid_purge_client(clp); | 297 | nfs4_deviceid_purge_client(clp); |
298 | 298 | ||
299 | kfree(clp->cl_hostname); | 299 | kfree(clp->cl_hostname); |
300 | kfree(clp->server_scope); | 300 | kfree(clp->server_scope); |
301 | kfree(clp); | 301 | kfree(clp); |
302 | 302 | ||
303 | dprintk("<-- nfs_free_client()\n"); | 303 | dprintk("<-- nfs_free_client()\n"); |
304 | } | 304 | } |
305 | 305 | ||
306 | /* | 306 | /* |
307 | * Release a reference to a shared client record | 307 | * Release a reference to a shared client record |
308 | */ | 308 | */ |
309 | void nfs_put_client(struct nfs_client *clp) | 309 | void nfs_put_client(struct nfs_client *clp) |
310 | { | 310 | { |
311 | if (!clp) | 311 | if (!clp) |
312 | return; | 312 | return; |
313 | 313 | ||
314 | dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count)); | 314 | dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count)); |
315 | 315 | ||
316 | if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { | 316 | if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { |
317 | list_del(&clp->cl_share_link); | 317 | list_del(&clp->cl_share_link); |
318 | nfs_cb_idr_remove_locked(clp); | 318 | nfs_cb_idr_remove_locked(clp); |
319 | spin_unlock(&nfs_client_lock); | 319 | spin_unlock(&nfs_client_lock); |
320 | 320 | ||
321 | BUG_ON(!list_empty(&clp->cl_superblocks)); | 321 | BUG_ON(!list_empty(&clp->cl_superblocks)); |
322 | 322 | ||
323 | nfs_free_client(clp); | 323 | nfs_free_client(clp); |
324 | } | 324 | } |
325 | } | 325 | } |
326 | EXPORT_SYMBOL_GPL(nfs_put_client); | 326 | EXPORT_SYMBOL_GPL(nfs_put_client); |
327 | 327 | ||
328 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 328 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
329 | /* | 329 | /* |
330 | * Test if two ip6 socket addresses refer to the same socket by | 330 | * Test if two ip6 socket addresses refer to the same socket by |
331 | * comparing relevant fields. The padding bytes specifically, are not | 331 | * comparing relevant fields. The padding bytes specifically, are not |
332 | * compared. sin6_flowinfo is not compared because it only affects QoS | 332 | * compared. sin6_flowinfo is not compared because it only affects QoS |
333 | * and sin6_scope_id is only compared if the address is "link local" | 333 | * and sin6_scope_id is only compared if the address is "link local" |
334 | * because "link local" addresses need only be unique to a specific | 334 | * because "link local" addresses need only be unique to a specific |
335 | * link. Conversely, ordinary unicast addresses might have different | 335 | * link. Conversely, ordinary unicast addresses might have different |
336 | * sin6_scope_id. | 336 | * sin6_scope_id. |
337 | * | 337 | * |
338 | * The caller should ensure both socket addresses are AF_INET6. | 338 | * The caller should ensure both socket addresses are AF_INET6. |
339 | */ | 339 | */ |
340 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | 340 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
341 | const struct sockaddr *sa2) | 341 | const struct sockaddr *sa2) |
342 | { | 342 | { |
343 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; | 343 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; |
344 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; | 344 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; |
345 | 345 | ||
346 | if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) | 346 | if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) |
347 | return 0; | 347 | return 0; |
348 | else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 348 | else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
349 | return sin1->sin6_scope_id == sin2->sin6_scope_id; | 349 | return sin1->sin6_scope_id == sin2->sin6_scope_id; |
350 | 350 | ||
351 | return 1; | 351 | return 1; |
352 | } | 352 | } |
353 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ | 353 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ |
354 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | 354 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
355 | const struct sockaddr *sa2) | 355 | const struct sockaddr *sa2) |
356 | { | 356 | { |
357 | return 0; | 357 | return 0; |
358 | } | 358 | } |
359 | #endif | 359 | #endif |
360 | 360 | ||
361 | /* | 361 | /* |
362 | * Test if two ip4 socket addresses refer to the same socket, by | 362 | * Test if two ip4 socket addresses refer to the same socket, by |
363 | * comparing relevant fields. The padding bytes specifically, are | 363 | * comparing relevant fields. The padding bytes specifically, are |
364 | * not compared. | 364 | * not compared. |
365 | * | 365 | * |
366 | * The caller should ensure both socket addresses are AF_INET. | 366 | * The caller should ensure both socket addresses are AF_INET. |
367 | */ | 367 | */ |
368 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1, | 368 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1, |
369 | const struct sockaddr *sa2) | 369 | const struct sockaddr *sa2) |
370 | { | 370 | { |
371 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; | 371 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; |
372 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; | 372 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; |
373 | 373 | ||
374 | return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; | 374 | return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; |
375 | } | 375 | } |
376 | 376 | ||
377 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, | 377 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, |
378 | const struct sockaddr *sa2) | 378 | const struct sockaddr *sa2) |
379 | { | 379 | { |
380 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; | 380 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; |
381 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; | 381 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; |
382 | 382 | ||
383 | return nfs_sockaddr_match_ipaddr6(sa1, sa2) && | 383 | return nfs_sockaddr_match_ipaddr6(sa1, sa2) && |
384 | (sin1->sin6_port == sin2->sin6_port); | 384 | (sin1->sin6_port == sin2->sin6_port); |
385 | } | 385 | } |
386 | 386 | ||
387 | static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, | 387 | static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, |
388 | const struct sockaddr *sa2) | 388 | const struct sockaddr *sa2) |
389 | { | 389 | { |
390 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; | 390 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; |
391 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; | 391 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; |
392 | 392 | ||
393 | return nfs_sockaddr_match_ipaddr4(sa1, sa2) && | 393 | return nfs_sockaddr_match_ipaddr4(sa1, sa2) && |
394 | (sin1->sin_port == sin2->sin_port); | 394 | (sin1->sin_port == sin2->sin_port); |
395 | } | 395 | } |
396 | 396 | ||
397 | /* | 397 | /* |
398 | * Test if two socket addresses represent the same actual socket, | 398 | * Test if two socket addresses represent the same actual socket, |
399 | * by comparing (only) relevant fields, excluding the port number. | 399 | * by comparing (only) relevant fields, excluding the port number. |
400 | */ | 400 | */ |
401 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | 401 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, |
402 | const struct sockaddr *sa2) | 402 | const struct sockaddr *sa2) |
403 | { | 403 | { |
404 | if (sa1->sa_family != sa2->sa_family) | 404 | if (sa1->sa_family != sa2->sa_family) |
405 | return 0; | 405 | return 0; |
406 | 406 | ||
407 | switch (sa1->sa_family) { | 407 | switch (sa1->sa_family) { |
408 | case AF_INET: | 408 | case AF_INET: |
409 | return nfs_sockaddr_match_ipaddr4(sa1, sa2); | 409 | return nfs_sockaddr_match_ipaddr4(sa1, sa2); |
410 | case AF_INET6: | 410 | case AF_INET6: |
411 | return nfs_sockaddr_match_ipaddr6(sa1, sa2); | 411 | return nfs_sockaddr_match_ipaddr6(sa1, sa2); |
412 | } | 412 | } |
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | 415 | ||
416 | /* | 416 | /* |
417 | * Test if two socket addresses represent the same actual socket, | 417 | * Test if two socket addresses represent the same actual socket, |
418 | * by comparing (only) relevant fields, including the port number. | 418 | * by comparing (only) relevant fields, including the port number. |
419 | */ | 419 | */ |
420 | static int nfs_sockaddr_cmp(const struct sockaddr *sa1, | 420 | static int nfs_sockaddr_cmp(const struct sockaddr *sa1, |
421 | const struct sockaddr *sa2) | 421 | const struct sockaddr *sa2) |
422 | { | 422 | { |
423 | if (sa1->sa_family != sa2->sa_family) | 423 | if (sa1->sa_family != sa2->sa_family) |
424 | return 0; | 424 | return 0; |
425 | 425 | ||
426 | switch (sa1->sa_family) { | 426 | switch (sa1->sa_family) { |
427 | case AF_INET: | 427 | case AF_INET: |
428 | return nfs_sockaddr_cmp_ip4(sa1, sa2); | 428 | return nfs_sockaddr_cmp_ip4(sa1, sa2); |
429 | case AF_INET6: | 429 | case AF_INET6: |
430 | return nfs_sockaddr_cmp_ip6(sa1, sa2); | 430 | return nfs_sockaddr_cmp_ip6(sa1, sa2); |
431 | } | 431 | } |
432 | return 0; | 432 | return 0; |
433 | } | 433 | } |
434 | 434 | ||
435 | /* Common match routine for v4.0 and v4.1 callback services */ | 435 | /* Common match routine for v4.0 and v4.1 callback services */ |
436 | bool | 436 | bool |
437 | nfs4_cb_match_client(const struct sockaddr *addr, struct nfs_client *clp, | 437 | nfs4_cb_match_client(const struct sockaddr *addr, struct nfs_client *clp, |
438 | u32 minorversion) | 438 | u32 minorversion) |
439 | { | 439 | { |
440 | struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; | 440 | struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; |
441 | 441 | ||
442 | /* Don't match clients that failed to initialise */ | 442 | /* Don't match clients that failed to initialise */ |
443 | if (!(clp->cl_cons_state == NFS_CS_READY || | 443 | if (!(clp->cl_cons_state == NFS_CS_READY || |
444 | clp->cl_cons_state == NFS_CS_SESSION_INITING)) | 444 | clp->cl_cons_state == NFS_CS_SESSION_INITING)) |
445 | return false; | 445 | return false; |
446 | 446 | ||
447 | /* Match the version and minorversion */ | 447 | /* Match the version and minorversion */ |
448 | if (clp->rpc_ops->version != 4 || | 448 | if (clp->rpc_ops->version != 4 || |
449 | clp->cl_minorversion != minorversion) | 449 | clp->cl_minorversion != minorversion) |
450 | return false; | 450 | return false; |
451 | 451 | ||
452 | /* Match only the IP address, not the port number */ | 452 | /* Match only the IP address, not the port number */ |
453 | if (!nfs_sockaddr_match_ipaddr(addr, clap)) | 453 | if (!nfs_sockaddr_match_ipaddr(addr, clap)) |
454 | return false; | 454 | return false; |
455 | 455 | ||
456 | return true; | 456 | return true; |
457 | } | 457 | } |
458 | 458 | ||
459 | /* | 459 | /* |
460 | * Find an nfs_client on the list that matches the initialisation data | 460 | * Find an nfs_client on the list that matches the initialisation data |
461 | * that is supplied. | 461 | * that is supplied. |
462 | */ | 462 | */ |
463 | static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data) | 463 | static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data) |
464 | { | 464 | { |
465 | struct nfs_client *clp; | 465 | struct nfs_client *clp; |
466 | const struct sockaddr *sap = data->addr; | 466 | const struct sockaddr *sap = data->addr; |
467 | 467 | ||
468 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { | 468 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { |
469 | const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; | 469 | const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; |
470 | /* Don't match clients that failed to initialise properly */ | 470 | /* Don't match clients that failed to initialise properly */ |
471 | if (clp->cl_cons_state < 0) | 471 | if (clp->cl_cons_state < 0) |
472 | continue; | 472 | continue; |
473 | 473 | ||
474 | /* Different NFS versions cannot share the same nfs_client */ | 474 | /* Different NFS versions cannot share the same nfs_client */ |
475 | if (clp->rpc_ops != data->rpc_ops) | 475 | if (clp->rpc_ops != data->rpc_ops) |
476 | continue; | 476 | continue; |
477 | 477 | ||
478 | if (clp->cl_proto != data->proto) | 478 | if (clp->cl_proto != data->proto) |
479 | continue; | 479 | continue; |
480 | /* Match nfsv4 minorversion */ | 480 | /* Match nfsv4 minorversion */ |
481 | if (clp->cl_minorversion != data->minorversion) | 481 | if (clp->cl_minorversion != data->minorversion) |
482 | continue; | 482 | continue; |
483 | /* Match the full socket address */ | 483 | /* Match the full socket address */ |
484 | if (!nfs_sockaddr_cmp(sap, clap)) | 484 | if (!nfs_sockaddr_cmp(sap, clap)) |
485 | continue; | 485 | continue; |
486 | /* Match network namespace */ | 486 | /* Match network namespace */ |
487 | if (clp->net != data->net) | 487 | if (clp->net != data->net) |
488 | continue; | 488 | continue; |
489 | 489 | ||
490 | atomic_inc(&clp->cl_count); | 490 | atomic_inc(&clp->cl_count); |
491 | return clp; | 491 | return clp; |
492 | } | 492 | } |
493 | return NULL; | 493 | return NULL; |
494 | } | 494 | } |
495 | 495 | ||
496 | /* | 496 | /* |
497 | * Look up a client by IP address and protocol version | 497 | * Look up a client by IP address and protocol version |
498 | * - creates a new record if one doesn't yet exist | 498 | * - creates a new record if one doesn't yet exist |
499 | */ | 499 | */ |
500 | static struct nfs_client * | 500 | static struct nfs_client * |
501 | nfs_get_client(const struct nfs_client_initdata *cl_init, | 501 | nfs_get_client(const struct nfs_client_initdata *cl_init, |
502 | const struct rpc_timeout *timeparms, | 502 | const struct rpc_timeout *timeparms, |
503 | const char *ip_addr, | 503 | const char *ip_addr, |
504 | rpc_authflavor_t authflavour, | 504 | rpc_authflavor_t authflavour, |
505 | int noresvport) | 505 | int noresvport) |
506 | { | 506 | { |
507 | struct nfs_client *clp, *new = NULL; | 507 | struct nfs_client *clp, *new = NULL; |
508 | int error; | 508 | int error; |
509 | 509 | ||
510 | dprintk("--> nfs_get_client(%s,v%u)\n", | 510 | dprintk("--> nfs_get_client(%s,v%u)\n", |
511 | cl_init->hostname ?: "", cl_init->rpc_ops->version); | 511 | cl_init->hostname ?: "", cl_init->rpc_ops->version); |
512 | 512 | ||
513 | /* see if the client already exists */ | 513 | /* see if the client already exists */ |
514 | do { | 514 | do { |
515 | spin_lock(&nfs_client_lock); | 515 | spin_lock(&nfs_client_lock); |
516 | 516 | ||
517 | clp = nfs_match_client(cl_init); | 517 | clp = nfs_match_client(cl_init); |
518 | if (clp) | 518 | if (clp) |
519 | goto found_client; | 519 | goto found_client; |
520 | if (new) | 520 | if (new) |
521 | goto install_client; | 521 | goto install_client; |
522 | 522 | ||
523 | spin_unlock(&nfs_client_lock); | 523 | spin_unlock(&nfs_client_lock); |
524 | 524 | ||
525 | new = nfs_alloc_client(cl_init); | 525 | new = nfs_alloc_client(cl_init); |
526 | } while (!IS_ERR(new)); | 526 | } while (!IS_ERR(new)); |
527 | 527 | ||
528 | dprintk("--> nfs_get_client() = %ld [failed]\n", PTR_ERR(new)); | 528 | dprintk("--> nfs_get_client() = %ld [failed]\n", PTR_ERR(new)); |
529 | return new; | 529 | return new; |
530 | 530 | ||
531 | /* install a new client and return with it unready */ | 531 | /* install a new client and return with it unready */ |
532 | install_client: | 532 | install_client: |
533 | clp = new; | 533 | clp = new; |
534 | list_add(&clp->cl_share_link, &nfs_client_list); | 534 | list_add(&clp->cl_share_link, &nfs_client_list); |
535 | spin_unlock(&nfs_client_lock); | 535 | spin_unlock(&nfs_client_lock); |
536 | 536 | ||
537 | error = cl_init->rpc_ops->init_client(clp, timeparms, ip_addr, | 537 | error = cl_init->rpc_ops->init_client(clp, timeparms, ip_addr, |
538 | authflavour, noresvport); | 538 | authflavour, noresvport); |
539 | if (error < 0) { | 539 | if (error < 0) { |
540 | nfs_put_client(clp); | 540 | nfs_put_client(clp); |
541 | return ERR_PTR(error); | 541 | return ERR_PTR(error); |
542 | } | 542 | } |
543 | dprintk("--> nfs_get_client() = %p [new]\n", clp); | 543 | dprintk("--> nfs_get_client() = %p [new]\n", clp); |
544 | return clp; | 544 | return clp; |
545 | 545 | ||
546 | /* found an existing client | 546 | /* found an existing client |
547 | * - make sure it's ready before returning | 547 | * - make sure it's ready before returning |
548 | */ | 548 | */ |
549 | found_client: | 549 | found_client: |
550 | spin_unlock(&nfs_client_lock); | 550 | spin_unlock(&nfs_client_lock); |
551 | 551 | ||
552 | if (new) | 552 | if (new) |
553 | nfs_free_client(new); | 553 | nfs_free_client(new); |
554 | 554 | ||
555 | error = wait_event_killable(nfs_client_active_wq, | 555 | error = wait_event_killable(nfs_client_active_wq, |
556 | clp->cl_cons_state < NFS_CS_INITING); | 556 | clp->cl_cons_state < NFS_CS_INITING); |
557 | if (error < 0) { | 557 | if (error < 0) { |
558 | nfs_put_client(clp); | 558 | nfs_put_client(clp); |
559 | return ERR_PTR(-ERESTARTSYS); | 559 | return ERR_PTR(-ERESTARTSYS); |
560 | } | 560 | } |
561 | 561 | ||
562 | if (clp->cl_cons_state < NFS_CS_READY) { | 562 | if (clp->cl_cons_state < NFS_CS_READY) { |
563 | error = clp->cl_cons_state; | 563 | error = clp->cl_cons_state; |
564 | nfs_put_client(clp); | 564 | nfs_put_client(clp); |
565 | return ERR_PTR(error); | 565 | return ERR_PTR(error); |
566 | } | 566 | } |
567 | 567 | ||
568 | BUG_ON(clp->cl_cons_state != NFS_CS_READY); | 568 | BUG_ON(clp->cl_cons_state != NFS_CS_READY); |
569 | 569 | ||
570 | dprintk("--> nfs_get_client() = %p [share]\n", clp); | 570 | dprintk("--> nfs_get_client() = %p [share]\n", clp); |
571 | return clp; | 571 | return clp; |
572 | } | 572 | } |
573 | 573 | ||
574 | /* | 574 | /* |
575 | * Mark a server as ready or failed | 575 | * Mark a server as ready or failed |
576 | */ | 576 | */ |
577 | void nfs_mark_client_ready(struct nfs_client *clp, int state) | 577 | void nfs_mark_client_ready(struct nfs_client *clp, int state) |
578 | { | 578 | { |
579 | clp->cl_cons_state = state; | 579 | clp->cl_cons_state = state; |
580 | wake_up_all(&nfs_client_active_wq); | 580 | wake_up_all(&nfs_client_active_wq); |
581 | } | 581 | } |
582 | 582 | ||
583 | /* | 583 | /* |
584 | * With sessions, the client is not marked ready until after a | 584 | * With sessions, the client is not marked ready until after a |
585 | * successful EXCHANGE_ID and CREATE_SESSION. | 585 | * successful EXCHANGE_ID and CREATE_SESSION. |
586 | * | 586 | * |
587 | * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate | 587 | * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate |
588 | * other versions of NFS can be tried. | 588 | * other versions of NFS can be tried. |
589 | */ | 589 | */ |
590 | int nfs4_check_client_ready(struct nfs_client *clp) | 590 | int nfs4_check_client_ready(struct nfs_client *clp) |
591 | { | 591 | { |
592 | if (!nfs4_has_session(clp)) | 592 | if (!nfs4_has_session(clp)) |
593 | return 0; | 593 | return 0; |
594 | if (clp->cl_cons_state < NFS_CS_READY) | 594 | if (clp->cl_cons_state < NFS_CS_READY) |
595 | return -EPROTONOSUPPORT; | 595 | return -EPROTONOSUPPORT; |
596 | return 0; | 596 | return 0; |
597 | } | 597 | } |
598 | 598 | ||
599 | /* | 599 | /* |
600 | * Initialise the timeout values for a connection | 600 | * Initialise the timeout values for a connection |
601 | */ | 601 | */ |
602 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | 602 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, |
603 | unsigned int timeo, unsigned int retrans) | 603 | unsigned int timeo, unsigned int retrans) |
604 | { | 604 | { |
605 | to->to_initval = timeo * HZ / 10; | 605 | to->to_initval = timeo * HZ / 10; |
606 | to->to_retries = retrans; | 606 | to->to_retries = retrans; |
607 | 607 | ||
608 | switch (proto) { | 608 | switch (proto) { |
609 | case XPRT_TRANSPORT_TCP: | 609 | case XPRT_TRANSPORT_TCP: |
610 | case XPRT_TRANSPORT_RDMA: | 610 | case XPRT_TRANSPORT_RDMA: |
611 | if (to->to_retries == 0) | 611 | if (to->to_retries == 0) |
612 | to->to_retries = NFS_DEF_TCP_RETRANS; | 612 | to->to_retries = NFS_DEF_TCP_RETRANS; |
613 | if (to->to_initval == 0) | 613 | if (to->to_initval == 0) |
614 | to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10; | 614 | to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10; |
615 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | 615 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) |
616 | to->to_initval = NFS_MAX_TCP_TIMEOUT; | 616 | to->to_initval = NFS_MAX_TCP_TIMEOUT; |
617 | to->to_increment = to->to_initval; | 617 | to->to_increment = to->to_initval; |
618 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | 618 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); |
619 | if (to->to_maxval > NFS_MAX_TCP_TIMEOUT) | 619 | if (to->to_maxval > NFS_MAX_TCP_TIMEOUT) |
620 | to->to_maxval = NFS_MAX_TCP_TIMEOUT; | 620 | to->to_maxval = NFS_MAX_TCP_TIMEOUT; |
621 | if (to->to_maxval < to->to_initval) | 621 | if (to->to_maxval < to->to_initval) |
622 | to->to_maxval = to->to_initval; | 622 | to->to_maxval = to->to_initval; |
623 | to->to_exponential = 0; | 623 | to->to_exponential = 0; |
624 | break; | 624 | break; |
625 | case XPRT_TRANSPORT_UDP: | 625 | case XPRT_TRANSPORT_UDP: |
626 | if (to->to_retries == 0) | 626 | if (to->to_retries == 0) |
627 | to->to_retries = NFS_DEF_UDP_RETRANS; | 627 | to->to_retries = NFS_DEF_UDP_RETRANS; |
628 | if (!to->to_initval) | 628 | if (!to->to_initval) |
629 | to->to_initval = NFS_DEF_UDP_TIMEO * HZ / 10; | 629 | to->to_initval = NFS_DEF_UDP_TIMEO * HZ / 10; |
630 | if (to->to_initval > NFS_MAX_UDP_TIMEOUT) | 630 | if (to->to_initval > NFS_MAX_UDP_TIMEOUT) |
631 | to->to_initval = NFS_MAX_UDP_TIMEOUT; | 631 | to->to_initval = NFS_MAX_UDP_TIMEOUT; |
632 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; | 632 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; |
633 | to->to_exponential = 1; | 633 | to->to_exponential = 1; |
634 | break; | 634 | break; |
635 | default: | 635 | default: |
636 | BUG(); | 636 | BUG(); |
637 | } | 637 | } |
638 | } | 638 | } |
639 | 639 | ||
640 | /* | 640 | /* |
641 | * Create an RPC client handle | 641 | * Create an RPC client handle |
642 | */ | 642 | */ |
643 | static int nfs_create_rpc_client(struct nfs_client *clp, | 643 | static int nfs_create_rpc_client(struct nfs_client *clp, |
644 | const struct rpc_timeout *timeparms, | 644 | const struct rpc_timeout *timeparms, |
645 | rpc_authflavor_t flavor, | 645 | rpc_authflavor_t flavor, |
646 | int discrtry, int noresvport) | 646 | int discrtry, int noresvport) |
647 | { | 647 | { |
648 | struct rpc_clnt *clnt = NULL; | 648 | struct rpc_clnt *clnt = NULL; |
649 | struct rpc_create_args args = { | 649 | struct rpc_create_args args = { |
650 | .net = clp->net, | 650 | .net = clp->net, |
651 | .protocol = clp->cl_proto, | 651 | .protocol = clp->cl_proto, |
652 | .address = (struct sockaddr *)&clp->cl_addr, | 652 | .address = (struct sockaddr *)&clp->cl_addr, |
653 | .addrsize = clp->cl_addrlen, | 653 | .addrsize = clp->cl_addrlen, |
654 | .timeout = timeparms, | 654 | .timeout = timeparms, |
655 | .servername = clp->cl_hostname, | 655 | .servername = clp->cl_hostname, |
656 | .program = &nfs_program, | 656 | .program = &nfs_program, |
657 | .version = clp->rpc_ops->version, | 657 | .version = clp->rpc_ops->version, |
658 | .authflavor = flavor, | 658 | .authflavor = flavor, |
659 | }; | 659 | }; |
660 | 660 | ||
661 | if (discrtry) | 661 | if (discrtry) |
662 | args.flags |= RPC_CLNT_CREATE_DISCRTRY; | 662 | args.flags |= RPC_CLNT_CREATE_DISCRTRY; |
663 | if (noresvport) | 663 | if (noresvport) |
664 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | 664 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
665 | 665 | ||
666 | if (!IS_ERR(clp->cl_rpcclient)) | 666 | if (!IS_ERR(clp->cl_rpcclient)) |
667 | return 0; | 667 | return 0; |
668 | 668 | ||
669 | clnt = rpc_create(&args); | 669 | clnt = rpc_create(&args); |
670 | if (IS_ERR(clnt)) { | 670 | if (IS_ERR(clnt)) { |
671 | dprintk("%s: cannot create RPC client. Error = %ld\n", | 671 | dprintk("%s: cannot create RPC client. Error = %ld\n", |
672 | __func__, PTR_ERR(clnt)); | 672 | __func__, PTR_ERR(clnt)); |
673 | return PTR_ERR(clnt); | 673 | return PTR_ERR(clnt); |
674 | } | 674 | } |
675 | 675 | ||
676 | clp->cl_rpcclient = clnt; | 676 | clp->cl_rpcclient = clnt; |
677 | return 0; | 677 | return 0; |
678 | } | 678 | } |
679 | 679 | ||
680 | /* | 680 | /* |
681 | * Version 2 or 3 client destruction | 681 | * Version 2 or 3 client destruction |
682 | */ | 682 | */ |
683 | static void nfs_destroy_server(struct nfs_server *server) | 683 | static void nfs_destroy_server(struct nfs_server *server) |
684 | { | 684 | { |
685 | if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) || | 685 | if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) || |
686 | !(server->flags & NFS_MOUNT_LOCAL_FCNTL)) | 686 | !(server->flags & NFS_MOUNT_LOCAL_FCNTL)) |
687 | nlmclnt_done(server->nlm_host); | 687 | nlmclnt_done(server->nlm_host); |
688 | } | 688 | } |
689 | 689 | ||
690 | /* | 690 | /* |
691 | * Version 2 or 3 lockd setup | 691 | * Version 2 or 3 lockd setup |
692 | */ | 692 | */ |
693 | static int nfs_start_lockd(struct nfs_server *server) | 693 | static int nfs_start_lockd(struct nfs_server *server) |
694 | { | 694 | { |
695 | struct nlm_host *host; | 695 | struct nlm_host *host; |
696 | struct nfs_client *clp = server->nfs_client; | 696 | struct nfs_client *clp = server->nfs_client; |
697 | struct nlmclnt_initdata nlm_init = { | 697 | struct nlmclnt_initdata nlm_init = { |
698 | .hostname = clp->cl_hostname, | 698 | .hostname = clp->cl_hostname, |
699 | .address = (struct sockaddr *)&clp->cl_addr, | 699 | .address = (struct sockaddr *)&clp->cl_addr, |
700 | .addrlen = clp->cl_addrlen, | 700 | .addrlen = clp->cl_addrlen, |
701 | .nfs_version = clp->rpc_ops->version, | 701 | .nfs_version = clp->rpc_ops->version, |
702 | .noresvport = server->flags & NFS_MOUNT_NORESVPORT ? | 702 | .noresvport = server->flags & NFS_MOUNT_NORESVPORT ? |
703 | 1 : 0, | 703 | 1 : 0, |
704 | }; | 704 | }; |
705 | 705 | ||
706 | if (nlm_init.nfs_version > 3) | 706 | if (nlm_init.nfs_version > 3) |
707 | return 0; | 707 | return 0; |
708 | if ((server->flags & NFS_MOUNT_LOCAL_FLOCK) && | 708 | if ((server->flags & NFS_MOUNT_LOCAL_FLOCK) && |
709 | (server->flags & NFS_MOUNT_LOCAL_FCNTL)) | 709 | (server->flags & NFS_MOUNT_LOCAL_FCNTL)) |
710 | return 0; | 710 | return 0; |
711 | 711 | ||
712 | switch (clp->cl_proto) { | 712 | switch (clp->cl_proto) { |
713 | default: | 713 | default: |
714 | nlm_init.protocol = IPPROTO_TCP; | 714 | nlm_init.protocol = IPPROTO_TCP; |
715 | break; | 715 | break; |
716 | case XPRT_TRANSPORT_UDP: | 716 | case XPRT_TRANSPORT_UDP: |
717 | nlm_init.protocol = IPPROTO_UDP; | 717 | nlm_init.protocol = IPPROTO_UDP; |
718 | } | 718 | } |
719 | 719 | ||
720 | host = nlmclnt_init(&nlm_init); | 720 | host = nlmclnt_init(&nlm_init); |
721 | if (IS_ERR(host)) | 721 | if (IS_ERR(host)) |
722 | return PTR_ERR(host); | 722 | return PTR_ERR(host); |
723 | 723 | ||
724 | server->nlm_host = host; | 724 | server->nlm_host = host; |
725 | server->destroy = nfs_destroy_server; | 725 | server->destroy = nfs_destroy_server; |
726 | return 0; | 726 | return 0; |
727 | } | 727 | } |
728 | 728 | ||
729 | /* | 729 | /* |
730 | * Initialise an NFSv3 ACL client connection | 730 | * Initialise an NFSv3 ACL client connection |
731 | */ | 731 | */ |
732 | #ifdef CONFIG_NFS_V3_ACL | 732 | #ifdef CONFIG_NFS_V3_ACL |
733 | static void nfs_init_server_aclclient(struct nfs_server *server) | 733 | static void nfs_init_server_aclclient(struct nfs_server *server) |
734 | { | 734 | { |
735 | if (server->nfs_client->rpc_ops->version != 3) | 735 | if (server->nfs_client->rpc_ops->version != 3) |
736 | goto out_noacl; | 736 | goto out_noacl; |
737 | if (server->flags & NFS_MOUNT_NOACL) | 737 | if (server->flags & NFS_MOUNT_NOACL) |
738 | goto out_noacl; | 738 | goto out_noacl; |
739 | 739 | ||
740 | server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); | 740 | server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); |
741 | if (IS_ERR(server->client_acl)) | 741 | if (IS_ERR(server->client_acl)) |
742 | goto out_noacl; | 742 | goto out_noacl; |
743 | 743 | ||
744 | /* No errors! Assume that Sun nfsacls are supported */ | 744 | /* No errors! Assume that Sun nfsacls are supported */ |
745 | server->caps |= NFS_CAP_ACLS; | 745 | server->caps |= NFS_CAP_ACLS; |
746 | return; | 746 | return; |
747 | 747 | ||
748 | out_noacl: | 748 | out_noacl: |
749 | server->caps &= ~NFS_CAP_ACLS; | 749 | server->caps &= ~NFS_CAP_ACLS; |
750 | } | 750 | } |
751 | #else | 751 | #else |
752 | static inline void nfs_init_server_aclclient(struct nfs_server *server) | 752 | static inline void nfs_init_server_aclclient(struct nfs_server *server) |
753 | { | 753 | { |
754 | server->flags &= ~NFS_MOUNT_NOACL; | 754 | server->flags &= ~NFS_MOUNT_NOACL; |
755 | server->caps &= ~NFS_CAP_ACLS; | 755 | server->caps &= ~NFS_CAP_ACLS; |
756 | } | 756 | } |
757 | #endif | 757 | #endif |
758 | 758 | ||
759 | /* | 759 | /* |
760 | * Create a general RPC client | 760 | * Create a general RPC client |
761 | */ | 761 | */ |
762 | static int nfs_init_server_rpcclient(struct nfs_server *server, | 762 | static int nfs_init_server_rpcclient(struct nfs_server *server, |
763 | const struct rpc_timeout *timeo, | 763 | const struct rpc_timeout *timeo, |
764 | rpc_authflavor_t pseudoflavour) | 764 | rpc_authflavor_t pseudoflavour) |
765 | { | 765 | { |
766 | struct nfs_client *clp = server->nfs_client; | 766 | struct nfs_client *clp = server->nfs_client; |
767 | 767 | ||
768 | server->client = rpc_clone_client(clp->cl_rpcclient); | 768 | server->client = rpc_clone_client(clp->cl_rpcclient); |
769 | if (IS_ERR(server->client)) { | 769 | if (IS_ERR(server->client)) { |
770 | dprintk("%s: couldn't create rpc_client!\n", __func__); | 770 | dprintk("%s: couldn't create rpc_client!\n", __func__); |
771 | return PTR_ERR(server->client); | 771 | return PTR_ERR(server->client); |
772 | } | 772 | } |
773 | 773 | ||
774 | memcpy(&server->client->cl_timeout_default, | 774 | memcpy(&server->client->cl_timeout_default, |
775 | timeo, | 775 | timeo, |
776 | sizeof(server->client->cl_timeout_default)); | 776 | sizeof(server->client->cl_timeout_default)); |
777 | server->client->cl_timeout = &server->client->cl_timeout_default; | 777 | server->client->cl_timeout = &server->client->cl_timeout_default; |
778 | 778 | ||
779 | if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { | 779 | if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { |
780 | struct rpc_auth *auth; | 780 | struct rpc_auth *auth; |
781 | 781 | ||
782 | auth = rpcauth_create(pseudoflavour, server->client); | 782 | auth = rpcauth_create(pseudoflavour, server->client); |
783 | if (IS_ERR(auth)) { | 783 | if (IS_ERR(auth)) { |
784 | dprintk("%s: couldn't create credcache!\n", __func__); | 784 | dprintk("%s: couldn't create credcache!\n", __func__); |
785 | return PTR_ERR(auth); | 785 | return PTR_ERR(auth); |
786 | } | 786 | } |
787 | } | 787 | } |
788 | server->client->cl_softrtry = 0; | 788 | server->client->cl_softrtry = 0; |
789 | if (server->flags & NFS_MOUNT_SOFT) | 789 | if (server->flags & NFS_MOUNT_SOFT) |
790 | server->client->cl_softrtry = 1; | 790 | server->client->cl_softrtry = 1; |
791 | 791 | ||
792 | return 0; | 792 | return 0; |
793 | } | 793 | } |
794 | 794 | ||
795 | /* | 795 | /* |
796 | * Initialise an NFS2 or NFS3 client | 796 | * Initialise an NFS2 or NFS3 client |
797 | */ | 797 | */ |
798 | int nfs_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms, | 798 | int nfs_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms, |
799 | const char *ip_addr, rpc_authflavor_t authflavour, | 799 | const char *ip_addr, rpc_authflavor_t authflavour, |
800 | int noresvport) | 800 | int noresvport) |
801 | { | 801 | { |
802 | int error; | 802 | int error; |
803 | 803 | ||
804 | if (clp->cl_cons_state == NFS_CS_READY) { | 804 | if (clp->cl_cons_state == NFS_CS_READY) { |
805 | /* the client is already initialised */ | 805 | /* the client is already initialised */ |
806 | dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp); | 806 | dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp); |
807 | return 0; | 807 | return 0; |
808 | } | 808 | } |
809 | 809 | ||
810 | /* | 810 | /* |
811 | * Create a client RPC handle for doing FSSTAT with UNIX auth only | 811 | * Create a client RPC handle for doing FSSTAT with UNIX auth only |
812 | * - RFC 2623, sec 2.3.2 | 812 | * - RFC 2623, sec 2.3.2 |
813 | */ | 813 | */ |
814 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, | 814 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, |
815 | 0, noresvport); | 815 | 0, noresvport); |
816 | if (error < 0) | 816 | if (error < 0) |
817 | goto error; | 817 | goto error; |
818 | nfs_mark_client_ready(clp, NFS_CS_READY); | 818 | nfs_mark_client_ready(clp, NFS_CS_READY); |
819 | return 0; | 819 | return 0; |
820 | 820 | ||
821 | error: | 821 | error: |
822 | nfs_mark_client_ready(clp, error); | 822 | nfs_mark_client_ready(clp, error); |
823 | dprintk("<-- nfs_init_client() = xerror %d\n", error); | 823 | dprintk("<-- nfs_init_client() = xerror %d\n", error); |
824 | return error; | 824 | return error; |
825 | } | 825 | } |
826 | 826 | ||
827 | /* | 827 | /* |
828 | * Create a version 2 or 3 client | 828 | * Create a version 2 or 3 client |
829 | */ | 829 | */ |
830 | static int nfs_init_server(struct nfs_server *server, | 830 | static int nfs_init_server(struct nfs_server *server, |
831 | const struct nfs_parsed_mount_data *data) | 831 | const struct nfs_parsed_mount_data *data) |
832 | { | 832 | { |
833 | struct nfs_client_initdata cl_init = { | 833 | struct nfs_client_initdata cl_init = { |
834 | .hostname = data->nfs_server.hostname, | 834 | .hostname = data->nfs_server.hostname, |
835 | .addr = (const struct sockaddr *)&data->nfs_server.address, | 835 | .addr = (const struct sockaddr *)&data->nfs_server.address, |
836 | .addrlen = data->nfs_server.addrlen, | 836 | .addrlen = data->nfs_server.addrlen, |
837 | .rpc_ops = &nfs_v2_clientops, | 837 | .rpc_ops = &nfs_v2_clientops, |
838 | .proto = data->nfs_server.protocol, | 838 | .proto = data->nfs_server.protocol, |
839 | .net = data->net, | 839 | .net = data->net, |
840 | }; | 840 | }; |
841 | struct rpc_timeout timeparms; | 841 | struct rpc_timeout timeparms; |
842 | struct nfs_client *clp; | 842 | struct nfs_client *clp; |
843 | int error; | 843 | int error; |
844 | 844 | ||
845 | dprintk("--> nfs_init_server()\n"); | 845 | dprintk("--> nfs_init_server()\n"); |
846 | 846 | ||
847 | #ifdef CONFIG_NFS_V3 | 847 | #ifdef CONFIG_NFS_V3 |
848 | if (data->version == 3) | 848 | if (data->version == 3) |
849 | cl_init.rpc_ops = &nfs_v3_clientops; | 849 | cl_init.rpc_ops = &nfs_v3_clientops; |
850 | #endif | 850 | #endif |
851 | 851 | ||
852 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, | 852 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, |
853 | data->timeo, data->retrans); | 853 | data->timeo, data->retrans); |
854 | 854 | ||
855 | /* Allocate or find a client reference we can use */ | 855 | /* Allocate or find a client reference we can use */ |
856 | clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX, | 856 | clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX, |
857 | data->flags & NFS_MOUNT_NORESVPORT); | 857 | data->flags & NFS_MOUNT_NORESVPORT); |
858 | if (IS_ERR(clp)) { | 858 | if (IS_ERR(clp)) { |
859 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); | 859 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); |
860 | return PTR_ERR(clp); | 860 | return PTR_ERR(clp); |
861 | } | 861 | } |
862 | 862 | ||
863 | server->nfs_client = clp; | 863 | server->nfs_client = clp; |
864 | 864 | ||
865 | /* Initialise the client representation from the mount data */ | 865 | /* Initialise the client representation from the mount data */ |
866 | server->flags = data->flags; | 866 | server->flags = data->flags; |
867 | server->options = data->options; | 867 | server->options = data->options; |
868 | server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID| | 868 | server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID| |
869 | NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP| | 869 | NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP| |
870 | NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME; | 870 | NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME; |
871 | 871 | ||
872 | if (data->rsize) | 872 | if (data->rsize) |
873 | server->rsize = nfs_block_size(data->rsize, NULL); | 873 | server->rsize = nfs_block_size(data->rsize, NULL); |
874 | if (data->wsize) | 874 | if (data->wsize) |
875 | server->wsize = nfs_block_size(data->wsize, NULL); | 875 | server->wsize = nfs_block_size(data->wsize, NULL); |
876 | 876 | ||
877 | server->acregmin = data->acregmin * HZ; | 877 | server->acregmin = data->acregmin * HZ; |
878 | server->acregmax = data->acregmax * HZ; | 878 | server->acregmax = data->acregmax * HZ; |
879 | server->acdirmin = data->acdirmin * HZ; | 879 | server->acdirmin = data->acdirmin * HZ; |
880 | server->acdirmax = data->acdirmax * HZ; | 880 | server->acdirmax = data->acdirmax * HZ; |
881 | 881 | ||
882 | /* Start lockd here, before we might error out */ | 882 | /* Start lockd here, before we might error out */ |
883 | error = nfs_start_lockd(server); | 883 | error = nfs_start_lockd(server); |
884 | if (error < 0) | 884 | if (error < 0) |
885 | goto error; | 885 | goto error; |
886 | 886 | ||
887 | server->port = data->nfs_server.port; | 887 | server->port = data->nfs_server.port; |
888 | 888 | ||
889 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); | 889 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); |
890 | if (error < 0) | 890 | if (error < 0) |
891 | goto error; | 891 | goto error; |
892 | 892 | ||
893 | /* Preserve the values of mount_server-related mount options */ | 893 | /* Preserve the values of mount_server-related mount options */ |
894 | if (data->mount_server.addrlen) { | 894 | if (data->mount_server.addrlen) { |
895 | memcpy(&server->mountd_address, &data->mount_server.address, | 895 | memcpy(&server->mountd_address, &data->mount_server.address, |
896 | data->mount_server.addrlen); | 896 | data->mount_server.addrlen); |
897 | server->mountd_addrlen = data->mount_server.addrlen; | 897 | server->mountd_addrlen = data->mount_server.addrlen; |
898 | } | 898 | } |
899 | server->mountd_version = data->mount_server.version; | 899 | server->mountd_version = data->mount_server.version; |
900 | server->mountd_port = data->mount_server.port; | 900 | server->mountd_port = data->mount_server.port; |
901 | server->mountd_protocol = data->mount_server.protocol; | 901 | server->mountd_protocol = data->mount_server.protocol; |
902 | 902 | ||
903 | server->namelen = data->namlen; | 903 | server->namelen = data->namlen; |
904 | /* Create a client RPC handle for the NFSv3 ACL management interface */ | 904 | /* Create a client RPC handle for the NFSv3 ACL management interface */ |
905 | nfs_init_server_aclclient(server); | 905 | nfs_init_server_aclclient(server); |
906 | dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); | 906 | dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); |
907 | return 0; | 907 | return 0; |
908 | 908 | ||
909 | error: | 909 | error: |
910 | server->nfs_client = NULL; | 910 | server->nfs_client = NULL; |
911 | nfs_put_client(clp); | 911 | nfs_put_client(clp); |
912 | dprintk("<-- nfs_init_server() = xerror %d\n", error); | 912 | dprintk("<-- nfs_init_server() = xerror %d\n", error); |
913 | return error; | 913 | return error; |
914 | } | 914 | } |
915 | 915 | ||
916 | /* | 916 | /* |
917 | * Load up the server record from information gained in an fsinfo record | 917 | * Load up the server record from information gained in an fsinfo record |
918 | */ | 918 | */ |
919 | static void nfs_server_set_fsinfo(struct nfs_server *server, | 919 | static void nfs_server_set_fsinfo(struct nfs_server *server, |
920 | struct nfs_fh *mntfh, | 920 | struct nfs_fh *mntfh, |
921 | struct nfs_fsinfo *fsinfo) | 921 | struct nfs_fsinfo *fsinfo) |
922 | { | 922 | { |
923 | unsigned long max_rpc_payload; | 923 | unsigned long max_rpc_payload; |
924 | 924 | ||
925 | /* Work out a lot of parameters */ | 925 | /* Work out a lot of parameters */ |
926 | if (server->rsize == 0) | 926 | if (server->rsize == 0) |
927 | server->rsize = nfs_block_size(fsinfo->rtpref, NULL); | 927 | server->rsize = nfs_block_size(fsinfo->rtpref, NULL); |
928 | if (server->wsize == 0) | 928 | if (server->wsize == 0) |
929 | server->wsize = nfs_block_size(fsinfo->wtpref, NULL); | 929 | server->wsize = nfs_block_size(fsinfo->wtpref, NULL); |
930 | 930 | ||
931 | if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax) | 931 | if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax) |
932 | server->rsize = nfs_block_size(fsinfo->rtmax, NULL); | 932 | server->rsize = nfs_block_size(fsinfo->rtmax, NULL); |
933 | if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) | 933 | if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) |
934 | server->wsize = nfs_block_size(fsinfo->wtmax, NULL); | 934 | server->wsize = nfs_block_size(fsinfo->wtmax, NULL); |
935 | 935 | ||
936 | max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); | 936 | max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); |
937 | if (server->rsize > max_rpc_payload) | 937 | if (server->rsize > max_rpc_payload) |
938 | server->rsize = max_rpc_payload; | 938 | server->rsize = max_rpc_payload; |
939 | if (server->rsize > NFS_MAX_FILE_IO_SIZE) | 939 | if (server->rsize > NFS_MAX_FILE_IO_SIZE) |
940 | server->rsize = NFS_MAX_FILE_IO_SIZE; | 940 | server->rsize = NFS_MAX_FILE_IO_SIZE; |
941 | server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 941 | server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
942 | 942 | ||
943 | server->backing_dev_info.name = "nfs"; | 943 | server->backing_dev_info.name = "nfs"; |
944 | server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; | 944 | server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; |
945 | 945 | ||
946 | if (server->wsize > max_rpc_payload) | 946 | if (server->wsize > max_rpc_payload) |
947 | server->wsize = max_rpc_payload; | 947 | server->wsize = max_rpc_payload; |
948 | if (server->wsize > NFS_MAX_FILE_IO_SIZE) | 948 | if (server->wsize > NFS_MAX_FILE_IO_SIZE) |
949 | server->wsize = NFS_MAX_FILE_IO_SIZE; | 949 | server->wsize = NFS_MAX_FILE_IO_SIZE; |
950 | server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 950 | server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
951 | server->pnfs_blksize = fsinfo->blksize; | 951 | server->pnfs_blksize = fsinfo->blksize; |
952 | set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype); | 952 | set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype); |
953 | 953 | ||
954 | server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); | 954 | server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); |
955 | 955 | ||
956 | server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); | 956 | server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); |
957 | if (server->dtsize > PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES) | 957 | if (server->dtsize > PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES) |
958 | server->dtsize = PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES; | 958 | server->dtsize = PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES; |
959 | if (server->dtsize > server->rsize) | 959 | if (server->dtsize > server->rsize) |
960 | server->dtsize = server->rsize; | 960 | server->dtsize = server->rsize; |
961 | 961 | ||
962 | if (server->flags & NFS_MOUNT_NOAC) { | 962 | if (server->flags & NFS_MOUNT_NOAC) { |
963 | server->acregmin = server->acregmax = 0; | 963 | server->acregmin = server->acregmax = 0; |
964 | server->acdirmin = server->acdirmax = 0; | 964 | server->acdirmin = server->acdirmax = 0; |
965 | } | 965 | } |
966 | 966 | ||
967 | server->maxfilesize = fsinfo->maxfilesize; | 967 | server->maxfilesize = fsinfo->maxfilesize; |
968 | 968 | ||
969 | server->time_delta = fsinfo->time_delta; | 969 | server->time_delta = fsinfo->time_delta; |
970 | 970 | ||
971 | /* We're airborne Set socket buffersize */ | 971 | /* We're airborne Set socket buffersize */ |
972 | rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); | 972 | rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); |
973 | } | 973 | } |
974 | 974 | ||
975 | /* | 975 | /* |
976 | * Probe filesystem information, including the FSID on v2/v3 | 976 | * Probe filesystem information, including the FSID on v2/v3 |
977 | */ | 977 | */ |
978 | static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr) | 978 | static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr) |
979 | { | 979 | { |
980 | struct nfs_fsinfo fsinfo; | 980 | struct nfs_fsinfo fsinfo; |
981 | struct nfs_client *clp = server->nfs_client; | 981 | struct nfs_client *clp = server->nfs_client; |
982 | int error; | 982 | int error; |
983 | 983 | ||
984 | dprintk("--> nfs_probe_fsinfo()\n"); | 984 | dprintk("--> nfs_probe_fsinfo()\n"); |
985 | 985 | ||
986 | if (clp->rpc_ops->set_capabilities != NULL) { | 986 | if (clp->rpc_ops->set_capabilities != NULL) { |
987 | error = clp->rpc_ops->set_capabilities(server, mntfh); | 987 | error = clp->rpc_ops->set_capabilities(server, mntfh); |
988 | if (error < 0) | 988 | if (error < 0) |
989 | goto out_error; | 989 | goto out_error; |
990 | } | 990 | } |
991 | 991 | ||
992 | fsinfo.fattr = fattr; | 992 | fsinfo.fattr = fattr; |
993 | fsinfo.layouttype = 0; | 993 | fsinfo.layouttype = 0; |
994 | error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); | 994 | error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); |
995 | if (error < 0) | 995 | if (error < 0) |
996 | goto out_error; | 996 | goto out_error; |
997 | 997 | ||
998 | nfs_server_set_fsinfo(server, mntfh, &fsinfo); | 998 | nfs_server_set_fsinfo(server, mntfh, &fsinfo); |
999 | 999 | ||
1000 | /* Get some general file system info */ | 1000 | /* Get some general file system info */ |
1001 | if (server->namelen == 0) { | 1001 | if (server->namelen == 0) { |
1002 | struct nfs_pathconf pathinfo; | 1002 | struct nfs_pathconf pathinfo; |
1003 | 1003 | ||
1004 | pathinfo.fattr = fattr; | 1004 | pathinfo.fattr = fattr; |
1005 | nfs_fattr_init(fattr); | 1005 | nfs_fattr_init(fattr); |
1006 | 1006 | ||
1007 | if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) | 1007 | if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) |
1008 | server->namelen = pathinfo.max_namelen; | 1008 | server->namelen = pathinfo.max_namelen; |
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | dprintk("<-- nfs_probe_fsinfo() = 0\n"); | 1011 | dprintk("<-- nfs_probe_fsinfo() = 0\n"); |
1012 | return 0; | 1012 | return 0; |
1013 | 1013 | ||
1014 | out_error: | 1014 | out_error: |
1015 | dprintk("nfs_probe_fsinfo: error = %d\n", -error); | 1015 | dprintk("nfs_probe_fsinfo: error = %d\n", -error); |
1016 | return error; | 1016 | return error; |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | /* | 1019 | /* |
1020 | * Copy useful information when duplicating a server record | 1020 | * Copy useful information when duplicating a server record |
1021 | */ | 1021 | */ |
1022 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) | 1022 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) |
1023 | { | 1023 | { |
1024 | target->flags = source->flags; | 1024 | target->flags = source->flags; |
1025 | target->rsize = source->rsize; | 1025 | target->rsize = source->rsize; |
1026 | target->wsize = source->wsize; | 1026 | target->wsize = source->wsize; |
1027 | target->acregmin = source->acregmin; | 1027 | target->acregmin = source->acregmin; |
1028 | target->acregmax = source->acregmax; | 1028 | target->acregmax = source->acregmax; |
1029 | target->acdirmin = source->acdirmin; | 1029 | target->acdirmin = source->acdirmin; |
1030 | target->acdirmax = source->acdirmax; | 1030 | target->acdirmax = source->acdirmax; |
1031 | target->caps = source->caps; | 1031 | target->caps = source->caps; |
1032 | target->options = source->options; | 1032 | target->options = source->options; |
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | static void nfs_server_insert_lists(struct nfs_server *server) | 1035 | static void nfs_server_insert_lists(struct nfs_server *server) |
1036 | { | 1036 | { |
1037 | struct nfs_client *clp = server->nfs_client; | 1037 | struct nfs_client *clp = server->nfs_client; |
1038 | 1038 | ||
1039 | spin_lock(&nfs_client_lock); | 1039 | spin_lock(&nfs_client_lock); |
1040 | list_add_tail_rcu(&server->client_link, &clp->cl_superblocks); | 1040 | list_add_tail_rcu(&server->client_link, &clp->cl_superblocks); |
1041 | list_add_tail(&server->master_link, &nfs_volume_list); | 1041 | list_add_tail(&server->master_link, &nfs_volume_list); |
1042 | clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); | 1042 | clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); |
1043 | spin_unlock(&nfs_client_lock); | 1043 | spin_unlock(&nfs_client_lock); |
1044 | 1044 | ||
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static void nfs_server_remove_lists(struct nfs_server *server) | 1047 | static void nfs_server_remove_lists(struct nfs_server *server) |
1048 | { | 1048 | { |
1049 | struct nfs_client *clp = server->nfs_client; | 1049 | struct nfs_client *clp = server->nfs_client; |
1050 | 1050 | ||
1051 | spin_lock(&nfs_client_lock); | 1051 | spin_lock(&nfs_client_lock); |
1052 | list_del_rcu(&server->client_link); | 1052 | list_del_rcu(&server->client_link); |
1053 | if (clp && list_empty(&clp->cl_superblocks)) | 1053 | if (clp && list_empty(&clp->cl_superblocks)) |
1054 | set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); | 1054 | set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); |
1055 | list_del(&server->master_link); | 1055 | list_del(&server->master_link); |
1056 | spin_unlock(&nfs_client_lock); | 1056 | spin_unlock(&nfs_client_lock); |
1057 | 1057 | ||
1058 | synchronize_rcu(); | 1058 | synchronize_rcu(); |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | /* | 1061 | /* |
1062 | * Allocate and initialise a server record | 1062 | * Allocate and initialise a server record |
1063 | */ | 1063 | */ |
1064 | static struct nfs_server *nfs_alloc_server(void) | 1064 | static struct nfs_server *nfs_alloc_server(void) |
1065 | { | 1065 | { |
1066 | struct nfs_server *server; | 1066 | struct nfs_server *server; |
1067 | 1067 | ||
1068 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | 1068 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); |
1069 | if (!server) | 1069 | if (!server) |
1070 | return NULL; | 1070 | return NULL; |
1071 | 1071 | ||
1072 | server->client = server->client_acl = ERR_PTR(-EINVAL); | 1072 | server->client = server->client_acl = ERR_PTR(-EINVAL); |
1073 | 1073 | ||
1074 | /* Zero out the NFS state stuff */ | 1074 | /* Zero out the NFS state stuff */ |
1075 | INIT_LIST_HEAD(&server->client_link); | 1075 | INIT_LIST_HEAD(&server->client_link); |
1076 | INIT_LIST_HEAD(&server->master_link); | 1076 | INIT_LIST_HEAD(&server->master_link); |
1077 | INIT_LIST_HEAD(&server->delegations); | 1077 | INIT_LIST_HEAD(&server->delegations); |
1078 | INIT_LIST_HEAD(&server->layouts); | 1078 | INIT_LIST_HEAD(&server->layouts); |
1079 | INIT_LIST_HEAD(&server->state_owners_lru); | 1079 | INIT_LIST_HEAD(&server->state_owners_lru); |
1080 | 1080 | ||
1081 | atomic_set(&server->active, 0); | 1081 | atomic_set(&server->active, 0); |
1082 | 1082 | ||
1083 | server->io_stats = nfs_alloc_iostats(); | 1083 | server->io_stats = nfs_alloc_iostats(); |
1084 | if (!server->io_stats) { | 1084 | if (!server->io_stats) { |
1085 | kfree(server); | 1085 | kfree(server); |
1086 | return NULL; | 1086 | return NULL; |
1087 | } | 1087 | } |
1088 | 1088 | ||
1089 | if (bdi_init(&server->backing_dev_info)) { | 1089 | if (bdi_init(&server->backing_dev_info)) { |
1090 | nfs_free_iostats(server->io_stats); | 1090 | nfs_free_iostats(server->io_stats); |
1091 | kfree(server); | 1091 | kfree(server); |
1092 | return NULL; | 1092 | return NULL; |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | ida_init(&server->openowner_id); | 1095 | ida_init(&server->openowner_id); |
1096 | ida_init(&server->lockowner_id); | 1096 | ida_init(&server->lockowner_id); |
1097 | pnfs_init_server(server); | 1097 | pnfs_init_server(server); |
1098 | 1098 | ||
1099 | return server; | 1099 | return server; |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | /* | 1102 | /* |
1103 | * Free up a server record | 1103 | * Free up a server record |
1104 | */ | 1104 | */ |
1105 | void nfs_free_server(struct nfs_server *server) | 1105 | void nfs_free_server(struct nfs_server *server) |
1106 | { | 1106 | { |
1107 | dprintk("--> nfs_free_server()\n"); | 1107 | dprintk("--> nfs_free_server()\n"); |
1108 | 1108 | ||
1109 | nfs_server_remove_lists(server); | 1109 | nfs_server_remove_lists(server); |
1110 | unset_pnfs_layoutdriver(server); | 1110 | unset_pnfs_layoutdriver(server); |
1111 | 1111 | ||
1112 | if (server->destroy != NULL) | 1112 | if (server->destroy != NULL) |
1113 | server->destroy(server); | 1113 | server->destroy(server); |
1114 | 1114 | ||
1115 | if (!IS_ERR(server->client_acl)) | 1115 | if (!IS_ERR(server->client_acl)) |
1116 | rpc_shutdown_client(server->client_acl); | 1116 | rpc_shutdown_client(server->client_acl); |
1117 | if (!IS_ERR(server->client)) | 1117 | if (!IS_ERR(server->client)) |
1118 | rpc_shutdown_client(server->client); | 1118 | rpc_shutdown_client(server->client); |
1119 | 1119 | ||
1120 | nfs_put_client(server->nfs_client); | 1120 | nfs_put_client(server->nfs_client); |
1121 | 1121 | ||
1122 | ida_destroy(&server->lockowner_id); | 1122 | ida_destroy(&server->lockowner_id); |
1123 | ida_destroy(&server->openowner_id); | 1123 | ida_destroy(&server->openowner_id); |
1124 | nfs_free_iostats(server->io_stats); | 1124 | nfs_free_iostats(server->io_stats); |
1125 | bdi_destroy(&server->backing_dev_info); | 1125 | bdi_destroy(&server->backing_dev_info); |
1126 | kfree(server); | 1126 | kfree(server); |
1127 | nfs_release_automount_timer(); | 1127 | nfs_release_automount_timer(); |
1128 | dprintk("<-- nfs_free_server()\n"); | 1128 | dprintk("<-- nfs_free_server()\n"); |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | /* | 1131 | /* |
1132 | * Create a version 2 or 3 volume record | 1132 | * Create a version 2 or 3 volume record |
1133 | * - keyed on server and FSID | 1133 | * - keyed on server and FSID |
1134 | */ | 1134 | */ |
1135 | struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, | 1135 | struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, |
1136 | struct nfs_fh *mntfh) | 1136 | struct nfs_fh *mntfh) |
1137 | { | 1137 | { |
1138 | struct nfs_server *server; | 1138 | struct nfs_server *server; |
1139 | struct nfs_fattr *fattr; | 1139 | struct nfs_fattr *fattr; |
1140 | int error; | 1140 | int error; |
1141 | 1141 | ||
1142 | server = nfs_alloc_server(); | 1142 | server = nfs_alloc_server(); |
1143 | if (!server) | 1143 | if (!server) |
1144 | return ERR_PTR(-ENOMEM); | 1144 | return ERR_PTR(-ENOMEM); |
1145 | 1145 | ||
1146 | error = -ENOMEM; | 1146 | error = -ENOMEM; |
1147 | fattr = nfs_alloc_fattr(); | 1147 | fattr = nfs_alloc_fattr(); |
1148 | if (fattr == NULL) | 1148 | if (fattr == NULL) |
1149 | goto error; | 1149 | goto error; |
1150 | 1150 | ||
1151 | /* Get a client representation */ | 1151 | /* Get a client representation */ |
1152 | error = nfs_init_server(server, data); | 1152 | error = nfs_init_server(server, data); |
1153 | if (error < 0) | 1153 | if (error < 0) |
1154 | goto error; | 1154 | goto error; |
1155 | 1155 | ||
1156 | BUG_ON(!server->nfs_client); | 1156 | BUG_ON(!server->nfs_client); |
1157 | BUG_ON(!server->nfs_client->rpc_ops); | 1157 | BUG_ON(!server->nfs_client->rpc_ops); |
1158 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1158 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1159 | 1159 | ||
1160 | /* Probe the root fh to retrieve its FSID */ | 1160 | /* Probe the root fh to retrieve its FSID */ |
1161 | error = nfs_probe_fsinfo(server, mntfh, fattr); | 1161 | error = nfs_probe_fsinfo(server, mntfh, fattr); |
1162 | if (error < 0) | 1162 | if (error < 0) |
1163 | goto error; | 1163 | goto error; |
1164 | if (server->nfs_client->rpc_ops->version == 3) { | 1164 | if (server->nfs_client->rpc_ops->version == 3) { |
1165 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) | 1165 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) |
1166 | server->namelen = NFS3_MAXNAMLEN; | 1166 | server->namelen = NFS3_MAXNAMLEN; |
1167 | if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) | 1167 | if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) |
1168 | server->caps |= NFS_CAP_READDIRPLUS; | 1168 | server->caps |= NFS_CAP_READDIRPLUS; |
1169 | } else { | 1169 | } else { |
1170 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | 1170 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) |
1171 | server->namelen = NFS2_MAXNAMLEN; | 1171 | server->namelen = NFS2_MAXNAMLEN; |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1174 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1175 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); | 1175 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); |
1176 | if (error < 0) { | 1176 | if (error < 0) { |
1177 | dprintk("nfs_create_server: getattr error = %d\n", -error); | 1177 | dprintk("nfs_create_server: getattr error = %d\n", -error); |
1178 | goto error; | 1178 | goto error; |
1179 | } | 1179 | } |
1180 | } | 1180 | } |
1181 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); | 1181 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); |
1182 | 1182 | ||
1183 | dprintk("Server FSID: %llx:%llx\n", | 1183 | dprintk("Server FSID: %llx:%llx\n", |
1184 | (unsigned long long) server->fsid.major, | 1184 | (unsigned long long) server->fsid.major, |
1185 | (unsigned long long) server->fsid.minor); | 1185 | (unsigned long long) server->fsid.minor); |
1186 | 1186 | ||
1187 | nfs_server_insert_lists(server); | 1187 | nfs_server_insert_lists(server); |
1188 | server->mount_time = jiffies; | 1188 | server->mount_time = jiffies; |
1189 | nfs_free_fattr(fattr); | 1189 | nfs_free_fattr(fattr); |
1190 | return server; | 1190 | return server; |
1191 | 1191 | ||
1192 | error: | 1192 | error: |
1193 | nfs_free_fattr(fattr); | 1193 | nfs_free_fattr(fattr); |
1194 | nfs_free_server(server); | 1194 | nfs_free_server(server); |
1195 | return ERR_PTR(error); | 1195 | return ERR_PTR(error); |
1196 | } | 1196 | } |
1197 | 1197 | ||
1198 | #ifdef CONFIG_NFS_V4 | 1198 | #ifdef CONFIG_NFS_V4 |
1199 | /* | 1199 | /* |
1200 | * NFSv4.0 callback thread helper | 1200 | * NFSv4.0 callback thread helper |
1201 | * | 1201 | * |
1202 | * Find a client by callback identifier | 1202 | * Find a client by callback identifier |
1203 | */ | 1203 | */ |
1204 | struct nfs_client * | 1204 | struct nfs_client * |
1205 | nfs4_find_client_ident(int cb_ident) | 1205 | nfs4_find_client_ident(int cb_ident) |
1206 | { | 1206 | { |
1207 | struct nfs_client *clp; | 1207 | struct nfs_client *clp; |
1208 | 1208 | ||
1209 | spin_lock(&nfs_client_lock); | 1209 | spin_lock(&nfs_client_lock); |
1210 | clp = idr_find(&cb_ident_idr, cb_ident); | 1210 | clp = idr_find(&cb_ident_idr, cb_ident); |
1211 | if (clp) | 1211 | if (clp) |
1212 | atomic_inc(&clp->cl_count); | 1212 | atomic_inc(&clp->cl_count); |
1213 | spin_unlock(&nfs_client_lock); | 1213 | spin_unlock(&nfs_client_lock); |
1214 | return clp; | 1214 | return clp; |
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | #if defined(CONFIG_NFS_V4_1) | 1217 | #if defined(CONFIG_NFS_V4_1) |
1218 | /* | 1218 | /* |
1219 | * NFSv4.1 callback thread helper | 1219 | * NFSv4.1 callback thread helper |
1220 | * For CB_COMPOUND calls, find a client by IP address, protocol version, | 1220 | * For CB_COMPOUND calls, find a client by IP address, protocol version, |
1221 | * minorversion, and sessionID | 1221 | * minorversion, and sessionID |
1222 | * | 1222 | * |
1223 | * Returns NULL if no such client | 1223 | * Returns NULL if no such client |
1224 | */ | 1224 | */ |
1225 | struct nfs_client * | 1225 | struct nfs_client * |
1226 | nfs4_find_client_sessionid(const struct sockaddr *addr, | 1226 | nfs4_find_client_sessionid(const struct sockaddr *addr, |
1227 | struct nfs4_sessionid *sid) | 1227 | struct nfs4_sessionid *sid) |
1228 | { | 1228 | { |
1229 | struct nfs_client *clp; | 1229 | struct nfs_client *clp; |
1230 | 1230 | ||
1231 | spin_lock(&nfs_client_lock); | 1231 | spin_lock(&nfs_client_lock); |
1232 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { | 1232 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { |
1233 | if (nfs4_cb_match_client(addr, clp, 1) == false) | 1233 | if (nfs4_cb_match_client(addr, clp, 1) == false) |
1234 | continue; | 1234 | continue; |
1235 | 1235 | ||
1236 | if (!nfs4_has_session(clp)) | 1236 | if (!nfs4_has_session(clp)) |
1237 | continue; | 1237 | continue; |
1238 | 1238 | ||
1239 | /* Match sessionid*/ | 1239 | /* Match sessionid*/ |
1240 | if (memcmp(clp->cl_session->sess_id.data, | 1240 | if (memcmp(clp->cl_session->sess_id.data, |
1241 | sid->data, NFS4_MAX_SESSIONID_LEN) != 0) | 1241 | sid->data, NFS4_MAX_SESSIONID_LEN) != 0) |
1242 | continue; | 1242 | continue; |
1243 | 1243 | ||
1244 | atomic_inc(&clp->cl_count); | 1244 | atomic_inc(&clp->cl_count); |
1245 | spin_unlock(&nfs_client_lock); | 1245 | spin_unlock(&nfs_client_lock); |
1246 | return clp; | 1246 | return clp; |
1247 | } | 1247 | } |
1248 | spin_unlock(&nfs_client_lock); | 1248 | spin_unlock(&nfs_client_lock); |
1249 | return NULL; | 1249 | return NULL; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | #else /* CONFIG_NFS_V4_1 */ | 1252 | #else /* CONFIG_NFS_V4_1 */ |
1253 | 1253 | ||
1254 | struct nfs_client * | 1254 | struct nfs_client * |
1255 | nfs4_find_client_sessionid(const struct sockaddr *addr, | 1255 | nfs4_find_client_sessionid(const struct sockaddr *addr, |
1256 | struct nfs4_sessionid *sid) | 1256 | struct nfs4_sessionid *sid) |
1257 | { | 1257 | { |
1258 | return NULL; | 1258 | return NULL; |
1259 | } | 1259 | } |
1260 | #endif /* CONFIG_NFS_V4_1 */ | 1260 | #endif /* CONFIG_NFS_V4_1 */ |
1261 | 1261 | ||
1262 | /* | 1262 | /* |
1263 | * Initialize the NFS4 callback service | 1263 | * Initialize the NFS4 callback service |
1264 | */ | 1264 | */ |
1265 | static int nfs4_init_callback(struct nfs_client *clp) | 1265 | static int nfs4_init_callback(struct nfs_client *clp) |
1266 | { | 1266 | { |
1267 | int error; | 1267 | int error; |
1268 | 1268 | ||
1269 | if (clp->rpc_ops->version == 4) { | 1269 | if (clp->rpc_ops->version == 4) { |
1270 | if (nfs4_has_session(clp)) { | 1270 | if (nfs4_has_session(clp)) { |
1271 | error = xprt_setup_backchannel( | 1271 | error = xprt_setup_backchannel( |
1272 | clp->cl_rpcclient->cl_xprt, | 1272 | clp->cl_rpcclient->cl_xprt, |
1273 | NFS41_BC_MIN_CALLBACKS); | 1273 | NFS41_BC_MIN_CALLBACKS); |
1274 | if (error < 0) | 1274 | if (error < 0) |
1275 | return error; | 1275 | return error; |
1276 | } | 1276 | } |
1277 | 1277 | ||
1278 | error = nfs_callback_up(clp->cl_mvops->minor_version, | 1278 | error = nfs_callback_up(clp->cl_mvops->minor_version, |
1279 | clp->cl_rpcclient->cl_xprt); | 1279 | clp->cl_rpcclient->cl_xprt); |
1280 | if (error < 0) { | 1280 | if (error < 0) { |
1281 | dprintk("%s: failed to start callback. Error = %d\n", | 1281 | dprintk("%s: failed to start callback. Error = %d\n", |
1282 | __func__, error); | 1282 | __func__, error); |
1283 | return error; | 1283 | return error; |
1284 | } | 1284 | } |
1285 | __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); | 1285 | __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); |
1286 | } | 1286 | } |
1287 | return 0; | 1287 | return 0; |
1288 | } | 1288 | } |
1289 | 1289 | ||
1290 | /* | 1290 | /* |
1291 | * Initialize the minor version specific parts of an NFS4 client record | 1291 | * Initialize the minor version specific parts of an NFS4 client record |
1292 | */ | 1292 | */ |
1293 | static int nfs4_init_client_minor_version(struct nfs_client *clp) | 1293 | static int nfs4_init_client_minor_version(struct nfs_client *clp) |
1294 | { | 1294 | { |
1295 | #if defined(CONFIG_NFS_V4_1) | 1295 | #if defined(CONFIG_NFS_V4_1) |
1296 | if (clp->cl_mvops->minor_version) { | 1296 | if (clp->cl_mvops->minor_version) { |
1297 | struct nfs4_session *session = NULL; | 1297 | struct nfs4_session *session = NULL; |
1298 | /* | 1298 | /* |
1299 | * Create the session and mark it expired. | 1299 | * Create the session and mark it expired. |
1300 | * When a SEQUENCE operation encounters the expired session | 1300 | * When a SEQUENCE operation encounters the expired session |
1301 | * it will do session recovery to initialize it. | 1301 | * it will do session recovery to initialize it. |
1302 | */ | 1302 | */ |
1303 | session = nfs4_alloc_session(clp); | 1303 | session = nfs4_alloc_session(clp); |
1304 | if (!session) | 1304 | if (!session) |
1305 | return -ENOMEM; | 1305 | return -ENOMEM; |
1306 | 1306 | ||
1307 | clp->cl_session = session; | 1307 | clp->cl_session = session; |
1308 | /* | 1308 | /* |
1309 | * The create session reply races with the server back | 1309 | * The create session reply races with the server back |
1310 | * channel probe. Mark the client NFS_CS_SESSION_INITING | 1310 | * channel probe. Mark the client NFS_CS_SESSION_INITING |
1311 | * so that the client back channel can find the | 1311 | * so that the client back channel can find the |
1312 | * nfs_client struct | 1312 | * nfs_client struct |
1313 | */ | 1313 | */ |
1314 | clp->cl_cons_state = NFS_CS_SESSION_INITING; | 1314 | clp->cl_cons_state = NFS_CS_SESSION_INITING; |
1315 | } | 1315 | } |
1316 | #endif /* CONFIG_NFS_V4_1 */ | 1316 | #endif /* CONFIG_NFS_V4_1 */ |
1317 | 1317 | ||
1318 | return nfs4_init_callback(clp); | 1318 | return nfs4_init_callback(clp); |
1319 | } | 1319 | } |
1320 | 1320 | ||
1321 | /* | 1321 | /* |
1322 | * Initialise an NFS4 client record | 1322 | * Initialise an NFS4 client record |
1323 | */ | 1323 | */ |
1324 | int nfs4_init_client(struct nfs_client *clp, | 1324 | int nfs4_init_client(struct nfs_client *clp, |
1325 | const struct rpc_timeout *timeparms, | 1325 | const struct rpc_timeout *timeparms, |
1326 | const char *ip_addr, | 1326 | const char *ip_addr, |
1327 | rpc_authflavor_t authflavour, | 1327 | rpc_authflavor_t authflavour, |
1328 | int noresvport) | 1328 | int noresvport) |
1329 | { | 1329 | { |
1330 | int error; | 1330 | int error; |
1331 | 1331 | ||
1332 | if (clp->cl_cons_state == NFS_CS_READY) { | 1332 | if (clp->cl_cons_state == NFS_CS_READY) { |
1333 | /* the client is initialised already */ | 1333 | /* the client is initialised already */ |
1334 | dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); | 1334 | dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); |
1335 | return 0; | 1335 | return 0; |
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | /* Check NFS protocol revision and initialize RPC op vector */ | 1338 | /* Check NFS protocol revision and initialize RPC op vector */ |
1339 | clp->rpc_ops = &nfs_v4_clientops; | 1339 | clp->rpc_ops = &nfs_v4_clientops; |
1340 | 1340 | ||
1341 | error = nfs_create_rpc_client(clp, timeparms, authflavour, | 1341 | error = nfs_create_rpc_client(clp, timeparms, authflavour, |
1342 | 1, noresvport); | 1342 | 1, noresvport); |
1343 | if (error < 0) | 1343 | if (error < 0) |
1344 | goto error; | 1344 | goto error; |
1345 | strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); | 1345 | strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); |
1346 | 1346 | ||
1347 | error = nfs_idmap_new(clp); | 1347 | error = nfs_idmap_new(clp); |
1348 | if (error < 0) { | 1348 | if (error < 0) { |
1349 | dprintk("%s: failed to create idmapper. Error = %d\n", | 1349 | dprintk("%s: failed to create idmapper. Error = %d\n", |
1350 | __func__, error); | 1350 | __func__, error); |
1351 | goto error; | 1351 | goto error; |
1352 | } | 1352 | } |
1353 | __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); | 1353 | __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); |
1354 | 1354 | ||
1355 | error = nfs4_init_client_minor_version(clp); | 1355 | error = nfs4_init_client_minor_version(clp); |
1356 | if (error < 0) | 1356 | if (error < 0) |
1357 | goto error; | 1357 | goto error; |
1358 | 1358 | ||
1359 | if (!nfs4_has_session(clp)) | 1359 | if (!nfs4_has_session(clp)) |
1360 | nfs_mark_client_ready(clp, NFS_CS_READY); | 1360 | nfs_mark_client_ready(clp, NFS_CS_READY); |
1361 | return 0; | 1361 | return 0; |
1362 | 1362 | ||
1363 | error: | 1363 | error: |
1364 | nfs_mark_client_ready(clp, error); | 1364 | nfs_mark_client_ready(clp, error); |
1365 | dprintk("<-- nfs4_init_client() = xerror %d\n", error); | 1365 | dprintk("<-- nfs4_init_client() = xerror %d\n", error); |
1366 | return error; | 1366 | return error; |
1367 | } | 1367 | } |
1368 | 1368 | ||
1369 | /* | 1369 | /* |
1370 | * Set up an NFS4 client | 1370 | * Set up an NFS4 client |
1371 | */ | 1371 | */ |
1372 | static int nfs4_set_client(struct nfs_server *server, | 1372 | static int nfs4_set_client(struct nfs_server *server, |
1373 | const char *hostname, | 1373 | const char *hostname, |
1374 | const struct sockaddr *addr, | 1374 | const struct sockaddr *addr, |
1375 | const size_t addrlen, | 1375 | const size_t addrlen, |
1376 | const char *ip_addr, | 1376 | const char *ip_addr, |
1377 | rpc_authflavor_t authflavour, | 1377 | rpc_authflavor_t authflavour, |
1378 | int proto, const struct rpc_timeout *timeparms, | 1378 | int proto, const struct rpc_timeout *timeparms, |
1379 | u32 minorversion, struct net *net) | 1379 | u32 minorversion, struct net *net) |
1380 | { | 1380 | { |
1381 | struct nfs_client_initdata cl_init = { | 1381 | struct nfs_client_initdata cl_init = { |
1382 | .hostname = hostname, | 1382 | .hostname = hostname, |
1383 | .addr = addr, | 1383 | .addr = addr, |
1384 | .addrlen = addrlen, | 1384 | .addrlen = addrlen, |
1385 | .rpc_ops = &nfs_v4_clientops, | 1385 | .rpc_ops = &nfs_v4_clientops, |
1386 | .proto = proto, | 1386 | .proto = proto, |
1387 | .minorversion = minorversion, | 1387 | .minorversion = minorversion, |
1388 | .net = net, | 1388 | .net = net, |
1389 | }; | 1389 | }; |
1390 | struct nfs_client *clp; | 1390 | struct nfs_client *clp; |
1391 | int error; | 1391 | int error; |
1392 | 1392 | ||
1393 | dprintk("--> nfs4_set_client()\n"); | 1393 | dprintk("--> nfs4_set_client()\n"); |
1394 | 1394 | ||
1395 | /* Allocate or find a client reference we can use */ | 1395 | /* Allocate or find a client reference we can use */ |
1396 | clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour, | 1396 | clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour, |
1397 | server->flags & NFS_MOUNT_NORESVPORT); | 1397 | server->flags & NFS_MOUNT_NORESVPORT); |
1398 | if (IS_ERR(clp)) { | 1398 | if (IS_ERR(clp)) { |
1399 | error = PTR_ERR(clp); | 1399 | error = PTR_ERR(clp); |
1400 | goto error; | 1400 | goto error; |
1401 | } | 1401 | } |
1402 | 1402 | ||
1403 | /* | 1403 | /* |
1404 | * Query for the lease time on clientid setup or renewal | 1404 | * Query for the lease time on clientid setup or renewal |
1405 | * | 1405 | * |
1406 | * Note that this will be set on nfs_clients that were created | 1406 | * Note that this will be set on nfs_clients that were created |
1407 | * only for the DS role and did not set this bit, but now will | 1407 | * only for the DS role and did not set this bit, but now will |
1408 | * serve a dual role. | 1408 | * serve a dual role. |
1409 | */ | 1409 | */ |
1410 | set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state); | 1410 | set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state); |
1411 | 1411 | ||
1412 | server->nfs_client = clp; | 1412 | server->nfs_client = clp; |
1413 | dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); | 1413 | dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); |
1414 | return 0; | 1414 | return 0; |
1415 | error: | 1415 | error: |
1416 | dprintk("<-- nfs4_set_client() = xerror %d\n", error); | 1416 | dprintk("<-- nfs4_set_client() = xerror %d\n", error); |
1417 | return error; | 1417 | return error; |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | /* | 1420 | /* |
1421 | * Set up a pNFS Data Server client. | 1421 | * Set up a pNFS Data Server client. |
1422 | * | 1422 | * |
1423 | * Return any existing nfs_client that matches server address,port,version | 1423 | * Return any existing nfs_client that matches server address,port,version |
1424 | * and minorversion. | 1424 | * and minorversion. |
1425 | * | 1425 | * |
1426 | * For a new nfs_client, use a soft mount (default), a low retrans and a | 1426 | * For a new nfs_client, use a soft mount (default), a low retrans and a |
1427 | * low timeout interval so that if a connection is lost, we retry through | 1427 | * low timeout interval so that if a connection is lost, we retry through |
1428 | * the MDS. | 1428 | * the MDS. |
1429 | */ | 1429 | */ |
1430 | struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, | 1430 | struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, |
1431 | const struct sockaddr *ds_addr, | 1431 | const struct sockaddr *ds_addr, |
1432 | int ds_addrlen, int ds_proto) | 1432 | int ds_addrlen, int ds_proto) |
1433 | { | 1433 | { |
1434 | struct nfs_client_initdata cl_init = { | 1434 | struct nfs_client_initdata cl_init = { |
1435 | .addr = ds_addr, | 1435 | .addr = ds_addr, |
1436 | .addrlen = ds_addrlen, | 1436 | .addrlen = ds_addrlen, |
1437 | .rpc_ops = &nfs_v4_clientops, | 1437 | .rpc_ops = &nfs_v4_clientops, |
1438 | .proto = ds_proto, | 1438 | .proto = ds_proto, |
1439 | .minorversion = mds_clp->cl_minorversion, | 1439 | .minorversion = mds_clp->cl_minorversion, |
1440 | .net = mds_clp->net, | 1440 | .net = mds_clp->net, |
1441 | }; | 1441 | }; |
1442 | struct rpc_timeout ds_timeout = { | 1442 | struct rpc_timeout ds_timeout = { |
1443 | .to_initval = 15 * HZ, | 1443 | .to_initval = 15 * HZ, |
1444 | .to_maxval = 15 * HZ, | 1444 | .to_maxval = 15 * HZ, |
1445 | .to_retries = 1, | 1445 | .to_retries = 1, |
1446 | .to_exponential = 1, | 1446 | .to_exponential = 1, |
1447 | }; | 1447 | }; |
1448 | struct nfs_client *clp; | 1448 | struct nfs_client *clp; |
1449 | 1449 | ||
1450 | /* | 1450 | /* |
1451 | * Set an authflavor equual to the MDS value. Use the MDS nfs_client | 1451 | * Set an authflavor equual to the MDS value. Use the MDS nfs_client |
1452 | * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS | 1452 | * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS |
1453 | * (section 13.1 RFC 5661). | 1453 | * (section 13.1 RFC 5661). |
1454 | */ | 1454 | */ |
1455 | clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr, | 1455 | clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr, |
1456 | mds_clp->cl_rpcclient->cl_auth->au_flavor, 0); | 1456 | mds_clp->cl_rpcclient->cl_auth->au_flavor, 0); |
1457 | 1457 | ||
1458 | dprintk("<-- %s %p\n", __func__, clp); | 1458 | dprintk("<-- %s %p\n", __func__, clp); |
1459 | return clp; | 1459 | return clp; |
1460 | } | 1460 | } |
1461 | EXPORT_SYMBOL_GPL(nfs4_set_ds_client); | 1461 | EXPORT_SYMBOL_GPL(nfs4_set_ds_client); |
1462 | 1462 | ||
1463 | /* | 1463 | /* |
1464 | * Session has been established, and the client marked ready. | 1464 | * Session has been established, and the client marked ready. |
1465 | * Set the mount rsize and wsize with negotiated fore channel | 1465 | * Set the mount rsize and wsize with negotiated fore channel |
1466 | * attributes which will be bound checked in nfs_server_set_fsinfo. | 1466 | * attributes which will be bound checked in nfs_server_set_fsinfo. |
1467 | */ | 1467 | */ |
1468 | static void nfs4_session_set_rwsize(struct nfs_server *server) | 1468 | static void nfs4_session_set_rwsize(struct nfs_server *server) |
1469 | { | 1469 | { |
1470 | #ifdef CONFIG_NFS_V4_1 | 1470 | #ifdef CONFIG_NFS_V4_1 |
1471 | struct nfs4_session *sess; | 1471 | struct nfs4_session *sess; |
1472 | u32 server_resp_sz; | 1472 | u32 server_resp_sz; |
1473 | u32 server_rqst_sz; | 1473 | u32 server_rqst_sz; |
1474 | 1474 | ||
1475 | if (!nfs4_has_session(server->nfs_client)) | 1475 | if (!nfs4_has_session(server->nfs_client)) |
1476 | return; | 1476 | return; |
1477 | sess = server->nfs_client->cl_session; | 1477 | sess = server->nfs_client->cl_session; |
1478 | server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead; | 1478 | server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead; |
1479 | server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead; | 1479 | server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead; |
1480 | 1480 | ||
1481 | if (server->rsize > server_resp_sz) | 1481 | if (server->rsize > server_resp_sz) |
1482 | server->rsize = server_resp_sz; | 1482 | server->rsize = server_resp_sz; |
1483 | if (server->wsize > server_rqst_sz) | 1483 | if (server->wsize > server_rqst_sz) |
1484 | server->wsize = server_rqst_sz; | 1484 | server->wsize = server_rqst_sz; |
1485 | #endif /* CONFIG_NFS_V4_1 */ | 1485 | #endif /* CONFIG_NFS_V4_1 */ |
1486 | } | 1486 | } |
1487 | 1487 | ||
1488 | static int nfs4_server_common_setup(struct nfs_server *server, | 1488 | static int nfs4_server_common_setup(struct nfs_server *server, |
1489 | struct nfs_fh *mntfh) | 1489 | struct nfs_fh *mntfh) |
1490 | { | 1490 | { |
1491 | struct nfs_fattr *fattr; | 1491 | struct nfs_fattr *fattr; |
1492 | int error; | 1492 | int error; |
1493 | 1493 | ||
1494 | BUG_ON(!server->nfs_client); | 1494 | BUG_ON(!server->nfs_client); |
1495 | BUG_ON(!server->nfs_client->rpc_ops); | 1495 | BUG_ON(!server->nfs_client->rpc_ops); |
1496 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1496 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1497 | 1497 | ||
1498 | /* data servers support only a subset of NFSv4.1 */ | 1498 | /* data servers support only a subset of NFSv4.1 */ |
1499 | if (is_ds_only_client(server->nfs_client)) | 1499 | if (is_ds_only_client(server->nfs_client)) |
1500 | return -EPROTONOSUPPORT; | 1500 | return -EPROTONOSUPPORT; |
1501 | 1501 | ||
1502 | fattr = nfs_alloc_fattr(); | 1502 | fattr = nfs_alloc_fattr(); |
1503 | if (fattr == NULL) | 1503 | if (fattr == NULL) |
1504 | return -ENOMEM; | 1504 | return -ENOMEM; |
1505 | 1505 | ||
1506 | /* We must ensure the session is initialised first */ | 1506 | /* We must ensure the session is initialised first */ |
1507 | error = nfs4_init_session(server); | 1507 | error = nfs4_init_session(server); |
1508 | if (error < 0) | 1508 | if (error < 0) |
1509 | goto out; | 1509 | goto out; |
1510 | 1510 | ||
1511 | /* Probe the root fh to retrieve its FSID and filehandle */ | 1511 | /* Probe the root fh to retrieve its FSID and filehandle */ |
1512 | error = nfs4_get_rootfh(server, mntfh); | 1512 | error = nfs4_get_rootfh(server, mntfh); |
1513 | if (error < 0) | 1513 | if (error < 0) |
1514 | goto out; | 1514 | goto out; |
1515 | 1515 | ||
1516 | dprintk("Server FSID: %llx:%llx\n", | 1516 | dprintk("Server FSID: %llx:%llx\n", |
1517 | (unsigned long long) server->fsid.major, | 1517 | (unsigned long long) server->fsid.major, |
1518 | (unsigned long long) server->fsid.minor); | 1518 | (unsigned long long) server->fsid.minor); |
1519 | dprintk("Mount FH: %d\n", mntfh->size); | 1519 | dprintk("Mount FH: %d\n", mntfh->size); |
1520 | 1520 | ||
1521 | nfs4_session_set_rwsize(server); | 1521 | nfs4_session_set_rwsize(server); |
1522 | 1522 | ||
1523 | error = nfs_probe_fsinfo(server, mntfh, fattr); | 1523 | error = nfs_probe_fsinfo(server, mntfh, fattr); |
1524 | if (error < 0) | 1524 | if (error < 0) |
1525 | goto out; | 1525 | goto out; |
1526 | 1526 | ||
1527 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | 1527 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) |
1528 | server->namelen = NFS4_MAXNAMLEN; | 1528 | server->namelen = NFS4_MAXNAMLEN; |
1529 | 1529 | ||
1530 | nfs_server_insert_lists(server); | 1530 | nfs_server_insert_lists(server); |
1531 | server->mount_time = jiffies; | 1531 | server->mount_time = jiffies; |
1532 | server->destroy = nfs4_destroy_server; | 1532 | server->destroy = nfs4_destroy_server; |
1533 | out: | 1533 | out: |
1534 | nfs_free_fattr(fattr); | 1534 | nfs_free_fattr(fattr); |
1535 | return error; | 1535 | return error; |
1536 | } | 1536 | } |
1537 | 1537 | ||
1538 | /* | 1538 | /* |
1539 | * Create a version 4 volume record | 1539 | * Create a version 4 volume record |
1540 | */ | 1540 | */ |
1541 | static int nfs4_init_server(struct nfs_server *server, | 1541 | static int nfs4_init_server(struct nfs_server *server, |
1542 | const struct nfs_parsed_mount_data *data) | 1542 | const struct nfs_parsed_mount_data *data) |
1543 | { | 1543 | { |
1544 | struct rpc_timeout timeparms; | 1544 | struct rpc_timeout timeparms; |
1545 | int error; | 1545 | int error; |
1546 | 1546 | ||
1547 | dprintk("--> nfs4_init_server()\n"); | 1547 | dprintk("--> nfs4_init_server()\n"); |
1548 | 1548 | ||
1549 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, | 1549 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, |
1550 | data->timeo, data->retrans); | 1550 | data->timeo, data->retrans); |
1551 | 1551 | ||
1552 | /* Initialise the client representation from the mount data */ | 1552 | /* Initialise the client representation from the mount data */ |
1553 | server->flags = data->flags; | 1553 | server->flags = data->flags; |
1554 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK; | 1554 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK; |
1555 | if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) | 1555 | if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) |
1556 | server->caps |= NFS_CAP_READDIRPLUS; | 1556 | server->caps |= NFS_CAP_READDIRPLUS; |
1557 | server->options = data->options; | 1557 | server->options = data->options; |
1558 | 1558 | ||
1559 | /* Get a client record */ | 1559 | /* Get a client record */ |
1560 | error = nfs4_set_client(server, | 1560 | error = nfs4_set_client(server, |
1561 | data->nfs_server.hostname, | 1561 | data->nfs_server.hostname, |
1562 | (const struct sockaddr *)&data->nfs_server.address, | 1562 | (const struct sockaddr *)&data->nfs_server.address, |
1563 | data->nfs_server.addrlen, | 1563 | data->nfs_server.addrlen, |
1564 | data->client_address, | 1564 | data->client_address, |
1565 | data->auth_flavors[0], | 1565 | data->auth_flavors[0], |
1566 | data->nfs_server.protocol, | 1566 | data->nfs_server.protocol, |
1567 | &timeparms, | 1567 | &timeparms, |
1568 | data->minorversion, | 1568 | data->minorversion, |
1569 | data->net); | 1569 | data->net); |
1570 | if (error < 0) | 1570 | if (error < 0) |
1571 | goto error; | 1571 | goto error; |
1572 | 1572 | ||
1573 | /* | 1573 | /* |
1574 | * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower | 1574 | * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower |
1575 | * authentication. | 1575 | * authentication. |
1576 | */ | 1576 | */ |
1577 | if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX) | 1577 | if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX) |
1578 | server->caps |= NFS_CAP_UIDGID_NOMAP; | 1578 | server->caps |= NFS_CAP_UIDGID_NOMAP; |
1579 | 1579 | ||
1580 | if (data->rsize) | 1580 | if (data->rsize) |
1581 | server->rsize = nfs_block_size(data->rsize, NULL); | 1581 | server->rsize = nfs_block_size(data->rsize, NULL); |
1582 | if (data->wsize) | 1582 | if (data->wsize) |
1583 | server->wsize = nfs_block_size(data->wsize, NULL); | 1583 | server->wsize = nfs_block_size(data->wsize, NULL); |
1584 | 1584 | ||
1585 | server->acregmin = data->acregmin * HZ; | 1585 | server->acregmin = data->acregmin * HZ; |
1586 | server->acregmax = data->acregmax * HZ; | 1586 | server->acregmax = data->acregmax * HZ; |
1587 | server->acdirmin = data->acdirmin * HZ; | 1587 | server->acdirmin = data->acdirmin * HZ; |
1588 | server->acdirmax = data->acdirmax * HZ; | 1588 | server->acdirmax = data->acdirmax * HZ; |
1589 | 1589 | ||
1590 | server->port = data->nfs_server.port; | 1590 | server->port = data->nfs_server.port; |
1591 | 1591 | ||
1592 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); | 1592 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); |
1593 | 1593 | ||
1594 | error: | 1594 | error: |
1595 | /* Done */ | 1595 | /* Done */ |
1596 | dprintk("<-- nfs4_init_server() = %d\n", error); | 1596 | dprintk("<-- nfs4_init_server() = %d\n", error); |
1597 | return error; | 1597 | return error; |
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | /* | 1600 | /* |
1601 | * Create a version 4 volume record | 1601 | * Create a version 4 volume record |
1602 | * - keyed on server and FSID | 1602 | * - keyed on server and FSID |
1603 | */ | 1603 | */ |
1604 | struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | 1604 | struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, |
1605 | struct nfs_fh *mntfh) | 1605 | struct nfs_fh *mntfh) |
1606 | { | 1606 | { |
1607 | struct nfs_server *server; | 1607 | struct nfs_server *server; |
1608 | int error; | 1608 | int error; |
1609 | 1609 | ||
1610 | dprintk("--> nfs4_create_server()\n"); | 1610 | dprintk("--> nfs4_create_server()\n"); |
1611 | 1611 | ||
1612 | server = nfs_alloc_server(); | 1612 | server = nfs_alloc_server(); |
1613 | if (!server) | 1613 | if (!server) |
1614 | return ERR_PTR(-ENOMEM); | 1614 | return ERR_PTR(-ENOMEM); |
1615 | 1615 | ||
1616 | /* set up the general RPC client */ | 1616 | /* set up the general RPC client */ |
1617 | error = nfs4_init_server(server, data); | 1617 | error = nfs4_init_server(server, data); |
1618 | if (error < 0) | 1618 | if (error < 0) |
1619 | goto error; | 1619 | goto error; |
1620 | 1620 | ||
1621 | error = nfs4_server_common_setup(server, mntfh); | 1621 | error = nfs4_server_common_setup(server, mntfh); |
1622 | if (error < 0) | 1622 | if (error < 0) |
1623 | goto error; | 1623 | goto error; |
1624 | 1624 | ||
1625 | dprintk("<-- nfs4_create_server() = %p\n", server); | 1625 | dprintk("<-- nfs4_create_server() = %p\n", server); |
1626 | return server; | 1626 | return server; |
1627 | 1627 | ||
1628 | error: | 1628 | error: |
1629 | nfs_free_server(server); | 1629 | nfs_free_server(server); |
1630 | dprintk("<-- nfs4_create_server() = error %d\n", error); | 1630 | dprintk("<-- nfs4_create_server() = error %d\n", error); |
1631 | return ERR_PTR(error); | 1631 | return ERR_PTR(error); |
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | /* | 1634 | /* |
1635 | * Create an NFS4 referral server record | 1635 | * Create an NFS4 referral server record |
1636 | */ | 1636 | */ |
1637 | struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | 1637 | struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, |
1638 | struct nfs_fh *mntfh) | 1638 | struct nfs_fh *mntfh) |
1639 | { | 1639 | { |
1640 | struct nfs_client *parent_client; | 1640 | struct nfs_client *parent_client; |
1641 | struct nfs_server *server, *parent_server; | 1641 | struct nfs_server *server, *parent_server; |
1642 | int error; | 1642 | int error; |
1643 | 1643 | ||
1644 | dprintk("--> nfs4_create_referral_server()\n"); | 1644 | dprintk("--> nfs4_create_referral_server()\n"); |
1645 | 1645 | ||
1646 | server = nfs_alloc_server(); | 1646 | server = nfs_alloc_server(); |
1647 | if (!server) | 1647 | if (!server) |
1648 | return ERR_PTR(-ENOMEM); | 1648 | return ERR_PTR(-ENOMEM); |
1649 | 1649 | ||
1650 | parent_server = NFS_SB(data->sb); | 1650 | parent_server = NFS_SB(data->sb); |
1651 | parent_client = parent_server->nfs_client; | 1651 | parent_client = parent_server->nfs_client; |
1652 | 1652 | ||
1653 | /* Initialise the client representation from the parent server */ | 1653 | /* Initialise the client representation from the parent server */ |
1654 | nfs_server_copy_userdata(server, parent_server); | 1654 | nfs_server_copy_userdata(server, parent_server); |
1655 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR; | 1655 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR; |
1656 | 1656 | ||
1657 | /* Get a client representation. | 1657 | /* Get a client representation. |
1658 | * Note: NFSv4 always uses TCP, */ | 1658 | * Note: NFSv4 always uses TCP, */ |
1659 | error = nfs4_set_client(server, data->hostname, | 1659 | error = nfs4_set_client(server, data->hostname, |
1660 | data->addr, | 1660 | data->addr, |
1661 | data->addrlen, | 1661 | data->addrlen, |
1662 | parent_client->cl_ipaddr, | 1662 | parent_client->cl_ipaddr, |
1663 | data->authflavor, | 1663 | data->authflavor, |
1664 | parent_server->client->cl_xprt->prot, | 1664 | parent_server->client->cl_xprt->prot, |
1665 | parent_server->client->cl_timeout, | 1665 | parent_server->client->cl_timeout, |
1666 | parent_client->cl_mvops->minor_version, | 1666 | parent_client->cl_mvops->minor_version, |
1667 | parent_client->net); | 1667 | parent_client->net); |
1668 | if (error < 0) | 1668 | if (error < 0) |
1669 | goto error; | 1669 | goto error; |
1670 | 1670 | ||
1671 | error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor); | 1671 | error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor); |
1672 | if (error < 0) | 1672 | if (error < 0) |
1673 | goto error; | 1673 | goto error; |
1674 | 1674 | ||
1675 | error = nfs4_server_common_setup(server, mntfh); | 1675 | error = nfs4_server_common_setup(server, mntfh); |
1676 | if (error < 0) | 1676 | if (error < 0) |
1677 | goto error; | 1677 | goto error; |
1678 | 1678 | ||
1679 | dprintk("<-- nfs_create_referral_server() = %p\n", server); | 1679 | dprintk("<-- nfs_create_referral_server() = %p\n", server); |
1680 | return server; | 1680 | return server; |
1681 | 1681 | ||
1682 | error: | 1682 | error: |
1683 | nfs_free_server(server); | 1683 | nfs_free_server(server); |
1684 | dprintk("<-- nfs4_create_referral_server() = error %d\n", error); | 1684 | dprintk("<-- nfs4_create_referral_server() = error %d\n", error); |
1685 | return ERR_PTR(error); | 1685 | return ERR_PTR(error); |
1686 | } | 1686 | } |
1687 | 1687 | ||
1688 | #endif /* CONFIG_NFS_V4 */ | 1688 | #endif /* CONFIG_NFS_V4 */ |
1689 | 1689 | ||
1690 | /* | 1690 | /* |
1691 | * Clone an NFS2, NFS3 or NFS4 server record | 1691 | * Clone an NFS2, NFS3 or NFS4 server record |
1692 | */ | 1692 | */ |
1693 | struct nfs_server *nfs_clone_server(struct nfs_server *source, | 1693 | struct nfs_server *nfs_clone_server(struct nfs_server *source, |
1694 | struct nfs_fh *fh, | 1694 | struct nfs_fh *fh, |
1695 | struct nfs_fattr *fattr) | 1695 | struct nfs_fattr *fattr) |
1696 | { | 1696 | { |
1697 | struct nfs_server *server; | 1697 | struct nfs_server *server; |
1698 | struct nfs_fattr *fattr_fsinfo; | 1698 | struct nfs_fattr *fattr_fsinfo; |
1699 | int error; | 1699 | int error; |
1700 | 1700 | ||
1701 | dprintk("--> nfs_clone_server(,%llx:%llx,)\n", | 1701 | dprintk("--> nfs_clone_server(,%llx:%llx,)\n", |
1702 | (unsigned long long) fattr->fsid.major, | 1702 | (unsigned long long) fattr->fsid.major, |
1703 | (unsigned long long) fattr->fsid.minor); | 1703 | (unsigned long long) fattr->fsid.minor); |
1704 | 1704 | ||
1705 | server = nfs_alloc_server(); | 1705 | server = nfs_alloc_server(); |
1706 | if (!server) | 1706 | if (!server) |
1707 | return ERR_PTR(-ENOMEM); | 1707 | return ERR_PTR(-ENOMEM); |
1708 | 1708 | ||
1709 | error = -ENOMEM; | 1709 | error = -ENOMEM; |
1710 | fattr_fsinfo = nfs_alloc_fattr(); | 1710 | fattr_fsinfo = nfs_alloc_fattr(); |
1711 | if (fattr_fsinfo == NULL) | 1711 | if (fattr_fsinfo == NULL) |
1712 | goto out_free_server; | 1712 | goto out_free_server; |
1713 | 1713 | ||
1714 | /* Copy data from the source */ | 1714 | /* Copy data from the source */ |
1715 | server->nfs_client = source->nfs_client; | 1715 | server->nfs_client = source->nfs_client; |
1716 | server->destroy = source->destroy; | 1716 | server->destroy = source->destroy; |
1717 | atomic_inc(&server->nfs_client->cl_count); | 1717 | atomic_inc(&server->nfs_client->cl_count); |
1718 | nfs_server_copy_userdata(server, source); | 1718 | nfs_server_copy_userdata(server, source); |
1719 | 1719 | ||
1720 | server->fsid = fattr->fsid; | 1720 | server->fsid = fattr->fsid; |
1721 | 1721 | ||
1722 | error = nfs_init_server_rpcclient(server, | 1722 | error = nfs_init_server_rpcclient(server, |
1723 | source->client->cl_timeout, | 1723 | source->client->cl_timeout, |
1724 | source->client->cl_auth->au_flavor); | 1724 | source->client->cl_auth->au_flavor); |
1725 | if (error < 0) | 1725 | if (error < 0) |
1726 | goto out_free_server; | 1726 | goto out_free_server; |
1727 | if (!IS_ERR(source->client_acl)) | 1727 | if (!IS_ERR(source->client_acl)) |
1728 | nfs_init_server_aclclient(server); | 1728 | nfs_init_server_aclclient(server); |
1729 | 1729 | ||
1730 | /* probe the filesystem info for this server filesystem */ | 1730 | /* probe the filesystem info for this server filesystem */ |
1731 | error = nfs_probe_fsinfo(server, fh, fattr_fsinfo); | 1731 | error = nfs_probe_fsinfo(server, fh, fattr_fsinfo); |
1732 | if (error < 0) | 1732 | if (error < 0) |
1733 | goto out_free_server; | 1733 | goto out_free_server; |
1734 | 1734 | ||
1735 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | 1735 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) |
1736 | server->namelen = NFS4_MAXNAMLEN; | 1736 | server->namelen = NFS4_MAXNAMLEN; |
1737 | 1737 | ||
1738 | dprintk("Cloned FSID: %llx:%llx\n", | 1738 | dprintk("Cloned FSID: %llx:%llx\n", |
1739 | (unsigned long long) server->fsid.major, | 1739 | (unsigned long long) server->fsid.major, |
1740 | (unsigned long long) server->fsid.minor); | 1740 | (unsigned long long) server->fsid.minor); |
1741 | 1741 | ||
1742 | error = nfs_start_lockd(server); | 1742 | error = nfs_start_lockd(server); |
1743 | if (error < 0) | 1743 | if (error < 0) |
1744 | goto out_free_server; | 1744 | goto out_free_server; |
1745 | 1745 | ||
1746 | nfs_server_insert_lists(server); | 1746 | nfs_server_insert_lists(server); |
1747 | server->mount_time = jiffies; | 1747 | server->mount_time = jiffies; |
1748 | 1748 | ||
1749 | nfs_free_fattr(fattr_fsinfo); | 1749 | nfs_free_fattr(fattr_fsinfo); |
1750 | dprintk("<-- nfs_clone_server() = %p\n", server); | 1750 | dprintk("<-- nfs_clone_server() = %p\n", server); |
1751 | return server; | 1751 | return server; |
1752 | 1752 | ||
1753 | out_free_server: | 1753 | out_free_server: |
1754 | nfs_free_fattr(fattr_fsinfo); | 1754 | nfs_free_fattr(fattr_fsinfo); |
1755 | nfs_free_server(server); | 1755 | nfs_free_server(server); |
1756 | dprintk("<-- nfs_clone_server() = error %d\n", error); | 1756 | dprintk("<-- nfs_clone_server() = error %d\n", error); |
1757 | return ERR_PTR(error); | 1757 | return ERR_PTR(error); |
1758 | } | 1758 | } |
1759 | 1759 | ||
1760 | #ifdef CONFIG_PROC_FS | 1760 | #ifdef CONFIG_PROC_FS |
1761 | static struct proc_dir_entry *proc_fs_nfs; | 1761 | static struct proc_dir_entry *proc_fs_nfs; |
1762 | 1762 | ||
1763 | static int nfs_server_list_open(struct inode *inode, struct file *file); | 1763 | static int nfs_server_list_open(struct inode *inode, struct file *file); |
1764 | static void *nfs_server_list_start(struct seq_file *p, loff_t *pos); | 1764 | static void *nfs_server_list_start(struct seq_file *p, loff_t *pos); |
1765 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos); | 1765 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos); |
1766 | static void nfs_server_list_stop(struct seq_file *p, void *v); | 1766 | static void nfs_server_list_stop(struct seq_file *p, void *v); |
1767 | static int nfs_server_list_show(struct seq_file *m, void *v); | 1767 | static int nfs_server_list_show(struct seq_file *m, void *v); |
1768 | 1768 | ||
1769 | static const struct seq_operations nfs_server_list_ops = { | 1769 | static const struct seq_operations nfs_server_list_ops = { |
1770 | .start = nfs_server_list_start, | 1770 | .start = nfs_server_list_start, |
1771 | .next = nfs_server_list_next, | 1771 | .next = nfs_server_list_next, |
1772 | .stop = nfs_server_list_stop, | 1772 | .stop = nfs_server_list_stop, |
1773 | .show = nfs_server_list_show, | 1773 | .show = nfs_server_list_show, |
1774 | }; | 1774 | }; |
1775 | 1775 | ||
1776 | static const struct file_operations nfs_server_list_fops = { | 1776 | static const struct file_operations nfs_server_list_fops = { |
1777 | .open = nfs_server_list_open, | 1777 | .open = nfs_server_list_open, |
1778 | .read = seq_read, | 1778 | .read = seq_read, |
1779 | .llseek = seq_lseek, | 1779 | .llseek = seq_lseek, |
1780 | .release = seq_release, | 1780 | .release = seq_release, |
1781 | .owner = THIS_MODULE, | 1781 | .owner = THIS_MODULE, |
1782 | }; | 1782 | }; |
1783 | 1783 | ||
1784 | static int nfs_volume_list_open(struct inode *inode, struct file *file); | 1784 | static int nfs_volume_list_open(struct inode *inode, struct file *file); |
1785 | static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos); | 1785 | static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos); |
1786 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos); | 1786 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos); |
1787 | static void nfs_volume_list_stop(struct seq_file *p, void *v); | 1787 | static void nfs_volume_list_stop(struct seq_file *p, void *v); |
1788 | static int nfs_volume_list_show(struct seq_file *m, void *v); | 1788 | static int nfs_volume_list_show(struct seq_file *m, void *v); |
1789 | 1789 | ||
1790 | static const struct seq_operations nfs_volume_list_ops = { | 1790 | static const struct seq_operations nfs_volume_list_ops = { |
1791 | .start = nfs_volume_list_start, | 1791 | .start = nfs_volume_list_start, |
1792 | .next = nfs_volume_list_next, | 1792 | .next = nfs_volume_list_next, |
1793 | .stop = nfs_volume_list_stop, | 1793 | .stop = nfs_volume_list_stop, |
1794 | .show = nfs_volume_list_show, | 1794 | .show = nfs_volume_list_show, |
1795 | }; | 1795 | }; |
1796 | 1796 | ||
1797 | static const struct file_operations nfs_volume_list_fops = { | 1797 | static const struct file_operations nfs_volume_list_fops = { |
1798 | .open = nfs_volume_list_open, | 1798 | .open = nfs_volume_list_open, |
1799 | .read = seq_read, | 1799 | .read = seq_read, |
1800 | .llseek = seq_lseek, | 1800 | .llseek = seq_lseek, |
1801 | .release = seq_release, | 1801 | .release = seq_release, |
1802 | .owner = THIS_MODULE, | 1802 | .owner = THIS_MODULE, |
1803 | }; | 1803 | }; |
1804 | 1804 | ||
1805 | /* | 1805 | /* |
1806 | * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which | 1806 | * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which |
1807 | * we're dealing | 1807 | * we're dealing |
1808 | */ | 1808 | */ |
1809 | static int nfs_server_list_open(struct inode *inode, struct file *file) | 1809 | static int nfs_server_list_open(struct inode *inode, struct file *file) |
1810 | { | 1810 | { |
1811 | struct seq_file *m; | 1811 | struct seq_file *m; |
1812 | int ret; | 1812 | int ret; |
1813 | 1813 | ||
1814 | ret = seq_open(file, &nfs_server_list_ops); | 1814 | ret = seq_open(file, &nfs_server_list_ops); |
1815 | if (ret < 0) | 1815 | if (ret < 0) |
1816 | return ret; | 1816 | return ret; |
1817 | 1817 | ||
1818 | m = file->private_data; | 1818 | m = file->private_data; |
1819 | m->private = PDE(inode)->data; | 1819 | m->private = PDE(inode)->data; |
1820 | 1820 | ||
1821 | return 0; | 1821 | return 0; |
1822 | } | 1822 | } |
1823 | 1823 | ||
1824 | /* | 1824 | /* |
1825 | * set up the iterator to start reading from the server list and return the first item | 1825 | * set up the iterator to start reading from the server list and return the first item |
1826 | */ | 1826 | */ |
1827 | static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) | 1827 | static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) |
1828 | { | 1828 | { |
1829 | /* lock the list against modification */ | 1829 | /* lock the list against modification */ |
1830 | spin_lock(&nfs_client_lock); | 1830 | spin_lock(&nfs_client_lock); |
1831 | return seq_list_start_head(&nfs_client_list, *_pos); | 1831 | return seq_list_start_head(&nfs_client_list, *_pos); |
1832 | } | 1832 | } |
1833 | 1833 | ||
1834 | /* | 1834 | /* |
1835 | * move to next server | 1835 | * move to next server |
1836 | */ | 1836 | */ |
1837 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) | 1837 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) |
1838 | { | 1838 | { |
1839 | return seq_list_next(v, &nfs_client_list, pos); | 1839 | return seq_list_next(v, &nfs_client_list, pos); |
1840 | } | 1840 | } |
1841 | 1841 | ||
1842 | /* | 1842 | /* |
1843 | * clean up after reading from the transports list | 1843 | * clean up after reading from the transports list |
1844 | */ | 1844 | */ |
1845 | static void nfs_server_list_stop(struct seq_file *p, void *v) | 1845 | static void nfs_server_list_stop(struct seq_file *p, void *v) |
1846 | { | 1846 | { |
1847 | spin_unlock(&nfs_client_lock); | 1847 | spin_unlock(&nfs_client_lock); |
1848 | } | 1848 | } |
1849 | 1849 | ||
1850 | /* | 1850 | /* |
1851 | * display a header line followed by a load of call lines | 1851 | * display a header line followed by a load of call lines |
1852 | */ | 1852 | */ |
1853 | static int nfs_server_list_show(struct seq_file *m, void *v) | 1853 | static int nfs_server_list_show(struct seq_file *m, void *v) |
1854 | { | 1854 | { |
1855 | struct nfs_client *clp; | 1855 | struct nfs_client *clp; |
1856 | 1856 | ||
1857 | /* display header on line 1 */ | 1857 | /* display header on line 1 */ |
1858 | if (v == &nfs_client_list) { | 1858 | if (v == &nfs_client_list) { |
1859 | seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); | 1859 | seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); |
1860 | return 0; | 1860 | return 0; |
1861 | } | 1861 | } |
1862 | 1862 | ||
1863 | /* display one transport per line on subsequent lines */ | 1863 | /* display one transport per line on subsequent lines */ |
1864 | clp = list_entry(v, struct nfs_client, cl_share_link); | 1864 | clp = list_entry(v, struct nfs_client, cl_share_link); |
1865 | 1865 | ||
1866 | /* Check if the client is initialized */ | 1866 | /* Check if the client is initialized */ |
1867 | if (clp->cl_cons_state != NFS_CS_READY) | 1867 | if (clp->cl_cons_state != NFS_CS_READY) |
1868 | return 0; | 1868 | return 0; |
1869 | 1869 | ||
1870 | seq_printf(m, "v%u %s %s %3d %s\n", | 1870 | seq_printf(m, "v%u %s %s %3d %s\n", |
1871 | clp->rpc_ops->version, | 1871 | clp->rpc_ops->version, |
1872 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), | 1872 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), |
1873 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), | 1873 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), |
1874 | atomic_read(&clp->cl_count), | 1874 | atomic_read(&clp->cl_count), |
1875 | clp->cl_hostname); | 1875 | clp->cl_hostname); |
1876 | 1876 | ||
1877 | return 0; | 1877 | return 0; |
1878 | } | 1878 | } |
1879 | 1879 | ||
1880 | /* | 1880 | /* |
1881 | * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes | 1881 | * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes |
1882 | */ | 1882 | */ |
1883 | static int nfs_volume_list_open(struct inode *inode, struct file *file) | 1883 | static int nfs_volume_list_open(struct inode *inode, struct file *file) |
1884 | { | 1884 | { |
1885 | struct seq_file *m; | 1885 | struct seq_file *m; |
1886 | int ret; | 1886 | int ret; |
1887 | 1887 | ||
1888 | ret = seq_open(file, &nfs_volume_list_ops); | 1888 | ret = seq_open(file, &nfs_volume_list_ops); |
1889 | if (ret < 0) | 1889 | if (ret < 0) |
1890 | return ret; | 1890 | return ret; |
1891 | 1891 | ||
1892 | m = file->private_data; | 1892 | m = file->private_data; |
1893 | m->private = PDE(inode)->data; | 1893 | m->private = PDE(inode)->data; |
1894 | 1894 | ||
1895 | return 0; | 1895 | return 0; |
1896 | } | 1896 | } |
1897 | 1897 | ||
1898 | /* | 1898 | /* |
1899 | * set up the iterator to start reading from the volume list and return the first item | 1899 | * set up the iterator to start reading from the volume list and return the first item |
1900 | */ | 1900 | */ |
1901 | static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) | 1901 | static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) |
1902 | { | 1902 | { |
1903 | /* lock the list against modification */ | 1903 | /* lock the list against modification */ |
1904 | spin_lock(&nfs_client_lock); | 1904 | spin_lock(&nfs_client_lock); |
1905 | return seq_list_start_head(&nfs_volume_list, *_pos); | 1905 | return seq_list_start_head(&nfs_volume_list, *_pos); |
1906 | } | 1906 | } |
1907 | 1907 | ||
1908 | /* | 1908 | /* |
1909 | * move to next volume | 1909 | * move to next volume |
1910 | */ | 1910 | */ |
1911 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) | 1911 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) |
1912 | { | 1912 | { |
1913 | return seq_list_next(v, &nfs_volume_list, pos); | 1913 | return seq_list_next(v, &nfs_volume_list, pos); |
1914 | } | 1914 | } |
1915 | 1915 | ||
1916 | /* | 1916 | /* |
1917 | * clean up after reading from the transports list | 1917 | * clean up after reading from the transports list |
1918 | */ | 1918 | */ |
1919 | static void nfs_volume_list_stop(struct seq_file *p, void *v) | 1919 | static void nfs_volume_list_stop(struct seq_file *p, void *v) |
1920 | { | 1920 | { |
1921 | spin_unlock(&nfs_client_lock); | 1921 | spin_unlock(&nfs_client_lock); |
1922 | } | 1922 | } |
1923 | 1923 | ||
1924 | /* | 1924 | /* |
1925 | * display a header line followed by a load of call lines | 1925 | * display a header line followed by a load of call lines |
1926 | */ | 1926 | */ |
1927 | static int nfs_volume_list_show(struct seq_file *m, void *v) | 1927 | static int nfs_volume_list_show(struct seq_file *m, void *v) |
1928 | { | 1928 | { |
1929 | struct nfs_server *server; | 1929 | struct nfs_server *server; |
1930 | struct nfs_client *clp; | 1930 | struct nfs_client *clp; |
1931 | char dev[8], fsid[17]; | 1931 | char dev[8], fsid[17]; |
1932 | 1932 | ||
1933 | /* display header on line 1 */ | 1933 | /* display header on line 1 */ |
1934 | if (v == &nfs_volume_list) { | 1934 | if (v == &nfs_volume_list) { |
1935 | seq_puts(m, "NV SERVER PORT DEV FSID FSC\n"); | 1935 | seq_puts(m, "NV SERVER PORT DEV FSID FSC\n"); |
1936 | return 0; | 1936 | return 0; |
1937 | } | 1937 | } |
1938 | /* display one transport per line on subsequent lines */ | 1938 | /* display one transport per line on subsequent lines */ |
1939 | server = list_entry(v, struct nfs_server, master_link); | 1939 | server = list_entry(v, struct nfs_server, master_link); |
1940 | clp = server->nfs_client; | 1940 | clp = server->nfs_client; |
1941 | 1941 | ||
1942 | snprintf(dev, 8, "%u:%u", | 1942 | snprintf(dev, 8, "%u:%u", |
1943 | MAJOR(server->s_dev), MINOR(server->s_dev)); | 1943 | MAJOR(server->s_dev), MINOR(server->s_dev)); |
1944 | 1944 | ||
1945 | snprintf(fsid, 17, "%llx:%llx", | 1945 | snprintf(fsid, 17, "%llx:%llx", |
1946 | (unsigned long long) server->fsid.major, | 1946 | (unsigned long long) server->fsid.major, |
1947 | (unsigned long long) server->fsid.minor); | 1947 | (unsigned long long) server->fsid.minor); |
1948 | 1948 | ||
1949 | seq_printf(m, "v%u %s %s %-7s %-17s %s\n", | 1949 | seq_printf(m, "v%u %s %s %-7s %-17s %s\n", |
1950 | clp->rpc_ops->version, | 1950 | clp->rpc_ops->version, |
1951 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), | 1951 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), |
1952 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), | 1952 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), |
1953 | dev, | 1953 | dev, |
1954 | fsid, | 1954 | fsid, |
1955 | nfs_server_fscache_state(server)); | 1955 | nfs_server_fscache_state(server)); |
1956 | 1956 | ||
1957 | return 0; | 1957 | return 0; |
1958 | } | 1958 | } |
1959 | 1959 | ||
1960 | /* | 1960 | /* |
1961 | * initialise the /proc/fs/nfsfs/ directory | 1961 | * initialise the /proc/fs/nfsfs/ directory |
1962 | */ | 1962 | */ |
1963 | int __init nfs_fs_proc_init(void) | 1963 | int __init nfs_fs_proc_init(void) |
1964 | { | 1964 | { |
1965 | struct proc_dir_entry *p; | 1965 | struct proc_dir_entry *p; |
1966 | 1966 | ||
1967 | proc_fs_nfs = proc_mkdir("fs/nfsfs", NULL); | 1967 | proc_fs_nfs = proc_mkdir("fs/nfsfs", NULL); |
1968 | if (!proc_fs_nfs) | 1968 | if (!proc_fs_nfs) |
1969 | goto error_0; | 1969 | goto error_0; |
1970 | 1970 | ||
1971 | /* a file of servers with which we're dealing */ | 1971 | /* a file of servers with which we're dealing */ |
1972 | p = proc_create("servers", S_IFREG|S_IRUGO, | 1972 | p = proc_create("servers", S_IFREG|S_IRUGO, |
1973 | proc_fs_nfs, &nfs_server_list_fops); | 1973 | proc_fs_nfs, &nfs_server_list_fops); |
1974 | if (!p) | 1974 | if (!p) |
1975 | goto error_1; | 1975 | goto error_1; |
1976 | 1976 | ||
1977 | /* a file of volumes that we have mounted */ | 1977 | /* a file of volumes that we have mounted */ |
1978 | p = proc_create("volumes", S_IFREG|S_IRUGO, | 1978 | p = proc_create("volumes", S_IFREG|S_IRUGO, |
1979 | proc_fs_nfs, &nfs_volume_list_fops); | 1979 | proc_fs_nfs, &nfs_volume_list_fops); |
1980 | if (!p) | 1980 | if (!p) |
1981 | goto error_2; | 1981 | goto error_2; |
1982 | return 0; | 1982 | return 0; |
1983 | 1983 | ||
1984 | error_2: | 1984 | error_2: |
1985 | remove_proc_entry("servers", proc_fs_nfs); | 1985 | remove_proc_entry("servers", proc_fs_nfs); |
1986 | error_1: | 1986 | error_1: |
1987 | remove_proc_entry("fs/nfsfs", NULL); | 1987 | remove_proc_entry("fs/nfsfs", NULL); |
1988 | error_0: | 1988 | error_0: |
1989 | return -ENOMEM; | 1989 | return -ENOMEM; |
1990 | } | 1990 | } |
1991 | 1991 | ||
1992 | /* | 1992 | /* |
1993 | * clean up the /proc/fs/nfsfs/ directory | 1993 | * clean up the /proc/fs/nfsfs/ directory |
1994 | */ | 1994 | */ |
1995 | void nfs_fs_proc_exit(void) | 1995 | void nfs_fs_proc_exit(void) |
1996 | { | 1996 | { |
1997 | remove_proc_entry("volumes", proc_fs_nfs); | 1997 | remove_proc_entry("volumes", proc_fs_nfs); |
1998 | remove_proc_entry("servers", proc_fs_nfs); | 1998 | remove_proc_entry("servers", proc_fs_nfs); |
1999 | remove_proc_entry("fs/nfsfs", NULL); | 1999 | remove_proc_entry("fs/nfsfs", NULL); |
2000 | } | 2000 | } |
2001 | 2001 | ||
2002 | #endif /* CONFIG_PROC_FS */ | 2002 | #endif /* CONFIG_PROC_FS */ |
2003 | 2003 | ||
2004 | module_param(nfs4_disable_idmapping, bool, 0644); | 2004 | module_param(nfs4_disable_idmapping, bool, 0644); |
2005 | MODULE_PARM_DESC(nfs4_disable_idmapping, | 2005 | MODULE_PARM_DESC(nfs4_disable_idmapping, |
2006 | "Turn off NFSv4 idmapping when using 'sec=sys'"); | 2006 | "Turn off NFSv4 idmapping when using 'sec=sys'"); |
2007 | 2007 |
fs/nfs/internal.h
1 | /* | 1 | /* |
2 | * NFS internal definitions | 2 | * NFS internal definitions |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include "nfs4_fs.h" | 5 | #include "nfs4_fs.h" |
6 | #include <linux/mount.h> | 6 | #include <linux/mount.h> |
7 | #include <linux/security.h> | 7 | #include <linux/security.h> |
8 | 8 | ||
9 | #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) | 9 | #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) |
10 | 10 | ||
11 | struct nfs_string; | 11 | struct nfs_string; |
12 | 12 | ||
13 | /* Maximum number of readahead requests | 13 | /* Maximum number of readahead requests |
14 | * FIXME: this should really be a sysctl so that users may tune it to suit | 14 | * FIXME: this should really be a sysctl so that users may tune it to suit |
15 | * their needs. People that do NFS over a slow network, might for | 15 | * their needs. People that do NFS over a slow network, might for |
16 | * instance want to reduce it to something closer to 1 for improved | 16 | * instance want to reduce it to something closer to 1 for improved |
17 | * interactive response. | 17 | * interactive response. |
18 | */ | 18 | */ |
19 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) | 19 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * Determine if sessions are in use. | 22 | * Determine if sessions are in use. |
23 | */ | 23 | */ |
24 | static inline int nfs4_has_session(const struct nfs_client *clp) | 24 | static inline int nfs4_has_session(const struct nfs_client *clp) |
25 | { | 25 | { |
26 | #ifdef CONFIG_NFS_V4_1 | 26 | #ifdef CONFIG_NFS_V4_1 |
27 | if (clp->cl_session) | 27 | if (clp->cl_session) |
28 | return 1; | 28 | return 1; |
29 | #endif /* CONFIG_NFS_V4_1 */ | 29 | #endif /* CONFIG_NFS_V4_1 */ |
30 | return 0; | 30 | return 0; |
31 | } | 31 | } |
32 | 32 | ||
33 | static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | 33 | static inline int nfs4_has_persistent_session(const struct nfs_client *clp) |
34 | { | 34 | { |
35 | #ifdef CONFIG_NFS_V4_1 | 35 | #ifdef CONFIG_NFS_V4_1 |
36 | if (nfs4_has_session(clp)) | 36 | if (nfs4_has_session(clp)) |
37 | return (clp->cl_session->flags & SESSION4_PERSIST); | 37 | return (clp->cl_session->flags & SESSION4_PERSIST); |
38 | #endif /* CONFIG_NFS_V4_1 */ | 38 | #endif /* CONFIG_NFS_V4_1 */ |
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) | 42 | static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) |
43 | { | 43 | { |
44 | if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) | 44 | if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) |
45 | fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; | 45 | fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; |
46 | } | 46 | } |
47 | 47 | ||
48 | static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr) | 48 | static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr) |
49 | { | 49 | { |
50 | if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) || | 50 | if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) || |
51 | (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) && | 51 | (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) && |
52 | ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0))) | 52 | ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0))) |
53 | return 0; | 53 | return 0; |
54 | 54 | ||
55 | fattr->fileid = fattr->mounted_on_fileid; | 55 | fattr->fileid = fattr->mounted_on_fileid; |
56 | return 1; | 56 | return 1; |
57 | } | 57 | } |
58 | 58 | ||
59 | struct nfs_clone_mount { | 59 | struct nfs_clone_mount { |
60 | const struct super_block *sb; | 60 | const struct super_block *sb; |
61 | const struct dentry *dentry; | 61 | const struct dentry *dentry; |
62 | struct nfs_fh *fh; | 62 | struct nfs_fh *fh; |
63 | struct nfs_fattr *fattr; | 63 | struct nfs_fattr *fattr; |
64 | char *hostname; | 64 | char *hostname; |
65 | char *mnt_path; | 65 | char *mnt_path; |
66 | struct sockaddr *addr; | 66 | struct sockaddr *addr; |
67 | size_t addrlen; | 67 | size_t addrlen; |
68 | rpc_authflavor_t authflavor; | 68 | rpc_authflavor_t authflavor; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * Note: RFC 1813 doesn't limit the number of auth flavors that | 72 | * Note: RFC 1813 doesn't limit the number of auth flavors that |
73 | * a server can return, so make something up. | 73 | * a server can return, so make something up. |
74 | */ | 74 | */ |
75 | #define NFS_MAX_SECFLAVORS (12) | 75 | #define NFS_MAX_SECFLAVORS (12) |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * Value used if the user did not specify a port value. | 78 | * Value used if the user did not specify a port value. |
79 | */ | 79 | */ |
80 | #define NFS_UNSPEC_PORT (-1) | 80 | #define NFS_UNSPEC_PORT (-1) |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * Maximum number of pages that readdir can use for creating | 83 | * Maximum number of pages that readdir can use for creating |
84 | * a vmapped array of pages. | 84 | * a vmapped array of pages. |
85 | */ | 85 | */ |
86 | #define NFS_MAX_READDIR_PAGES 8 | 86 | #define NFS_MAX_READDIR_PAGES 8 |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * In-kernel mount arguments | 89 | * In-kernel mount arguments |
90 | */ | 90 | */ |
91 | struct nfs_parsed_mount_data { | 91 | struct nfs_parsed_mount_data { |
92 | int flags; | 92 | int flags; |
93 | int rsize, wsize; | 93 | int rsize, wsize; |
94 | int timeo, retrans; | 94 | int timeo, retrans; |
95 | int acregmin, acregmax, | 95 | int acregmin, acregmax, |
96 | acdirmin, acdirmax; | 96 | acdirmin, acdirmax; |
97 | int namlen; | 97 | int namlen; |
98 | unsigned int options; | 98 | unsigned int options; |
99 | unsigned int bsize; | 99 | unsigned int bsize; |
100 | unsigned int auth_flavor_len; | 100 | unsigned int auth_flavor_len; |
101 | rpc_authflavor_t auth_flavors[1]; | 101 | rpc_authflavor_t auth_flavors[1]; |
102 | char *client_address; | 102 | char *client_address; |
103 | unsigned int version; | 103 | unsigned int version; |
104 | unsigned int minorversion; | 104 | unsigned int minorversion; |
105 | char *fscache_uniq; | 105 | char *fscache_uniq; |
106 | 106 | ||
107 | struct { | 107 | struct { |
108 | struct sockaddr_storage address; | 108 | struct sockaddr_storage address; |
109 | size_t addrlen; | 109 | size_t addrlen; |
110 | char *hostname; | 110 | char *hostname; |
111 | u32 version; | 111 | u32 version; |
112 | int port; | 112 | int port; |
113 | unsigned short protocol; | 113 | unsigned short protocol; |
114 | } mount_server; | 114 | } mount_server; |
115 | 115 | ||
116 | struct { | 116 | struct { |
117 | struct sockaddr_storage address; | 117 | struct sockaddr_storage address; |
118 | size_t addrlen; | 118 | size_t addrlen; |
119 | char *hostname; | 119 | char *hostname; |
120 | char *export_path; | 120 | char *export_path; |
121 | int port; | 121 | int port; |
122 | unsigned short protocol; | 122 | unsigned short protocol; |
123 | } nfs_server; | 123 | } nfs_server; |
124 | 124 | ||
125 | struct security_mnt_opts lsm_opts; | 125 | struct security_mnt_opts lsm_opts; |
126 | struct net *net; | 126 | struct net *net; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | /* mount_clnt.c */ | 129 | /* mount_clnt.c */ |
130 | struct nfs_mount_request { | 130 | struct nfs_mount_request { |
131 | struct sockaddr *sap; | 131 | struct sockaddr *sap; |
132 | size_t salen; | 132 | size_t salen; |
133 | char *hostname; | 133 | char *hostname; |
134 | char *dirpath; | 134 | char *dirpath; |
135 | u32 version; | 135 | u32 version; |
136 | unsigned short protocol; | 136 | unsigned short protocol; |
137 | struct nfs_fh *fh; | 137 | struct nfs_fh *fh; |
138 | int noresvport; | 138 | int noresvport; |
139 | unsigned int *auth_flav_len; | 139 | unsigned int *auth_flav_len; |
140 | rpc_authflavor_t *auth_flavs; | 140 | rpc_authflavor_t *auth_flavs; |
141 | struct net *net; | 141 | struct net *net; |
142 | }; | 142 | }; |
143 | 143 | ||
144 | extern int nfs_mount(struct nfs_mount_request *info); | 144 | extern int nfs_mount(struct nfs_mount_request *info); |
145 | extern void nfs_umount(const struct nfs_mount_request *info); | 145 | extern void nfs_umount(const struct nfs_mount_request *info); |
146 | 146 | ||
147 | /* client.c */ | 147 | /* client.c */ |
148 | extern struct rpc_program nfs_program; | 148 | extern const struct rpc_program nfs_program; |
149 | 149 | ||
150 | extern void nfs_cleanup_cb_ident_idr(void); | 150 | extern void nfs_cleanup_cb_ident_idr(void); |
151 | extern void nfs_put_client(struct nfs_client *); | 151 | extern void nfs_put_client(struct nfs_client *); |
152 | extern struct nfs_client *nfs4_find_client_ident(int); | 152 | extern struct nfs_client *nfs4_find_client_ident(int); |
153 | extern struct nfs_client * | 153 | extern struct nfs_client * |
154 | nfs4_find_client_sessionid(const struct sockaddr *, struct nfs4_sessionid *); | 154 | nfs4_find_client_sessionid(const struct sockaddr *, struct nfs4_sessionid *); |
155 | extern struct nfs_server *nfs_create_server( | 155 | extern struct nfs_server *nfs_create_server( |
156 | const struct nfs_parsed_mount_data *, | 156 | const struct nfs_parsed_mount_data *, |
157 | struct nfs_fh *); | 157 | struct nfs_fh *); |
158 | extern struct nfs_server *nfs4_create_server( | 158 | extern struct nfs_server *nfs4_create_server( |
159 | const struct nfs_parsed_mount_data *, | 159 | const struct nfs_parsed_mount_data *, |
160 | struct nfs_fh *); | 160 | struct nfs_fh *); |
161 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, | 161 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, |
162 | struct nfs_fh *); | 162 | struct nfs_fh *); |
163 | extern void nfs_free_server(struct nfs_server *server); | 163 | extern void nfs_free_server(struct nfs_server *server); |
164 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, | 164 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, |
165 | struct nfs_fh *, | 165 | struct nfs_fh *, |
166 | struct nfs_fattr *); | 166 | struct nfs_fattr *); |
167 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); | 167 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); |
168 | extern int nfs4_check_client_ready(struct nfs_client *clp); | 168 | extern int nfs4_check_client_ready(struct nfs_client *clp); |
169 | extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, | 169 | extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, |
170 | const struct sockaddr *ds_addr, | 170 | const struct sockaddr *ds_addr, |
171 | int ds_addrlen, int ds_proto); | 171 | int ds_addrlen, int ds_proto); |
172 | #ifdef CONFIG_PROC_FS | 172 | #ifdef CONFIG_PROC_FS |
173 | extern int __init nfs_fs_proc_init(void); | 173 | extern int __init nfs_fs_proc_init(void); |
174 | extern void nfs_fs_proc_exit(void); | 174 | extern void nfs_fs_proc_exit(void); |
175 | #else | 175 | #else |
176 | static inline int nfs_fs_proc_init(void) | 176 | static inline int nfs_fs_proc_init(void) |
177 | { | 177 | { |
178 | return 0; | 178 | return 0; |
179 | } | 179 | } |
180 | static inline void nfs_fs_proc_exit(void) | 180 | static inline void nfs_fs_proc_exit(void) |
181 | { | 181 | { |
182 | } | 182 | } |
183 | #endif | 183 | #endif |
184 | #ifdef CONFIG_NFS_V4 | 184 | #ifdef CONFIG_NFS_V4 |
185 | extern spinlock_t nfs_client_lock; | 185 | extern spinlock_t nfs_client_lock; |
186 | extern struct list_head nfs_client_list; | 186 | extern struct list_head nfs_client_list; |
187 | #endif | 187 | #endif |
188 | 188 | ||
189 | /* nfs4namespace.c */ | 189 | /* nfs4namespace.c */ |
190 | #ifdef CONFIG_NFS_V4 | 190 | #ifdef CONFIG_NFS_V4 |
191 | extern struct vfsmount *nfs_do_refmount(struct dentry *dentry); | 191 | extern struct vfsmount *nfs_do_refmount(struct dentry *dentry); |
192 | #else | 192 | #else |
193 | static inline | 193 | static inline |
194 | struct vfsmount *nfs_do_refmount(struct dentry *dentry) | 194 | struct vfsmount *nfs_do_refmount(struct dentry *dentry) |
195 | { | 195 | { |
196 | return ERR_PTR(-ENOENT); | 196 | return ERR_PTR(-ENOENT); |
197 | } | 197 | } |
198 | #endif | 198 | #endif |
199 | 199 | ||
200 | /* callback_xdr.c */ | 200 | /* callback_xdr.c */ |
201 | extern struct svc_version nfs4_callback_version1; | 201 | extern struct svc_version nfs4_callback_version1; |
202 | extern struct svc_version nfs4_callback_version4; | 202 | extern struct svc_version nfs4_callback_version4; |
203 | 203 | ||
204 | /* pagelist.c */ | 204 | /* pagelist.c */ |
205 | extern int __init nfs_init_nfspagecache(void); | 205 | extern int __init nfs_init_nfspagecache(void); |
206 | extern void nfs_destroy_nfspagecache(void); | 206 | extern void nfs_destroy_nfspagecache(void); |
207 | extern int __init nfs_init_readpagecache(void); | 207 | extern int __init nfs_init_readpagecache(void); |
208 | extern void nfs_destroy_readpagecache(void); | 208 | extern void nfs_destroy_readpagecache(void); |
209 | extern int __init nfs_init_writepagecache(void); | 209 | extern int __init nfs_init_writepagecache(void); |
210 | extern void nfs_destroy_writepagecache(void); | 210 | extern void nfs_destroy_writepagecache(void); |
211 | 211 | ||
212 | extern int __init nfs_init_directcache(void); | 212 | extern int __init nfs_init_directcache(void); |
213 | extern void nfs_destroy_directcache(void); | 213 | extern void nfs_destroy_directcache(void); |
214 | 214 | ||
215 | /* nfs2xdr.c */ | 215 | /* nfs2xdr.c */ |
216 | extern int nfs_stat_to_errno(enum nfs_stat); | 216 | extern int nfs_stat_to_errno(enum nfs_stat); |
217 | extern struct rpc_procinfo nfs_procedures[]; | 217 | extern struct rpc_procinfo nfs_procedures[]; |
218 | extern int nfs2_decode_dirent(struct xdr_stream *, | 218 | extern int nfs2_decode_dirent(struct xdr_stream *, |
219 | struct nfs_entry *, int); | 219 | struct nfs_entry *, int); |
220 | 220 | ||
221 | /* nfs3xdr.c */ | 221 | /* nfs3xdr.c */ |
222 | extern struct rpc_procinfo nfs3_procedures[]; | 222 | extern struct rpc_procinfo nfs3_procedures[]; |
223 | extern int nfs3_decode_dirent(struct xdr_stream *, | 223 | extern int nfs3_decode_dirent(struct xdr_stream *, |
224 | struct nfs_entry *, int); | 224 | struct nfs_entry *, int); |
225 | 225 | ||
226 | /* nfs4xdr.c */ | 226 | /* nfs4xdr.c */ |
227 | #ifdef CONFIG_NFS_V4 | 227 | #ifdef CONFIG_NFS_V4 |
228 | extern int nfs4_decode_dirent(struct xdr_stream *, | 228 | extern int nfs4_decode_dirent(struct xdr_stream *, |
229 | struct nfs_entry *, int); | 229 | struct nfs_entry *, int); |
230 | #endif | 230 | #endif |
231 | #ifdef CONFIG_NFS_V4_1 | 231 | #ifdef CONFIG_NFS_V4_1 |
232 | extern const u32 nfs41_maxread_overhead; | 232 | extern const u32 nfs41_maxread_overhead; |
233 | extern const u32 nfs41_maxwrite_overhead; | 233 | extern const u32 nfs41_maxwrite_overhead; |
234 | #endif | 234 | #endif |
235 | 235 | ||
236 | /* nfs4proc.c */ | 236 | /* nfs4proc.c */ |
237 | #ifdef CONFIG_NFS_V4 | 237 | #ifdef CONFIG_NFS_V4 |
238 | extern struct rpc_procinfo nfs4_procedures[]; | 238 | extern struct rpc_procinfo nfs4_procedures[]; |
239 | void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *); | 239 | void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *); |
240 | #endif | 240 | #endif |
241 | 241 | ||
242 | extern int nfs4_init_ds_session(struct nfs_client *clp); | 242 | extern int nfs4_init_ds_session(struct nfs_client *clp); |
243 | 243 | ||
244 | /* proc.c */ | 244 | /* proc.c */ |
245 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | 245 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); |
246 | extern int nfs_init_client(struct nfs_client *clp, | 246 | extern int nfs_init_client(struct nfs_client *clp, |
247 | const struct rpc_timeout *timeparms, | 247 | const struct rpc_timeout *timeparms, |
248 | const char *ip_addr, rpc_authflavor_t authflavour, | 248 | const char *ip_addr, rpc_authflavor_t authflavour, |
249 | int noresvport); | 249 | int noresvport); |
250 | 250 | ||
251 | /* dir.c */ | 251 | /* dir.c */ |
252 | extern int nfs_access_cache_shrinker(struct shrinker *shrink, | 252 | extern int nfs_access_cache_shrinker(struct shrinker *shrink, |
253 | struct shrink_control *sc); | 253 | struct shrink_control *sc); |
254 | 254 | ||
255 | /* inode.c */ | 255 | /* inode.c */ |
256 | extern struct workqueue_struct *nfsiod_workqueue; | 256 | extern struct workqueue_struct *nfsiod_workqueue; |
257 | extern struct inode *nfs_alloc_inode(struct super_block *sb); | 257 | extern struct inode *nfs_alloc_inode(struct super_block *sb); |
258 | extern void nfs_destroy_inode(struct inode *); | 258 | extern void nfs_destroy_inode(struct inode *); |
259 | extern int nfs_write_inode(struct inode *, struct writeback_control *); | 259 | extern int nfs_write_inode(struct inode *, struct writeback_control *); |
260 | extern void nfs_evict_inode(struct inode *); | 260 | extern void nfs_evict_inode(struct inode *); |
261 | #ifdef CONFIG_NFS_V4 | 261 | #ifdef CONFIG_NFS_V4 |
262 | extern void nfs4_evict_inode(struct inode *); | 262 | extern void nfs4_evict_inode(struct inode *); |
263 | #endif | 263 | #endif |
264 | void nfs_zap_acl_cache(struct inode *inode); | 264 | void nfs_zap_acl_cache(struct inode *inode); |
265 | extern int nfs_wait_bit_killable(void *word); | 265 | extern int nfs_wait_bit_killable(void *word); |
266 | 266 | ||
267 | /* super.c */ | 267 | /* super.c */ |
268 | extern struct file_system_type nfs_xdev_fs_type; | 268 | extern struct file_system_type nfs_xdev_fs_type; |
269 | #ifdef CONFIG_NFS_V4 | 269 | #ifdef CONFIG_NFS_V4 |
270 | extern struct file_system_type nfs4_xdev_fs_type; | 270 | extern struct file_system_type nfs4_xdev_fs_type; |
271 | extern struct file_system_type nfs4_referral_fs_type; | 271 | extern struct file_system_type nfs4_referral_fs_type; |
272 | #endif | 272 | #endif |
273 | 273 | ||
274 | extern struct rpc_stat nfs_rpcstat; | 274 | extern struct rpc_stat nfs_rpcstat; |
275 | 275 | ||
276 | extern int __init register_nfs_fs(void); | 276 | extern int __init register_nfs_fs(void); |
277 | extern void __exit unregister_nfs_fs(void); | 277 | extern void __exit unregister_nfs_fs(void); |
278 | extern void nfs_sb_active(struct super_block *sb); | 278 | extern void nfs_sb_active(struct super_block *sb); |
279 | extern void nfs_sb_deactive(struct super_block *sb); | 279 | extern void nfs_sb_deactive(struct super_block *sb); |
280 | 280 | ||
281 | /* namespace.c */ | 281 | /* namespace.c */ |
282 | extern char *nfs_path(char **p, struct dentry *dentry, | 282 | extern char *nfs_path(char **p, struct dentry *dentry, |
283 | char *buffer, ssize_t buflen); | 283 | char *buffer, ssize_t buflen); |
284 | extern struct vfsmount *nfs_d_automount(struct path *path); | 284 | extern struct vfsmount *nfs_d_automount(struct path *path); |
285 | #ifdef CONFIG_NFS_V4 | 285 | #ifdef CONFIG_NFS_V4 |
286 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); | 286 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); |
287 | #endif | 287 | #endif |
288 | 288 | ||
289 | /* getroot.c */ | 289 | /* getroot.c */ |
290 | extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *, | 290 | extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *, |
291 | const char *); | 291 | const char *); |
292 | #ifdef CONFIG_NFS_V4 | 292 | #ifdef CONFIG_NFS_V4 |
293 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *, | 293 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *, |
294 | const char *); | 294 | const char *); |
295 | 295 | ||
296 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); | 296 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); |
297 | #endif | 297 | #endif |
298 | 298 | ||
299 | struct nfs_pageio_descriptor; | 299 | struct nfs_pageio_descriptor; |
300 | /* read.c */ | 300 | /* read.c */ |
301 | extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, | 301 | extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, |
302 | const struct rpc_call_ops *call_ops); | 302 | const struct rpc_call_ops *call_ops); |
303 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | 303 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); |
304 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, | 304 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, |
305 | struct list_head *head); | 305 | struct list_head *head); |
306 | 306 | ||
307 | extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, | 307 | extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, |
308 | struct inode *inode); | 308 | struct inode *inode); |
309 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | 309 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); |
310 | extern void nfs_readdata_release(struct nfs_read_data *rdata); | 310 | extern void nfs_readdata_release(struct nfs_read_data *rdata); |
311 | 311 | ||
312 | /* write.c */ | 312 | /* write.c */ |
313 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | 313 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, |
314 | struct list_head *head); | 314 | struct list_head *head); |
315 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 315 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, |
316 | struct inode *inode, int ioflags); | 316 | struct inode *inode, int ioflags); |
317 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); | 317 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); |
318 | extern void nfs_writedata_release(struct nfs_write_data *wdata); | 318 | extern void nfs_writedata_release(struct nfs_write_data *wdata); |
319 | extern void nfs_commit_free(struct nfs_write_data *p); | 319 | extern void nfs_commit_free(struct nfs_write_data *p); |
320 | extern int nfs_initiate_write(struct nfs_write_data *data, | 320 | extern int nfs_initiate_write(struct nfs_write_data *data, |
321 | struct rpc_clnt *clnt, | 321 | struct rpc_clnt *clnt, |
322 | const struct rpc_call_ops *call_ops, | 322 | const struct rpc_call_ops *call_ops, |
323 | int how); | 323 | int how); |
324 | extern void nfs_write_prepare(struct rpc_task *task, void *calldata); | 324 | extern void nfs_write_prepare(struct rpc_task *task, void *calldata); |
325 | extern int nfs_initiate_commit(struct nfs_write_data *data, | 325 | extern int nfs_initiate_commit(struct nfs_write_data *data, |
326 | struct rpc_clnt *clnt, | 326 | struct rpc_clnt *clnt, |
327 | const struct rpc_call_ops *call_ops, | 327 | const struct rpc_call_ops *call_ops, |
328 | int how); | 328 | int how); |
329 | extern void nfs_init_commit(struct nfs_write_data *data, | 329 | extern void nfs_init_commit(struct nfs_write_data *data, |
330 | struct list_head *head, | 330 | struct list_head *head, |
331 | struct pnfs_layout_segment *lseg); | 331 | struct pnfs_layout_segment *lseg); |
332 | void nfs_retry_commit(struct list_head *page_list, | 332 | void nfs_retry_commit(struct list_head *page_list, |
333 | struct pnfs_layout_segment *lseg); | 333 | struct pnfs_layout_segment *lseg); |
334 | void nfs_commit_clear_lock(struct nfs_inode *nfsi); | 334 | void nfs_commit_clear_lock(struct nfs_inode *nfsi); |
335 | void nfs_commitdata_release(void *data); | 335 | void nfs_commitdata_release(void *data); |
336 | void nfs_commit_release_pages(struct nfs_write_data *data); | 336 | void nfs_commit_release_pages(struct nfs_write_data *data); |
337 | 337 | ||
338 | #ifdef CONFIG_MIGRATION | 338 | #ifdef CONFIG_MIGRATION |
339 | extern int nfs_migrate_page(struct address_space *, | 339 | extern int nfs_migrate_page(struct address_space *, |
340 | struct page *, struct page *, enum migrate_mode); | 340 | struct page *, struct page *, enum migrate_mode); |
341 | #else | 341 | #else |
342 | #define nfs_migrate_page NULL | 342 | #define nfs_migrate_page NULL |
343 | #endif | 343 | #endif |
344 | 344 | ||
345 | /* nfs4proc.c */ | 345 | /* nfs4proc.c */ |
346 | extern void __nfs4_read_done_cb(struct nfs_read_data *); | 346 | extern void __nfs4_read_done_cb(struct nfs_read_data *); |
347 | extern void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data); | 347 | extern void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data); |
348 | extern int nfs4_init_client(struct nfs_client *clp, | 348 | extern int nfs4_init_client(struct nfs_client *clp, |
349 | const struct rpc_timeout *timeparms, | 349 | const struct rpc_timeout *timeparms, |
350 | const char *ip_addr, | 350 | const char *ip_addr, |
351 | rpc_authflavor_t authflavour, | 351 | rpc_authflavor_t authflavour, |
352 | int noresvport); | 352 | int noresvport); |
353 | extern void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data); | 353 | extern void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data); |
354 | extern int _nfs4_call_sync(struct rpc_clnt *clnt, | 354 | extern int _nfs4_call_sync(struct rpc_clnt *clnt, |
355 | struct nfs_server *server, | 355 | struct nfs_server *server, |
356 | struct rpc_message *msg, | 356 | struct rpc_message *msg, |
357 | struct nfs4_sequence_args *args, | 357 | struct nfs4_sequence_args *args, |
358 | struct nfs4_sequence_res *res, | 358 | struct nfs4_sequence_res *res, |
359 | int cache_reply); | 359 | int cache_reply); |
360 | extern int _nfs4_call_sync_session(struct rpc_clnt *clnt, | 360 | extern int _nfs4_call_sync_session(struct rpc_clnt *clnt, |
361 | struct nfs_server *server, | 361 | struct nfs_server *server, |
362 | struct rpc_message *msg, | 362 | struct rpc_message *msg, |
363 | struct nfs4_sequence_args *args, | 363 | struct nfs4_sequence_args *args, |
364 | struct nfs4_sequence_res *res, | 364 | struct nfs4_sequence_res *res, |
365 | int cache_reply); | 365 | int cache_reply); |
366 | 366 | ||
367 | /* | 367 | /* |
368 | * Determine the device name as a string | 368 | * Determine the device name as a string |
369 | */ | 369 | */ |
370 | static inline char *nfs_devname(struct dentry *dentry, | 370 | static inline char *nfs_devname(struct dentry *dentry, |
371 | char *buffer, ssize_t buflen) | 371 | char *buffer, ssize_t buflen) |
372 | { | 372 | { |
373 | char *dummy; | 373 | char *dummy; |
374 | return nfs_path(&dummy, dentry, buffer, buflen); | 374 | return nfs_path(&dummy, dentry, buffer, buflen); |
375 | } | 375 | } |
376 | 376 | ||
377 | /* | 377 | /* |
378 | * Determine the actual block size (and log2 thereof) | 378 | * Determine the actual block size (and log2 thereof) |
379 | */ | 379 | */ |
380 | static inline | 380 | static inline |
381 | unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) | 381 | unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) |
382 | { | 382 | { |
383 | /* make sure blocksize is a power of two */ | 383 | /* make sure blocksize is a power of two */ |
384 | if ((bsize & (bsize - 1)) || nrbitsp) { | 384 | if ((bsize & (bsize - 1)) || nrbitsp) { |
385 | unsigned char nrbits; | 385 | unsigned char nrbits; |
386 | 386 | ||
387 | for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) | 387 | for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) |
388 | ; | 388 | ; |
389 | bsize = 1 << nrbits; | 389 | bsize = 1 << nrbits; |
390 | if (nrbitsp) | 390 | if (nrbitsp) |
391 | *nrbitsp = nrbits; | 391 | *nrbitsp = nrbits; |
392 | } | 392 | } |
393 | 393 | ||
394 | return bsize; | 394 | return bsize; |
395 | } | 395 | } |
396 | 396 | ||
397 | /* | 397 | /* |
398 | * Calculate the number of 512byte blocks used. | 398 | * Calculate the number of 512byte blocks used. |
399 | */ | 399 | */ |
400 | static inline blkcnt_t nfs_calc_block_size(u64 tsize) | 400 | static inline blkcnt_t nfs_calc_block_size(u64 tsize) |
401 | { | 401 | { |
402 | blkcnt_t used = (tsize + 511) >> 9; | 402 | blkcnt_t used = (tsize + 511) >> 9; |
403 | return (used > ULONG_MAX) ? ULONG_MAX : used; | 403 | return (used > ULONG_MAX) ? ULONG_MAX : used; |
404 | } | 404 | } |
405 | 405 | ||
406 | /* | 406 | /* |
407 | * Compute and set NFS server blocksize | 407 | * Compute and set NFS server blocksize |
408 | */ | 408 | */ |
409 | static inline | 409 | static inline |
410 | unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) | 410 | unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) |
411 | { | 411 | { |
412 | if (bsize < NFS_MIN_FILE_IO_SIZE) | 412 | if (bsize < NFS_MIN_FILE_IO_SIZE) |
413 | bsize = NFS_DEF_FILE_IO_SIZE; | 413 | bsize = NFS_DEF_FILE_IO_SIZE; |
414 | else if (bsize >= NFS_MAX_FILE_IO_SIZE) | 414 | else if (bsize >= NFS_MAX_FILE_IO_SIZE) |
415 | bsize = NFS_MAX_FILE_IO_SIZE; | 415 | bsize = NFS_MAX_FILE_IO_SIZE; |
416 | 416 | ||
417 | return nfs_block_bits(bsize, nrbitsp); | 417 | return nfs_block_bits(bsize, nrbitsp); |
418 | } | 418 | } |
419 | 419 | ||
420 | /* | 420 | /* |
421 | * Determine the maximum file size for a superblock | 421 | * Determine the maximum file size for a superblock |
422 | */ | 422 | */ |
423 | static inline | 423 | static inline |
424 | void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) | 424 | void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) |
425 | { | 425 | { |
426 | sb->s_maxbytes = (loff_t)maxfilesize; | 426 | sb->s_maxbytes = (loff_t)maxfilesize; |
427 | if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) | 427 | if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) |
428 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 428 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* | 431 | /* |
432 | * Determine the number of bytes of data the page contains | 432 | * Determine the number of bytes of data the page contains |
433 | */ | 433 | */ |
434 | static inline | 434 | static inline |
435 | unsigned int nfs_page_length(struct page *page) | 435 | unsigned int nfs_page_length(struct page *page) |
436 | { | 436 | { |
437 | loff_t i_size = i_size_read(page->mapping->host); | 437 | loff_t i_size = i_size_read(page->mapping->host); |
438 | 438 | ||
439 | if (i_size > 0) { | 439 | if (i_size > 0) { |
440 | pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; | 440 | pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; |
441 | if (page->index < end_index) | 441 | if (page->index < end_index) |
442 | return PAGE_CACHE_SIZE; | 442 | return PAGE_CACHE_SIZE; |
443 | if (page->index == end_index) | 443 | if (page->index == end_index) |
444 | return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1; | 444 | return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1; |
445 | } | 445 | } |
446 | return 0; | 446 | return 0; |
447 | } | 447 | } |
448 | 448 | ||
449 | /* | 449 | /* |
450 | * Convert a umode to a dirent->d_type | 450 | * Convert a umode to a dirent->d_type |
451 | */ | 451 | */ |
452 | static inline | 452 | static inline |
453 | unsigned char nfs_umode_to_dtype(umode_t mode) | 453 | unsigned char nfs_umode_to_dtype(umode_t mode) |
454 | { | 454 | { |
455 | return (mode >> 12) & 15; | 455 | return (mode >> 12) & 15; |
456 | } | 456 | } |
457 | 457 | ||
458 | /* | 458 | /* |
459 | * Determine the number of pages in an array of length 'len' and | 459 | * Determine the number of pages in an array of length 'len' and |
460 | * with a base offset of 'base' | 460 | * with a base offset of 'base' |
461 | */ | 461 | */ |
462 | static inline | 462 | static inline |
463 | unsigned int nfs_page_array_len(unsigned int base, size_t len) | 463 | unsigned int nfs_page_array_len(unsigned int base, size_t len) |
464 | { | 464 | { |
465 | return ((unsigned long)len + (unsigned long)base + | 465 | return ((unsigned long)len + (unsigned long)base + |
466 | PAGE_SIZE - 1) >> PAGE_SHIFT; | 466 | PAGE_SIZE - 1) >> PAGE_SHIFT; |
467 | } | 467 | } |
468 | 468 | ||
469 | 469 |
fs/nfs/mount_clnt.c
1 | /* | 1 | /* |
2 | * In-kernel MOUNT protocol client | 2 | * In-kernel MOUNT protocol client |
3 | * | 3 | * |
4 | * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de> | 4 | * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/socket.h> | 8 | #include <linux/socket.h> |
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/uio.h> | 11 | #include <linux/uio.h> |
12 | #include <linux/net.h> | 12 | #include <linux/net.h> |
13 | #include <linux/in.h> | 13 | #include <linux/in.h> |
14 | #include <linux/sunrpc/clnt.h> | 14 | #include <linux/sunrpc/clnt.h> |
15 | #include <linux/sunrpc/sched.h> | 15 | #include <linux/sunrpc/sched.h> |
16 | #include <linux/nfs_fs.h> | 16 | #include <linux/nfs_fs.h> |
17 | #include "internal.h" | 17 | #include "internal.h" |
18 | 18 | ||
19 | #ifdef RPC_DEBUG | 19 | #ifdef RPC_DEBUG |
20 | # define NFSDBG_FACILITY NFSDBG_MOUNT | 20 | # define NFSDBG_FACILITY NFSDBG_MOUNT |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Defined by RFC 1094, section A.3; and RFC 1813, section 5.1.4 | 24 | * Defined by RFC 1094, section A.3; and RFC 1813, section 5.1.4 |
25 | */ | 25 | */ |
26 | #define MNTPATHLEN (1024) | 26 | #define MNTPATHLEN (1024) |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * XDR data type sizes | 29 | * XDR data type sizes |
30 | */ | 30 | */ |
31 | #define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN)) | 31 | #define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN)) |
32 | #define MNT_status_sz (1) | 32 | #define MNT_status_sz (1) |
33 | #define MNT_fhs_status_sz (1) | 33 | #define MNT_fhs_status_sz (1) |
34 | #define MNT_fhandle_sz XDR_QUADLEN(NFS2_FHSIZE) | 34 | #define MNT_fhandle_sz XDR_QUADLEN(NFS2_FHSIZE) |
35 | #define MNT_fhandle3_sz (1 + XDR_QUADLEN(NFS3_FHSIZE)) | 35 | #define MNT_fhandle3_sz (1 + XDR_QUADLEN(NFS3_FHSIZE)) |
36 | #define MNT_authflav3_sz (1 + NFS_MAX_SECFLAVORS) | 36 | #define MNT_authflav3_sz (1 + NFS_MAX_SECFLAVORS) |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * XDR argument and result sizes | 39 | * XDR argument and result sizes |
40 | */ | 40 | */ |
41 | #define MNT_enc_dirpath_sz encode_dirpath_sz | 41 | #define MNT_enc_dirpath_sz encode_dirpath_sz |
42 | #define MNT_dec_mountres_sz (MNT_status_sz + MNT_fhandle_sz) | 42 | #define MNT_dec_mountres_sz (MNT_status_sz + MNT_fhandle_sz) |
43 | #define MNT_dec_mountres3_sz (MNT_status_sz + MNT_fhandle_sz + \ | 43 | #define MNT_dec_mountres3_sz (MNT_status_sz + MNT_fhandle_sz + \ |
44 | MNT_authflav3_sz) | 44 | MNT_authflav3_sz) |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Defined by RFC 1094, section A.5 | 47 | * Defined by RFC 1094, section A.5 |
48 | */ | 48 | */ |
49 | enum { | 49 | enum { |
50 | MOUNTPROC_NULL = 0, | 50 | MOUNTPROC_NULL = 0, |
51 | MOUNTPROC_MNT = 1, | 51 | MOUNTPROC_MNT = 1, |
52 | MOUNTPROC_DUMP = 2, | 52 | MOUNTPROC_DUMP = 2, |
53 | MOUNTPROC_UMNT = 3, | 53 | MOUNTPROC_UMNT = 3, |
54 | MOUNTPROC_UMNTALL = 4, | 54 | MOUNTPROC_UMNTALL = 4, |
55 | MOUNTPROC_EXPORT = 5, | 55 | MOUNTPROC_EXPORT = 5, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * Defined by RFC 1813, section 5.2 | 59 | * Defined by RFC 1813, section 5.2 |
60 | */ | 60 | */ |
61 | enum { | 61 | enum { |
62 | MOUNTPROC3_NULL = 0, | 62 | MOUNTPROC3_NULL = 0, |
63 | MOUNTPROC3_MNT = 1, | 63 | MOUNTPROC3_MNT = 1, |
64 | MOUNTPROC3_DUMP = 2, | 64 | MOUNTPROC3_DUMP = 2, |
65 | MOUNTPROC3_UMNT = 3, | 65 | MOUNTPROC3_UMNT = 3, |
66 | MOUNTPROC3_UMNTALL = 4, | 66 | MOUNTPROC3_UMNTALL = 4, |
67 | MOUNTPROC3_EXPORT = 5, | 67 | MOUNTPROC3_EXPORT = 5, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static struct rpc_program mnt_program; | 70 | static const struct rpc_program mnt_program; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * Defined by OpenGroup XNFS Version 3W, chapter 8 | 73 | * Defined by OpenGroup XNFS Version 3W, chapter 8 |
74 | */ | 74 | */ |
75 | enum mountstat { | 75 | enum mountstat { |
76 | MNT_OK = 0, | 76 | MNT_OK = 0, |
77 | MNT_EPERM = 1, | 77 | MNT_EPERM = 1, |
78 | MNT_ENOENT = 2, | 78 | MNT_ENOENT = 2, |
79 | MNT_EACCES = 13, | 79 | MNT_EACCES = 13, |
80 | MNT_EINVAL = 22, | 80 | MNT_EINVAL = 22, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | static struct { | 83 | static struct { |
84 | u32 status; | 84 | u32 status; |
85 | int errno; | 85 | int errno; |
86 | } mnt_errtbl[] = { | 86 | } mnt_errtbl[] = { |
87 | { .status = MNT_OK, .errno = 0, }, | 87 | { .status = MNT_OK, .errno = 0, }, |
88 | { .status = MNT_EPERM, .errno = -EPERM, }, | 88 | { .status = MNT_EPERM, .errno = -EPERM, }, |
89 | { .status = MNT_ENOENT, .errno = -ENOENT, }, | 89 | { .status = MNT_ENOENT, .errno = -ENOENT, }, |
90 | { .status = MNT_EACCES, .errno = -EACCES, }, | 90 | { .status = MNT_EACCES, .errno = -EACCES, }, |
91 | { .status = MNT_EINVAL, .errno = -EINVAL, }, | 91 | { .status = MNT_EINVAL, .errno = -EINVAL, }, |
92 | }; | 92 | }; |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * Defined by RFC 1813, section 5.1.5 | 95 | * Defined by RFC 1813, section 5.1.5 |
96 | */ | 96 | */ |
97 | enum mountstat3 { | 97 | enum mountstat3 { |
98 | MNT3_OK = 0, /* no error */ | 98 | MNT3_OK = 0, /* no error */ |
99 | MNT3ERR_PERM = 1, /* Not owner */ | 99 | MNT3ERR_PERM = 1, /* Not owner */ |
100 | MNT3ERR_NOENT = 2, /* No such file or directory */ | 100 | MNT3ERR_NOENT = 2, /* No such file or directory */ |
101 | MNT3ERR_IO = 5, /* I/O error */ | 101 | MNT3ERR_IO = 5, /* I/O error */ |
102 | MNT3ERR_ACCES = 13, /* Permission denied */ | 102 | MNT3ERR_ACCES = 13, /* Permission denied */ |
103 | MNT3ERR_NOTDIR = 20, /* Not a directory */ | 103 | MNT3ERR_NOTDIR = 20, /* Not a directory */ |
104 | MNT3ERR_INVAL = 22, /* Invalid argument */ | 104 | MNT3ERR_INVAL = 22, /* Invalid argument */ |
105 | MNT3ERR_NAMETOOLONG = 63, /* Filename too long */ | 105 | MNT3ERR_NAMETOOLONG = 63, /* Filename too long */ |
106 | MNT3ERR_NOTSUPP = 10004, /* Operation not supported */ | 106 | MNT3ERR_NOTSUPP = 10004, /* Operation not supported */ |
107 | MNT3ERR_SERVERFAULT = 10006, /* A failure on the server */ | 107 | MNT3ERR_SERVERFAULT = 10006, /* A failure on the server */ |
108 | }; | 108 | }; |
109 | 109 | ||
110 | static struct { | 110 | static struct { |
111 | u32 status; | 111 | u32 status; |
112 | int errno; | 112 | int errno; |
113 | } mnt3_errtbl[] = { | 113 | } mnt3_errtbl[] = { |
114 | { .status = MNT3_OK, .errno = 0, }, | 114 | { .status = MNT3_OK, .errno = 0, }, |
115 | { .status = MNT3ERR_PERM, .errno = -EPERM, }, | 115 | { .status = MNT3ERR_PERM, .errno = -EPERM, }, |
116 | { .status = MNT3ERR_NOENT, .errno = -ENOENT, }, | 116 | { .status = MNT3ERR_NOENT, .errno = -ENOENT, }, |
117 | { .status = MNT3ERR_IO, .errno = -EIO, }, | 117 | { .status = MNT3ERR_IO, .errno = -EIO, }, |
118 | { .status = MNT3ERR_ACCES, .errno = -EACCES, }, | 118 | { .status = MNT3ERR_ACCES, .errno = -EACCES, }, |
119 | { .status = MNT3ERR_NOTDIR, .errno = -ENOTDIR, }, | 119 | { .status = MNT3ERR_NOTDIR, .errno = -ENOTDIR, }, |
120 | { .status = MNT3ERR_INVAL, .errno = -EINVAL, }, | 120 | { .status = MNT3ERR_INVAL, .errno = -EINVAL, }, |
121 | { .status = MNT3ERR_NAMETOOLONG, .errno = -ENAMETOOLONG, }, | 121 | { .status = MNT3ERR_NAMETOOLONG, .errno = -ENAMETOOLONG, }, |
122 | { .status = MNT3ERR_NOTSUPP, .errno = -ENOTSUPP, }, | 122 | { .status = MNT3ERR_NOTSUPP, .errno = -ENOTSUPP, }, |
123 | { .status = MNT3ERR_SERVERFAULT, .errno = -EREMOTEIO, }, | 123 | { .status = MNT3ERR_SERVERFAULT, .errno = -EREMOTEIO, }, |
124 | }; | 124 | }; |
125 | 125 | ||
126 | struct mountres { | 126 | struct mountres { |
127 | int errno; | 127 | int errno; |
128 | struct nfs_fh *fh; | 128 | struct nfs_fh *fh; |
129 | unsigned int *auth_count; | 129 | unsigned int *auth_count; |
130 | rpc_authflavor_t *auth_flavors; | 130 | rpc_authflavor_t *auth_flavors; |
131 | }; | 131 | }; |
132 | 132 | ||
133 | struct mnt_fhstatus { | 133 | struct mnt_fhstatus { |
134 | u32 status; | 134 | u32 status; |
135 | struct nfs_fh *fh; | 135 | struct nfs_fh *fh; |
136 | }; | 136 | }; |
137 | 137 | ||
138 | /** | 138 | /** |
139 | * nfs_mount - Obtain an NFS file handle for the given host and path | 139 | * nfs_mount - Obtain an NFS file handle for the given host and path |
140 | * @info: pointer to mount request arguments | 140 | * @info: pointer to mount request arguments |
141 | * | 141 | * |
142 | * Uses default timeout parameters specified by underlying transport. | 142 | * Uses default timeout parameters specified by underlying transport. |
143 | */ | 143 | */ |
144 | int nfs_mount(struct nfs_mount_request *info) | 144 | int nfs_mount(struct nfs_mount_request *info) |
145 | { | 145 | { |
146 | struct mountres result = { | 146 | struct mountres result = { |
147 | .fh = info->fh, | 147 | .fh = info->fh, |
148 | .auth_count = info->auth_flav_len, | 148 | .auth_count = info->auth_flav_len, |
149 | .auth_flavors = info->auth_flavs, | 149 | .auth_flavors = info->auth_flavs, |
150 | }; | 150 | }; |
151 | struct rpc_message msg = { | 151 | struct rpc_message msg = { |
152 | .rpc_argp = info->dirpath, | 152 | .rpc_argp = info->dirpath, |
153 | .rpc_resp = &result, | 153 | .rpc_resp = &result, |
154 | }; | 154 | }; |
155 | struct rpc_create_args args = { | 155 | struct rpc_create_args args = { |
156 | .net = info->net, | 156 | .net = info->net, |
157 | .protocol = info->protocol, | 157 | .protocol = info->protocol, |
158 | .address = info->sap, | 158 | .address = info->sap, |
159 | .addrsize = info->salen, | 159 | .addrsize = info->salen, |
160 | .servername = info->hostname, | 160 | .servername = info->hostname, |
161 | .program = &mnt_program, | 161 | .program = &mnt_program, |
162 | .version = info->version, | 162 | .version = info->version, |
163 | .authflavor = RPC_AUTH_UNIX, | 163 | .authflavor = RPC_AUTH_UNIX, |
164 | }; | 164 | }; |
165 | struct rpc_clnt *mnt_clnt; | 165 | struct rpc_clnt *mnt_clnt; |
166 | int status; | 166 | int status; |
167 | 167 | ||
168 | dprintk("NFS: sending MNT request for %s:%s\n", | 168 | dprintk("NFS: sending MNT request for %s:%s\n", |
169 | (info->hostname ? info->hostname : "server"), | 169 | (info->hostname ? info->hostname : "server"), |
170 | info->dirpath); | 170 | info->dirpath); |
171 | 171 | ||
172 | if (info->noresvport) | 172 | if (info->noresvport) |
173 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | 173 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
174 | 174 | ||
175 | mnt_clnt = rpc_create(&args); | 175 | mnt_clnt = rpc_create(&args); |
176 | if (IS_ERR(mnt_clnt)) | 176 | if (IS_ERR(mnt_clnt)) |
177 | goto out_clnt_err; | 177 | goto out_clnt_err; |
178 | 178 | ||
179 | if (info->version == NFS_MNT3_VERSION) | 179 | if (info->version == NFS_MNT3_VERSION) |
180 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT]; | 180 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT]; |
181 | else | 181 | else |
182 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; | 182 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; |
183 | 183 | ||
184 | status = rpc_call_sync(mnt_clnt, &msg, 0); | 184 | status = rpc_call_sync(mnt_clnt, &msg, 0); |
185 | rpc_shutdown_client(mnt_clnt); | 185 | rpc_shutdown_client(mnt_clnt); |
186 | 186 | ||
187 | if (status < 0) | 187 | if (status < 0) |
188 | goto out_call_err; | 188 | goto out_call_err; |
189 | if (result.errno != 0) | 189 | if (result.errno != 0) |
190 | goto out_mnt_err; | 190 | goto out_mnt_err; |
191 | 191 | ||
192 | dprintk("NFS: MNT request succeeded\n"); | 192 | dprintk("NFS: MNT request succeeded\n"); |
193 | status = 0; | 193 | status = 0; |
194 | 194 | ||
195 | out: | 195 | out: |
196 | return status; | 196 | return status; |
197 | 197 | ||
198 | out_clnt_err: | 198 | out_clnt_err: |
199 | status = PTR_ERR(mnt_clnt); | 199 | status = PTR_ERR(mnt_clnt); |
200 | dprintk("NFS: failed to create MNT RPC client, status=%d\n", status); | 200 | dprintk("NFS: failed to create MNT RPC client, status=%d\n", status); |
201 | goto out; | 201 | goto out; |
202 | 202 | ||
203 | out_call_err: | 203 | out_call_err: |
204 | dprintk("NFS: MNT request failed, status=%d\n", status); | 204 | dprintk("NFS: MNT request failed, status=%d\n", status); |
205 | goto out; | 205 | goto out; |
206 | 206 | ||
207 | out_mnt_err: | 207 | out_mnt_err: |
208 | dprintk("NFS: MNT server returned result %d\n", result.errno); | 208 | dprintk("NFS: MNT server returned result %d\n", result.errno); |
209 | status = result.errno; | 209 | status = result.errno; |
210 | goto out; | 210 | goto out; |
211 | } | 211 | } |
212 | 212 | ||
213 | /** | 213 | /** |
214 | * nfs_umount - Notify a server that we have unmounted this export | 214 | * nfs_umount - Notify a server that we have unmounted this export |
215 | * @info: pointer to umount request arguments | 215 | * @info: pointer to umount request arguments |
216 | * | 216 | * |
217 | * MOUNTPROC_UMNT is advisory, so we set a short timeout, and always | 217 | * MOUNTPROC_UMNT is advisory, so we set a short timeout, and always |
218 | * use UDP. | 218 | * use UDP. |
219 | */ | 219 | */ |
220 | void nfs_umount(const struct nfs_mount_request *info) | 220 | void nfs_umount(const struct nfs_mount_request *info) |
221 | { | 221 | { |
222 | static const struct rpc_timeout nfs_umnt_timeout = { | 222 | static const struct rpc_timeout nfs_umnt_timeout = { |
223 | .to_initval = 1 * HZ, | 223 | .to_initval = 1 * HZ, |
224 | .to_maxval = 3 * HZ, | 224 | .to_maxval = 3 * HZ, |
225 | .to_retries = 2, | 225 | .to_retries = 2, |
226 | }; | 226 | }; |
227 | struct rpc_create_args args = { | 227 | struct rpc_create_args args = { |
228 | .net = info->net, | 228 | .net = info->net, |
229 | .protocol = IPPROTO_UDP, | 229 | .protocol = IPPROTO_UDP, |
230 | .address = info->sap, | 230 | .address = info->sap, |
231 | .addrsize = info->salen, | 231 | .addrsize = info->salen, |
232 | .timeout = &nfs_umnt_timeout, | 232 | .timeout = &nfs_umnt_timeout, |
233 | .servername = info->hostname, | 233 | .servername = info->hostname, |
234 | .program = &mnt_program, | 234 | .program = &mnt_program, |
235 | .version = info->version, | 235 | .version = info->version, |
236 | .authflavor = RPC_AUTH_UNIX, | 236 | .authflavor = RPC_AUTH_UNIX, |
237 | .flags = RPC_CLNT_CREATE_NOPING, | 237 | .flags = RPC_CLNT_CREATE_NOPING, |
238 | }; | 238 | }; |
239 | struct rpc_message msg = { | 239 | struct rpc_message msg = { |
240 | .rpc_argp = info->dirpath, | 240 | .rpc_argp = info->dirpath, |
241 | }; | 241 | }; |
242 | struct rpc_clnt *clnt; | 242 | struct rpc_clnt *clnt; |
243 | int status; | 243 | int status; |
244 | 244 | ||
245 | if (info->noresvport) | 245 | if (info->noresvport) |
246 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | 246 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
247 | 247 | ||
248 | clnt = rpc_create(&args); | 248 | clnt = rpc_create(&args); |
249 | if (IS_ERR(clnt)) | 249 | if (IS_ERR(clnt)) |
250 | goto out_clnt_err; | 250 | goto out_clnt_err; |
251 | 251 | ||
252 | dprintk("NFS: sending UMNT request for %s:%s\n", | 252 | dprintk("NFS: sending UMNT request for %s:%s\n", |
253 | (info->hostname ? info->hostname : "server"), info->dirpath); | 253 | (info->hostname ? info->hostname : "server"), info->dirpath); |
254 | 254 | ||
255 | if (info->version == NFS_MNT3_VERSION) | 255 | if (info->version == NFS_MNT3_VERSION) |
256 | msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT]; | 256 | msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT]; |
257 | else | 257 | else |
258 | msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT]; | 258 | msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT]; |
259 | 259 | ||
260 | status = rpc_call_sync(clnt, &msg, 0); | 260 | status = rpc_call_sync(clnt, &msg, 0); |
261 | rpc_shutdown_client(clnt); | 261 | rpc_shutdown_client(clnt); |
262 | 262 | ||
263 | if (unlikely(status < 0)) | 263 | if (unlikely(status < 0)) |
264 | goto out_call_err; | 264 | goto out_call_err; |
265 | 265 | ||
266 | return; | 266 | return; |
267 | 267 | ||
268 | out_clnt_err: | 268 | out_clnt_err: |
269 | dprintk("NFS: failed to create UMNT RPC client, status=%ld\n", | 269 | dprintk("NFS: failed to create UMNT RPC client, status=%ld\n", |
270 | PTR_ERR(clnt)); | 270 | PTR_ERR(clnt)); |
271 | return; | 271 | return; |
272 | 272 | ||
273 | out_call_err: | 273 | out_call_err: |
274 | dprintk("NFS: UMNT request failed, status=%d\n", status); | 274 | dprintk("NFS: UMNT request failed, status=%d\n", status); |
275 | } | 275 | } |
276 | 276 | ||
277 | /* | 277 | /* |
278 | * XDR encode/decode functions for MOUNT | 278 | * XDR encode/decode functions for MOUNT |
279 | */ | 279 | */ |
280 | 280 | ||
281 | static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname) | 281 | static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname) |
282 | { | 282 | { |
283 | const u32 pathname_len = strlen(pathname); | 283 | const u32 pathname_len = strlen(pathname); |
284 | __be32 *p; | 284 | __be32 *p; |
285 | 285 | ||
286 | BUG_ON(pathname_len > MNTPATHLEN); | 286 | BUG_ON(pathname_len > MNTPATHLEN); |
287 | p = xdr_reserve_space(xdr, 4 + pathname_len); | 287 | p = xdr_reserve_space(xdr, 4 + pathname_len); |
288 | xdr_encode_opaque(p, pathname, pathname_len); | 288 | xdr_encode_opaque(p, pathname, pathname_len); |
289 | } | 289 | } |
290 | 290 | ||
291 | static void mnt_xdr_enc_dirpath(struct rpc_rqst *req, struct xdr_stream *xdr, | 291 | static void mnt_xdr_enc_dirpath(struct rpc_rqst *req, struct xdr_stream *xdr, |
292 | const char *dirpath) | 292 | const char *dirpath) |
293 | { | 293 | { |
294 | encode_mntdirpath(xdr, dirpath); | 294 | encode_mntdirpath(xdr, dirpath); |
295 | } | 295 | } |
296 | 296 | ||
297 | /* | 297 | /* |
298 | * RFC 1094: "A non-zero status indicates some sort of error. In this | 298 | * RFC 1094: "A non-zero status indicates some sort of error. In this |
299 | * case, the status is a UNIX error number." This can be problematic | 299 | * case, the status is a UNIX error number." This can be problematic |
300 | * if the server and client use different errno values for the same | 300 | * if the server and client use different errno values for the same |
301 | * error. | 301 | * error. |
302 | * | 302 | * |
303 | * However, the OpenGroup XNFS spec provides a simple mapping that is | 303 | * However, the OpenGroup XNFS spec provides a simple mapping that is |
304 | * independent of local errno values on the server and the client. | 304 | * independent of local errno values on the server and the client. |
305 | */ | 305 | */ |
306 | static int decode_status(struct xdr_stream *xdr, struct mountres *res) | 306 | static int decode_status(struct xdr_stream *xdr, struct mountres *res) |
307 | { | 307 | { |
308 | unsigned int i; | 308 | unsigned int i; |
309 | u32 status; | 309 | u32 status; |
310 | __be32 *p; | 310 | __be32 *p; |
311 | 311 | ||
312 | p = xdr_inline_decode(xdr, 4); | 312 | p = xdr_inline_decode(xdr, 4); |
313 | if (unlikely(p == NULL)) | 313 | if (unlikely(p == NULL)) |
314 | return -EIO; | 314 | return -EIO; |
315 | status = be32_to_cpup(p); | 315 | status = be32_to_cpup(p); |
316 | 316 | ||
317 | for (i = 0; i < ARRAY_SIZE(mnt_errtbl); i++) { | 317 | for (i = 0; i < ARRAY_SIZE(mnt_errtbl); i++) { |
318 | if (mnt_errtbl[i].status == status) { | 318 | if (mnt_errtbl[i].status == status) { |
319 | res->errno = mnt_errtbl[i].errno; | 319 | res->errno = mnt_errtbl[i].errno; |
320 | return 0; | 320 | return 0; |
321 | } | 321 | } |
322 | } | 322 | } |
323 | 323 | ||
324 | dprintk("NFS: unrecognized MNT status code: %u\n", status); | 324 | dprintk("NFS: unrecognized MNT status code: %u\n", status); |
325 | res->errno = -EACCES; | 325 | res->errno = -EACCES; |
326 | return 0; | 326 | return 0; |
327 | } | 327 | } |
328 | 328 | ||
329 | static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res) | 329 | static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res) |
330 | { | 330 | { |
331 | struct nfs_fh *fh = res->fh; | 331 | struct nfs_fh *fh = res->fh; |
332 | __be32 *p; | 332 | __be32 *p; |
333 | 333 | ||
334 | p = xdr_inline_decode(xdr, NFS2_FHSIZE); | 334 | p = xdr_inline_decode(xdr, NFS2_FHSIZE); |
335 | if (unlikely(p == NULL)) | 335 | if (unlikely(p == NULL)) |
336 | return -EIO; | 336 | return -EIO; |
337 | 337 | ||
338 | fh->size = NFS2_FHSIZE; | 338 | fh->size = NFS2_FHSIZE; |
339 | memcpy(fh->data, p, NFS2_FHSIZE); | 339 | memcpy(fh->data, p, NFS2_FHSIZE); |
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | 342 | ||
343 | static int mnt_xdr_dec_mountres(struct rpc_rqst *req, | 343 | static int mnt_xdr_dec_mountres(struct rpc_rqst *req, |
344 | struct xdr_stream *xdr, | 344 | struct xdr_stream *xdr, |
345 | struct mountres *res) | 345 | struct mountres *res) |
346 | { | 346 | { |
347 | int status; | 347 | int status; |
348 | 348 | ||
349 | status = decode_status(xdr, res); | 349 | status = decode_status(xdr, res); |
350 | if (unlikely(status != 0 || res->errno != 0)) | 350 | if (unlikely(status != 0 || res->errno != 0)) |
351 | return status; | 351 | return status; |
352 | return decode_fhandle(xdr, res); | 352 | return decode_fhandle(xdr, res); |
353 | } | 353 | } |
354 | 354 | ||
355 | static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res) | 355 | static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res) |
356 | { | 356 | { |
357 | unsigned int i; | 357 | unsigned int i; |
358 | u32 status; | 358 | u32 status; |
359 | __be32 *p; | 359 | __be32 *p; |
360 | 360 | ||
361 | p = xdr_inline_decode(xdr, 4); | 361 | p = xdr_inline_decode(xdr, 4); |
362 | if (unlikely(p == NULL)) | 362 | if (unlikely(p == NULL)) |
363 | return -EIO; | 363 | return -EIO; |
364 | status = be32_to_cpup(p); | 364 | status = be32_to_cpup(p); |
365 | 365 | ||
366 | for (i = 0; i < ARRAY_SIZE(mnt3_errtbl); i++) { | 366 | for (i = 0; i < ARRAY_SIZE(mnt3_errtbl); i++) { |
367 | if (mnt3_errtbl[i].status == status) { | 367 | if (mnt3_errtbl[i].status == status) { |
368 | res->errno = mnt3_errtbl[i].errno; | 368 | res->errno = mnt3_errtbl[i].errno; |
369 | return 0; | 369 | return 0; |
370 | } | 370 | } |
371 | } | 371 | } |
372 | 372 | ||
373 | dprintk("NFS: unrecognized MNT3 status code: %u\n", status); | 373 | dprintk("NFS: unrecognized MNT3 status code: %u\n", status); |
374 | res->errno = -EACCES; | 374 | res->errno = -EACCES; |
375 | return 0; | 375 | return 0; |
376 | } | 376 | } |
377 | 377 | ||
378 | static int decode_fhandle3(struct xdr_stream *xdr, struct mountres *res) | 378 | static int decode_fhandle3(struct xdr_stream *xdr, struct mountres *res) |
379 | { | 379 | { |
380 | struct nfs_fh *fh = res->fh; | 380 | struct nfs_fh *fh = res->fh; |
381 | u32 size; | 381 | u32 size; |
382 | __be32 *p; | 382 | __be32 *p; |
383 | 383 | ||
384 | p = xdr_inline_decode(xdr, 4); | 384 | p = xdr_inline_decode(xdr, 4); |
385 | if (unlikely(p == NULL)) | 385 | if (unlikely(p == NULL)) |
386 | return -EIO; | 386 | return -EIO; |
387 | 387 | ||
388 | size = be32_to_cpup(p); | 388 | size = be32_to_cpup(p); |
389 | if (size > NFS3_FHSIZE || size == 0) | 389 | if (size > NFS3_FHSIZE || size == 0) |
390 | return -EIO; | 390 | return -EIO; |
391 | 391 | ||
392 | p = xdr_inline_decode(xdr, size); | 392 | p = xdr_inline_decode(xdr, size); |
393 | if (unlikely(p == NULL)) | 393 | if (unlikely(p == NULL)) |
394 | return -EIO; | 394 | return -EIO; |
395 | 395 | ||
396 | fh->size = size; | 396 | fh->size = size; |
397 | memcpy(fh->data, p, size); | 397 | memcpy(fh->data, p, size); |
398 | return 0; | 398 | return 0; |
399 | } | 399 | } |
400 | 400 | ||
401 | static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res) | 401 | static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res) |
402 | { | 402 | { |
403 | rpc_authflavor_t *flavors = res->auth_flavors; | 403 | rpc_authflavor_t *flavors = res->auth_flavors; |
404 | unsigned int *count = res->auth_count; | 404 | unsigned int *count = res->auth_count; |
405 | u32 entries, i; | 405 | u32 entries, i; |
406 | __be32 *p; | 406 | __be32 *p; |
407 | 407 | ||
408 | if (*count == 0) | 408 | if (*count == 0) |
409 | return 0; | 409 | return 0; |
410 | 410 | ||
411 | p = xdr_inline_decode(xdr, 4); | 411 | p = xdr_inline_decode(xdr, 4); |
412 | if (unlikely(p == NULL)) | 412 | if (unlikely(p == NULL)) |
413 | return -EIO; | 413 | return -EIO; |
414 | entries = be32_to_cpup(p); | 414 | entries = be32_to_cpup(p); |
415 | dprintk("NFS: received %u auth flavors\n", entries); | 415 | dprintk("NFS: received %u auth flavors\n", entries); |
416 | if (entries > NFS_MAX_SECFLAVORS) | 416 | if (entries > NFS_MAX_SECFLAVORS) |
417 | entries = NFS_MAX_SECFLAVORS; | 417 | entries = NFS_MAX_SECFLAVORS; |
418 | 418 | ||
419 | p = xdr_inline_decode(xdr, 4 * entries); | 419 | p = xdr_inline_decode(xdr, 4 * entries); |
420 | if (unlikely(p == NULL)) | 420 | if (unlikely(p == NULL)) |
421 | return -EIO; | 421 | return -EIO; |
422 | 422 | ||
423 | if (entries > *count) | 423 | if (entries > *count) |
424 | entries = *count; | 424 | entries = *count; |
425 | 425 | ||
426 | for (i = 0; i < entries; i++) { | 426 | for (i = 0; i < entries; i++) { |
427 | flavors[i] = be32_to_cpup(p++); | 427 | flavors[i] = be32_to_cpup(p++); |
428 | dprintk("NFS: auth flavor[%u]: %d\n", i, flavors[i]); | 428 | dprintk("NFS: auth flavor[%u]: %d\n", i, flavors[i]); |
429 | } | 429 | } |
430 | *count = i; | 430 | *count = i; |
431 | 431 | ||
432 | return 0; | 432 | return 0; |
433 | } | 433 | } |
434 | 434 | ||
435 | static int mnt_xdr_dec_mountres3(struct rpc_rqst *req, | 435 | static int mnt_xdr_dec_mountres3(struct rpc_rqst *req, |
436 | struct xdr_stream *xdr, | 436 | struct xdr_stream *xdr, |
437 | struct mountres *res) | 437 | struct mountres *res) |
438 | { | 438 | { |
439 | int status; | 439 | int status; |
440 | 440 | ||
441 | status = decode_fhs_status(xdr, res); | 441 | status = decode_fhs_status(xdr, res); |
442 | if (unlikely(status != 0 || res->errno != 0)) | 442 | if (unlikely(status != 0 || res->errno != 0)) |
443 | return status; | 443 | return status; |
444 | status = decode_fhandle3(xdr, res); | 444 | status = decode_fhandle3(xdr, res); |
445 | if (unlikely(status != 0)) { | 445 | if (unlikely(status != 0)) { |
446 | res->errno = -EBADHANDLE; | 446 | res->errno = -EBADHANDLE; |
447 | return 0; | 447 | return 0; |
448 | } | 448 | } |
449 | return decode_auth_flavors(xdr, res); | 449 | return decode_auth_flavors(xdr, res); |
450 | } | 450 | } |
451 | 451 | ||
452 | static struct rpc_procinfo mnt_procedures[] = { | 452 | static struct rpc_procinfo mnt_procedures[] = { |
453 | [MOUNTPROC_MNT] = { | 453 | [MOUNTPROC_MNT] = { |
454 | .p_proc = MOUNTPROC_MNT, | 454 | .p_proc = MOUNTPROC_MNT, |
455 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, | 455 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, |
456 | .p_decode = (kxdrdproc_t)mnt_xdr_dec_mountres, | 456 | .p_decode = (kxdrdproc_t)mnt_xdr_dec_mountres, |
457 | .p_arglen = MNT_enc_dirpath_sz, | 457 | .p_arglen = MNT_enc_dirpath_sz, |
458 | .p_replen = MNT_dec_mountres_sz, | 458 | .p_replen = MNT_dec_mountres_sz, |
459 | .p_statidx = MOUNTPROC_MNT, | 459 | .p_statidx = MOUNTPROC_MNT, |
460 | .p_name = "MOUNT", | 460 | .p_name = "MOUNT", |
461 | }, | 461 | }, |
462 | [MOUNTPROC_UMNT] = { | 462 | [MOUNTPROC_UMNT] = { |
463 | .p_proc = MOUNTPROC_UMNT, | 463 | .p_proc = MOUNTPROC_UMNT, |
464 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, | 464 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, |
465 | .p_arglen = MNT_enc_dirpath_sz, | 465 | .p_arglen = MNT_enc_dirpath_sz, |
466 | .p_statidx = MOUNTPROC_UMNT, | 466 | .p_statidx = MOUNTPROC_UMNT, |
467 | .p_name = "UMOUNT", | 467 | .p_name = "UMOUNT", |
468 | }, | 468 | }, |
469 | }; | 469 | }; |
470 | 470 | ||
471 | static struct rpc_procinfo mnt3_procedures[] = { | 471 | static struct rpc_procinfo mnt3_procedures[] = { |
472 | [MOUNTPROC3_MNT] = { | 472 | [MOUNTPROC3_MNT] = { |
473 | .p_proc = MOUNTPROC3_MNT, | 473 | .p_proc = MOUNTPROC3_MNT, |
474 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, | 474 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, |
475 | .p_decode = (kxdrdproc_t)mnt_xdr_dec_mountres3, | 475 | .p_decode = (kxdrdproc_t)mnt_xdr_dec_mountres3, |
476 | .p_arglen = MNT_enc_dirpath_sz, | 476 | .p_arglen = MNT_enc_dirpath_sz, |
477 | .p_replen = MNT_dec_mountres3_sz, | 477 | .p_replen = MNT_dec_mountres3_sz, |
478 | .p_statidx = MOUNTPROC3_MNT, | 478 | .p_statidx = MOUNTPROC3_MNT, |
479 | .p_name = "MOUNT", | 479 | .p_name = "MOUNT", |
480 | }, | 480 | }, |
481 | [MOUNTPROC3_UMNT] = { | 481 | [MOUNTPROC3_UMNT] = { |
482 | .p_proc = MOUNTPROC3_UMNT, | 482 | .p_proc = MOUNTPROC3_UMNT, |
483 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, | 483 | .p_encode = (kxdreproc_t)mnt_xdr_enc_dirpath, |
484 | .p_arglen = MNT_enc_dirpath_sz, | 484 | .p_arglen = MNT_enc_dirpath_sz, |
485 | .p_statidx = MOUNTPROC3_UMNT, | 485 | .p_statidx = MOUNTPROC3_UMNT, |
486 | .p_name = "UMOUNT", | 486 | .p_name = "UMOUNT", |
487 | }, | 487 | }, |
488 | }; | 488 | }; |
489 | 489 | ||
490 | 490 | ||
491 | static struct rpc_version mnt_version1 = { | 491 | static const struct rpc_version mnt_version1 = { |
492 | .number = 1, | 492 | .number = 1, |
493 | .nrprocs = ARRAY_SIZE(mnt_procedures), | 493 | .nrprocs = ARRAY_SIZE(mnt_procedures), |
494 | .procs = mnt_procedures, | 494 | .procs = mnt_procedures, |
495 | }; | 495 | }; |
496 | 496 | ||
497 | static struct rpc_version mnt_version3 = { | 497 | static const struct rpc_version mnt_version3 = { |
498 | .number = 3, | 498 | .number = 3, |
499 | .nrprocs = ARRAY_SIZE(mnt3_procedures), | 499 | .nrprocs = ARRAY_SIZE(mnt3_procedures), |
500 | .procs = mnt3_procedures, | 500 | .procs = mnt3_procedures, |
501 | }; | 501 | }; |
502 | 502 | ||
503 | static struct rpc_version *mnt_version[] = { | 503 | static const struct rpc_version *mnt_version[] = { |
504 | NULL, | 504 | NULL, |
505 | &mnt_version1, | 505 | &mnt_version1, |
506 | NULL, | 506 | NULL, |
507 | &mnt_version3, | 507 | &mnt_version3, |
508 | }; | 508 | }; |
509 | 509 | ||
510 | static struct rpc_stat mnt_stats; | 510 | static struct rpc_stat mnt_stats; |
511 | 511 | ||
512 | static struct rpc_program mnt_program = { | 512 | static const struct rpc_program mnt_program = { |
513 | .name = "mount", | 513 | .name = "mount", |
514 | .number = NFS_MNT_PROGRAM, | 514 | .number = NFS_MNT_PROGRAM, |
515 | .nrvers = ARRAY_SIZE(mnt_version), | 515 | .nrvers = ARRAY_SIZE(mnt_version), |
516 | .version = mnt_version, | 516 | .version = mnt_version, |
517 | .stats = &mnt_stats, | 517 | .stats = &mnt_stats, |
518 | }; | 518 | }; |
519 | 519 |
fs/nfs/nfs2xdr.c
1 | /* | 1 | /* |
2 | * linux/fs/nfs/nfs2xdr.c | 2 | * linux/fs/nfs/nfs2xdr.c |
3 | * | 3 | * |
4 | * XDR functions to encode/decode NFS RPC arguments and results. | 4 | * XDR functions to encode/decode NFS RPC arguments and results. |
5 | * | 5 | * |
6 | * Copyright (C) 1992, 1993, 1994 Rick Sladkey | 6 | * Copyright (C) 1992, 1993, 1994 Rick Sladkey |
7 | * Copyright (C) 1996 Olaf Kirch | 7 | * Copyright (C) 1996 Olaf Kirch |
8 | * 04 Aug 1998 Ion Badulescu <ionut@cs.columbia.edu> | 8 | * 04 Aug 1998 Ion Badulescu <ionut@cs.columbia.edu> |
9 | * FIFO's need special handling in NFSv2 | 9 | * FIFO's need special handling in NFSv2 |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/param.h> | 12 | #include <linux/param.h> |
13 | #include <linux/time.h> | 13 | #include <linux/time.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/in.h> | 17 | #include <linux/in.h> |
18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
19 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
20 | #include <linux/sunrpc/clnt.h> | 20 | #include <linux/sunrpc/clnt.h> |
21 | #include <linux/nfs.h> | 21 | #include <linux/nfs.h> |
22 | #include <linux/nfs2.h> | 22 | #include <linux/nfs2.h> |
23 | #include <linux/nfs_fs.h> | 23 | #include <linux/nfs_fs.h> |
24 | #include "internal.h" | 24 | #include "internal.h" |
25 | 25 | ||
26 | #define NFSDBG_FACILITY NFSDBG_XDR | 26 | #define NFSDBG_FACILITY NFSDBG_XDR |
27 | 27 | ||
28 | /* Mapping from NFS error code to "errno" error code. */ | 28 | /* Mapping from NFS error code to "errno" error code. */ |
29 | #define errno_NFSERR_IO EIO | 29 | #define errno_NFSERR_IO EIO |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * Declare the space requirements for NFS arguments and replies as | 32 | * Declare the space requirements for NFS arguments and replies as |
33 | * number of 32bit-words | 33 | * number of 32bit-words |
34 | */ | 34 | */ |
35 | #define NFS_fhandle_sz (8) | 35 | #define NFS_fhandle_sz (8) |
36 | #define NFS_sattr_sz (8) | 36 | #define NFS_sattr_sz (8) |
37 | #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2)) | 37 | #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2)) |
38 | #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2)) | 38 | #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2)) |
39 | #define NFS_fattr_sz (17) | 39 | #define NFS_fattr_sz (17) |
40 | #define NFS_info_sz (5) | 40 | #define NFS_info_sz (5) |
41 | #define NFS_entry_sz (NFS_filename_sz+3) | 41 | #define NFS_entry_sz (NFS_filename_sz+3) |
42 | 42 | ||
43 | #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz) | 43 | #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz) |
44 | #define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz) | 44 | #define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz) |
45 | #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz) | 45 | #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz) |
46 | #define NFS_readlinkargs_sz (NFS_fhandle_sz) | 46 | #define NFS_readlinkargs_sz (NFS_fhandle_sz) |
47 | #define NFS_readargs_sz (NFS_fhandle_sz+3) | 47 | #define NFS_readargs_sz (NFS_fhandle_sz+3) |
48 | #define NFS_writeargs_sz (NFS_fhandle_sz+4) | 48 | #define NFS_writeargs_sz (NFS_fhandle_sz+4) |
49 | #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz) | 49 | #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz) |
50 | #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz) | 50 | #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz) |
51 | #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz) | 51 | #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz) |
52 | #define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz) | 52 | #define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz) |
53 | #define NFS_readdirargs_sz (NFS_fhandle_sz+2) | 53 | #define NFS_readdirargs_sz (NFS_fhandle_sz+2) |
54 | 54 | ||
55 | #define NFS_attrstat_sz (1+NFS_fattr_sz) | 55 | #define NFS_attrstat_sz (1+NFS_fattr_sz) |
56 | #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz) | 56 | #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz) |
57 | #define NFS_readlinkres_sz (2) | 57 | #define NFS_readlinkres_sz (2) |
58 | #define NFS_readres_sz (1+NFS_fattr_sz+1) | 58 | #define NFS_readres_sz (1+NFS_fattr_sz+1) |
59 | #define NFS_writeres_sz (NFS_attrstat_sz) | 59 | #define NFS_writeres_sz (NFS_attrstat_sz) |
60 | #define NFS_stat_sz (1) | 60 | #define NFS_stat_sz (1) |
61 | #define NFS_readdirres_sz (1) | 61 | #define NFS_readdirres_sz (1) |
62 | #define NFS_statfsres_sz (1+NFS_info_sz) | 62 | #define NFS_statfsres_sz (1+NFS_info_sz) |
63 | 63 | ||
64 | 64 | ||
65 | /* | 65 | /* |
66 | * While encoding arguments, set up the reply buffer in advance to | 66 | * While encoding arguments, set up the reply buffer in advance to |
67 | * receive reply data directly into the page cache. | 67 | * receive reply data directly into the page cache. |
68 | */ | 68 | */ |
69 | static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages, | 69 | static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages, |
70 | unsigned int base, unsigned int len, | 70 | unsigned int base, unsigned int len, |
71 | unsigned int bufsize) | 71 | unsigned int bufsize) |
72 | { | 72 | { |
73 | struct rpc_auth *auth = req->rq_cred->cr_auth; | 73 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
74 | unsigned int replen; | 74 | unsigned int replen; |
75 | 75 | ||
76 | replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize; | 76 | replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize; |
77 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); | 77 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); |
78 | } | 78 | } |
79 | 79 | ||
80 | /* | 80 | /* |
81 | * Handle decode buffer overflows out-of-line. | 81 | * Handle decode buffer overflows out-of-line. |
82 | */ | 82 | */ |
83 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 83 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
84 | { | 84 | { |
85 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " | 85 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " |
86 | "Remaining buffer length is %tu words.\n", | 86 | "Remaining buffer length is %tu words.\n", |
87 | func, xdr->end - xdr->p); | 87 | func, xdr->end - xdr->p); |
88 | } | 88 | } |
89 | 89 | ||
90 | 90 | ||
91 | /* | 91 | /* |
92 | * Encode/decode NFSv2 basic data types | 92 | * Encode/decode NFSv2 basic data types |
93 | * | 93 | * |
94 | * Basic NFSv2 data types are defined in section 2.3 of RFC 1094: | 94 | * Basic NFSv2 data types are defined in section 2.3 of RFC 1094: |
95 | * "NFS: Network File System Protocol Specification". | 95 | * "NFS: Network File System Protocol Specification". |
96 | * | 96 | * |
97 | * Not all basic data types have their own encoding and decoding | 97 | * Not all basic data types have their own encoding and decoding |
98 | * functions. For run-time efficiency, some data types are encoded | 98 | * functions. For run-time efficiency, some data types are encoded |
99 | * or decoded inline. | 99 | * or decoded inline. |
100 | */ | 100 | */ |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * typedef opaque nfsdata<>; | 103 | * typedef opaque nfsdata<>; |
104 | */ | 104 | */ |
105 | static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result) | 105 | static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result) |
106 | { | 106 | { |
107 | u32 recvd, count; | 107 | u32 recvd, count; |
108 | size_t hdrlen; | 108 | size_t hdrlen; |
109 | __be32 *p; | 109 | __be32 *p; |
110 | 110 | ||
111 | p = xdr_inline_decode(xdr, 4); | 111 | p = xdr_inline_decode(xdr, 4); |
112 | if (unlikely(p == NULL)) | 112 | if (unlikely(p == NULL)) |
113 | goto out_overflow; | 113 | goto out_overflow; |
114 | count = be32_to_cpup(p); | 114 | count = be32_to_cpup(p); |
115 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 115 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; |
116 | recvd = xdr->buf->len - hdrlen; | 116 | recvd = xdr->buf->len - hdrlen; |
117 | if (unlikely(count > recvd)) | 117 | if (unlikely(count > recvd)) |
118 | goto out_cheating; | 118 | goto out_cheating; |
119 | out: | 119 | out: |
120 | xdr_read_pages(xdr, count); | 120 | xdr_read_pages(xdr, count); |
121 | result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */ | 121 | result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */ |
122 | result->count = count; | 122 | result->count = count; |
123 | return count; | 123 | return count; |
124 | out_cheating: | 124 | out_cheating: |
125 | dprintk("NFS: server cheating in read result: " | 125 | dprintk("NFS: server cheating in read result: " |
126 | "count %u > recvd %u\n", count, recvd); | 126 | "count %u > recvd %u\n", count, recvd); |
127 | count = recvd; | 127 | count = recvd; |
128 | goto out; | 128 | goto out; |
129 | out_overflow: | 129 | out_overflow: |
130 | print_overflow_msg(__func__, xdr); | 130 | print_overflow_msg(__func__, xdr); |
131 | return -EIO; | 131 | return -EIO; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* | 134 | /* |
135 | * enum stat { | 135 | * enum stat { |
136 | * NFS_OK = 0, | 136 | * NFS_OK = 0, |
137 | * NFSERR_PERM = 1, | 137 | * NFSERR_PERM = 1, |
138 | * NFSERR_NOENT = 2, | 138 | * NFSERR_NOENT = 2, |
139 | * NFSERR_IO = 5, | 139 | * NFSERR_IO = 5, |
140 | * NFSERR_NXIO = 6, | 140 | * NFSERR_NXIO = 6, |
141 | * NFSERR_ACCES = 13, | 141 | * NFSERR_ACCES = 13, |
142 | * NFSERR_EXIST = 17, | 142 | * NFSERR_EXIST = 17, |
143 | * NFSERR_NODEV = 19, | 143 | * NFSERR_NODEV = 19, |
144 | * NFSERR_NOTDIR = 20, | 144 | * NFSERR_NOTDIR = 20, |
145 | * NFSERR_ISDIR = 21, | 145 | * NFSERR_ISDIR = 21, |
146 | * NFSERR_FBIG = 27, | 146 | * NFSERR_FBIG = 27, |
147 | * NFSERR_NOSPC = 28, | 147 | * NFSERR_NOSPC = 28, |
148 | * NFSERR_ROFS = 30, | 148 | * NFSERR_ROFS = 30, |
149 | * NFSERR_NAMETOOLONG = 63, | 149 | * NFSERR_NAMETOOLONG = 63, |
150 | * NFSERR_NOTEMPTY = 66, | 150 | * NFSERR_NOTEMPTY = 66, |
151 | * NFSERR_DQUOT = 69, | 151 | * NFSERR_DQUOT = 69, |
152 | * NFSERR_STALE = 70, | 152 | * NFSERR_STALE = 70, |
153 | * NFSERR_WFLUSH = 99 | 153 | * NFSERR_WFLUSH = 99 |
154 | * }; | 154 | * }; |
155 | */ | 155 | */ |
156 | static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status) | 156 | static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status) |
157 | { | 157 | { |
158 | __be32 *p; | 158 | __be32 *p; |
159 | 159 | ||
160 | p = xdr_inline_decode(xdr, 4); | 160 | p = xdr_inline_decode(xdr, 4); |
161 | if (unlikely(p == NULL)) | 161 | if (unlikely(p == NULL)) |
162 | goto out_overflow; | 162 | goto out_overflow; |
163 | *status = be32_to_cpup(p); | 163 | *status = be32_to_cpup(p); |
164 | return 0; | 164 | return 0; |
165 | out_overflow: | 165 | out_overflow: |
166 | print_overflow_msg(__func__, xdr); | 166 | print_overflow_msg(__func__, xdr); |
167 | return -EIO; | 167 | return -EIO; |
168 | } | 168 | } |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * 2.3.2. ftype | 171 | * 2.3.2. ftype |
172 | * | 172 | * |
173 | * enum ftype { | 173 | * enum ftype { |
174 | * NFNON = 0, | 174 | * NFNON = 0, |
175 | * NFREG = 1, | 175 | * NFREG = 1, |
176 | * NFDIR = 2, | 176 | * NFDIR = 2, |
177 | * NFBLK = 3, | 177 | * NFBLK = 3, |
178 | * NFCHR = 4, | 178 | * NFCHR = 4, |
179 | * NFLNK = 5 | 179 | * NFLNK = 5 |
180 | * }; | 180 | * }; |
181 | * | 181 | * |
182 | */ | 182 | */ |
183 | static __be32 *xdr_decode_ftype(__be32 *p, u32 *type) | 183 | static __be32 *xdr_decode_ftype(__be32 *p, u32 *type) |
184 | { | 184 | { |
185 | *type = be32_to_cpup(p++); | 185 | *type = be32_to_cpup(p++); |
186 | if (unlikely(*type > NF2FIFO)) | 186 | if (unlikely(*type > NF2FIFO)) |
187 | *type = NFBAD; | 187 | *type = NFBAD; |
188 | return p; | 188 | return p; |
189 | } | 189 | } |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * 2.3.3. fhandle | 192 | * 2.3.3. fhandle |
193 | * | 193 | * |
194 | * typedef opaque fhandle[FHSIZE]; | 194 | * typedef opaque fhandle[FHSIZE]; |
195 | */ | 195 | */ |
196 | static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh) | 196 | static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh) |
197 | { | 197 | { |
198 | __be32 *p; | 198 | __be32 *p; |
199 | 199 | ||
200 | BUG_ON(fh->size != NFS2_FHSIZE); | 200 | BUG_ON(fh->size != NFS2_FHSIZE); |
201 | p = xdr_reserve_space(xdr, NFS2_FHSIZE); | 201 | p = xdr_reserve_space(xdr, NFS2_FHSIZE); |
202 | memcpy(p, fh->data, NFS2_FHSIZE); | 202 | memcpy(p, fh->data, NFS2_FHSIZE); |
203 | } | 203 | } |
204 | 204 | ||
205 | static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh) | 205 | static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh) |
206 | { | 206 | { |
207 | __be32 *p; | 207 | __be32 *p; |
208 | 208 | ||
209 | p = xdr_inline_decode(xdr, NFS2_FHSIZE); | 209 | p = xdr_inline_decode(xdr, NFS2_FHSIZE); |
210 | if (unlikely(p == NULL)) | 210 | if (unlikely(p == NULL)) |
211 | goto out_overflow; | 211 | goto out_overflow; |
212 | fh->size = NFS2_FHSIZE; | 212 | fh->size = NFS2_FHSIZE; |
213 | memcpy(fh->data, p, NFS2_FHSIZE); | 213 | memcpy(fh->data, p, NFS2_FHSIZE); |
214 | return 0; | 214 | return 0; |
215 | out_overflow: | 215 | out_overflow: |
216 | print_overflow_msg(__func__, xdr); | 216 | print_overflow_msg(__func__, xdr); |
217 | return -EIO; | 217 | return -EIO; |
218 | } | 218 | } |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * 2.3.4. timeval | 221 | * 2.3.4. timeval |
222 | * | 222 | * |
223 | * struct timeval { | 223 | * struct timeval { |
224 | * unsigned int seconds; | 224 | * unsigned int seconds; |
225 | * unsigned int useconds; | 225 | * unsigned int useconds; |
226 | * }; | 226 | * }; |
227 | */ | 227 | */ |
228 | static __be32 *xdr_encode_time(__be32 *p, const struct timespec *timep) | 228 | static __be32 *xdr_encode_time(__be32 *p, const struct timespec *timep) |
229 | { | 229 | { |
230 | *p++ = cpu_to_be32(timep->tv_sec); | 230 | *p++ = cpu_to_be32(timep->tv_sec); |
231 | if (timep->tv_nsec != 0) | 231 | if (timep->tv_nsec != 0) |
232 | *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC); | 232 | *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC); |
233 | else | 233 | else |
234 | *p++ = cpu_to_be32(0); | 234 | *p++ = cpu_to_be32(0); |
235 | return p; | 235 | return p; |
236 | } | 236 | } |
237 | 237 | ||
238 | /* | 238 | /* |
239 | * Passing the invalid value useconds=1000000 is a Sun convention for | 239 | * Passing the invalid value useconds=1000000 is a Sun convention for |
240 | * "set to current server time". It's needed to make permissions checks | 240 | * "set to current server time". It's needed to make permissions checks |
241 | * for the "touch" program across v2 mounts to Solaris and Irix servers | 241 | * for the "touch" program across v2 mounts to Solaris and Irix servers |
242 | * work correctly. See description of sattr in section 6.1 of "NFS | 242 | * work correctly. See description of sattr in section 6.1 of "NFS |
243 | * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5. | 243 | * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5. |
244 | */ | 244 | */ |
245 | static __be32 *xdr_encode_current_server_time(__be32 *p, | 245 | static __be32 *xdr_encode_current_server_time(__be32 *p, |
246 | const struct timespec *timep) | 246 | const struct timespec *timep) |
247 | { | 247 | { |
248 | *p++ = cpu_to_be32(timep->tv_sec); | 248 | *p++ = cpu_to_be32(timep->tv_sec); |
249 | *p++ = cpu_to_be32(1000000); | 249 | *p++ = cpu_to_be32(1000000); |
250 | return p; | 250 | return p; |
251 | } | 251 | } |
252 | 252 | ||
253 | static __be32 *xdr_decode_time(__be32 *p, struct timespec *timep) | 253 | static __be32 *xdr_decode_time(__be32 *p, struct timespec *timep) |
254 | { | 254 | { |
255 | timep->tv_sec = be32_to_cpup(p++); | 255 | timep->tv_sec = be32_to_cpup(p++); |
256 | timep->tv_nsec = be32_to_cpup(p++) * NSEC_PER_USEC; | 256 | timep->tv_nsec = be32_to_cpup(p++) * NSEC_PER_USEC; |
257 | return p; | 257 | return p; |
258 | } | 258 | } |
259 | 259 | ||
260 | /* | 260 | /* |
261 | * 2.3.5. fattr | 261 | * 2.3.5. fattr |
262 | * | 262 | * |
263 | * struct fattr { | 263 | * struct fattr { |
264 | * ftype type; | 264 | * ftype type; |
265 | * unsigned int mode; | 265 | * unsigned int mode; |
266 | * unsigned int nlink; | 266 | * unsigned int nlink; |
267 | * unsigned int uid; | 267 | * unsigned int uid; |
268 | * unsigned int gid; | 268 | * unsigned int gid; |
269 | * unsigned int size; | 269 | * unsigned int size; |
270 | * unsigned int blocksize; | 270 | * unsigned int blocksize; |
271 | * unsigned int rdev; | 271 | * unsigned int rdev; |
272 | * unsigned int blocks; | 272 | * unsigned int blocks; |
273 | * unsigned int fsid; | 273 | * unsigned int fsid; |
274 | * unsigned int fileid; | 274 | * unsigned int fileid; |
275 | * timeval atime; | 275 | * timeval atime; |
276 | * timeval mtime; | 276 | * timeval mtime; |
277 | * timeval ctime; | 277 | * timeval ctime; |
278 | * }; | 278 | * }; |
279 | * | 279 | * |
280 | */ | 280 | */ |
281 | static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 281 | static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr) |
282 | { | 282 | { |
283 | u32 rdev, type; | 283 | u32 rdev, type; |
284 | __be32 *p; | 284 | __be32 *p; |
285 | 285 | ||
286 | p = xdr_inline_decode(xdr, NFS_fattr_sz << 2); | 286 | p = xdr_inline_decode(xdr, NFS_fattr_sz << 2); |
287 | if (unlikely(p == NULL)) | 287 | if (unlikely(p == NULL)) |
288 | goto out_overflow; | 288 | goto out_overflow; |
289 | 289 | ||
290 | fattr->valid |= NFS_ATTR_FATTR_V2; | 290 | fattr->valid |= NFS_ATTR_FATTR_V2; |
291 | 291 | ||
292 | p = xdr_decode_ftype(p, &type); | 292 | p = xdr_decode_ftype(p, &type); |
293 | 293 | ||
294 | fattr->mode = be32_to_cpup(p++); | 294 | fattr->mode = be32_to_cpup(p++); |
295 | fattr->nlink = be32_to_cpup(p++); | 295 | fattr->nlink = be32_to_cpup(p++); |
296 | fattr->uid = be32_to_cpup(p++); | 296 | fattr->uid = be32_to_cpup(p++); |
297 | fattr->gid = be32_to_cpup(p++); | 297 | fattr->gid = be32_to_cpup(p++); |
298 | fattr->size = be32_to_cpup(p++); | 298 | fattr->size = be32_to_cpup(p++); |
299 | fattr->du.nfs2.blocksize = be32_to_cpup(p++); | 299 | fattr->du.nfs2.blocksize = be32_to_cpup(p++); |
300 | 300 | ||
301 | rdev = be32_to_cpup(p++); | 301 | rdev = be32_to_cpup(p++); |
302 | fattr->rdev = new_decode_dev(rdev); | 302 | fattr->rdev = new_decode_dev(rdev); |
303 | if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) { | 303 | if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) { |
304 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; | 304 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; |
305 | fattr->rdev = 0; | 305 | fattr->rdev = 0; |
306 | } | 306 | } |
307 | 307 | ||
308 | fattr->du.nfs2.blocks = be32_to_cpup(p++); | 308 | fattr->du.nfs2.blocks = be32_to_cpup(p++); |
309 | fattr->fsid.major = be32_to_cpup(p++); | 309 | fattr->fsid.major = be32_to_cpup(p++); |
310 | fattr->fsid.minor = 0; | 310 | fattr->fsid.minor = 0; |
311 | fattr->fileid = be32_to_cpup(p++); | 311 | fattr->fileid = be32_to_cpup(p++); |
312 | 312 | ||
313 | p = xdr_decode_time(p, &fattr->atime); | 313 | p = xdr_decode_time(p, &fattr->atime); |
314 | p = xdr_decode_time(p, &fattr->mtime); | 314 | p = xdr_decode_time(p, &fattr->mtime); |
315 | xdr_decode_time(p, &fattr->ctime); | 315 | xdr_decode_time(p, &fattr->ctime); |
316 | return 0; | 316 | return 0; |
317 | out_overflow: | 317 | out_overflow: |
318 | print_overflow_msg(__func__, xdr); | 318 | print_overflow_msg(__func__, xdr); |
319 | return -EIO; | 319 | return -EIO; |
320 | } | 320 | } |
321 | 321 | ||
322 | /* | 322 | /* |
323 | * 2.3.6. sattr | 323 | * 2.3.6. sattr |
324 | * | 324 | * |
325 | * struct sattr { | 325 | * struct sattr { |
326 | * unsigned int mode; | 326 | * unsigned int mode; |
327 | * unsigned int uid; | 327 | * unsigned int uid; |
328 | * unsigned int gid; | 328 | * unsigned int gid; |
329 | * unsigned int size; | 329 | * unsigned int size; |
330 | * timeval atime; | 330 | * timeval atime; |
331 | * timeval mtime; | 331 | * timeval mtime; |
332 | * }; | 332 | * }; |
333 | */ | 333 | */ |
334 | 334 | ||
335 | #define NFS2_SATTR_NOT_SET (0xffffffff) | 335 | #define NFS2_SATTR_NOT_SET (0xffffffff) |
336 | 336 | ||
337 | static __be32 *xdr_time_not_set(__be32 *p) | 337 | static __be32 *xdr_time_not_set(__be32 *p) |
338 | { | 338 | { |
339 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 339 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
340 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 340 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
341 | return p; | 341 | return p; |
342 | } | 342 | } |
343 | 343 | ||
344 | static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr) | 344 | static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr) |
345 | { | 345 | { |
346 | __be32 *p; | 346 | __be32 *p; |
347 | 347 | ||
348 | p = xdr_reserve_space(xdr, NFS_sattr_sz << 2); | 348 | p = xdr_reserve_space(xdr, NFS_sattr_sz << 2); |
349 | 349 | ||
350 | if (attr->ia_valid & ATTR_MODE) | 350 | if (attr->ia_valid & ATTR_MODE) |
351 | *p++ = cpu_to_be32(attr->ia_mode); | 351 | *p++ = cpu_to_be32(attr->ia_mode); |
352 | else | 352 | else |
353 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 353 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
354 | if (attr->ia_valid & ATTR_UID) | 354 | if (attr->ia_valid & ATTR_UID) |
355 | *p++ = cpu_to_be32(attr->ia_uid); | 355 | *p++ = cpu_to_be32(attr->ia_uid); |
356 | else | 356 | else |
357 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 357 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
358 | if (attr->ia_valid & ATTR_GID) | 358 | if (attr->ia_valid & ATTR_GID) |
359 | *p++ = cpu_to_be32(attr->ia_gid); | 359 | *p++ = cpu_to_be32(attr->ia_gid); |
360 | else | 360 | else |
361 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 361 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
362 | if (attr->ia_valid & ATTR_SIZE) | 362 | if (attr->ia_valid & ATTR_SIZE) |
363 | *p++ = cpu_to_be32((u32)attr->ia_size); | 363 | *p++ = cpu_to_be32((u32)attr->ia_size); |
364 | else | 364 | else |
365 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); | 365 | *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET); |
366 | 366 | ||
367 | if (attr->ia_valid & ATTR_ATIME_SET) | 367 | if (attr->ia_valid & ATTR_ATIME_SET) |
368 | p = xdr_encode_time(p, &attr->ia_atime); | 368 | p = xdr_encode_time(p, &attr->ia_atime); |
369 | else if (attr->ia_valid & ATTR_ATIME) | 369 | else if (attr->ia_valid & ATTR_ATIME) |
370 | p = xdr_encode_current_server_time(p, &attr->ia_atime); | 370 | p = xdr_encode_current_server_time(p, &attr->ia_atime); |
371 | else | 371 | else |
372 | p = xdr_time_not_set(p); | 372 | p = xdr_time_not_set(p); |
373 | if (attr->ia_valid & ATTR_MTIME_SET) | 373 | if (attr->ia_valid & ATTR_MTIME_SET) |
374 | xdr_encode_time(p, &attr->ia_mtime); | 374 | xdr_encode_time(p, &attr->ia_mtime); |
375 | else if (attr->ia_valid & ATTR_MTIME) | 375 | else if (attr->ia_valid & ATTR_MTIME) |
376 | xdr_encode_current_server_time(p, &attr->ia_mtime); | 376 | xdr_encode_current_server_time(p, &attr->ia_mtime); |
377 | else | 377 | else |
378 | xdr_time_not_set(p); | 378 | xdr_time_not_set(p); |
379 | } | 379 | } |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * 2.3.7. filename | 382 | * 2.3.7. filename |
383 | * | 383 | * |
384 | * typedef string filename<MAXNAMLEN>; | 384 | * typedef string filename<MAXNAMLEN>; |
385 | */ | 385 | */ |
386 | static void encode_filename(struct xdr_stream *xdr, | 386 | static void encode_filename(struct xdr_stream *xdr, |
387 | const char *name, u32 length) | 387 | const char *name, u32 length) |
388 | { | 388 | { |
389 | __be32 *p; | 389 | __be32 *p; |
390 | 390 | ||
391 | BUG_ON(length > NFS2_MAXNAMLEN); | 391 | BUG_ON(length > NFS2_MAXNAMLEN); |
392 | p = xdr_reserve_space(xdr, 4 + length); | 392 | p = xdr_reserve_space(xdr, 4 + length); |
393 | xdr_encode_opaque(p, name, length); | 393 | xdr_encode_opaque(p, name, length); |
394 | } | 394 | } |
395 | 395 | ||
396 | static int decode_filename_inline(struct xdr_stream *xdr, | 396 | static int decode_filename_inline(struct xdr_stream *xdr, |
397 | const char **name, u32 *length) | 397 | const char **name, u32 *length) |
398 | { | 398 | { |
399 | __be32 *p; | 399 | __be32 *p; |
400 | u32 count; | 400 | u32 count; |
401 | 401 | ||
402 | p = xdr_inline_decode(xdr, 4); | 402 | p = xdr_inline_decode(xdr, 4); |
403 | if (unlikely(p == NULL)) | 403 | if (unlikely(p == NULL)) |
404 | goto out_overflow; | 404 | goto out_overflow; |
405 | count = be32_to_cpup(p); | 405 | count = be32_to_cpup(p); |
406 | if (count > NFS3_MAXNAMLEN) | 406 | if (count > NFS3_MAXNAMLEN) |
407 | goto out_nametoolong; | 407 | goto out_nametoolong; |
408 | p = xdr_inline_decode(xdr, count); | 408 | p = xdr_inline_decode(xdr, count); |
409 | if (unlikely(p == NULL)) | 409 | if (unlikely(p == NULL)) |
410 | goto out_overflow; | 410 | goto out_overflow; |
411 | *name = (const char *)p; | 411 | *name = (const char *)p; |
412 | *length = count; | 412 | *length = count; |
413 | return 0; | 413 | return 0; |
414 | out_nametoolong: | 414 | out_nametoolong: |
415 | dprintk("NFS: returned filename too long: %u\n", count); | 415 | dprintk("NFS: returned filename too long: %u\n", count); |
416 | return -ENAMETOOLONG; | 416 | return -ENAMETOOLONG; |
417 | out_overflow: | 417 | out_overflow: |
418 | print_overflow_msg(__func__, xdr); | 418 | print_overflow_msg(__func__, xdr); |
419 | return -EIO; | 419 | return -EIO; |
420 | } | 420 | } |
421 | 421 | ||
422 | /* | 422 | /* |
423 | * 2.3.8. path | 423 | * 2.3.8. path |
424 | * | 424 | * |
425 | * typedef string path<MAXPATHLEN>; | 425 | * typedef string path<MAXPATHLEN>; |
426 | */ | 426 | */ |
427 | static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length) | 427 | static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length) |
428 | { | 428 | { |
429 | __be32 *p; | 429 | __be32 *p; |
430 | 430 | ||
431 | BUG_ON(length > NFS2_MAXPATHLEN); | 431 | BUG_ON(length > NFS2_MAXPATHLEN); |
432 | p = xdr_reserve_space(xdr, 4); | 432 | p = xdr_reserve_space(xdr, 4); |
433 | *p = cpu_to_be32(length); | 433 | *p = cpu_to_be32(length); |
434 | xdr_write_pages(xdr, pages, 0, length); | 434 | xdr_write_pages(xdr, pages, 0, length); |
435 | } | 435 | } |
436 | 436 | ||
437 | static int decode_path(struct xdr_stream *xdr) | 437 | static int decode_path(struct xdr_stream *xdr) |
438 | { | 438 | { |
439 | u32 length, recvd; | 439 | u32 length, recvd; |
440 | size_t hdrlen; | 440 | size_t hdrlen; |
441 | __be32 *p; | 441 | __be32 *p; |
442 | 442 | ||
443 | p = xdr_inline_decode(xdr, 4); | 443 | p = xdr_inline_decode(xdr, 4); |
444 | if (unlikely(p == NULL)) | 444 | if (unlikely(p == NULL)) |
445 | goto out_overflow; | 445 | goto out_overflow; |
446 | length = be32_to_cpup(p); | 446 | length = be32_to_cpup(p); |
447 | if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) | 447 | if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) |
448 | goto out_size; | 448 | goto out_size; |
449 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 449 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; |
450 | recvd = xdr->buf->len - hdrlen; | 450 | recvd = xdr->buf->len - hdrlen; |
451 | if (unlikely(length > recvd)) | 451 | if (unlikely(length > recvd)) |
452 | goto out_cheating; | 452 | goto out_cheating; |
453 | 453 | ||
454 | xdr_read_pages(xdr, length); | 454 | xdr_read_pages(xdr, length); |
455 | xdr_terminate_string(xdr->buf, length); | 455 | xdr_terminate_string(xdr->buf, length); |
456 | return 0; | 456 | return 0; |
457 | out_size: | 457 | out_size: |
458 | dprintk("NFS: returned pathname too long: %u\n", length); | 458 | dprintk("NFS: returned pathname too long: %u\n", length); |
459 | return -ENAMETOOLONG; | 459 | return -ENAMETOOLONG; |
460 | out_cheating: | 460 | out_cheating: |
461 | dprintk("NFS: server cheating in pathname result: " | 461 | dprintk("NFS: server cheating in pathname result: " |
462 | "length %u > received %u\n", length, recvd); | 462 | "length %u > received %u\n", length, recvd); |
463 | return -EIO; | 463 | return -EIO; |
464 | out_overflow: | 464 | out_overflow: |
465 | print_overflow_msg(__func__, xdr); | 465 | print_overflow_msg(__func__, xdr); |
466 | return -EIO; | 466 | return -EIO; |
467 | } | 467 | } |
468 | 468 | ||
469 | /* | 469 | /* |
470 | * 2.3.9. attrstat | 470 | * 2.3.9. attrstat |
471 | * | 471 | * |
472 | * union attrstat switch (stat status) { | 472 | * union attrstat switch (stat status) { |
473 | * case NFS_OK: | 473 | * case NFS_OK: |
474 | * fattr attributes; | 474 | * fattr attributes; |
475 | * default: | 475 | * default: |
476 | * void; | 476 | * void; |
477 | * }; | 477 | * }; |
478 | */ | 478 | */ |
479 | static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result) | 479 | static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result) |
480 | { | 480 | { |
481 | enum nfs_stat status; | 481 | enum nfs_stat status; |
482 | int error; | 482 | int error; |
483 | 483 | ||
484 | error = decode_stat(xdr, &status); | 484 | error = decode_stat(xdr, &status); |
485 | if (unlikely(error)) | 485 | if (unlikely(error)) |
486 | goto out; | 486 | goto out; |
487 | if (status != NFS_OK) | 487 | if (status != NFS_OK) |
488 | goto out_default; | 488 | goto out_default; |
489 | error = decode_fattr(xdr, result); | 489 | error = decode_fattr(xdr, result); |
490 | out: | 490 | out: |
491 | return error; | 491 | return error; |
492 | out_default: | 492 | out_default: |
493 | return nfs_stat_to_errno(status); | 493 | return nfs_stat_to_errno(status); |
494 | } | 494 | } |
495 | 495 | ||
496 | /* | 496 | /* |
497 | * 2.3.10. diropargs | 497 | * 2.3.10. diropargs |
498 | * | 498 | * |
499 | * struct diropargs { | 499 | * struct diropargs { |
500 | * fhandle dir; | 500 | * fhandle dir; |
501 | * filename name; | 501 | * filename name; |
502 | * }; | 502 | * }; |
503 | */ | 503 | */ |
504 | static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh, | 504 | static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh, |
505 | const char *name, u32 length) | 505 | const char *name, u32 length) |
506 | { | 506 | { |
507 | encode_fhandle(xdr, fh); | 507 | encode_fhandle(xdr, fh); |
508 | encode_filename(xdr, name, length); | 508 | encode_filename(xdr, name, length); |
509 | } | 509 | } |
510 | 510 | ||
511 | /* | 511 | /* |
512 | * 2.3.11. diropres | 512 | * 2.3.11. diropres |
513 | * | 513 | * |
514 | * union diropres switch (stat status) { | 514 | * union diropres switch (stat status) { |
515 | * case NFS_OK: | 515 | * case NFS_OK: |
516 | * struct { | 516 | * struct { |
517 | * fhandle file; | 517 | * fhandle file; |
518 | * fattr attributes; | 518 | * fattr attributes; |
519 | * } diropok; | 519 | * } diropok; |
520 | * default: | 520 | * default: |
521 | * void; | 521 | * void; |
522 | * }; | 522 | * }; |
523 | */ | 523 | */ |
524 | static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result) | 524 | static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result) |
525 | { | 525 | { |
526 | int error; | 526 | int error; |
527 | 527 | ||
528 | error = decode_fhandle(xdr, result->fh); | 528 | error = decode_fhandle(xdr, result->fh); |
529 | if (unlikely(error)) | 529 | if (unlikely(error)) |
530 | goto out; | 530 | goto out; |
531 | error = decode_fattr(xdr, result->fattr); | 531 | error = decode_fattr(xdr, result->fattr); |
532 | out: | 532 | out: |
533 | return error; | 533 | return error; |
534 | } | 534 | } |
535 | 535 | ||
536 | static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result) | 536 | static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result) |
537 | { | 537 | { |
538 | enum nfs_stat status; | 538 | enum nfs_stat status; |
539 | int error; | 539 | int error; |
540 | 540 | ||
541 | error = decode_stat(xdr, &status); | 541 | error = decode_stat(xdr, &status); |
542 | if (unlikely(error)) | 542 | if (unlikely(error)) |
543 | goto out; | 543 | goto out; |
544 | if (status != NFS_OK) | 544 | if (status != NFS_OK) |
545 | goto out_default; | 545 | goto out_default; |
546 | error = decode_diropok(xdr, result); | 546 | error = decode_diropok(xdr, result); |
547 | out: | 547 | out: |
548 | return error; | 548 | return error; |
549 | out_default: | 549 | out_default: |
550 | return nfs_stat_to_errno(status); | 550 | return nfs_stat_to_errno(status); |
551 | } | 551 | } |
552 | 552 | ||
553 | 553 | ||
554 | /* | 554 | /* |
555 | * NFSv2 XDR encode functions | 555 | * NFSv2 XDR encode functions |
556 | * | 556 | * |
557 | * NFSv2 argument types are defined in section 2.2 of RFC 1094: | 557 | * NFSv2 argument types are defined in section 2.2 of RFC 1094: |
558 | * "NFS: Network File System Protocol Specification". | 558 | * "NFS: Network File System Protocol Specification". |
559 | */ | 559 | */ |
560 | 560 | ||
561 | static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req, | 561 | static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req, |
562 | struct xdr_stream *xdr, | 562 | struct xdr_stream *xdr, |
563 | const struct nfs_fh *fh) | 563 | const struct nfs_fh *fh) |
564 | { | 564 | { |
565 | encode_fhandle(xdr, fh); | 565 | encode_fhandle(xdr, fh); |
566 | } | 566 | } |
567 | 567 | ||
568 | /* | 568 | /* |
569 | * 2.2.3. sattrargs | 569 | * 2.2.3. sattrargs |
570 | * | 570 | * |
571 | * struct sattrargs { | 571 | * struct sattrargs { |
572 | * fhandle file; | 572 | * fhandle file; |
573 | * sattr attributes; | 573 | * sattr attributes; |
574 | * }; | 574 | * }; |
575 | */ | 575 | */ |
576 | static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req, | 576 | static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req, |
577 | struct xdr_stream *xdr, | 577 | struct xdr_stream *xdr, |
578 | const struct nfs_sattrargs *args) | 578 | const struct nfs_sattrargs *args) |
579 | { | 579 | { |
580 | encode_fhandle(xdr, args->fh); | 580 | encode_fhandle(xdr, args->fh); |
581 | encode_sattr(xdr, args->sattr); | 581 | encode_sattr(xdr, args->sattr); |
582 | } | 582 | } |
583 | 583 | ||
584 | static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req, | 584 | static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req, |
585 | struct xdr_stream *xdr, | 585 | struct xdr_stream *xdr, |
586 | const struct nfs_diropargs *args) | 586 | const struct nfs_diropargs *args) |
587 | { | 587 | { |
588 | encode_diropargs(xdr, args->fh, args->name, args->len); | 588 | encode_diropargs(xdr, args->fh, args->name, args->len); |
589 | } | 589 | } |
590 | 590 | ||
591 | static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req, | 591 | static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req, |
592 | struct xdr_stream *xdr, | 592 | struct xdr_stream *xdr, |
593 | const struct nfs_readlinkargs *args) | 593 | const struct nfs_readlinkargs *args) |
594 | { | 594 | { |
595 | encode_fhandle(xdr, args->fh); | 595 | encode_fhandle(xdr, args->fh); |
596 | prepare_reply_buffer(req, args->pages, args->pgbase, | 596 | prepare_reply_buffer(req, args->pages, args->pgbase, |
597 | args->pglen, NFS_readlinkres_sz); | 597 | args->pglen, NFS_readlinkres_sz); |
598 | } | 598 | } |
599 | 599 | ||
600 | /* | 600 | /* |
601 | * 2.2.7. readargs | 601 | * 2.2.7. readargs |
602 | * | 602 | * |
603 | * struct readargs { | 603 | * struct readargs { |
604 | * fhandle file; | 604 | * fhandle file; |
605 | * unsigned offset; | 605 | * unsigned offset; |
606 | * unsigned count; | 606 | * unsigned count; |
607 | * unsigned totalcount; | 607 | * unsigned totalcount; |
608 | * }; | 608 | * }; |
609 | */ | 609 | */ |
610 | static void encode_readargs(struct xdr_stream *xdr, | 610 | static void encode_readargs(struct xdr_stream *xdr, |
611 | const struct nfs_readargs *args) | 611 | const struct nfs_readargs *args) |
612 | { | 612 | { |
613 | u32 offset = args->offset; | 613 | u32 offset = args->offset; |
614 | u32 count = args->count; | 614 | u32 count = args->count; |
615 | __be32 *p; | 615 | __be32 *p; |
616 | 616 | ||
617 | encode_fhandle(xdr, args->fh); | 617 | encode_fhandle(xdr, args->fh); |
618 | 618 | ||
619 | p = xdr_reserve_space(xdr, 4 + 4 + 4); | 619 | p = xdr_reserve_space(xdr, 4 + 4 + 4); |
620 | *p++ = cpu_to_be32(offset); | 620 | *p++ = cpu_to_be32(offset); |
621 | *p++ = cpu_to_be32(count); | 621 | *p++ = cpu_to_be32(count); |
622 | *p = cpu_to_be32(count); | 622 | *p = cpu_to_be32(count); |
623 | } | 623 | } |
624 | 624 | ||
625 | static void nfs2_xdr_enc_readargs(struct rpc_rqst *req, | 625 | static void nfs2_xdr_enc_readargs(struct rpc_rqst *req, |
626 | struct xdr_stream *xdr, | 626 | struct xdr_stream *xdr, |
627 | const struct nfs_readargs *args) | 627 | const struct nfs_readargs *args) |
628 | { | 628 | { |
629 | encode_readargs(xdr, args); | 629 | encode_readargs(xdr, args); |
630 | prepare_reply_buffer(req, args->pages, args->pgbase, | 630 | prepare_reply_buffer(req, args->pages, args->pgbase, |
631 | args->count, NFS_readres_sz); | 631 | args->count, NFS_readres_sz); |
632 | req->rq_rcv_buf.flags |= XDRBUF_READ; | 632 | req->rq_rcv_buf.flags |= XDRBUF_READ; |
633 | } | 633 | } |
634 | 634 | ||
635 | /* | 635 | /* |
636 | * 2.2.9. writeargs | 636 | * 2.2.9. writeargs |
637 | * | 637 | * |
638 | * struct writeargs { | 638 | * struct writeargs { |
639 | * fhandle file; | 639 | * fhandle file; |
640 | * unsigned beginoffset; | 640 | * unsigned beginoffset; |
641 | * unsigned offset; | 641 | * unsigned offset; |
642 | * unsigned totalcount; | 642 | * unsigned totalcount; |
643 | * nfsdata data; | 643 | * nfsdata data; |
644 | * }; | 644 | * }; |
645 | */ | 645 | */ |
646 | static void encode_writeargs(struct xdr_stream *xdr, | 646 | static void encode_writeargs(struct xdr_stream *xdr, |
647 | const struct nfs_writeargs *args) | 647 | const struct nfs_writeargs *args) |
648 | { | 648 | { |
649 | u32 offset = args->offset; | 649 | u32 offset = args->offset; |
650 | u32 count = args->count; | 650 | u32 count = args->count; |
651 | __be32 *p; | 651 | __be32 *p; |
652 | 652 | ||
653 | encode_fhandle(xdr, args->fh); | 653 | encode_fhandle(xdr, args->fh); |
654 | 654 | ||
655 | p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4); | 655 | p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4); |
656 | *p++ = cpu_to_be32(offset); | 656 | *p++ = cpu_to_be32(offset); |
657 | *p++ = cpu_to_be32(offset); | 657 | *p++ = cpu_to_be32(offset); |
658 | *p++ = cpu_to_be32(count); | 658 | *p++ = cpu_to_be32(count); |
659 | 659 | ||
660 | /* nfsdata */ | 660 | /* nfsdata */ |
661 | *p = cpu_to_be32(count); | 661 | *p = cpu_to_be32(count); |
662 | xdr_write_pages(xdr, args->pages, args->pgbase, count); | 662 | xdr_write_pages(xdr, args->pages, args->pgbase, count); |
663 | } | 663 | } |
664 | 664 | ||
665 | static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req, | 665 | static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req, |
666 | struct xdr_stream *xdr, | 666 | struct xdr_stream *xdr, |
667 | const struct nfs_writeargs *args) | 667 | const struct nfs_writeargs *args) |
668 | { | 668 | { |
669 | encode_writeargs(xdr, args); | 669 | encode_writeargs(xdr, args); |
670 | xdr->buf->flags |= XDRBUF_WRITE; | 670 | xdr->buf->flags |= XDRBUF_WRITE; |
671 | } | 671 | } |
672 | 672 | ||
673 | /* | 673 | /* |
674 | * 2.2.10. createargs | 674 | * 2.2.10. createargs |
675 | * | 675 | * |
676 | * struct createargs { | 676 | * struct createargs { |
677 | * diropargs where; | 677 | * diropargs where; |
678 | * sattr attributes; | 678 | * sattr attributes; |
679 | * }; | 679 | * }; |
680 | */ | 680 | */ |
681 | static void nfs2_xdr_enc_createargs(struct rpc_rqst *req, | 681 | static void nfs2_xdr_enc_createargs(struct rpc_rqst *req, |
682 | struct xdr_stream *xdr, | 682 | struct xdr_stream *xdr, |
683 | const struct nfs_createargs *args) | 683 | const struct nfs_createargs *args) |
684 | { | 684 | { |
685 | encode_diropargs(xdr, args->fh, args->name, args->len); | 685 | encode_diropargs(xdr, args->fh, args->name, args->len); |
686 | encode_sattr(xdr, args->sattr); | 686 | encode_sattr(xdr, args->sattr); |
687 | } | 687 | } |
688 | 688 | ||
689 | static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req, | 689 | static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req, |
690 | struct xdr_stream *xdr, | 690 | struct xdr_stream *xdr, |
691 | const struct nfs_removeargs *args) | 691 | const struct nfs_removeargs *args) |
692 | { | 692 | { |
693 | encode_diropargs(xdr, args->fh, args->name.name, args->name.len); | 693 | encode_diropargs(xdr, args->fh, args->name.name, args->name.len); |
694 | } | 694 | } |
695 | 695 | ||
696 | /* | 696 | /* |
697 | * 2.2.12. renameargs | 697 | * 2.2.12. renameargs |
698 | * | 698 | * |
699 | * struct renameargs { | 699 | * struct renameargs { |
700 | * diropargs from; | 700 | * diropargs from; |
701 | * diropargs to; | 701 | * diropargs to; |
702 | * }; | 702 | * }; |
703 | */ | 703 | */ |
704 | static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req, | 704 | static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req, |
705 | struct xdr_stream *xdr, | 705 | struct xdr_stream *xdr, |
706 | const struct nfs_renameargs *args) | 706 | const struct nfs_renameargs *args) |
707 | { | 707 | { |
708 | const struct qstr *old = args->old_name; | 708 | const struct qstr *old = args->old_name; |
709 | const struct qstr *new = args->new_name; | 709 | const struct qstr *new = args->new_name; |
710 | 710 | ||
711 | encode_diropargs(xdr, args->old_dir, old->name, old->len); | 711 | encode_diropargs(xdr, args->old_dir, old->name, old->len); |
712 | encode_diropargs(xdr, args->new_dir, new->name, new->len); | 712 | encode_diropargs(xdr, args->new_dir, new->name, new->len); |
713 | } | 713 | } |
714 | 714 | ||
715 | /* | 715 | /* |
716 | * 2.2.13. linkargs | 716 | * 2.2.13. linkargs |
717 | * | 717 | * |
718 | * struct linkargs { | 718 | * struct linkargs { |
719 | * fhandle from; | 719 | * fhandle from; |
720 | * diropargs to; | 720 | * diropargs to; |
721 | * }; | 721 | * }; |
722 | */ | 722 | */ |
723 | static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req, | 723 | static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req, |
724 | struct xdr_stream *xdr, | 724 | struct xdr_stream *xdr, |
725 | const struct nfs_linkargs *args) | 725 | const struct nfs_linkargs *args) |
726 | { | 726 | { |
727 | encode_fhandle(xdr, args->fromfh); | 727 | encode_fhandle(xdr, args->fromfh); |
728 | encode_diropargs(xdr, args->tofh, args->toname, args->tolen); | 728 | encode_diropargs(xdr, args->tofh, args->toname, args->tolen); |
729 | } | 729 | } |
730 | 730 | ||
731 | /* | 731 | /* |
732 | * 2.2.14. symlinkargs | 732 | * 2.2.14. symlinkargs |
733 | * | 733 | * |
734 | * struct symlinkargs { | 734 | * struct symlinkargs { |
735 | * diropargs from; | 735 | * diropargs from; |
736 | * path to; | 736 | * path to; |
737 | * sattr attributes; | 737 | * sattr attributes; |
738 | * }; | 738 | * }; |
739 | */ | 739 | */ |
740 | static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req, | 740 | static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req, |
741 | struct xdr_stream *xdr, | 741 | struct xdr_stream *xdr, |
742 | const struct nfs_symlinkargs *args) | 742 | const struct nfs_symlinkargs *args) |
743 | { | 743 | { |
744 | encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen); | 744 | encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen); |
745 | encode_path(xdr, args->pages, args->pathlen); | 745 | encode_path(xdr, args->pages, args->pathlen); |
746 | encode_sattr(xdr, args->sattr); | 746 | encode_sattr(xdr, args->sattr); |
747 | } | 747 | } |
748 | 748 | ||
749 | /* | 749 | /* |
750 | * 2.2.17. readdirargs | 750 | * 2.2.17. readdirargs |
751 | * | 751 | * |
752 | * struct readdirargs { | 752 | * struct readdirargs { |
753 | * fhandle dir; | 753 | * fhandle dir; |
754 | * nfscookie cookie; | 754 | * nfscookie cookie; |
755 | * unsigned count; | 755 | * unsigned count; |
756 | * }; | 756 | * }; |
757 | */ | 757 | */ |
758 | static void encode_readdirargs(struct xdr_stream *xdr, | 758 | static void encode_readdirargs(struct xdr_stream *xdr, |
759 | const struct nfs_readdirargs *args) | 759 | const struct nfs_readdirargs *args) |
760 | { | 760 | { |
761 | __be32 *p; | 761 | __be32 *p; |
762 | 762 | ||
763 | encode_fhandle(xdr, args->fh); | 763 | encode_fhandle(xdr, args->fh); |
764 | 764 | ||
765 | p = xdr_reserve_space(xdr, 4 + 4); | 765 | p = xdr_reserve_space(xdr, 4 + 4); |
766 | *p++ = cpu_to_be32(args->cookie); | 766 | *p++ = cpu_to_be32(args->cookie); |
767 | *p = cpu_to_be32(args->count); | 767 | *p = cpu_to_be32(args->count); |
768 | } | 768 | } |
769 | 769 | ||
770 | static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req, | 770 | static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req, |
771 | struct xdr_stream *xdr, | 771 | struct xdr_stream *xdr, |
772 | const struct nfs_readdirargs *args) | 772 | const struct nfs_readdirargs *args) |
773 | { | 773 | { |
774 | encode_readdirargs(xdr, args); | 774 | encode_readdirargs(xdr, args); |
775 | prepare_reply_buffer(req, args->pages, 0, | 775 | prepare_reply_buffer(req, args->pages, 0, |
776 | args->count, NFS_readdirres_sz); | 776 | args->count, NFS_readdirres_sz); |
777 | } | 777 | } |
778 | 778 | ||
779 | /* | 779 | /* |
780 | * NFSv2 XDR decode functions | 780 | * NFSv2 XDR decode functions |
781 | * | 781 | * |
782 | * NFSv2 result types are defined in section 2.2 of RFC 1094: | 782 | * NFSv2 result types are defined in section 2.2 of RFC 1094: |
783 | * "NFS: Network File System Protocol Specification". | 783 | * "NFS: Network File System Protocol Specification". |
784 | */ | 784 | */ |
785 | 785 | ||
786 | static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr, | 786 | static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr, |
787 | void *__unused) | 787 | void *__unused) |
788 | { | 788 | { |
789 | enum nfs_stat status; | 789 | enum nfs_stat status; |
790 | int error; | 790 | int error; |
791 | 791 | ||
792 | error = decode_stat(xdr, &status); | 792 | error = decode_stat(xdr, &status); |
793 | if (unlikely(error)) | 793 | if (unlikely(error)) |
794 | goto out; | 794 | goto out; |
795 | if (status != NFS_OK) | 795 | if (status != NFS_OK) |
796 | goto out_default; | 796 | goto out_default; |
797 | out: | 797 | out: |
798 | return error; | 798 | return error; |
799 | out_default: | 799 | out_default: |
800 | return nfs_stat_to_errno(status); | 800 | return nfs_stat_to_errno(status); |
801 | } | 801 | } |
802 | 802 | ||
803 | static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr, | 803 | static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr, |
804 | struct nfs_fattr *result) | 804 | struct nfs_fattr *result) |
805 | { | 805 | { |
806 | return decode_attrstat(xdr, result); | 806 | return decode_attrstat(xdr, result); |
807 | } | 807 | } |
808 | 808 | ||
809 | static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr, | 809 | static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr, |
810 | struct nfs_diropok *result) | 810 | struct nfs_diropok *result) |
811 | { | 811 | { |
812 | return decode_diropres(xdr, result); | 812 | return decode_diropres(xdr, result); |
813 | } | 813 | } |
814 | 814 | ||
815 | /* | 815 | /* |
816 | * 2.2.6. readlinkres | 816 | * 2.2.6. readlinkres |
817 | * | 817 | * |
818 | * union readlinkres switch (stat status) { | 818 | * union readlinkres switch (stat status) { |
819 | * case NFS_OK: | 819 | * case NFS_OK: |
820 | * path data; | 820 | * path data; |
821 | * default: | 821 | * default: |
822 | * void; | 822 | * void; |
823 | * }; | 823 | * }; |
824 | */ | 824 | */ |
825 | static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req, | 825 | static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req, |
826 | struct xdr_stream *xdr, void *__unused) | 826 | struct xdr_stream *xdr, void *__unused) |
827 | { | 827 | { |
828 | enum nfs_stat status; | 828 | enum nfs_stat status; |
829 | int error; | 829 | int error; |
830 | 830 | ||
831 | error = decode_stat(xdr, &status); | 831 | error = decode_stat(xdr, &status); |
832 | if (unlikely(error)) | 832 | if (unlikely(error)) |
833 | goto out; | 833 | goto out; |
834 | if (status != NFS_OK) | 834 | if (status != NFS_OK) |
835 | goto out_default; | 835 | goto out_default; |
836 | error = decode_path(xdr); | 836 | error = decode_path(xdr); |
837 | out: | 837 | out: |
838 | return error; | 838 | return error; |
839 | out_default: | 839 | out_default: |
840 | return nfs_stat_to_errno(status); | 840 | return nfs_stat_to_errno(status); |
841 | } | 841 | } |
842 | 842 | ||
843 | /* | 843 | /* |
844 | * 2.2.7. readres | 844 | * 2.2.7. readres |
845 | * | 845 | * |
846 | * union readres switch (stat status) { | 846 | * union readres switch (stat status) { |
847 | * case NFS_OK: | 847 | * case NFS_OK: |
848 | * fattr attributes; | 848 | * fattr attributes; |
849 | * nfsdata data; | 849 | * nfsdata data; |
850 | * default: | 850 | * default: |
851 | * void; | 851 | * void; |
852 | * }; | 852 | * }; |
853 | */ | 853 | */ |
854 | static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr, | 854 | static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr, |
855 | struct nfs_readres *result) | 855 | struct nfs_readres *result) |
856 | { | 856 | { |
857 | enum nfs_stat status; | 857 | enum nfs_stat status; |
858 | int error; | 858 | int error; |
859 | 859 | ||
860 | error = decode_stat(xdr, &status); | 860 | error = decode_stat(xdr, &status); |
861 | if (unlikely(error)) | 861 | if (unlikely(error)) |
862 | goto out; | 862 | goto out; |
863 | if (status != NFS_OK) | 863 | if (status != NFS_OK) |
864 | goto out_default; | 864 | goto out_default; |
865 | error = decode_fattr(xdr, result->fattr); | 865 | error = decode_fattr(xdr, result->fattr); |
866 | if (unlikely(error)) | 866 | if (unlikely(error)) |
867 | goto out; | 867 | goto out; |
868 | error = decode_nfsdata(xdr, result); | 868 | error = decode_nfsdata(xdr, result); |
869 | out: | 869 | out: |
870 | return error; | 870 | return error; |
871 | out_default: | 871 | out_default: |
872 | return nfs_stat_to_errno(status); | 872 | return nfs_stat_to_errno(status); |
873 | } | 873 | } |
874 | 874 | ||
875 | static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr, | 875 | static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr, |
876 | struct nfs_writeres *result) | 876 | struct nfs_writeres *result) |
877 | { | 877 | { |
878 | /* All NFSv2 writes are "file sync" writes */ | 878 | /* All NFSv2 writes are "file sync" writes */ |
879 | result->verf->committed = NFS_FILE_SYNC; | 879 | result->verf->committed = NFS_FILE_SYNC; |
880 | return decode_attrstat(xdr, result->fattr); | 880 | return decode_attrstat(xdr, result->fattr); |
881 | } | 881 | } |
882 | 882 | ||
883 | /** | 883 | /** |
884 | * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in | 884 | * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in |
885 | * the local page cache. | 885 | * the local page cache. |
886 | * @xdr: XDR stream where entry resides | 886 | * @xdr: XDR stream where entry resides |
887 | * @entry: buffer to fill in with entry data | 887 | * @entry: buffer to fill in with entry data |
888 | * @plus: boolean indicating whether this should be a readdirplus entry | 888 | * @plus: boolean indicating whether this should be a readdirplus entry |
889 | * | 889 | * |
890 | * Returns zero if successful, otherwise a negative errno value is | 890 | * Returns zero if successful, otherwise a negative errno value is |
891 | * returned. | 891 | * returned. |
892 | * | 892 | * |
893 | * This function is not invoked during READDIR reply decoding, but | 893 | * This function is not invoked during READDIR reply decoding, but |
894 | * rather whenever an application invokes the getdents(2) system call | 894 | * rather whenever an application invokes the getdents(2) system call |
895 | * on a directory already in our cache. | 895 | * on a directory already in our cache. |
896 | * | 896 | * |
897 | * 2.2.17. entry | 897 | * 2.2.17. entry |
898 | * | 898 | * |
899 | * struct entry { | 899 | * struct entry { |
900 | * unsigned fileid; | 900 | * unsigned fileid; |
901 | * filename name; | 901 | * filename name; |
902 | * nfscookie cookie; | 902 | * nfscookie cookie; |
903 | * entry *nextentry; | 903 | * entry *nextentry; |
904 | * }; | 904 | * }; |
905 | */ | 905 | */ |
906 | int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 906 | int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
907 | int plus) | 907 | int plus) |
908 | { | 908 | { |
909 | __be32 *p; | 909 | __be32 *p; |
910 | int error; | 910 | int error; |
911 | 911 | ||
912 | p = xdr_inline_decode(xdr, 4); | 912 | p = xdr_inline_decode(xdr, 4); |
913 | if (unlikely(p == NULL)) | 913 | if (unlikely(p == NULL)) |
914 | goto out_overflow; | 914 | goto out_overflow; |
915 | if (*p++ == xdr_zero) { | 915 | if (*p++ == xdr_zero) { |
916 | p = xdr_inline_decode(xdr, 4); | 916 | p = xdr_inline_decode(xdr, 4); |
917 | if (unlikely(p == NULL)) | 917 | if (unlikely(p == NULL)) |
918 | goto out_overflow; | 918 | goto out_overflow; |
919 | if (*p++ == xdr_zero) | 919 | if (*p++ == xdr_zero) |
920 | return -EAGAIN; | 920 | return -EAGAIN; |
921 | entry->eof = 1; | 921 | entry->eof = 1; |
922 | return -EBADCOOKIE; | 922 | return -EBADCOOKIE; |
923 | } | 923 | } |
924 | 924 | ||
925 | p = xdr_inline_decode(xdr, 4); | 925 | p = xdr_inline_decode(xdr, 4); |
926 | if (unlikely(p == NULL)) | 926 | if (unlikely(p == NULL)) |
927 | goto out_overflow; | 927 | goto out_overflow; |
928 | entry->ino = be32_to_cpup(p); | 928 | entry->ino = be32_to_cpup(p); |
929 | 929 | ||
930 | error = decode_filename_inline(xdr, &entry->name, &entry->len); | 930 | error = decode_filename_inline(xdr, &entry->name, &entry->len); |
931 | if (unlikely(error)) | 931 | if (unlikely(error)) |
932 | return error; | 932 | return error; |
933 | 933 | ||
934 | /* | 934 | /* |
935 | * The type (size and byte order) of nfscookie isn't defined in | 935 | * The type (size and byte order) of nfscookie isn't defined in |
936 | * RFC 1094. This implementation assumes that it's an XDR uint32. | 936 | * RFC 1094. This implementation assumes that it's an XDR uint32. |
937 | */ | 937 | */ |
938 | entry->prev_cookie = entry->cookie; | 938 | entry->prev_cookie = entry->cookie; |
939 | p = xdr_inline_decode(xdr, 4); | 939 | p = xdr_inline_decode(xdr, 4); |
940 | if (unlikely(p == NULL)) | 940 | if (unlikely(p == NULL)) |
941 | goto out_overflow; | 941 | goto out_overflow; |
942 | entry->cookie = be32_to_cpup(p); | 942 | entry->cookie = be32_to_cpup(p); |
943 | 943 | ||
944 | entry->d_type = DT_UNKNOWN; | 944 | entry->d_type = DT_UNKNOWN; |
945 | 945 | ||
946 | return 0; | 946 | return 0; |
947 | 947 | ||
948 | out_overflow: | 948 | out_overflow: |
949 | print_overflow_msg(__func__, xdr); | 949 | print_overflow_msg(__func__, xdr); |
950 | return -EAGAIN; | 950 | return -EAGAIN; |
951 | } | 951 | } |
952 | 952 | ||
953 | /* | 953 | /* |
954 | * 2.2.17. readdirres | 954 | * 2.2.17. readdirres |
955 | * | 955 | * |
956 | * union readdirres switch (stat status) { | 956 | * union readdirres switch (stat status) { |
957 | * case NFS_OK: | 957 | * case NFS_OK: |
958 | * struct { | 958 | * struct { |
959 | * entry *entries; | 959 | * entry *entries; |
960 | * bool eof; | 960 | * bool eof; |
961 | * } readdirok; | 961 | * } readdirok; |
962 | * default: | 962 | * default: |
963 | * void; | 963 | * void; |
964 | * }; | 964 | * }; |
965 | * | 965 | * |
966 | * Read the directory contents into the page cache, but don't | 966 | * Read the directory contents into the page cache, but don't |
967 | * touch them. The actual decoding is done by nfs2_decode_dirent() | 967 | * touch them. The actual decoding is done by nfs2_decode_dirent() |
968 | * during subsequent nfs_readdir() calls. | 968 | * during subsequent nfs_readdir() calls. |
969 | */ | 969 | */ |
970 | static int decode_readdirok(struct xdr_stream *xdr) | 970 | static int decode_readdirok(struct xdr_stream *xdr) |
971 | { | 971 | { |
972 | u32 recvd, pglen; | 972 | u32 recvd, pglen; |
973 | size_t hdrlen; | 973 | size_t hdrlen; |
974 | 974 | ||
975 | pglen = xdr->buf->page_len; | 975 | pglen = xdr->buf->page_len; |
976 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 976 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; |
977 | recvd = xdr->buf->len - hdrlen; | 977 | recvd = xdr->buf->len - hdrlen; |
978 | if (unlikely(pglen > recvd)) | 978 | if (unlikely(pglen > recvd)) |
979 | goto out_cheating; | 979 | goto out_cheating; |
980 | out: | 980 | out: |
981 | xdr_read_pages(xdr, pglen); | 981 | xdr_read_pages(xdr, pglen); |
982 | return pglen; | 982 | return pglen; |
983 | out_cheating: | 983 | out_cheating: |
984 | dprintk("NFS: server cheating in readdir result: " | 984 | dprintk("NFS: server cheating in readdir result: " |
985 | "pglen %u > recvd %u\n", pglen, recvd); | 985 | "pglen %u > recvd %u\n", pglen, recvd); |
986 | pglen = recvd; | 986 | pglen = recvd; |
987 | goto out; | 987 | goto out; |
988 | } | 988 | } |
989 | 989 | ||
990 | static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, | 990 | static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, |
991 | struct xdr_stream *xdr, void *__unused) | 991 | struct xdr_stream *xdr, void *__unused) |
992 | { | 992 | { |
993 | enum nfs_stat status; | 993 | enum nfs_stat status; |
994 | int error; | 994 | int error; |
995 | 995 | ||
996 | error = decode_stat(xdr, &status); | 996 | error = decode_stat(xdr, &status); |
997 | if (unlikely(error)) | 997 | if (unlikely(error)) |
998 | goto out; | 998 | goto out; |
999 | if (status != NFS_OK) | 999 | if (status != NFS_OK) |
1000 | goto out_default; | 1000 | goto out_default; |
1001 | error = decode_readdirok(xdr); | 1001 | error = decode_readdirok(xdr); |
1002 | out: | 1002 | out: |
1003 | return error; | 1003 | return error; |
1004 | out_default: | 1004 | out_default: |
1005 | return nfs_stat_to_errno(status); | 1005 | return nfs_stat_to_errno(status); |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | /* | 1008 | /* |
1009 | * 2.2.18. statfsres | 1009 | * 2.2.18. statfsres |
1010 | * | 1010 | * |
1011 | * union statfsres (stat status) { | 1011 | * union statfsres (stat status) { |
1012 | * case NFS_OK: | 1012 | * case NFS_OK: |
1013 | * struct { | 1013 | * struct { |
1014 | * unsigned tsize; | 1014 | * unsigned tsize; |
1015 | * unsigned bsize; | 1015 | * unsigned bsize; |
1016 | * unsigned blocks; | 1016 | * unsigned blocks; |
1017 | * unsigned bfree; | 1017 | * unsigned bfree; |
1018 | * unsigned bavail; | 1018 | * unsigned bavail; |
1019 | * } info; | 1019 | * } info; |
1020 | * default: | 1020 | * default: |
1021 | * void; | 1021 | * void; |
1022 | * }; | 1022 | * }; |
1023 | */ | 1023 | */ |
1024 | static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result) | 1024 | static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result) |
1025 | { | 1025 | { |
1026 | __be32 *p; | 1026 | __be32 *p; |
1027 | 1027 | ||
1028 | p = xdr_inline_decode(xdr, NFS_info_sz << 2); | 1028 | p = xdr_inline_decode(xdr, NFS_info_sz << 2); |
1029 | if (unlikely(p == NULL)) | 1029 | if (unlikely(p == NULL)) |
1030 | goto out_overflow; | 1030 | goto out_overflow; |
1031 | result->tsize = be32_to_cpup(p++); | 1031 | result->tsize = be32_to_cpup(p++); |
1032 | result->bsize = be32_to_cpup(p++); | 1032 | result->bsize = be32_to_cpup(p++); |
1033 | result->blocks = be32_to_cpup(p++); | 1033 | result->blocks = be32_to_cpup(p++); |
1034 | result->bfree = be32_to_cpup(p++); | 1034 | result->bfree = be32_to_cpup(p++); |
1035 | result->bavail = be32_to_cpup(p); | 1035 | result->bavail = be32_to_cpup(p); |
1036 | return 0; | 1036 | return 0; |
1037 | out_overflow: | 1037 | out_overflow: |
1038 | print_overflow_msg(__func__, xdr); | 1038 | print_overflow_msg(__func__, xdr); |
1039 | return -EIO; | 1039 | return -EIO; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr, | 1042 | static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr, |
1043 | struct nfs2_fsstat *result) | 1043 | struct nfs2_fsstat *result) |
1044 | { | 1044 | { |
1045 | enum nfs_stat status; | 1045 | enum nfs_stat status; |
1046 | int error; | 1046 | int error; |
1047 | 1047 | ||
1048 | error = decode_stat(xdr, &status); | 1048 | error = decode_stat(xdr, &status); |
1049 | if (unlikely(error)) | 1049 | if (unlikely(error)) |
1050 | goto out; | 1050 | goto out; |
1051 | if (status != NFS_OK) | 1051 | if (status != NFS_OK) |
1052 | goto out_default; | 1052 | goto out_default; |
1053 | error = decode_info(xdr, result); | 1053 | error = decode_info(xdr, result); |
1054 | out: | 1054 | out: |
1055 | return error; | 1055 | return error; |
1056 | out_default: | 1056 | out_default: |
1057 | return nfs_stat_to_errno(status); | 1057 | return nfs_stat_to_errno(status); |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | 1060 | ||
1061 | /* | 1061 | /* |
1062 | * We need to translate between nfs status return values and | 1062 | * We need to translate between nfs status return values and |
1063 | * the local errno values which may not be the same. | 1063 | * the local errno values which may not be the same. |
1064 | */ | 1064 | */ |
1065 | static const struct { | 1065 | static const struct { |
1066 | int stat; | 1066 | int stat; |
1067 | int errno; | 1067 | int errno; |
1068 | } nfs_errtbl[] = { | 1068 | } nfs_errtbl[] = { |
1069 | { NFS_OK, 0 }, | 1069 | { NFS_OK, 0 }, |
1070 | { NFSERR_PERM, -EPERM }, | 1070 | { NFSERR_PERM, -EPERM }, |
1071 | { NFSERR_NOENT, -ENOENT }, | 1071 | { NFSERR_NOENT, -ENOENT }, |
1072 | { NFSERR_IO, -errno_NFSERR_IO}, | 1072 | { NFSERR_IO, -errno_NFSERR_IO}, |
1073 | { NFSERR_NXIO, -ENXIO }, | 1073 | { NFSERR_NXIO, -ENXIO }, |
1074 | /* { NFSERR_EAGAIN, -EAGAIN }, */ | 1074 | /* { NFSERR_EAGAIN, -EAGAIN }, */ |
1075 | { NFSERR_ACCES, -EACCES }, | 1075 | { NFSERR_ACCES, -EACCES }, |
1076 | { NFSERR_EXIST, -EEXIST }, | 1076 | { NFSERR_EXIST, -EEXIST }, |
1077 | { NFSERR_XDEV, -EXDEV }, | 1077 | { NFSERR_XDEV, -EXDEV }, |
1078 | { NFSERR_NODEV, -ENODEV }, | 1078 | { NFSERR_NODEV, -ENODEV }, |
1079 | { NFSERR_NOTDIR, -ENOTDIR }, | 1079 | { NFSERR_NOTDIR, -ENOTDIR }, |
1080 | { NFSERR_ISDIR, -EISDIR }, | 1080 | { NFSERR_ISDIR, -EISDIR }, |
1081 | { NFSERR_INVAL, -EINVAL }, | 1081 | { NFSERR_INVAL, -EINVAL }, |
1082 | { NFSERR_FBIG, -EFBIG }, | 1082 | { NFSERR_FBIG, -EFBIG }, |
1083 | { NFSERR_NOSPC, -ENOSPC }, | 1083 | { NFSERR_NOSPC, -ENOSPC }, |
1084 | { NFSERR_ROFS, -EROFS }, | 1084 | { NFSERR_ROFS, -EROFS }, |
1085 | { NFSERR_MLINK, -EMLINK }, | 1085 | { NFSERR_MLINK, -EMLINK }, |
1086 | { NFSERR_NAMETOOLONG, -ENAMETOOLONG }, | 1086 | { NFSERR_NAMETOOLONG, -ENAMETOOLONG }, |
1087 | { NFSERR_NOTEMPTY, -ENOTEMPTY }, | 1087 | { NFSERR_NOTEMPTY, -ENOTEMPTY }, |
1088 | { NFSERR_DQUOT, -EDQUOT }, | 1088 | { NFSERR_DQUOT, -EDQUOT }, |
1089 | { NFSERR_STALE, -ESTALE }, | 1089 | { NFSERR_STALE, -ESTALE }, |
1090 | { NFSERR_REMOTE, -EREMOTE }, | 1090 | { NFSERR_REMOTE, -EREMOTE }, |
1091 | #ifdef EWFLUSH | 1091 | #ifdef EWFLUSH |
1092 | { NFSERR_WFLUSH, -EWFLUSH }, | 1092 | { NFSERR_WFLUSH, -EWFLUSH }, |
1093 | #endif | 1093 | #endif |
1094 | { NFSERR_BADHANDLE, -EBADHANDLE }, | 1094 | { NFSERR_BADHANDLE, -EBADHANDLE }, |
1095 | { NFSERR_NOT_SYNC, -ENOTSYNC }, | 1095 | { NFSERR_NOT_SYNC, -ENOTSYNC }, |
1096 | { NFSERR_BAD_COOKIE, -EBADCOOKIE }, | 1096 | { NFSERR_BAD_COOKIE, -EBADCOOKIE }, |
1097 | { NFSERR_NOTSUPP, -ENOTSUPP }, | 1097 | { NFSERR_NOTSUPP, -ENOTSUPP }, |
1098 | { NFSERR_TOOSMALL, -ETOOSMALL }, | 1098 | { NFSERR_TOOSMALL, -ETOOSMALL }, |
1099 | { NFSERR_SERVERFAULT, -EREMOTEIO }, | 1099 | { NFSERR_SERVERFAULT, -EREMOTEIO }, |
1100 | { NFSERR_BADTYPE, -EBADTYPE }, | 1100 | { NFSERR_BADTYPE, -EBADTYPE }, |
1101 | { NFSERR_JUKEBOX, -EJUKEBOX }, | 1101 | { NFSERR_JUKEBOX, -EJUKEBOX }, |
1102 | { -1, -EIO } | 1102 | { -1, -EIO } |
1103 | }; | 1103 | }; |
1104 | 1104 | ||
1105 | /** | 1105 | /** |
1106 | * nfs_stat_to_errno - convert an NFS status code to a local errno | 1106 | * nfs_stat_to_errno - convert an NFS status code to a local errno |
1107 | * @status: NFS status code to convert | 1107 | * @status: NFS status code to convert |
1108 | * | 1108 | * |
1109 | * Returns a local errno value, or -EIO if the NFS status code is | 1109 | * Returns a local errno value, or -EIO if the NFS status code is |
1110 | * not recognized. This function is used jointly by NFSv2 and NFSv3. | 1110 | * not recognized. This function is used jointly by NFSv2 and NFSv3. |
1111 | */ | 1111 | */ |
1112 | int nfs_stat_to_errno(enum nfs_stat status) | 1112 | int nfs_stat_to_errno(enum nfs_stat status) |
1113 | { | 1113 | { |
1114 | int i; | 1114 | int i; |
1115 | 1115 | ||
1116 | for (i = 0; nfs_errtbl[i].stat != -1; i++) { | 1116 | for (i = 0; nfs_errtbl[i].stat != -1; i++) { |
1117 | if (nfs_errtbl[i].stat == (int)status) | 1117 | if (nfs_errtbl[i].stat == (int)status) |
1118 | return nfs_errtbl[i].errno; | 1118 | return nfs_errtbl[i].errno; |
1119 | } | 1119 | } |
1120 | dprintk("NFS: Unrecognized nfs status value: %u\n", status); | 1120 | dprintk("NFS: Unrecognized nfs status value: %u\n", status); |
1121 | return nfs_errtbl[i].errno; | 1121 | return nfs_errtbl[i].errno; |
1122 | } | 1122 | } |
1123 | 1123 | ||
1124 | #define PROC(proc, argtype, restype, timer) \ | 1124 | #define PROC(proc, argtype, restype, timer) \ |
1125 | [NFSPROC_##proc] = { \ | 1125 | [NFSPROC_##proc] = { \ |
1126 | .p_proc = NFSPROC_##proc, \ | 1126 | .p_proc = NFSPROC_##proc, \ |
1127 | .p_encode = (kxdreproc_t)nfs2_xdr_enc_##argtype, \ | 1127 | .p_encode = (kxdreproc_t)nfs2_xdr_enc_##argtype, \ |
1128 | .p_decode = (kxdrdproc_t)nfs2_xdr_dec_##restype, \ | 1128 | .p_decode = (kxdrdproc_t)nfs2_xdr_dec_##restype, \ |
1129 | .p_arglen = NFS_##argtype##_sz, \ | 1129 | .p_arglen = NFS_##argtype##_sz, \ |
1130 | .p_replen = NFS_##restype##_sz, \ | 1130 | .p_replen = NFS_##restype##_sz, \ |
1131 | .p_timer = timer, \ | 1131 | .p_timer = timer, \ |
1132 | .p_statidx = NFSPROC_##proc, \ | 1132 | .p_statidx = NFSPROC_##proc, \ |
1133 | .p_name = #proc, \ | 1133 | .p_name = #proc, \ |
1134 | } | 1134 | } |
1135 | struct rpc_procinfo nfs_procedures[] = { | 1135 | struct rpc_procinfo nfs_procedures[] = { |
1136 | PROC(GETATTR, fhandle, attrstat, 1), | 1136 | PROC(GETATTR, fhandle, attrstat, 1), |
1137 | PROC(SETATTR, sattrargs, attrstat, 0), | 1137 | PROC(SETATTR, sattrargs, attrstat, 0), |
1138 | PROC(LOOKUP, diropargs, diropres, 2), | 1138 | PROC(LOOKUP, diropargs, diropres, 2), |
1139 | PROC(READLINK, readlinkargs, readlinkres, 3), | 1139 | PROC(READLINK, readlinkargs, readlinkres, 3), |
1140 | PROC(READ, readargs, readres, 3), | 1140 | PROC(READ, readargs, readres, 3), |
1141 | PROC(WRITE, writeargs, writeres, 4), | 1141 | PROC(WRITE, writeargs, writeres, 4), |
1142 | PROC(CREATE, createargs, diropres, 0), | 1142 | PROC(CREATE, createargs, diropres, 0), |
1143 | PROC(REMOVE, removeargs, stat, 0), | 1143 | PROC(REMOVE, removeargs, stat, 0), |
1144 | PROC(RENAME, renameargs, stat, 0), | 1144 | PROC(RENAME, renameargs, stat, 0), |
1145 | PROC(LINK, linkargs, stat, 0), | 1145 | PROC(LINK, linkargs, stat, 0), |
1146 | PROC(SYMLINK, symlinkargs, stat, 0), | 1146 | PROC(SYMLINK, symlinkargs, stat, 0), |
1147 | PROC(MKDIR, createargs, diropres, 0), | 1147 | PROC(MKDIR, createargs, diropres, 0), |
1148 | PROC(RMDIR, diropargs, stat, 0), | 1148 | PROC(RMDIR, diropargs, stat, 0), |
1149 | PROC(READDIR, readdirargs, readdirres, 3), | 1149 | PROC(READDIR, readdirargs, readdirres, 3), |
1150 | PROC(STATFS, fhandle, statfsres, 0), | 1150 | PROC(STATFS, fhandle, statfsres, 0), |
1151 | }; | 1151 | }; |
1152 | 1152 | ||
1153 | struct rpc_version nfs_version2 = { | 1153 | const struct rpc_version nfs_version2 = { |
1154 | .number = 2, | 1154 | .number = 2, |
1155 | .nrprocs = ARRAY_SIZE(nfs_procedures), | 1155 | .nrprocs = ARRAY_SIZE(nfs_procedures), |
1156 | .procs = nfs_procedures | 1156 | .procs = nfs_procedures |
1157 | }; | 1157 | }; |
1158 | 1158 |
fs/nfs/nfs3xdr.c
1 | /* | 1 | /* |
2 | * linux/fs/nfs/nfs3xdr.c | 2 | * linux/fs/nfs/nfs3xdr.c |
3 | * | 3 | * |
4 | * XDR functions to encode/decode NFSv3 RPC arguments and results. | 4 | * XDR functions to encode/decode NFSv3 RPC arguments and results. |
5 | * | 5 | * |
6 | * Copyright (C) 1996, 1997 Olaf Kirch | 6 | * Copyright (C) 1996, 1997 Olaf Kirch |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/param.h> | 9 | #include <linux/param.h> |
10 | #include <linux/time.h> | 10 | #include <linux/time.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/in.h> | 14 | #include <linux/in.h> |
15 | #include <linux/pagemap.h> | 15 | #include <linux/pagemap.h> |
16 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
17 | #include <linux/kdev_t.h> | 17 | #include <linux/kdev_t.h> |
18 | #include <linux/sunrpc/clnt.h> | 18 | #include <linux/sunrpc/clnt.h> |
19 | #include <linux/nfs.h> | 19 | #include <linux/nfs.h> |
20 | #include <linux/nfs3.h> | 20 | #include <linux/nfs3.h> |
21 | #include <linux/nfs_fs.h> | 21 | #include <linux/nfs_fs.h> |
22 | #include <linux/nfsacl.h> | 22 | #include <linux/nfsacl.h> |
23 | #include "internal.h" | 23 | #include "internal.h" |
24 | 24 | ||
25 | #define NFSDBG_FACILITY NFSDBG_XDR | 25 | #define NFSDBG_FACILITY NFSDBG_XDR |
26 | 26 | ||
27 | /* Mapping from NFS error code to "errno" error code. */ | 27 | /* Mapping from NFS error code to "errno" error code. */ |
28 | #define errno_NFSERR_IO EIO | 28 | #define errno_NFSERR_IO EIO |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Declare the space requirements for NFS arguments and replies as | 31 | * Declare the space requirements for NFS arguments and replies as |
32 | * number of 32bit-words | 32 | * number of 32bit-words |
33 | */ | 33 | */ |
34 | #define NFS3_fhandle_sz (1+16) | 34 | #define NFS3_fhandle_sz (1+16) |
35 | #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */ | 35 | #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */ |
36 | #define NFS3_sattr_sz (15) | 36 | #define NFS3_sattr_sz (15) |
37 | #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) | 37 | #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) |
38 | #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) | 38 | #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) |
39 | #define NFS3_fattr_sz (21) | 39 | #define NFS3_fattr_sz (21) |
40 | #define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2) | 40 | #define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2) |
41 | #define NFS3_wcc_attr_sz (6) | 41 | #define NFS3_wcc_attr_sz (6) |
42 | #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz) | 42 | #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz) |
43 | #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz) | 43 | #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz) |
44 | #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz) | 44 | #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz) |
45 | #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz) | 45 | #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz) |
46 | 46 | ||
47 | #define NFS3_getattrargs_sz (NFS3_fh_sz) | 47 | #define NFS3_getattrargs_sz (NFS3_fh_sz) |
48 | #define NFS3_setattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3) | 48 | #define NFS3_setattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3) |
49 | #define NFS3_lookupargs_sz (NFS3_fh_sz+NFS3_filename_sz) | 49 | #define NFS3_lookupargs_sz (NFS3_fh_sz+NFS3_filename_sz) |
50 | #define NFS3_accessargs_sz (NFS3_fh_sz+1) | 50 | #define NFS3_accessargs_sz (NFS3_fh_sz+1) |
51 | #define NFS3_readlinkargs_sz (NFS3_fh_sz) | 51 | #define NFS3_readlinkargs_sz (NFS3_fh_sz) |
52 | #define NFS3_readargs_sz (NFS3_fh_sz+3) | 52 | #define NFS3_readargs_sz (NFS3_fh_sz+3) |
53 | #define NFS3_writeargs_sz (NFS3_fh_sz+5) | 53 | #define NFS3_writeargs_sz (NFS3_fh_sz+5) |
54 | #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) | 54 | #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) |
55 | #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) | 55 | #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) |
56 | #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz) | 56 | #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz) |
57 | #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) | 57 | #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) |
58 | #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz) | 58 | #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz) |
59 | #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) | 59 | #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) |
60 | #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) | 60 | #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) |
61 | #define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3) | 61 | #define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3) |
62 | #define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4) | 62 | #define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4) |
63 | #define NFS3_commitargs_sz (NFS3_fh_sz+3) | 63 | #define NFS3_commitargs_sz (NFS3_fh_sz+3) |
64 | 64 | ||
65 | #define NFS3_getattrres_sz (1+NFS3_fattr_sz) | 65 | #define NFS3_getattrres_sz (1+NFS3_fattr_sz) |
66 | #define NFS3_setattrres_sz (1+NFS3_wcc_data_sz) | 66 | #define NFS3_setattrres_sz (1+NFS3_wcc_data_sz) |
67 | #define NFS3_removeres_sz (NFS3_setattrres_sz) | 67 | #define NFS3_removeres_sz (NFS3_setattrres_sz) |
68 | #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) | 68 | #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) |
69 | #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) | 69 | #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) |
70 | #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) | 70 | #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) |
71 | #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3) | 71 | #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3) |
72 | #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) | 72 | #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) |
73 | #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) | 73 | #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) |
74 | #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) | 74 | #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) |
75 | #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) | 75 | #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) |
76 | #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2) | 76 | #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2) |
77 | #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13) | 77 | #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13) |
78 | #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12) | 78 | #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12) |
79 | #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) | 79 | #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) |
80 | #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) | 80 | #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) |
81 | 81 | ||
82 | #define ACL3_getaclargs_sz (NFS3_fh_sz+1) | 82 | #define ACL3_getaclargs_sz (NFS3_fh_sz+1) |
83 | #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \ | 83 | #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \ |
84 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) | 84 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) |
85 | #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \ | 85 | #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \ |
86 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) | 86 | XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) |
87 | #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) | 87 | #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * Map file type to S_IFMT bits | 90 | * Map file type to S_IFMT bits |
91 | */ | 91 | */ |
92 | static const umode_t nfs_type2fmt[] = { | 92 | static const umode_t nfs_type2fmt[] = { |
93 | [NF3BAD] = 0, | 93 | [NF3BAD] = 0, |
94 | [NF3REG] = S_IFREG, | 94 | [NF3REG] = S_IFREG, |
95 | [NF3DIR] = S_IFDIR, | 95 | [NF3DIR] = S_IFDIR, |
96 | [NF3BLK] = S_IFBLK, | 96 | [NF3BLK] = S_IFBLK, |
97 | [NF3CHR] = S_IFCHR, | 97 | [NF3CHR] = S_IFCHR, |
98 | [NF3LNK] = S_IFLNK, | 98 | [NF3LNK] = S_IFLNK, |
99 | [NF3SOCK] = S_IFSOCK, | 99 | [NF3SOCK] = S_IFSOCK, |
100 | [NF3FIFO] = S_IFIFO, | 100 | [NF3FIFO] = S_IFIFO, |
101 | }; | 101 | }; |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * While encoding arguments, set up the reply buffer in advance to | 104 | * While encoding arguments, set up the reply buffer in advance to |
105 | * receive reply data directly into the page cache. | 105 | * receive reply data directly into the page cache. |
106 | */ | 106 | */ |
107 | static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages, | 107 | static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages, |
108 | unsigned int base, unsigned int len, | 108 | unsigned int base, unsigned int len, |
109 | unsigned int bufsize) | 109 | unsigned int bufsize) |
110 | { | 110 | { |
111 | struct rpc_auth *auth = req->rq_cred->cr_auth; | 111 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
112 | unsigned int replen; | 112 | unsigned int replen; |
113 | 113 | ||
114 | replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize; | 114 | replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize; |
115 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); | 115 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * Handle decode buffer overflows out-of-line. | 119 | * Handle decode buffer overflows out-of-line. |
120 | */ | 120 | */ |
121 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 121 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
122 | { | 122 | { |
123 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " | 123 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " |
124 | "Remaining buffer length is %tu words.\n", | 124 | "Remaining buffer length is %tu words.\n", |
125 | func, xdr->end - xdr->p); | 125 | func, xdr->end - xdr->p); |
126 | } | 126 | } |
127 | 127 | ||
128 | 128 | ||
129 | /* | 129 | /* |
130 | * Encode/decode NFSv3 basic data types | 130 | * Encode/decode NFSv3 basic data types |
131 | * | 131 | * |
132 | * Basic NFSv3 data types are defined in section 2.5 of RFC 1813: | 132 | * Basic NFSv3 data types are defined in section 2.5 of RFC 1813: |
133 | * "NFS Version 3 Protocol Specification". | 133 | * "NFS Version 3 Protocol Specification". |
134 | * | 134 | * |
135 | * Not all basic data types have their own encoding and decoding | 135 | * Not all basic data types have their own encoding and decoding |
136 | * functions. For run-time efficiency, some data types are encoded | 136 | * functions. For run-time efficiency, some data types are encoded |
137 | * or decoded inline. | 137 | * or decoded inline. |
138 | */ | 138 | */ |
139 | 139 | ||
140 | static void encode_uint32(struct xdr_stream *xdr, u32 value) | 140 | static void encode_uint32(struct xdr_stream *xdr, u32 value) |
141 | { | 141 | { |
142 | __be32 *p = xdr_reserve_space(xdr, 4); | 142 | __be32 *p = xdr_reserve_space(xdr, 4); |
143 | *p = cpu_to_be32(value); | 143 | *p = cpu_to_be32(value); |
144 | } | 144 | } |
145 | 145 | ||
146 | static int decode_uint32(struct xdr_stream *xdr, u32 *value) | 146 | static int decode_uint32(struct xdr_stream *xdr, u32 *value) |
147 | { | 147 | { |
148 | __be32 *p; | 148 | __be32 *p; |
149 | 149 | ||
150 | p = xdr_inline_decode(xdr, 4); | 150 | p = xdr_inline_decode(xdr, 4); |
151 | if (unlikely(p == NULL)) | 151 | if (unlikely(p == NULL)) |
152 | goto out_overflow; | 152 | goto out_overflow; |
153 | *value = be32_to_cpup(p); | 153 | *value = be32_to_cpup(p); |
154 | return 0; | 154 | return 0; |
155 | out_overflow: | 155 | out_overflow: |
156 | print_overflow_msg(__func__, xdr); | 156 | print_overflow_msg(__func__, xdr); |
157 | return -EIO; | 157 | return -EIO; |
158 | } | 158 | } |
159 | 159 | ||
160 | static int decode_uint64(struct xdr_stream *xdr, u64 *value) | 160 | static int decode_uint64(struct xdr_stream *xdr, u64 *value) |
161 | { | 161 | { |
162 | __be32 *p; | 162 | __be32 *p; |
163 | 163 | ||
164 | p = xdr_inline_decode(xdr, 8); | 164 | p = xdr_inline_decode(xdr, 8); |
165 | if (unlikely(p == NULL)) | 165 | if (unlikely(p == NULL)) |
166 | goto out_overflow; | 166 | goto out_overflow; |
167 | xdr_decode_hyper(p, value); | 167 | xdr_decode_hyper(p, value); |
168 | return 0; | 168 | return 0; |
169 | out_overflow: | 169 | out_overflow: |
170 | print_overflow_msg(__func__, xdr); | 170 | print_overflow_msg(__func__, xdr); |
171 | return -EIO; | 171 | return -EIO; |
172 | } | 172 | } |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * fileid3 | 175 | * fileid3 |
176 | * | 176 | * |
177 | * typedef uint64 fileid3; | 177 | * typedef uint64 fileid3; |
178 | */ | 178 | */ |
179 | static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid) | 179 | static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid) |
180 | { | 180 | { |
181 | return xdr_decode_hyper(p, fileid); | 181 | return xdr_decode_hyper(p, fileid); |
182 | } | 182 | } |
183 | 183 | ||
184 | static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid) | 184 | static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid) |
185 | { | 185 | { |
186 | return decode_uint64(xdr, fileid); | 186 | return decode_uint64(xdr, fileid); |
187 | } | 187 | } |
188 | 188 | ||
189 | /* | 189 | /* |
190 | * filename3 | 190 | * filename3 |
191 | * | 191 | * |
192 | * typedef string filename3<>; | 192 | * typedef string filename3<>; |
193 | */ | 193 | */ |
194 | static void encode_filename3(struct xdr_stream *xdr, | 194 | static void encode_filename3(struct xdr_stream *xdr, |
195 | const char *name, u32 length) | 195 | const char *name, u32 length) |
196 | { | 196 | { |
197 | __be32 *p; | 197 | __be32 *p; |
198 | 198 | ||
199 | BUG_ON(length > NFS3_MAXNAMLEN); | 199 | BUG_ON(length > NFS3_MAXNAMLEN); |
200 | p = xdr_reserve_space(xdr, 4 + length); | 200 | p = xdr_reserve_space(xdr, 4 + length); |
201 | xdr_encode_opaque(p, name, length); | 201 | xdr_encode_opaque(p, name, length); |
202 | } | 202 | } |
203 | 203 | ||
204 | static int decode_inline_filename3(struct xdr_stream *xdr, | 204 | static int decode_inline_filename3(struct xdr_stream *xdr, |
205 | const char **name, u32 *length) | 205 | const char **name, u32 *length) |
206 | { | 206 | { |
207 | __be32 *p; | 207 | __be32 *p; |
208 | u32 count; | 208 | u32 count; |
209 | 209 | ||
210 | p = xdr_inline_decode(xdr, 4); | 210 | p = xdr_inline_decode(xdr, 4); |
211 | if (unlikely(p == NULL)) | 211 | if (unlikely(p == NULL)) |
212 | goto out_overflow; | 212 | goto out_overflow; |
213 | count = be32_to_cpup(p); | 213 | count = be32_to_cpup(p); |
214 | if (count > NFS3_MAXNAMLEN) | 214 | if (count > NFS3_MAXNAMLEN) |
215 | goto out_nametoolong; | 215 | goto out_nametoolong; |
216 | p = xdr_inline_decode(xdr, count); | 216 | p = xdr_inline_decode(xdr, count); |
217 | if (unlikely(p == NULL)) | 217 | if (unlikely(p == NULL)) |
218 | goto out_overflow; | 218 | goto out_overflow; |
219 | *name = (const char *)p; | 219 | *name = (const char *)p; |
220 | *length = count; | 220 | *length = count; |
221 | return 0; | 221 | return 0; |
222 | 222 | ||
223 | out_nametoolong: | 223 | out_nametoolong: |
224 | dprintk("NFS: returned filename too long: %u\n", count); | 224 | dprintk("NFS: returned filename too long: %u\n", count); |
225 | return -ENAMETOOLONG; | 225 | return -ENAMETOOLONG; |
226 | out_overflow: | 226 | out_overflow: |
227 | print_overflow_msg(__func__, xdr); | 227 | print_overflow_msg(__func__, xdr); |
228 | return -EIO; | 228 | return -EIO; |
229 | } | 229 | } |
230 | 230 | ||
231 | /* | 231 | /* |
232 | * nfspath3 | 232 | * nfspath3 |
233 | * | 233 | * |
234 | * typedef string nfspath3<>; | 234 | * typedef string nfspath3<>; |
235 | */ | 235 | */ |
236 | static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, | 236 | static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, |
237 | const u32 length) | 237 | const u32 length) |
238 | { | 238 | { |
239 | BUG_ON(length > NFS3_MAXPATHLEN); | 239 | BUG_ON(length > NFS3_MAXPATHLEN); |
240 | encode_uint32(xdr, length); | 240 | encode_uint32(xdr, length); |
241 | xdr_write_pages(xdr, pages, 0, length); | 241 | xdr_write_pages(xdr, pages, 0, length); |
242 | } | 242 | } |
243 | 243 | ||
244 | static int decode_nfspath3(struct xdr_stream *xdr) | 244 | static int decode_nfspath3(struct xdr_stream *xdr) |
245 | { | 245 | { |
246 | u32 recvd, count; | 246 | u32 recvd, count; |
247 | size_t hdrlen; | 247 | size_t hdrlen; |
248 | __be32 *p; | 248 | __be32 *p; |
249 | 249 | ||
250 | p = xdr_inline_decode(xdr, 4); | 250 | p = xdr_inline_decode(xdr, 4); |
251 | if (unlikely(p == NULL)) | 251 | if (unlikely(p == NULL)) |
252 | goto out_overflow; | 252 | goto out_overflow; |
253 | count = be32_to_cpup(p); | 253 | count = be32_to_cpup(p); |
254 | if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) | 254 | if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) |
255 | goto out_nametoolong; | 255 | goto out_nametoolong; |
256 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 256 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; |
257 | recvd = xdr->buf->len - hdrlen; | 257 | recvd = xdr->buf->len - hdrlen; |
258 | if (unlikely(count > recvd)) | 258 | if (unlikely(count > recvd)) |
259 | goto out_cheating; | 259 | goto out_cheating; |
260 | 260 | ||
261 | xdr_read_pages(xdr, count); | 261 | xdr_read_pages(xdr, count); |
262 | xdr_terminate_string(xdr->buf, count); | 262 | xdr_terminate_string(xdr->buf, count); |
263 | return 0; | 263 | return 0; |
264 | 264 | ||
265 | out_nametoolong: | 265 | out_nametoolong: |
266 | dprintk("NFS: returned pathname too long: %u\n", count); | 266 | dprintk("NFS: returned pathname too long: %u\n", count); |
267 | return -ENAMETOOLONG; | 267 | return -ENAMETOOLONG; |
268 | out_cheating: | 268 | out_cheating: |
269 | dprintk("NFS: server cheating in pathname result: " | 269 | dprintk("NFS: server cheating in pathname result: " |
270 | "count %u > recvd %u\n", count, recvd); | 270 | "count %u > recvd %u\n", count, recvd); |
271 | return -EIO; | 271 | return -EIO; |
272 | out_overflow: | 272 | out_overflow: |
273 | print_overflow_msg(__func__, xdr); | 273 | print_overflow_msg(__func__, xdr); |
274 | return -EIO; | 274 | return -EIO; |
275 | } | 275 | } |
276 | 276 | ||
277 | /* | 277 | /* |
278 | * cookie3 | 278 | * cookie3 |
279 | * | 279 | * |
280 | * typedef uint64 cookie3 | 280 | * typedef uint64 cookie3 |
281 | */ | 281 | */ |
282 | static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie) | 282 | static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie) |
283 | { | 283 | { |
284 | return xdr_encode_hyper(p, cookie); | 284 | return xdr_encode_hyper(p, cookie); |
285 | } | 285 | } |
286 | 286 | ||
287 | static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie) | 287 | static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie) |
288 | { | 288 | { |
289 | return decode_uint64(xdr, cookie); | 289 | return decode_uint64(xdr, cookie); |
290 | } | 290 | } |
291 | 291 | ||
292 | /* | 292 | /* |
293 | * cookieverf3 | 293 | * cookieverf3 |
294 | * | 294 | * |
295 | * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; | 295 | * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; |
296 | */ | 296 | */ |
297 | static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier) | 297 | static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier) |
298 | { | 298 | { |
299 | memcpy(p, verifier, NFS3_COOKIEVERFSIZE); | 299 | memcpy(p, verifier, NFS3_COOKIEVERFSIZE); |
300 | return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE); | 300 | return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE); |
301 | } | 301 | } |
302 | 302 | ||
303 | static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier) | 303 | static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier) |
304 | { | 304 | { |
305 | __be32 *p; | 305 | __be32 *p; |
306 | 306 | ||
307 | p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); | 307 | p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); |
308 | if (unlikely(p == NULL)) | 308 | if (unlikely(p == NULL)) |
309 | goto out_overflow; | 309 | goto out_overflow; |
310 | memcpy(verifier, p, NFS3_COOKIEVERFSIZE); | 310 | memcpy(verifier, p, NFS3_COOKIEVERFSIZE); |
311 | return 0; | 311 | return 0; |
312 | out_overflow: | 312 | out_overflow: |
313 | print_overflow_msg(__func__, xdr); | 313 | print_overflow_msg(__func__, xdr); |
314 | return -EIO; | 314 | return -EIO; |
315 | } | 315 | } |
316 | 316 | ||
317 | /* | 317 | /* |
318 | * createverf3 | 318 | * createverf3 |
319 | * | 319 | * |
320 | * typedef opaque createverf3[NFS3_CREATEVERFSIZE]; | 320 | * typedef opaque createverf3[NFS3_CREATEVERFSIZE]; |
321 | */ | 321 | */ |
322 | static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier) | 322 | static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier) |
323 | { | 323 | { |
324 | __be32 *p; | 324 | __be32 *p; |
325 | 325 | ||
326 | p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE); | 326 | p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE); |
327 | memcpy(p, verifier, NFS3_CREATEVERFSIZE); | 327 | memcpy(p, verifier, NFS3_CREATEVERFSIZE); |
328 | } | 328 | } |
329 | 329 | ||
330 | static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier) | 330 | static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier) |
331 | { | 331 | { |
332 | __be32 *p; | 332 | __be32 *p; |
333 | 333 | ||
334 | p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE); | 334 | p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE); |
335 | if (unlikely(p == NULL)) | 335 | if (unlikely(p == NULL)) |
336 | goto out_overflow; | 336 | goto out_overflow; |
337 | memcpy(verifier, p, NFS3_WRITEVERFSIZE); | 337 | memcpy(verifier, p, NFS3_WRITEVERFSIZE); |
338 | return 0; | 338 | return 0; |
339 | out_overflow: | 339 | out_overflow: |
340 | print_overflow_msg(__func__, xdr); | 340 | print_overflow_msg(__func__, xdr); |
341 | return -EIO; | 341 | return -EIO; |
342 | } | 342 | } |
343 | 343 | ||
344 | /* | 344 | /* |
345 | * size3 | 345 | * size3 |
346 | * | 346 | * |
347 | * typedef uint64 size3; | 347 | * typedef uint64 size3; |
348 | */ | 348 | */ |
349 | static __be32 *xdr_decode_size3(__be32 *p, u64 *size) | 349 | static __be32 *xdr_decode_size3(__be32 *p, u64 *size) |
350 | { | 350 | { |
351 | return xdr_decode_hyper(p, size); | 351 | return xdr_decode_hyper(p, size); |
352 | } | 352 | } |
353 | 353 | ||
354 | /* | 354 | /* |
355 | * nfsstat3 | 355 | * nfsstat3 |
356 | * | 356 | * |
357 | * enum nfsstat3 { | 357 | * enum nfsstat3 { |
358 | * NFS3_OK = 0, | 358 | * NFS3_OK = 0, |
359 | * ... | 359 | * ... |
360 | * } | 360 | * } |
361 | */ | 361 | */ |
362 | #define NFS3_OK NFS_OK | 362 | #define NFS3_OK NFS_OK |
363 | 363 | ||
364 | static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status) | 364 | static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status) |
365 | { | 365 | { |
366 | __be32 *p; | 366 | __be32 *p; |
367 | 367 | ||
368 | p = xdr_inline_decode(xdr, 4); | 368 | p = xdr_inline_decode(xdr, 4); |
369 | if (unlikely(p == NULL)) | 369 | if (unlikely(p == NULL)) |
370 | goto out_overflow; | 370 | goto out_overflow; |
371 | *status = be32_to_cpup(p); | 371 | *status = be32_to_cpup(p); |
372 | return 0; | 372 | return 0; |
373 | out_overflow: | 373 | out_overflow: |
374 | print_overflow_msg(__func__, xdr); | 374 | print_overflow_msg(__func__, xdr); |
375 | return -EIO; | 375 | return -EIO; |
376 | } | 376 | } |
377 | 377 | ||
378 | /* | 378 | /* |
379 | * ftype3 | 379 | * ftype3 |
380 | * | 380 | * |
381 | * enum ftype3 { | 381 | * enum ftype3 { |
382 | * NF3REG = 1, | 382 | * NF3REG = 1, |
383 | * NF3DIR = 2, | 383 | * NF3DIR = 2, |
384 | * NF3BLK = 3, | 384 | * NF3BLK = 3, |
385 | * NF3CHR = 4, | 385 | * NF3CHR = 4, |
386 | * NF3LNK = 5, | 386 | * NF3LNK = 5, |
387 | * NF3SOCK = 6, | 387 | * NF3SOCK = 6, |
388 | * NF3FIFO = 7 | 388 | * NF3FIFO = 7 |
389 | * }; | 389 | * }; |
390 | */ | 390 | */ |
391 | static void encode_ftype3(struct xdr_stream *xdr, const u32 type) | 391 | static void encode_ftype3(struct xdr_stream *xdr, const u32 type) |
392 | { | 392 | { |
393 | BUG_ON(type > NF3FIFO); | 393 | BUG_ON(type > NF3FIFO); |
394 | encode_uint32(xdr, type); | 394 | encode_uint32(xdr, type); |
395 | } | 395 | } |
396 | 396 | ||
397 | static __be32 *xdr_decode_ftype3(__be32 *p, umode_t *mode) | 397 | static __be32 *xdr_decode_ftype3(__be32 *p, umode_t *mode) |
398 | { | 398 | { |
399 | u32 type; | 399 | u32 type; |
400 | 400 | ||
401 | type = be32_to_cpup(p++); | 401 | type = be32_to_cpup(p++); |
402 | if (type > NF3FIFO) | 402 | if (type > NF3FIFO) |
403 | type = NF3NON; | 403 | type = NF3NON; |
404 | *mode = nfs_type2fmt[type]; | 404 | *mode = nfs_type2fmt[type]; |
405 | return p; | 405 | return p; |
406 | } | 406 | } |
407 | 407 | ||
408 | /* | 408 | /* |
409 | * specdata3 | 409 | * specdata3 |
410 | * | 410 | * |
411 | * struct specdata3 { | 411 | * struct specdata3 { |
412 | * uint32 specdata1; | 412 | * uint32 specdata1; |
413 | * uint32 specdata2; | 413 | * uint32 specdata2; |
414 | * }; | 414 | * }; |
415 | */ | 415 | */ |
416 | static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev) | 416 | static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev) |
417 | { | 417 | { |
418 | __be32 *p; | 418 | __be32 *p; |
419 | 419 | ||
420 | p = xdr_reserve_space(xdr, 8); | 420 | p = xdr_reserve_space(xdr, 8); |
421 | *p++ = cpu_to_be32(MAJOR(rdev)); | 421 | *p++ = cpu_to_be32(MAJOR(rdev)); |
422 | *p = cpu_to_be32(MINOR(rdev)); | 422 | *p = cpu_to_be32(MINOR(rdev)); |
423 | } | 423 | } |
424 | 424 | ||
425 | static __be32 *xdr_decode_specdata3(__be32 *p, dev_t *rdev) | 425 | static __be32 *xdr_decode_specdata3(__be32 *p, dev_t *rdev) |
426 | { | 426 | { |
427 | unsigned int major, minor; | 427 | unsigned int major, minor; |
428 | 428 | ||
429 | major = be32_to_cpup(p++); | 429 | major = be32_to_cpup(p++); |
430 | minor = be32_to_cpup(p++); | 430 | minor = be32_to_cpup(p++); |
431 | *rdev = MKDEV(major, minor); | 431 | *rdev = MKDEV(major, minor); |
432 | if (MAJOR(*rdev) != major || MINOR(*rdev) != minor) | 432 | if (MAJOR(*rdev) != major || MINOR(*rdev) != minor) |
433 | *rdev = 0; | 433 | *rdev = 0; |
434 | return p; | 434 | return p; |
435 | } | 435 | } |
436 | 436 | ||
437 | /* | 437 | /* |
438 | * nfs_fh3 | 438 | * nfs_fh3 |
439 | * | 439 | * |
440 | * struct nfs_fh3 { | 440 | * struct nfs_fh3 { |
441 | * opaque data<NFS3_FHSIZE>; | 441 | * opaque data<NFS3_FHSIZE>; |
442 | * }; | 442 | * }; |
443 | */ | 443 | */ |
444 | static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh) | 444 | static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh) |
445 | { | 445 | { |
446 | __be32 *p; | 446 | __be32 *p; |
447 | 447 | ||
448 | BUG_ON(fh->size > NFS3_FHSIZE); | 448 | BUG_ON(fh->size > NFS3_FHSIZE); |
449 | p = xdr_reserve_space(xdr, 4 + fh->size); | 449 | p = xdr_reserve_space(xdr, 4 + fh->size); |
450 | xdr_encode_opaque(p, fh->data, fh->size); | 450 | xdr_encode_opaque(p, fh->data, fh->size); |
451 | } | 451 | } |
452 | 452 | ||
453 | static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh) | 453 | static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh) |
454 | { | 454 | { |
455 | u32 length; | 455 | u32 length; |
456 | __be32 *p; | 456 | __be32 *p; |
457 | 457 | ||
458 | p = xdr_inline_decode(xdr, 4); | 458 | p = xdr_inline_decode(xdr, 4); |
459 | if (unlikely(p == NULL)) | 459 | if (unlikely(p == NULL)) |
460 | goto out_overflow; | 460 | goto out_overflow; |
461 | length = be32_to_cpup(p++); | 461 | length = be32_to_cpup(p++); |
462 | if (unlikely(length > NFS3_FHSIZE)) | 462 | if (unlikely(length > NFS3_FHSIZE)) |
463 | goto out_toobig; | 463 | goto out_toobig; |
464 | p = xdr_inline_decode(xdr, length); | 464 | p = xdr_inline_decode(xdr, length); |
465 | if (unlikely(p == NULL)) | 465 | if (unlikely(p == NULL)) |
466 | goto out_overflow; | 466 | goto out_overflow; |
467 | fh->size = length; | 467 | fh->size = length; |
468 | memcpy(fh->data, p, length); | 468 | memcpy(fh->data, p, length); |
469 | return 0; | 469 | return 0; |
470 | out_toobig: | 470 | out_toobig: |
471 | dprintk("NFS: file handle size (%u) too big\n", length); | 471 | dprintk("NFS: file handle size (%u) too big\n", length); |
472 | return -E2BIG; | 472 | return -E2BIG; |
473 | out_overflow: | 473 | out_overflow: |
474 | print_overflow_msg(__func__, xdr); | 474 | print_overflow_msg(__func__, xdr); |
475 | return -EIO; | 475 | return -EIO; |
476 | } | 476 | } |
477 | 477 | ||
478 | static void zero_nfs_fh3(struct nfs_fh *fh) | 478 | static void zero_nfs_fh3(struct nfs_fh *fh) |
479 | { | 479 | { |
480 | memset(fh, 0, sizeof(*fh)); | 480 | memset(fh, 0, sizeof(*fh)); |
481 | } | 481 | } |
482 | 482 | ||
483 | /* | 483 | /* |
484 | * nfstime3 | 484 | * nfstime3 |
485 | * | 485 | * |
486 | * struct nfstime3 { | 486 | * struct nfstime3 { |
487 | * uint32 seconds; | 487 | * uint32 seconds; |
488 | * uint32 nseconds; | 488 | * uint32 nseconds; |
489 | * }; | 489 | * }; |
490 | */ | 490 | */ |
491 | static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep) | 491 | static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep) |
492 | { | 492 | { |
493 | *p++ = cpu_to_be32(timep->tv_sec); | 493 | *p++ = cpu_to_be32(timep->tv_sec); |
494 | *p++ = cpu_to_be32(timep->tv_nsec); | 494 | *p++ = cpu_to_be32(timep->tv_nsec); |
495 | return p; | 495 | return p; |
496 | } | 496 | } |
497 | 497 | ||
498 | static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep) | 498 | static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep) |
499 | { | 499 | { |
500 | timep->tv_sec = be32_to_cpup(p++); | 500 | timep->tv_sec = be32_to_cpup(p++); |
501 | timep->tv_nsec = be32_to_cpup(p++); | 501 | timep->tv_nsec = be32_to_cpup(p++); |
502 | return p; | 502 | return p; |
503 | } | 503 | } |
504 | 504 | ||
505 | /* | 505 | /* |
506 | * sattr3 | 506 | * sattr3 |
507 | * | 507 | * |
508 | * enum time_how { | 508 | * enum time_how { |
509 | * DONT_CHANGE = 0, | 509 | * DONT_CHANGE = 0, |
510 | * SET_TO_SERVER_TIME = 1, | 510 | * SET_TO_SERVER_TIME = 1, |
511 | * SET_TO_CLIENT_TIME = 2 | 511 | * SET_TO_CLIENT_TIME = 2 |
512 | * }; | 512 | * }; |
513 | * | 513 | * |
514 | * union set_mode3 switch (bool set_it) { | 514 | * union set_mode3 switch (bool set_it) { |
515 | * case TRUE: | 515 | * case TRUE: |
516 | * mode3 mode; | 516 | * mode3 mode; |
517 | * default: | 517 | * default: |
518 | * void; | 518 | * void; |
519 | * }; | 519 | * }; |
520 | * | 520 | * |
521 | * union set_uid3 switch (bool set_it) { | 521 | * union set_uid3 switch (bool set_it) { |
522 | * case TRUE: | 522 | * case TRUE: |
523 | * uid3 uid; | 523 | * uid3 uid; |
524 | * default: | 524 | * default: |
525 | * void; | 525 | * void; |
526 | * }; | 526 | * }; |
527 | * | 527 | * |
528 | * union set_gid3 switch (bool set_it) { | 528 | * union set_gid3 switch (bool set_it) { |
529 | * case TRUE: | 529 | * case TRUE: |
530 | * gid3 gid; | 530 | * gid3 gid; |
531 | * default: | 531 | * default: |
532 | * void; | 532 | * void; |
533 | * }; | 533 | * }; |
534 | * | 534 | * |
535 | * union set_size3 switch (bool set_it) { | 535 | * union set_size3 switch (bool set_it) { |
536 | * case TRUE: | 536 | * case TRUE: |
537 | * size3 size; | 537 | * size3 size; |
538 | * default: | 538 | * default: |
539 | * void; | 539 | * void; |
540 | * }; | 540 | * }; |
541 | * | 541 | * |
542 | * union set_atime switch (time_how set_it) { | 542 | * union set_atime switch (time_how set_it) { |
543 | * case SET_TO_CLIENT_TIME: | 543 | * case SET_TO_CLIENT_TIME: |
544 | * nfstime3 atime; | 544 | * nfstime3 atime; |
545 | * default: | 545 | * default: |
546 | * void; | 546 | * void; |
547 | * }; | 547 | * }; |
548 | * | 548 | * |
549 | * union set_mtime switch (time_how set_it) { | 549 | * union set_mtime switch (time_how set_it) { |
550 | * case SET_TO_CLIENT_TIME: | 550 | * case SET_TO_CLIENT_TIME: |
551 | * nfstime3 mtime; | 551 | * nfstime3 mtime; |
552 | * default: | 552 | * default: |
553 | * void; | 553 | * void; |
554 | * }; | 554 | * }; |
555 | * | 555 | * |
556 | * struct sattr3 { | 556 | * struct sattr3 { |
557 | * set_mode3 mode; | 557 | * set_mode3 mode; |
558 | * set_uid3 uid; | 558 | * set_uid3 uid; |
559 | * set_gid3 gid; | 559 | * set_gid3 gid; |
560 | * set_size3 size; | 560 | * set_size3 size; |
561 | * set_atime atime; | 561 | * set_atime atime; |
562 | * set_mtime mtime; | 562 | * set_mtime mtime; |
563 | * }; | 563 | * }; |
564 | */ | 564 | */ |
565 | static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr) | 565 | static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr) |
566 | { | 566 | { |
567 | u32 nbytes; | 567 | u32 nbytes; |
568 | __be32 *p; | 568 | __be32 *p; |
569 | 569 | ||
570 | /* | 570 | /* |
571 | * In order to make only a single xdr_reserve_space() call, | 571 | * In order to make only a single xdr_reserve_space() call, |
572 | * pre-compute the total number of bytes to be reserved. | 572 | * pre-compute the total number of bytes to be reserved. |
573 | * Six boolean values, one for each set_foo field, are always | 573 | * Six boolean values, one for each set_foo field, are always |
574 | * present in the encoded result, so start there. | 574 | * present in the encoded result, so start there. |
575 | */ | 575 | */ |
576 | nbytes = 6 * 4; | 576 | nbytes = 6 * 4; |
577 | if (attr->ia_valid & ATTR_MODE) | 577 | if (attr->ia_valid & ATTR_MODE) |
578 | nbytes += 4; | 578 | nbytes += 4; |
579 | if (attr->ia_valid & ATTR_UID) | 579 | if (attr->ia_valid & ATTR_UID) |
580 | nbytes += 4; | 580 | nbytes += 4; |
581 | if (attr->ia_valid & ATTR_GID) | 581 | if (attr->ia_valid & ATTR_GID) |
582 | nbytes += 4; | 582 | nbytes += 4; |
583 | if (attr->ia_valid & ATTR_SIZE) | 583 | if (attr->ia_valid & ATTR_SIZE) |
584 | nbytes += 8; | 584 | nbytes += 8; |
585 | if (attr->ia_valid & ATTR_ATIME_SET) | 585 | if (attr->ia_valid & ATTR_ATIME_SET) |
586 | nbytes += 8; | 586 | nbytes += 8; |
587 | if (attr->ia_valid & ATTR_MTIME_SET) | 587 | if (attr->ia_valid & ATTR_MTIME_SET) |
588 | nbytes += 8; | 588 | nbytes += 8; |
589 | p = xdr_reserve_space(xdr, nbytes); | 589 | p = xdr_reserve_space(xdr, nbytes); |
590 | 590 | ||
591 | if (attr->ia_valid & ATTR_MODE) { | 591 | if (attr->ia_valid & ATTR_MODE) { |
592 | *p++ = xdr_one; | 592 | *p++ = xdr_one; |
593 | *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO); | 593 | *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO); |
594 | } else | 594 | } else |
595 | *p++ = xdr_zero; | 595 | *p++ = xdr_zero; |
596 | 596 | ||
597 | if (attr->ia_valid & ATTR_UID) { | 597 | if (attr->ia_valid & ATTR_UID) { |
598 | *p++ = xdr_one; | 598 | *p++ = xdr_one; |
599 | *p++ = cpu_to_be32(attr->ia_uid); | 599 | *p++ = cpu_to_be32(attr->ia_uid); |
600 | } else | 600 | } else |
601 | *p++ = xdr_zero; | 601 | *p++ = xdr_zero; |
602 | 602 | ||
603 | if (attr->ia_valid & ATTR_GID) { | 603 | if (attr->ia_valid & ATTR_GID) { |
604 | *p++ = xdr_one; | 604 | *p++ = xdr_one; |
605 | *p++ = cpu_to_be32(attr->ia_gid); | 605 | *p++ = cpu_to_be32(attr->ia_gid); |
606 | } else | 606 | } else |
607 | *p++ = xdr_zero; | 607 | *p++ = xdr_zero; |
608 | 608 | ||
609 | if (attr->ia_valid & ATTR_SIZE) { | 609 | if (attr->ia_valid & ATTR_SIZE) { |
610 | *p++ = xdr_one; | 610 | *p++ = xdr_one; |
611 | p = xdr_encode_hyper(p, (u64)attr->ia_size); | 611 | p = xdr_encode_hyper(p, (u64)attr->ia_size); |
612 | } else | 612 | } else |
613 | *p++ = xdr_zero; | 613 | *p++ = xdr_zero; |
614 | 614 | ||
615 | if (attr->ia_valid & ATTR_ATIME_SET) { | 615 | if (attr->ia_valid & ATTR_ATIME_SET) { |
616 | *p++ = xdr_two; | 616 | *p++ = xdr_two; |
617 | p = xdr_encode_nfstime3(p, &attr->ia_atime); | 617 | p = xdr_encode_nfstime3(p, &attr->ia_atime); |
618 | } else if (attr->ia_valid & ATTR_ATIME) { | 618 | } else if (attr->ia_valid & ATTR_ATIME) { |
619 | *p++ = xdr_one; | 619 | *p++ = xdr_one; |
620 | } else | 620 | } else |
621 | *p++ = xdr_zero; | 621 | *p++ = xdr_zero; |
622 | 622 | ||
623 | if (attr->ia_valid & ATTR_MTIME_SET) { | 623 | if (attr->ia_valid & ATTR_MTIME_SET) { |
624 | *p++ = xdr_two; | 624 | *p++ = xdr_two; |
625 | xdr_encode_nfstime3(p, &attr->ia_mtime); | 625 | xdr_encode_nfstime3(p, &attr->ia_mtime); |
626 | } else if (attr->ia_valid & ATTR_MTIME) { | 626 | } else if (attr->ia_valid & ATTR_MTIME) { |
627 | *p = xdr_one; | 627 | *p = xdr_one; |
628 | } else | 628 | } else |
629 | *p = xdr_zero; | 629 | *p = xdr_zero; |
630 | } | 630 | } |
631 | 631 | ||
632 | /* | 632 | /* |
633 | * fattr3 | 633 | * fattr3 |
634 | * | 634 | * |
635 | * struct fattr3 { | 635 | * struct fattr3 { |
636 | * ftype3 type; | 636 | * ftype3 type; |
637 | * mode3 mode; | 637 | * mode3 mode; |
638 | * uint32 nlink; | 638 | * uint32 nlink; |
639 | * uid3 uid; | 639 | * uid3 uid; |
640 | * gid3 gid; | 640 | * gid3 gid; |
641 | * size3 size; | 641 | * size3 size; |
642 | * size3 used; | 642 | * size3 used; |
643 | * specdata3 rdev; | 643 | * specdata3 rdev; |
644 | * uint64 fsid; | 644 | * uint64 fsid; |
645 | * fileid3 fileid; | 645 | * fileid3 fileid; |
646 | * nfstime3 atime; | 646 | * nfstime3 atime; |
647 | * nfstime3 mtime; | 647 | * nfstime3 mtime; |
648 | * nfstime3 ctime; | 648 | * nfstime3 ctime; |
649 | * }; | 649 | * }; |
650 | */ | 650 | */ |
651 | static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 651 | static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr) |
652 | { | 652 | { |
653 | umode_t fmode; | 653 | umode_t fmode; |
654 | __be32 *p; | 654 | __be32 *p; |
655 | 655 | ||
656 | p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2); | 656 | p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2); |
657 | if (unlikely(p == NULL)) | 657 | if (unlikely(p == NULL)) |
658 | goto out_overflow; | 658 | goto out_overflow; |
659 | 659 | ||
660 | p = xdr_decode_ftype3(p, &fmode); | 660 | p = xdr_decode_ftype3(p, &fmode); |
661 | 661 | ||
662 | fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode; | 662 | fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode; |
663 | fattr->nlink = be32_to_cpup(p++); | 663 | fattr->nlink = be32_to_cpup(p++); |
664 | fattr->uid = be32_to_cpup(p++); | 664 | fattr->uid = be32_to_cpup(p++); |
665 | fattr->gid = be32_to_cpup(p++); | 665 | fattr->gid = be32_to_cpup(p++); |
666 | 666 | ||
667 | p = xdr_decode_size3(p, &fattr->size); | 667 | p = xdr_decode_size3(p, &fattr->size); |
668 | p = xdr_decode_size3(p, &fattr->du.nfs3.used); | 668 | p = xdr_decode_size3(p, &fattr->du.nfs3.used); |
669 | p = xdr_decode_specdata3(p, &fattr->rdev); | 669 | p = xdr_decode_specdata3(p, &fattr->rdev); |
670 | 670 | ||
671 | p = xdr_decode_hyper(p, &fattr->fsid.major); | 671 | p = xdr_decode_hyper(p, &fattr->fsid.major); |
672 | fattr->fsid.minor = 0; | 672 | fattr->fsid.minor = 0; |
673 | 673 | ||
674 | p = xdr_decode_fileid3(p, &fattr->fileid); | 674 | p = xdr_decode_fileid3(p, &fattr->fileid); |
675 | p = xdr_decode_nfstime3(p, &fattr->atime); | 675 | p = xdr_decode_nfstime3(p, &fattr->atime); |
676 | p = xdr_decode_nfstime3(p, &fattr->mtime); | 676 | p = xdr_decode_nfstime3(p, &fattr->mtime); |
677 | xdr_decode_nfstime3(p, &fattr->ctime); | 677 | xdr_decode_nfstime3(p, &fattr->ctime); |
678 | 678 | ||
679 | fattr->valid |= NFS_ATTR_FATTR_V3; | 679 | fattr->valid |= NFS_ATTR_FATTR_V3; |
680 | return 0; | 680 | return 0; |
681 | out_overflow: | 681 | out_overflow: |
682 | print_overflow_msg(__func__, xdr); | 682 | print_overflow_msg(__func__, xdr); |
683 | return -EIO; | 683 | return -EIO; |
684 | } | 684 | } |
685 | 685 | ||
686 | /* | 686 | /* |
687 | * post_op_attr | 687 | * post_op_attr |
688 | * | 688 | * |
689 | * union post_op_attr switch (bool attributes_follow) { | 689 | * union post_op_attr switch (bool attributes_follow) { |
690 | * case TRUE: | 690 | * case TRUE: |
691 | * fattr3 attributes; | 691 | * fattr3 attributes; |
692 | * case FALSE: | 692 | * case FALSE: |
693 | * void; | 693 | * void; |
694 | * }; | 694 | * }; |
695 | */ | 695 | */ |
696 | static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 696 | static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) |
697 | { | 697 | { |
698 | __be32 *p; | 698 | __be32 *p; |
699 | 699 | ||
700 | p = xdr_inline_decode(xdr, 4); | 700 | p = xdr_inline_decode(xdr, 4); |
701 | if (unlikely(p == NULL)) | 701 | if (unlikely(p == NULL)) |
702 | goto out_overflow; | 702 | goto out_overflow; |
703 | if (*p != xdr_zero) | 703 | if (*p != xdr_zero) |
704 | return decode_fattr3(xdr, fattr); | 704 | return decode_fattr3(xdr, fattr); |
705 | return 0; | 705 | return 0; |
706 | out_overflow: | 706 | out_overflow: |
707 | print_overflow_msg(__func__, xdr); | 707 | print_overflow_msg(__func__, xdr); |
708 | return -EIO; | 708 | return -EIO; |
709 | } | 709 | } |
710 | 710 | ||
711 | /* | 711 | /* |
712 | * wcc_attr | 712 | * wcc_attr |
713 | * struct wcc_attr { | 713 | * struct wcc_attr { |
714 | * size3 size; | 714 | * size3 size; |
715 | * nfstime3 mtime; | 715 | * nfstime3 mtime; |
716 | * nfstime3 ctime; | 716 | * nfstime3 ctime; |
717 | * }; | 717 | * }; |
718 | */ | 718 | */ |
719 | static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 719 | static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) |
720 | { | 720 | { |
721 | __be32 *p; | 721 | __be32 *p; |
722 | 722 | ||
723 | p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2); | 723 | p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2); |
724 | if (unlikely(p == NULL)) | 724 | if (unlikely(p == NULL)) |
725 | goto out_overflow; | 725 | goto out_overflow; |
726 | 726 | ||
727 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE | 727 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE |
728 | | NFS_ATTR_FATTR_PREMTIME | 728 | | NFS_ATTR_FATTR_PREMTIME |
729 | | NFS_ATTR_FATTR_PRECTIME; | 729 | | NFS_ATTR_FATTR_PRECTIME; |
730 | 730 | ||
731 | p = xdr_decode_size3(p, &fattr->pre_size); | 731 | p = xdr_decode_size3(p, &fattr->pre_size); |
732 | p = xdr_decode_nfstime3(p, &fattr->pre_mtime); | 732 | p = xdr_decode_nfstime3(p, &fattr->pre_mtime); |
733 | xdr_decode_nfstime3(p, &fattr->pre_ctime); | 733 | xdr_decode_nfstime3(p, &fattr->pre_ctime); |
734 | 734 | ||
735 | return 0; | 735 | return 0; |
736 | out_overflow: | 736 | out_overflow: |
737 | print_overflow_msg(__func__, xdr); | 737 | print_overflow_msg(__func__, xdr); |
738 | return -EIO; | 738 | return -EIO; |
739 | } | 739 | } |
740 | 740 | ||
741 | /* | 741 | /* |
742 | * pre_op_attr | 742 | * pre_op_attr |
743 | * union pre_op_attr switch (bool attributes_follow) { | 743 | * union pre_op_attr switch (bool attributes_follow) { |
744 | * case TRUE: | 744 | * case TRUE: |
745 | * wcc_attr attributes; | 745 | * wcc_attr attributes; |
746 | * case FALSE: | 746 | * case FALSE: |
747 | * void; | 747 | * void; |
748 | * }; | 748 | * }; |
749 | * | 749 | * |
750 | * wcc_data | 750 | * wcc_data |
751 | * | 751 | * |
752 | * struct wcc_data { | 752 | * struct wcc_data { |
753 | * pre_op_attr before; | 753 | * pre_op_attr before; |
754 | * post_op_attr after; | 754 | * post_op_attr after; |
755 | * }; | 755 | * }; |
756 | */ | 756 | */ |
757 | static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 757 | static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr) |
758 | { | 758 | { |
759 | __be32 *p; | 759 | __be32 *p; |
760 | 760 | ||
761 | p = xdr_inline_decode(xdr, 4); | 761 | p = xdr_inline_decode(xdr, 4); |
762 | if (unlikely(p == NULL)) | 762 | if (unlikely(p == NULL)) |
763 | goto out_overflow; | 763 | goto out_overflow; |
764 | if (*p != xdr_zero) | 764 | if (*p != xdr_zero) |
765 | return decode_wcc_attr(xdr, fattr); | 765 | return decode_wcc_attr(xdr, fattr); |
766 | return 0; | 766 | return 0; |
767 | out_overflow: | 767 | out_overflow: |
768 | print_overflow_msg(__func__, xdr); | 768 | print_overflow_msg(__func__, xdr); |
769 | return -EIO; | 769 | return -EIO; |
770 | } | 770 | } |
771 | 771 | ||
772 | static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr) | 772 | static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr) |
773 | { | 773 | { |
774 | int error; | 774 | int error; |
775 | 775 | ||
776 | error = decode_pre_op_attr(xdr, fattr); | 776 | error = decode_pre_op_attr(xdr, fattr); |
777 | if (unlikely(error)) | 777 | if (unlikely(error)) |
778 | goto out; | 778 | goto out; |
779 | error = decode_post_op_attr(xdr, fattr); | 779 | error = decode_post_op_attr(xdr, fattr); |
780 | out: | 780 | out: |
781 | return error; | 781 | return error; |
782 | } | 782 | } |
783 | 783 | ||
784 | /* | 784 | /* |
785 | * post_op_fh3 | 785 | * post_op_fh3 |
786 | * | 786 | * |
787 | * union post_op_fh3 switch (bool handle_follows) { | 787 | * union post_op_fh3 switch (bool handle_follows) { |
788 | * case TRUE: | 788 | * case TRUE: |
789 | * nfs_fh3 handle; | 789 | * nfs_fh3 handle; |
790 | * case FALSE: | 790 | * case FALSE: |
791 | * void; | 791 | * void; |
792 | * }; | 792 | * }; |
793 | */ | 793 | */ |
794 | static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh) | 794 | static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh) |
795 | { | 795 | { |
796 | __be32 *p = xdr_inline_decode(xdr, 4); | 796 | __be32 *p = xdr_inline_decode(xdr, 4); |
797 | if (unlikely(p == NULL)) | 797 | if (unlikely(p == NULL)) |
798 | goto out_overflow; | 798 | goto out_overflow; |
799 | if (*p != xdr_zero) | 799 | if (*p != xdr_zero) |
800 | return decode_nfs_fh3(xdr, fh); | 800 | return decode_nfs_fh3(xdr, fh); |
801 | zero_nfs_fh3(fh); | 801 | zero_nfs_fh3(fh); |
802 | return 0; | 802 | return 0; |
803 | out_overflow: | 803 | out_overflow: |
804 | print_overflow_msg(__func__, xdr); | 804 | print_overflow_msg(__func__, xdr); |
805 | return -EIO; | 805 | return -EIO; |
806 | } | 806 | } |
807 | 807 | ||
808 | /* | 808 | /* |
809 | * diropargs3 | 809 | * diropargs3 |
810 | * | 810 | * |
811 | * struct diropargs3 { | 811 | * struct diropargs3 { |
812 | * nfs_fh3 dir; | 812 | * nfs_fh3 dir; |
813 | * filename3 name; | 813 | * filename3 name; |
814 | * }; | 814 | * }; |
815 | */ | 815 | */ |
816 | static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh, | 816 | static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh, |
817 | const char *name, u32 length) | 817 | const char *name, u32 length) |
818 | { | 818 | { |
819 | encode_nfs_fh3(xdr, fh); | 819 | encode_nfs_fh3(xdr, fh); |
820 | encode_filename3(xdr, name, length); | 820 | encode_filename3(xdr, name, length); |
821 | } | 821 | } |
822 | 822 | ||
823 | 823 | ||
824 | /* | 824 | /* |
825 | * NFSv3 XDR encode functions | 825 | * NFSv3 XDR encode functions |
826 | * | 826 | * |
827 | * NFSv3 argument types are defined in section 3.3 of RFC 1813: | 827 | * NFSv3 argument types are defined in section 3.3 of RFC 1813: |
828 | * "NFS Version 3 Protocol Specification". | 828 | * "NFS Version 3 Protocol Specification". |
829 | */ | 829 | */ |
830 | 830 | ||
831 | /* | 831 | /* |
832 | * 3.3.1 GETATTR3args | 832 | * 3.3.1 GETATTR3args |
833 | * | 833 | * |
834 | * struct GETATTR3args { | 834 | * struct GETATTR3args { |
835 | * nfs_fh3 object; | 835 | * nfs_fh3 object; |
836 | * }; | 836 | * }; |
837 | */ | 837 | */ |
838 | static void nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, | 838 | static void nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, |
839 | struct xdr_stream *xdr, | 839 | struct xdr_stream *xdr, |
840 | const struct nfs_fh *fh) | 840 | const struct nfs_fh *fh) |
841 | { | 841 | { |
842 | encode_nfs_fh3(xdr, fh); | 842 | encode_nfs_fh3(xdr, fh); |
843 | } | 843 | } |
844 | 844 | ||
845 | /* | 845 | /* |
846 | * 3.3.2 SETATTR3args | 846 | * 3.3.2 SETATTR3args |
847 | * | 847 | * |
848 | * union sattrguard3 switch (bool check) { | 848 | * union sattrguard3 switch (bool check) { |
849 | * case TRUE: | 849 | * case TRUE: |
850 | * nfstime3 obj_ctime; | 850 | * nfstime3 obj_ctime; |
851 | * case FALSE: | 851 | * case FALSE: |
852 | * void; | 852 | * void; |
853 | * }; | 853 | * }; |
854 | * | 854 | * |
855 | * struct SETATTR3args { | 855 | * struct SETATTR3args { |
856 | * nfs_fh3 object; | 856 | * nfs_fh3 object; |
857 | * sattr3 new_attributes; | 857 | * sattr3 new_attributes; |
858 | * sattrguard3 guard; | 858 | * sattrguard3 guard; |
859 | * }; | 859 | * }; |
860 | */ | 860 | */ |
861 | static void encode_sattrguard3(struct xdr_stream *xdr, | 861 | static void encode_sattrguard3(struct xdr_stream *xdr, |
862 | const struct nfs3_sattrargs *args) | 862 | const struct nfs3_sattrargs *args) |
863 | { | 863 | { |
864 | __be32 *p; | 864 | __be32 *p; |
865 | 865 | ||
866 | if (args->guard) { | 866 | if (args->guard) { |
867 | p = xdr_reserve_space(xdr, 4 + 8); | 867 | p = xdr_reserve_space(xdr, 4 + 8); |
868 | *p++ = xdr_one; | 868 | *p++ = xdr_one; |
869 | xdr_encode_nfstime3(p, &args->guardtime); | 869 | xdr_encode_nfstime3(p, &args->guardtime); |
870 | } else { | 870 | } else { |
871 | p = xdr_reserve_space(xdr, 4); | 871 | p = xdr_reserve_space(xdr, 4); |
872 | *p = xdr_zero; | 872 | *p = xdr_zero; |
873 | } | 873 | } |
874 | } | 874 | } |
875 | 875 | ||
876 | static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, | 876 | static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, |
877 | struct xdr_stream *xdr, | 877 | struct xdr_stream *xdr, |
878 | const struct nfs3_sattrargs *args) | 878 | const struct nfs3_sattrargs *args) |
879 | { | 879 | { |
880 | encode_nfs_fh3(xdr, args->fh); | 880 | encode_nfs_fh3(xdr, args->fh); |
881 | encode_sattr3(xdr, args->sattr); | 881 | encode_sattr3(xdr, args->sattr); |
882 | encode_sattrguard3(xdr, args); | 882 | encode_sattrguard3(xdr, args); |
883 | } | 883 | } |
884 | 884 | ||
885 | /* | 885 | /* |
886 | * 3.3.3 LOOKUP3args | 886 | * 3.3.3 LOOKUP3args |
887 | * | 887 | * |
888 | * struct LOOKUP3args { | 888 | * struct LOOKUP3args { |
889 | * diropargs3 what; | 889 | * diropargs3 what; |
890 | * }; | 890 | * }; |
891 | */ | 891 | */ |
892 | static void nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, | 892 | static void nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, |
893 | struct xdr_stream *xdr, | 893 | struct xdr_stream *xdr, |
894 | const struct nfs3_diropargs *args) | 894 | const struct nfs3_diropargs *args) |
895 | { | 895 | { |
896 | encode_diropargs3(xdr, args->fh, args->name, args->len); | 896 | encode_diropargs3(xdr, args->fh, args->name, args->len); |
897 | } | 897 | } |
898 | 898 | ||
899 | /* | 899 | /* |
900 | * 3.3.4 ACCESS3args | 900 | * 3.3.4 ACCESS3args |
901 | * | 901 | * |
902 | * struct ACCESS3args { | 902 | * struct ACCESS3args { |
903 | * nfs_fh3 object; | 903 | * nfs_fh3 object; |
904 | * uint32 access; | 904 | * uint32 access; |
905 | * }; | 905 | * }; |
906 | */ | 906 | */ |
907 | static void encode_access3args(struct xdr_stream *xdr, | 907 | static void encode_access3args(struct xdr_stream *xdr, |
908 | const struct nfs3_accessargs *args) | 908 | const struct nfs3_accessargs *args) |
909 | { | 909 | { |
910 | encode_nfs_fh3(xdr, args->fh); | 910 | encode_nfs_fh3(xdr, args->fh); |
911 | encode_uint32(xdr, args->access); | 911 | encode_uint32(xdr, args->access); |
912 | } | 912 | } |
913 | 913 | ||
914 | static void nfs3_xdr_enc_access3args(struct rpc_rqst *req, | 914 | static void nfs3_xdr_enc_access3args(struct rpc_rqst *req, |
915 | struct xdr_stream *xdr, | 915 | struct xdr_stream *xdr, |
916 | const struct nfs3_accessargs *args) | 916 | const struct nfs3_accessargs *args) |
917 | { | 917 | { |
918 | encode_access3args(xdr, args); | 918 | encode_access3args(xdr, args); |
919 | } | 919 | } |
920 | 920 | ||
921 | /* | 921 | /* |
922 | * 3.3.5 READLINK3args | 922 | * 3.3.5 READLINK3args |
923 | * | 923 | * |
924 | * struct READLINK3args { | 924 | * struct READLINK3args { |
925 | * nfs_fh3 symlink; | 925 | * nfs_fh3 symlink; |
926 | * }; | 926 | * }; |
927 | */ | 927 | */ |
928 | static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, | 928 | static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, |
929 | struct xdr_stream *xdr, | 929 | struct xdr_stream *xdr, |
930 | const struct nfs3_readlinkargs *args) | 930 | const struct nfs3_readlinkargs *args) |
931 | { | 931 | { |
932 | encode_nfs_fh3(xdr, args->fh); | 932 | encode_nfs_fh3(xdr, args->fh); |
933 | prepare_reply_buffer(req, args->pages, args->pgbase, | 933 | prepare_reply_buffer(req, args->pages, args->pgbase, |
934 | args->pglen, NFS3_readlinkres_sz); | 934 | args->pglen, NFS3_readlinkres_sz); |
935 | } | 935 | } |
936 | 936 | ||
937 | /* | 937 | /* |
938 | * 3.3.6 READ3args | 938 | * 3.3.6 READ3args |
939 | * | 939 | * |
940 | * struct READ3args { | 940 | * struct READ3args { |
941 | * nfs_fh3 file; | 941 | * nfs_fh3 file; |
942 | * offset3 offset; | 942 | * offset3 offset; |
943 | * count3 count; | 943 | * count3 count; |
944 | * }; | 944 | * }; |
945 | */ | 945 | */ |
946 | static void encode_read3args(struct xdr_stream *xdr, | 946 | static void encode_read3args(struct xdr_stream *xdr, |
947 | const struct nfs_readargs *args) | 947 | const struct nfs_readargs *args) |
948 | { | 948 | { |
949 | __be32 *p; | 949 | __be32 *p; |
950 | 950 | ||
951 | encode_nfs_fh3(xdr, args->fh); | 951 | encode_nfs_fh3(xdr, args->fh); |
952 | 952 | ||
953 | p = xdr_reserve_space(xdr, 8 + 4); | 953 | p = xdr_reserve_space(xdr, 8 + 4); |
954 | p = xdr_encode_hyper(p, args->offset); | 954 | p = xdr_encode_hyper(p, args->offset); |
955 | *p = cpu_to_be32(args->count); | 955 | *p = cpu_to_be32(args->count); |
956 | } | 956 | } |
957 | 957 | ||
958 | static void nfs3_xdr_enc_read3args(struct rpc_rqst *req, | 958 | static void nfs3_xdr_enc_read3args(struct rpc_rqst *req, |
959 | struct xdr_stream *xdr, | 959 | struct xdr_stream *xdr, |
960 | const struct nfs_readargs *args) | 960 | const struct nfs_readargs *args) |
961 | { | 961 | { |
962 | encode_read3args(xdr, args); | 962 | encode_read3args(xdr, args); |
963 | prepare_reply_buffer(req, args->pages, args->pgbase, | 963 | prepare_reply_buffer(req, args->pages, args->pgbase, |
964 | args->count, NFS3_readres_sz); | 964 | args->count, NFS3_readres_sz); |
965 | req->rq_rcv_buf.flags |= XDRBUF_READ; | 965 | req->rq_rcv_buf.flags |= XDRBUF_READ; |
966 | } | 966 | } |
967 | 967 | ||
968 | /* | 968 | /* |
969 | * 3.3.7 WRITE3args | 969 | * 3.3.7 WRITE3args |
970 | * | 970 | * |
971 | * enum stable_how { | 971 | * enum stable_how { |
972 | * UNSTABLE = 0, | 972 | * UNSTABLE = 0, |
973 | * DATA_SYNC = 1, | 973 | * DATA_SYNC = 1, |
974 | * FILE_SYNC = 2 | 974 | * FILE_SYNC = 2 |
975 | * }; | 975 | * }; |
976 | * | 976 | * |
977 | * struct WRITE3args { | 977 | * struct WRITE3args { |
978 | * nfs_fh3 file; | 978 | * nfs_fh3 file; |
979 | * offset3 offset; | 979 | * offset3 offset; |
980 | * count3 count; | 980 | * count3 count; |
981 | * stable_how stable; | 981 | * stable_how stable; |
982 | * opaque data<>; | 982 | * opaque data<>; |
983 | * }; | 983 | * }; |
984 | */ | 984 | */ |
985 | static void encode_write3args(struct xdr_stream *xdr, | 985 | static void encode_write3args(struct xdr_stream *xdr, |
986 | const struct nfs_writeargs *args) | 986 | const struct nfs_writeargs *args) |
987 | { | 987 | { |
988 | __be32 *p; | 988 | __be32 *p; |
989 | 989 | ||
990 | encode_nfs_fh3(xdr, args->fh); | 990 | encode_nfs_fh3(xdr, args->fh); |
991 | 991 | ||
992 | p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4); | 992 | p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4); |
993 | p = xdr_encode_hyper(p, args->offset); | 993 | p = xdr_encode_hyper(p, args->offset); |
994 | *p++ = cpu_to_be32(args->count); | 994 | *p++ = cpu_to_be32(args->count); |
995 | *p++ = cpu_to_be32(args->stable); | 995 | *p++ = cpu_to_be32(args->stable); |
996 | *p = cpu_to_be32(args->count); | 996 | *p = cpu_to_be32(args->count); |
997 | xdr_write_pages(xdr, args->pages, args->pgbase, args->count); | 997 | xdr_write_pages(xdr, args->pages, args->pgbase, args->count); |
998 | } | 998 | } |
999 | 999 | ||
1000 | static void nfs3_xdr_enc_write3args(struct rpc_rqst *req, | 1000 | static void nfs3_xdr_enc_write3args(struct rpc_rqst *req, |
1001 | struct xdr_stream *xdr, | 1001 | struct xdr_stream *xdr, |
1002 | const struct nfs_writeargs *args) | 1002 | const struct nfs_writeargs *args) |
1003 | { | 1003 | { |
1004 | encode_write3args(xdr, args); | 1004 | encode_write3args(xdr, args); |
1005 | xdr->buf->flags |= XDRBUF_WRITE; | 1005 | xdr->buf->flags |= XDRBUF_WRITE; |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | /* | 1008 | /* |
1009 | * 3.3.8 CREATE3args | 1009 | * 3.3.8 CREATE3args |
1010 | * | 1010 | * |
1011 | * enum createmode3 { | 1011 | * enum createmode3 { |
1012 | * UNCHECKED = 0, | 1012 | * UNCHECKED = 0, |
1013 | * GUARDED = 1, | 1013 | * GUARDED = 1, |
1014 | * EXCLUSIVE = 2 | 1014 | * EXCLUSIVE = 2 |
1015 | * }; | 1015 | * }; |
1016 | * | 1016 | * |
1017 | * union createhow3 switch (createmode3 mode) { | 1017 | * union createhow3 switch (createmode3 mode) { |
1018 | * case UNCHECKED: | 1018 | * case UNCHECKED: |
1019 | * case GUARDED: | 1019 | * case GUARDED: |
1020 | * sattr3 obj_attributes; | 1020 | * sattr3 obj_attributes; |
1021 | * case EXCLUSIVE: | 1021 | * case EXCLUSIVE: |
1022 | * createverf3 verf; | 1022 | * createverf3 verf; |
1023 | * }; | 1023 | * }; |
1024 | * | 1024 | * |
1025 | * struct CREATE3args { | 1025 | * struct CREATE3args { |
1026 | * diropargs3 where; | 1026 | * diropargs3 where; |
1027 | * createhow3 how; | 1027 | * createhow3 how; |
1028 | * }; | 1028 | * }; |
1029 | */ | 1029 | */ |
1030 | static void encode_createhow3(struct xdr_stream *xdr, | 1030 | static void encode_createhow3(struct xdr_stream *xdr, |
1031 | const struct nfs3_createargs *args) | 1031 | const struct nfs3_createargs *args) |
1032 | { | 1032 | { |
1033 | encode_uint32(xdr, args->createmode); | 1033 | encode_uint32(xdr, args->createmode); |
1034 | switch (args->createmode) { | 1034 | switch (args->createmode) { |
1035 | case NFS3_CREATE_UNCHECKED: | 1035 | case NFS3_CREATE_UNCHECKED: |
1036 | case NFS3_CREATE_GUARDED: | 1036 | case NFS3_CREATE_GUARDED: |
1037 | encode_sattr3(xdr, args->sattr); | 1037 | encode_sattr3(xdr, args->sattr); |
1038 | break; | 1038 | break; |
1039 | case NFS3_CREATE_EXCLUSIVE: | 1039 | case NFS3_CREATE_EXCLUSIVE: |
1040 | encode_createverf3(xdr, args->verifier); | 1040 | encode_createverf3(xdr, args->verifier); |
1041 | break; | 1041 | break; |
1042 | default: | 1042 | default: |
1043 | BUG(); | 1043 | BUG(); |
1044 | } | 1044 | } |
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static void nfs3_xdr_enc_create3args(struct rpc_rqst *req, | 1047 | static void nfs3_xdr_enc_create3args(struct rpc_rqst *req, |
1048 | struct xdr_stream *xdr, | 1048 | struct xdr_stream *xdr, |
1049 | const struct nfs3_createargs *args) | 1049 | const struct nfs3_createargs *args) |
1050 | { | 1050 | { |
1051 | encode_diropargs3(xdr, args->fh, args->name, args->len); | 1051 | encode_diropargs3(xdr, args->fh, args->name, args->len); |
1052 | encode_createhow3(xdr, args); | 1052 | encode_createhow3(xdr, args); |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | /* | 1055 | /* |
1056 | * 3.3.9 MKDIR3args | 1056 | * 3.3.9 MKDIR3args |
1057 | * | 1057 | * |
1058 | * struct MKDIR3args { | 1058 | * struct MKDIR3args { |
1059 | * diropargs3 where; | 1059 | * diropargs3 where; |
1060 | * sattr3 attributes; | 1060 | * sattr3 attributes; |
1061 | * }; | 1061 | * }; |
1062 | */ | 1062 | */ |
1063 | static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, | 1063 | static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, |
1064 | struct xdr_stream *xdr, | 1064 | struct xdr_stream *xdr, |
1065 | const struct nfs3_mkdirargs *args) | 1065 | const struct nfs3_mkdirargs *args) |
1066 | { | 1066 | { |
1067 | encode_diropargs3(xdr, args->fh, args->name, args->len); | 1067 | encode_diropargs3(xdr, args->fh, args->name, args->len); |
1068 | encode_sattr3(xdr, args->sattr); | 1068 | encode_sattr3(xdr, args->sattr); |
1069 | } | 1069 | } |
1070 | 1070 | ||
1071 | /* | 1071 | /* |
1072 | * 3.3.10 SYMLINK3args | 1072 | * 3.3.10 SYMLINK3args |
1073 | * | 1073 | * |
1074 | * struct symlinkdata3 { | 1074 | * struct symlinkdata3 { |
1075 | * sattr3 symlink_attributes; | 1075 | * sattr3 symlink_attributes; |
1076 | * nfspath3 symlink_data; | 1076 | * nfspath3 symlink_data; |
1077 | * }; | 1077 | * }; |
1078 | * | 1078 | * |
1079 | * struct SYMLINK3args { | 1079 | * struct SYMLINK3args { |
1080 | * diropargs3 where; | 1080 | * diropargs3 where; |
1081 | * symlinkdata3 symlink; | 1081 | * symlinkdata3 symlink; |
1082 | * }; | 1082 | * }; |
1083 | */ | 1083 | */ |
1084 | static void encode_symlinkdata3(struct xdr_stream *xdr, | 1084 | static void encode_symlinkdata3(struct xdr_stream *xdr, |
1085 | const struct nfs3_symlinkargs *args) | 1085 | const struct nfs3_symlinkargs *args) |
1086 | { | 1086 | { |
1087 | encode_sattr3(xdr, args->sattr); | 1087 | encode_sattr3(xdr, args->sattr); |
1088 | encode_nfspath3(xdr, args->pages, args->pathlen); | 1088 | encode_nfspath3(xdr, args->pages, args->pathlen); |
1089 | } | 1089 | } |
1090 | 1090 | ||
1091 | static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, | 1091 | static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, |
1092 | struct xdr_stream *xdr, | 1092 | struct xdr_stream *xdr, |
1093 | const struct nfs3_symlinkargs *args) | 1093 | const struct nfs3_symlinkargs *args) |
1094 | { | 1094 | { |
1095 | encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen); | 1095 | encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen); |
1096 | encode_symlinkdata3(xdr, args); | 1096 | encode_symlinkdata3(xdr, args); |
1097 | } | 1097 | } |
1098 | 1098 | ||
1099 | /* | 1099 | /* |
1100 | * 3.3.11 MKNOD3args | 1100 | * 3.3.11 MKNOD3args |
1101 | * | 1101 | * |
1102 | * struct devicedata3 { | 1102 | * struct devicedata3 { |
1103 | * sattr3 dev_attributes; | 1103 | * sattr3 dev_attributes; |
1104 | * specdata3 spec; | 1104 | * specdata3 spec; |
1105 | * }; | 1105 | * }; |
1106 | * | 1106 | * |
1107 | * union mknoddata3 switch (ftype3 type) { | 1107 | * union mknoddata3 switch (ftype3 type) { |
1108 | * case NF3CHR: | 1108 | * case NF3CHR: |
1109 | * case NF3BLK: | 1109 | * case NF3BLK: |
1110 | * devicedata3 device; | 1110 | * devicedata3 device; |
1111 | * case NF3SOCK: | 1111 | * case NF3SOCK: |
1112 | * case NF3FIFO: | 1112 | * case NF3FIFO: |
1113 | * sattr3 pipe_attributes; | 1113 | * sattr3 pipe_attributes; |
1114 | * default: | 1114 | * default: |
1115 | * void; | 1115 | * void; |
1116 | * }; | 1116 | * }; |
1117 | * | 1117 | * |
1118 | * struct MKNOD3args { | 1118 | * struct MKNOD3args { |
1119 | * diropargs3 where; | 1119 | * diropargs3 where; |
1120 | * mknoddata3 what; | 1120 | * mknoddata3 what; |
1121 | * }; | 1121 | * }; |
1122 | */ | 1122 | */ |
1123 | static void encode_devicedata3(struct xdr_stream *xdr, | 1123 | static void encode_devicedata3(struct xdr_stream *xdr, |
1124 | const struct nfs3_mknodargs *args) | 1124 | const struct nfs3_mknodargs *args) |
1125 | { | 1125 | { |
1126 | encode_sattr3(xdr, args->sattr); | 1126 | encode_sattr3(xdr, args->sattr); |
1127 | encode_specdata3(xdr, args->rdev); | 1127 | encode_specdata3(xdr, args->rdev); |
1128 | } | 1128 | } |
1129 | 1129 | ||
1130 | static void encode_mknoddata3(struct xdr_stream *xdr, | 1130 | static void encode_mknoddata3(struct xdr_stream *xdr, |
1131 | const struct nfs3_mknodargs *args) | 1131 | const struct nfs3_mknodargs *args) |
1132 | { | 1132 | { |
1133 | encode_ftype3(xdr, args->type); | 1133 | encode_ftype3(xdr, args->type); |
1134 | switch (args->type) { | 1134 | switch (args->type) { |
1135 | case NF3CHR: | 1135 | case NF3CHR: |
1136 | case NF3BLK: | 1136 | case NF3BLK: |
1137 | encode_devicedata3(xdr, args); | 1137 | encode_devicedata3(xdr, args); |
1138 | break; | 1138 | break; |
1139 | case NF3SOCK: | 1139 | case NF3SOCK: |
1140 | case NF3FIFO: | 1140 | case NF3FIFO: |
1141 | encode_sattr3(xdr, args->sattr); | 1141 | encode_sattr3(xdr, args->sattr); |
1142 | break; | 1142 | break; |
1143 | case NF3REG: | 1143 | case NF3REG: |
1144 | case NF3DIR: | 1144 | case NF3DIR: |
1145 | break; | 1145 | break; |
1146 | default: | 1146 | default: |
1147 | BUG(); | 1147 | BUG(); |
1148 | } | 1148 | } |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, | 1151 | static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, |
1152 | struct xdr_stream *xdr, | 1152 | struct xdr_stream *xdr, |
1153 | const struct nfs3_mknodargs *args) | 1153 | const struct nfs3_mknodargs *args) |
1154 | { | 1154 | { |
1155 | encode_diropargs3(xdr, args->fh, args->name, args->len); | 1155 | encode_diropargs3(xdr, args->fh, args->name, args->len); |
1156 | encode_mknoddata3(xdr, args); | 1156 | encode_mknoddata3(xdr, args); |
1157 | } | 1157 | } |
1158 | 1158 | ||
1159 | /* | 1159 | /* |
1160 | * 3.3.12 REMOVE3args | 1160 | * 3.3.12 REMOVE3args |
1161 | * | 1161 | * |
1162 | * struct REMOVE3args { | 1162 | * struct REMOVE3args { |
1163 | * diropargs3 object; | 1163 | * diropargs3 object; |
1164 | * }; | 1164 | * }; |
1165 | */ | 1165 | */ |
1166 | static void nfs3_xdr_enc_remove3args(struct rpc_rqst *req, | 1166 | static void nfs3_xdr_enc_remove3args(struct rpc_rqst *req, |
1167 | struct xdr_stream *xdr, | 1167 | struct xdr_stream *xdr, |
1168 | const struct nfs_removeargs *args) | 1168 | const struct nfs_removeargs *args) |
1169 | { | 1169 | { |
1170 | encode_diropargs3(xdr, args->fh, args->name.name, args->name.len); | 1170 | encode_diropargs3(xdr, args->fh, args->name.name, args->name.len); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | /* | 1173 | /* |
1174 | * 3.3.14 RENAME3args | 1174 | * 3.3.14 RENAME3args |
1175 | * | 1175 | * |
1176 | * struct RENAME3args { | 1176 | * struct RENAME3args { |
1177 | * diropargs3 from; | 1177 | * diropargs3 from; |
1178 | * diropargs3 to; | 1178 | * diropargs3 to; |
1179 | * }; | 1179 | * }; |
1180 | */ | 1180 | */ |
1181 | static void nfs3_xdr_enc_rename3args(struct rpc_rqst *req, | 1181 | static void nfs3_xdr_enc_rename3args(struct rpc_rqst *req, |
1182 | struct xdr_stream *xdr, | 1182 | struct xdr_stream *xdr, |
1183 | const struct nfs_renameargs *args) | 1183 | const struct nfs_renameargs *args) |
1184 | { | 1184 | { |
1185 | const struct qstr *old = args->old_name; | 1185 | const struct qstr *old = args->old_name; |
1186 | const struct qstr *new = args->new_name; | 1186 | const struct qstr *new = args->new_name; |
1187 | 1187 | ||
1188 | encode_diropargs3(xdr, args->old_dir, old->name, old->len); | 1188 | encode_diropargs3(xdr, args->old_dir, old->name, old->len); |
1189 | encode_diropargs3(xdr, args->new_dir, new->name, new->len); | 1189 | encode_diropargs3(xdr, args->new_dir, new->name, new->len); |
1190 | } | 1190 | } |
1191 | 1191 | ||
1192 | /* | 1192 | /* |
1193 | * 3.3.15 LINK3args | 1193 | * 3.3.15 LINK3args |
1194 | * | 1194 | * |
1195 | * struct LINK3args { | 1195 | * struct LINK3args { |
1196 | * nfs_fh3 file; | 1196 | * nfs_fh3 file; |
1197 | * diropargs3 link; | 1197 | * diropargs3 link; |
1198 | * }; | 1198 | * }; |
1199 | */ | 1199 | */ |
1200 | static void nfs3_xdr_enc_link3args(struct rpc_rqst *req, | 1200 | static void nfs3_xdr_enc_link3args(struct rpc_rqst *req, |
1201 | struct xdr_stream *xdr, | 1201 | struct xdr_stream *xdr, |
1202 | const struct nfs3_linkargs *args) | 1202 | const struct nfs3_linkargs *args) |
1203 | { | 1203 | { |
1204 | encode_nfs_fh3(xdr, args->fromfh); | 1204 | encode_nfs_fh3(xdr, args->fromfh); |
1205 | encode_diropargs3(xdr, args->tofh, args->toname, args->tolen); | 1205 | encode_diropargs3(xdr, args->tofh, args->toname, args->tolen); |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | /* | 1208 | /* |
1209 | * 3.3.16 READDIR3args | 1209 | * 3.3.16 READDIR3args |
1210 | * | 1210 | * |
1211 | * struct READDIR3args { | 1211 | * struct READDIR3args { |
1212 | * nfs_fh3 dir; | 1212 | * nfs_fh3 dir; |
1213 | * cookie3 cookie; | 1213 | * cookie3 cookie; |
1214 | * cookieverf3 cookieverf; | 1214 | * cookieverf3 cookieverf; |
1215 | * count3 count; | 1215 | * count3 count; |
1216 | * }; | 1216 | * }; |
1217 | */ | 1217 | */ |
1218 | static void encode_readdir3args(struct xdr_stream *xdr, | 1218 | static void encode_readdir3args(struct xdr_stream *xdr, |
1219 | const struct nfs3_readdirargs *args) | 1219 | const struct nfs3_readdirargs *args) |
1220 | { | 1220 | { |
1221 | __be32 *p; | 1221 | __be32 *p; |
1222 | 1222 | ||
1223 | encode_nfs_fh3(xdr, args->fh); | 1223 | encode_nfs_fh3(xdr, args->fh); |
1224 | 1224 | ||
1225 | p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4); | 1225 | p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4); |
1226 | p = xdr_encode_cookie3(p, args->cookie); | 1226 | p = xdr_encode_cookie3(p, args->cookie); |
1227 | p = xdr_encode_cookieverf3(p, args->verf); | 1227 | p = xdr_encode_cookieverf3(p, args->verf); |
1228 | *p = cpu_to_be32(args->count); | 1228 | *p = cpu_to_be32(args->count); |
1229 | } | 1229 | } |
1230 | 1230 | ||
1231 | static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, | 1231 | static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, |
1232 | struct xdr_stream *xdr, | 1232 | struct xdr_stream *xdr, |
1233 | const struct nfs3_readdirargs *args) | 1233 | const struct nfs3_readdirargs *args) |
1234 | { | 1234 | { |
1235 | encode_readdir3args(xdr, args); | 1235 | encode_readdir3args(xdr, args); |
1236 | prepare_reply_buffer(req, args->pages, 0, | 1236 | prepare_reply_buffer(req, args->pages, 0, |
1237 | args->count, NFS3_readdirres_sz); | 1237 | args->count, NFS3_readdirres_sz); |
1238 | } | 1238 | } |
1239 | 1239 | ||
1240 | /* | 1240 | /* |
1241 | * 3.3.17 READDIRPLUS3args | 1241 | * 3.3.17 READDIRPLUS3args |
1242 | * | 1242 | * |
1243 | * struct READDIRPLUS3args { | 1243 | * struct READDIRPLUS3args { |
1244 | * nfs_fh3 dir; | 1244 | * nfs_fh3 dir; |
1245 | * cookie3 cookie; | 1245 | * cookie3 cookie; |
1246 | * cookieverf3 cookieverf; | 1246 | * cookieverf3 cookieverf; |
1247 | * count3 dircount; | 1247 | * count3 dircount; |
1248 | * count3 maxcount; | 1248 | * count3 maxcount; |
1249 | * }; | 1249 | * }; |
1250 | */ | 1250 | */ |
1251 | static void encode_readdirplus3args(struct xdr_stream *xdr, | 1251 | static void encode_readdirplus3args(struct xdr_stream *xdr, |
1252 | const struct nfs3_readdirargs *args) | 1252 | const struct nfs3_readdirargs *args) |
1253 | { | 1253 | { |
1254 | __be32 *p; | 1254 | __be32 *p; |
1255 | 1255 | ||
1256 | encode_nfs_fh3(xdr, args->fh); | 1256 | encode_nfs_fh3(xdr, args->fh); |
1257 | 1257 | ||
1258 | p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4); | 1258 | p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4); |
1259 | p = xdr_encode_cookie3(p, args->cookie); | 1259 | p = xdr_encode_cookie3(p, args->cookie); |
1260 | p = xdr_encode_cookieverf3(p, args->verf); | 1260 | p = xdr_encode_cookieverf3(p, args->verf); |
1261 | 1261 | ||
1262 | /* | 1262 | /* |
1263 | * readdirplus: need dircount + buffer size. | 1263 | * readdirplus: need dircount + buffer size. |
1264 | * We just make sure we make dircount big enough | 1264 | * We just make sure we make dircount big enough |
1265 | */ | 1265 | */ |
1266 | *p++ = cpu_to_be32(args->count >> 3); | 1266 | *p++ = cpu_to_be32(args->count >> 3); |
1267 | 1267 | ||
1268 | *p = cpu_to_be32(args->count); | 1268 | *p = cpu_to_be32(args->count); |
1269 | } | 1269 | } |
1270 | 1270 | ||
1271 | static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, | 1271 | static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, |
1272 | struct xdr_stream *xdr, | 1272 | struct xdr_stream *xdr, |
1273 | const struct nfs3_readdirargs *args) | 1273 | const struct nfs3_readdirargs *args) |
1274 | { | 1274 | { |
1275 | encode_readdirplus3args(xdr, args); | 1275 | encode_readdirplus3args(xdr, args); |
1276 | prepare_reply_buffer(req, args->pages, 0, | 1276 | prepare_reply_buffer(req, args->pages, 0, |
1277 | args->count, NFS3_readdirres_sz); | 1277 | args->count, NFS3_readdirres_sz); |
1278 | } | 1278 | } |
1279 | 1279 | ||
1280 | /* | 1280 | /* |
1281 | * 3.3.21 COMMIT3args | 1281 | * 3.3.21 COMMIT3args |
1282 | * | 1282 | * |
1283 | * struct COMMIT3args { | 1283 | * struct COMMIT3args { |
1284 | * nfs_fh3 file; | 1284 | * nfs_fh3 file; |
1285 | * offset3 offset; | 1285 | * offset3 offset; |
1286 | * count3 count; | 1286 | * count3 count; |
1287 | * }; | 1287 | * }; |
1288 | */ | 1288 | */ |
1289 | static void encode_commit3args(struct xdr_stream *xdr, | 1289 | static void encode_commit3args(struct xdr_stream *xdr, |
1290 | const struct nfs_writeargs *args) | 1290 | const struct nfs_writeargs *args) |
1291 | { | 1291 | { |
1292 | __be32 *p; | 1292 | __be32 *p; |
1293 | 1293 | ||
1294 | encode_nfs_fh3(xdr, args->fh); | 1294 | encode_nfs_fh3(xdr, args->fh); |
1295 | 1295 | ||
1296 | p = xdr_reserve_space(xdr, 8 + 4); | 1296 | p = xdr_reserve_space(xdr, 8 + 4); |
1297 | p = xdr_encode_hyper(p, args->offset); | 1297 | p = xdr_encode_hyper(p, args->offset); |
1298 | *p = cpu_to_be32(args->count); | 1298 | *p = cpu_to_be32(args->count); |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req, | 1301 | static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req, |
1302 | struct xdr_stream *xdr, | 1302 | struct xdr_stream *xdr, |
1303 | const struct nfs_writeargs *args) | 1303 | const struct nfs_writeargs *args) |
1304 | { | 1304 | { |
1305 | encode_commit3args(xdr, args); | 1305 | encode_commit3args(xdr, args); |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | #ifdef CONFIG_NFS_V3_ACL | 1308 | #ifdef CONFIG_NFS_V3_ACL |
1309 | 1309 | ||
1310 | static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, | 1310 | static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, |
1311 | struct xdr_stream *xdr, | 1311 | struct xdr_stream *xdr, |
1312 | const struct nfs3_getaclargs *args) | 1312 | const struct nfs3_getaclargs *args) |
1313 | { | 1313 | { |
1314 | encode_nfs_fh3(xdr, args->fh); | 1314 | encode_nfs_fh3(xdr, args->fh); |
1315 | encode_uint32(xdr, args->mask); | 1315 | encode_uint32(xdr, args->mask); |
1316 | if (args->mask & (NFS_ACL | NFS_DFACL)) | 1316 | if (args->mask & (NFS_ACL | NFS_DFACL)) |
1317 | prepare_reply_buffer(req, args->pages, 0, | 1317 | prepare_reply_buffer(req, args->pages, 0, |
1318 | NFSACL_MAXPAGES << PAGE_SHIFT, | 1318 | NFSACL_MAXPAGES << PAGE_SHIFT, |
1319 | ACL3_getaclres_sz); | 1319 | ACL3_getaclres_sz); |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, | 1322 | static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, |
1323 | struct xdr_stream *xdr, | 1323 | struct xdr_stream *xdr, |
1324 | const struct nfs3_setaclargs *args) | 1324 | const struct nfs3_setaclargs *args) |
1325 | { | 1325 | { |
1326 | unsigned int base; | 1326 | unsigned int base; |
1327 | int error; | 1327 | int error; |
1328 | 1328 | ||
1329 | encode_nfs_fh3(xdr, NFS_FH(args->inode)); | 1329 | encode_nfs_fh3(xdr, NFS_FH(args->inode)); |
1330 | encode_uint32(xdr, args->mask); | 1330 | encode_uint32(xdr, args->mask); |
1331 | 1331 | ||
1332 | base = req->rq_slen; | 1332 | base = req->rq_slen; |
1333 | if (args->npages != 0) | 1333 | if (args->npages != 0) |
1334 | xdr_write_pages(xdr, args->pages, 0, args->len); | 1334 | xdr_write_pages(xdr, args->pages, 0, args->len); |
1335 | else | 1335 | else |
1336 | xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE); | 1336 | xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE); |
1337 | 1337 | ||
1338 | error = nfsacl_encode(xdr->buf, base, args->inode, | 1338 | error = nfsacl_encode(xdr->buf, base, args->inode, |
1339 | (args->mask & NFS_ACL) ? | 1339 | (args->mask & NFS_ACL) ? |
1340 | args->acl_access : NULL, 1, 0); | 1340 | args->acl_access : NULL, 1, 0); |
1341 | BUG_ON(error < 0); | 1341 | BUG_ON(error < 0); |
1342 | error = nfsacl_encode(xdr->buf, base + error, args->inode, | 1342 | error = nfsacl_encode(xdr->buf, base + error, args->inode, |
1343 | (args->mask & NFS_DFACL) ? | 1343 | (args->mask & NFS_DFACL) ? |
1344 | args->acl_default : NULL, 1, | 1344 | args->acl_default : NULL, 1, |
1345 | NFS_ACL_DEFAULT); | 1345 | NFS_ACL_DEFAULT); |
1346 | BUG_ON(error < 0); | 1346 | BUG_ON(error < 0); |
1347 | } | 1347 | } |
1348 | 1348 | ||
1349 | #endif /* CONFIG_NFS_V3_ACL */ | 1349 | #endif /* CONFIG_NFS_V3_ACL */ |
1350 | 1350 | ||
1351 | /* | 1351 | /* |
1352 | * NFSv3 XDR decode functions | 1352 | * NFSv3 XDR decode functions |
1353 | * | 1353 | * |
1354 | * NFSv3 result types are defined in section 3.3 of RFC 1813: | 1354 | * NFSv3 result types are defined in section 3.3 of RFC 1813: |
1355 | * "NFS Version 3 Protocol Specification". | 1355 | * "NFS Version 3 Protocol Specification". |
1356 | */ | 1356 | */ |
1357 | 1357 | ||
1358 | /* | 1358 | /* |
1359 | * 3.3.1 GETATTR3res | 1359 | * 3.3.1 GETATTR3res |
1360 | * | 1360 | * |
1361 | * struct GETATTR3resok { | 1361 | * struct GETATTR3resok { |
1362 | * fattr3 obj_attributes; | 1362 | * fattr3 obj_attributes; |
1363 | * }; | 1363 | * }; |
1364 | * | 1364 | * |
1365 | * union GETATTR3res switch (nfsstat3 status) { | 1365 | * union GETATTR3res switch (nfsstat3 status) { |
1366 | * case NFS3_OK: | 1366 | * case NFS3_OK: |
1367 | * GETATTR3resok resok; | 1367 | * GETATTR3resok resok; |
1368 | * default: | 1368 | * default: |
1369 | * void; | 1369 | * void; |
1370 | * }; | 1370 | * }; |
1371 | */ | 1371 | */ |
1372 | static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req, | 1372 | static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req, |
1373 | struct xdr_stream *xdr, | 1373 | struct xdr_stream *xdr, |
1374 | struct nfs_fattr *result) | 1374 | struct nfs_fattr *result) |
1375 | { | 1375 | { |
1376 | enum nfs_stat status; | 1376 | enum nfs_stat status; |
1377 | int error; | 1377 | int error; |
1378 | 1378 | ||
1379 | error = decode_nfsstat3(xdr, &status); | 1379 | error = decode_nfsstat3(xdr, &status); |
1380 | if (unlikely(error)) | 1380 | if (unlikely(error)) |
1381 | goto out; | 1381 | goto out; |
1382 | if (status != NFS3_OK) | 1382 | if (status != NFS3_OK) |
1383 | goto out_default; | 1383 | goto out_default; |
1384 | error = decode_fattr3(xdr, result); | 1384 | error = decode_fattr3(xdr, result); |
1385 | out: | 1385 | out: |
1386 | return error; | 1386 | return error; |
1387 | out_default: | 1387 | out_default: |
1388 | return nfs_stat_to_errno(status); | 1388 | return nfs_stat_to_errno(status); |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | /* | 1391 | /* |
1392 | * 3.3.2 SETATTR3res | 1392 | * 3.3.2 SETATTR3res |
1393 | * | 1393 | * |
1394 | * struct SETATTR3resok { | 1394 | * struct SETATTR3resok { |
1395 | * wcc_data obj_wcc; | 1395 | * wcc_data obj_wcc; |
1396 | * }; | 1396 | * }; |
1397 | * | 1397 | * |
1398 | * struct SETATTR3resfail { | 1398 | * struct SETATTR3resfail { |
1399 | * wcc_data obj_wcc; | 1399 | * wcc_data obj_wcc; |
1400 | * }; | 1400 | * }; |
1401 | * | 1401 | * |
1402 | * union SETATTR3res switch (nfsstat3 status) { | 1402 | * union SETATTR3res switch (nfsstat3 status) { |
1403 | * case NFS3_OK: | 1403 | * case NFS3_OK: |
1404 | * SETATTR3resok resok; | 1404 | * SETATTR3resok resok; |
1405 | * default: | 1405 | * default: |
1406 | * SETATTR3resfail resfail; | 1406 | * SETATTR3resfail resfail; |
1407 | * }; | 1407 | * }; |
1408 | */ | 1408 | */ |
1409 | static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req, | 1409 | static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req, |
1410 | struct xdr_stream *xdr, | 1410 | struct xdr_stream *xdr, |
1411 | struct nfs_fattr *result) | 1411 | struct nfs_fattr *result) |
1412 | { | 1412 | { |
1413 | enum nfs_stat status; | 1413 | enum nfs_stat status; |
1414 | int error; | 1414 | int error; |
1415 | 1415 | ||
1416 | error = decode_nfsstat3(xdr, &status); | 1416 | error = decode_nfsstat3(xdr, &status); |
1417 | if (unlikely(error)) | 1417 | if (unlikely(error)) |
1418 | goto out; | 1418 | goto out; |
1419 | error = decode_wcc_data(xdr, result); | 1419 | error = decode_wcc_data(xdr, result); |
1420 | if (unlikely(error)) | 1420 | if (unlikely(error)) |
1421 | goto out; | 1421 | goto out; |
1422 | if (status != NFS3_OK) | 1422 | if (status != NFS3_OK) |
1423 | goto out_status; | 1423 | goto out_status; |
1424 | out: | 1424 | out: |
1425 | return error; | 1425 | return error; |
1426 | out_status: | 1426 | out_status: |
1427 | return nfs_stat_to_errno(status); | 1427 | return nfs_stat_to_errno(status); |
1428 | } | 1428 | } |
1429 | 1429 | ||
1430 | /* | 1430 | /* |
1431 | * 3.3.3 LOOKUP3res | 1431 | * 3.3.3 LOOKUP3res |
1432 | * | 1432 | * |
1433 | * struct LOOKUP3resok { | 1433 | * struct LOOKUP3resok { |
1434 | * nfs_fh3 object; | 1434 | * nfs_fh3 object; |
1435 | * post_op_attr obj_attributes; | 1435 | * post_op_attr obj_attributes; |
1436 | * post_op_attr dir_attributes; | 1436 | * post_op_attr dir_attributes; |
1437 | * }; | 1437 | * }; |
1438 | * | 1438 | * |
1439 | * struct LOOKUP3resfail { | 1439 | * struct LOOKUP3resfail { |
1440 | * post_op_attr dir_attributes; | 1440 | * post_op_attr dir_attributes; |
1441 | * }; | 1441 | * }; |
1442 | * | 1442 | * |
1443 | * union LOOKUP3res switch (nfsstat3 status) { | 1443 | * union LOOKUP3res switch (nfsstat3 status) { |
1444 | * case NFS3_OK: | 1444 | * case NFS3_OK: |
1445 | * LOOKUP3resok resok; | 1445 | * LOOKUP3resok resok; |
1446 | * default: | 1446 | * default: |
1447 | * LOOKUP3resfail resfail; | 1447 | * LOOKUP3resfail resfail; |
1448 | * }; | 1448 | * }; |
1449 | */ | 1449 | */ |
1450 | static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req, | 1450 | static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req, |
1451 | struct xdr_stream *xdr, | 1451 | struct xdr_stream *xdr, |
1452 | struct nfs3_diropres *result) | 1452 | struct nfs3_diropres *result) |
1453 | { | 1453 | { |
1454 | enum nfs_stat status; | 1454 | enum nfs_stat status; |
1455 | int error; | 1455 | int error; |
1456 | 1456 | ||
1457 | error = decode_nfsstat3(xdr, &status); | 1457 | error = decode_nfsstat3(xdr, &status); |
1458 | if (unlikely(error)) | 1458 | if (unlikely(error)) |
1459 | goto out; | 1459 | goto out; |
1460 | if (status != NFS3_OK) | 1460 | if (status != NFS3_OK) |
1461 | goto out_default; | 1461 | goto out_default; |
1462 | error = decode_nfs_fh3(xdr, result->fh); | 1462 | error = decode_nfs_fh3(xdr, result->fh); |
1463 | if (unlikely(error)) | 1463 | if (unlikely(error)) |
1464 | goto out; | 1464 | goto out; |
1465 | error = decode_post_op_attr(xdr, result->fattr); | 1465 | error = decode_post_op_attr(xdr, result->fattr); |
1466 | if (unlikely(error)) | 1466 | if (unlikely(error)) |
1467 | goto out; | 1467 | goto out; |
1468 | error = decode_post_op_attr(xdr, result->dir_attr); | 1468 | error = decode_post_op_attr(xdr, result->dir_attr); |
1469 | out: | 1469 | out: |
1470 | return error; | 1470 | return error; |
1471 | out_default: | 1471 | out_default: |
1472 | error = decode_post_op_attr(xdr, result->dir_attr); | 1472 | error = decode_post_op_attr(xdr, result->dir_attr); |
1473 | if (unlikely(error)) | 1473 | if (unlikely(error)) |
1474 | goto out; | 1474 | goto out; |
1475 | return nfs_stat_to_errno(status); | 1475 | return nfs_stat_to_errno(status); |
1476 | } | 1476 | } |
1477 | 1477 | ||
1478 | /* | 1478 | /* |
1479 | * 3.3.4 ACCESS3res | 1479 | * 3.3.4 ACCESS3res |
1480 | * | 1480 | * |
1481 | * struct ACCESS3resok { | 1481 | * struct ACCESS3resok { |
1482 | * post_op_attr obj_attributes; | 1482 | * post_op_attr obj_attributes; |
1483 | * uint32 access; | 1483 | * uint32 access; |
1484 | * }; | 1484 | * }; |
1485 | * | 1485 | * |
1486 | * struct ACCESS3resfail { | 1486 | * struct ACCESS3resfail { |
1487 | * post_op_attr obj_attributes; | 1487 | * post_op_attr obj_attributes; |
1488 | * }; | 1488 | * }; |
1489 | * | 1489 | * |
1490 | * union ACCESS3res switch (nfsstat3 status) { | 1490 | * union ACCESS3res switch (nfsstat3 status) { |
1491 | * case NFS3_OK: | 1491 | * case NFS3_OK: |
1492 | * ACCESS3resok resok; | 1492 | * ACCESS3resok resok; |
1493 | * default: | 1493 | * default: |
1494 | * ACCESS3resfail resfail; | 1494 | * ACCESS3resfail resfail; |
1495 | * }; | 1495 | * }; |
1496 | */ | 1496 | */ |
1497 | static int nfs3_xdr_dec_access3res(struct rpc_rqst *req, | 1497 | static int nfs3_xdr_dec_access3res(struct rpc_rqst *req, |
1498 | struct xdr_stream *xdr, | 1498 | struct xdr_stream *xdr, |
1499 | struct nfs3_accessres *result) | 1499 | struct nfs3_accessres *result) |
1500 | { | 1500 | { |
1501 | enum nfs_stat status; | 1501 | enum nfs_stat status; |
1502 | int error; | 1502 | int error; |
1503 | 1503 | ||
1504 | error = decode_nfsstat3(xdr, &status); | 1504 | error = decode_nfsstat3(xdr, &status); |
1505 | if (unlikely(error)) | 1505 | if (unlikely(error)) |
1506 | goto out; | 1506 | goto out; |
1507 | error = decode_post_op_attr(xdr, result->fattr); | 1507 | error = decode_post_op_attr(xdr, result->fattr); |
1508 | if (unlikely(error)) | 1508 | if (unlikely(error)) |
1509 | goto out; | 1509 | goto out; |
1510 | if (status != NFS3_OK) | 1510 | if (status != NFS3_OK) |
1511 | goto out_default; | 1511 | goto out_default; |
1512 | error = decode_uint32(xdr, &result->access); | 1512 | error = decode_uint32(xdr, &result->access); |
1513 | out: | 1513 | out: |
1514 | return error; | 1514 | return error; |
1515 | out_default: | 1515 | out_default: |
1516 | return nfs_stat_to_errno(status); | 1516 | return nfs_stat_to_errno(status); |
1517 | } | 1517 | } |
1518 | 1518 | ||
1519 | /* | 1519 | /* |
1520 | * 3.3.5 READLINK3res | 1520 | * 3.3.5 READLINK3res |
1521 | * | 1521 | * |
1522 | * struct READLINK3resok { | 1522 | * struct READLINK3resok { |
1523 | * post_op_attr symlink_attributes; | 1523 | * post_op_attr symlink_attributes; |
1524 | * nfspath3 data; | 1524 | * nfspath3 data; |
1525 | * }; | 1525 | * }; |
1526 | * | 1526 | * |
1527 | * struct READLINK3resfail { | 1527 | * struct READLINK3resfail { |
1528 | * post_op_attr symlink_attributes; | 1528 | * post_op_attr symlink_attributes; |
1529 | * }; | 1529 | * }; |
1530 | * | 1530 | * |
1531 | * union READLINK3res switch (nfsstat3 status) { | 1531 | * union READLINK3res switch (nfsstat3 status) { |
1532 | * case NFS3_OK: | 1532 | * case NFS3_OK: |
1533 | * READLINK3resok resok; | 1533 | * READLINK3resok resok; |
1534 | * default: | 1534 | * default: |
1535 | * READLINK3resfail resfail; | 1535 | * READLINK3resfail resfail; |
1536 | * }; | 1536 | * }; |
1537 | */ | 1537 | */ |
1538 | static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req, | 1538 | static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req, |
1539 | struct xdr_stream *xdr, | 1539 | struct xdr_stream *xdr, |
1540 | struct nfs_fattr *result) | 1540 | struct nfs_fattr *result) |
1541 | { | 1541 | { |
1542 | enum nfs_stat status; | 1542 | enum nfs_stat status; |
1543 | int error; | 1543 | int error; |
1544 | 1544 | ||
1545 | error = decode_nfsstat3(xdr, &status); | 1545 | error = decode_nfsstat3(xdr, &status); |
1546 | if (unlikely(error)) | 1546 | if (unlikely(error)) |
1547 | goto out; | 1547 | goto out; |
1548 | error = decode_post_op_attr(xdr, result); | 1548 | error = decode_post_op_attr(xdr, result); |
1549 | if (unlikely(error)) | 1549 | if (unlikely(error)) |
1550 | goto out; | 1550 | goto out; |
1551 | if (status != NFS3_OK) | 1551 | if (status != NFS3_OK) |
1552 | goto out_default; | 1552 | goto out_default; |
1553 | error = decode_nfspath3(xdr); | 1553 | error = decode_nfspath3(xdr); |
1554 | out: | 1554 | out: |
1555 | return error; | 1555 | return error; |
1556 | out_default: | 1556 | out_default: |
1557 | return nfs_stat_to_errno(status); | 1557 | return nfs_stat_to_errno(status); |
1558 | } | 1558 | } |
1559 | 1559 | ||
1560 | /* | 1560 | /* |
1561 | * 3.3.6 READ3res | 1561 | * 3.3.6 READ3res |
1562 | * | 1562 | * |
1563 | * struct READ3resok { | 1563 | * struct READ3resok { |
1564 | * post_op_attr file_attributes; | 1564 | * post_op_attr file_attributes; |
1565 | * count3 count; | 1565 | * count3 count; |
1566 | * bool eof; | 1566 | * bool eof; |
1567 | * opaque data<>; | 1567 | * opaque data<>; |
1568 | * }; | 1568 | * }; |
1569 | * | 1569 | * |
1570 | * struct READ3resfail { | 1570 | * struct READ3resfail { |
1571 | * post_op_attr file_attributes; | 1571 | * post_op_attr file_attributes; |
1572 | * }; | 1572 | * }; |
1573 | * | 1573 | * |
1574 | * union READ3res switch (nfsstat3 status) { | 1574 | * union READ3res switch (nfsstat3 status) { |
1575 | * case NFS3_OK: | 1575 | * case NFS3_OK: |
1576 | * READ3resok resok; | 1576 | * READ3resok resok; |
1577 | * default: | 1577 | * default: |
1578 | * READ3resfail resfail; | 1578 | * READ3resfail resfail; |
1579 | * }; | 1579 | * }; |
1580 | */ | 1580 | */ |
1581 | static int decode_read3resok(struct xdr_stream *xdr, | 1581 | static int decode_read3resok(struct xdr_stream *xdr, |
1582 | struct nfs_readres *result) | 1582 | struct nfs_readres *result) |
1583 | { | 1583 | { |
1584 | u32 eof, count, ocount, recvd; | 1584 | u32 eof, count, ocount, recvd; |
1585 | size_t hdrlen; | 1585 | size_t hdrlen; |
1586 | __be32 *p; | 1586 | __be32 *p; |
1587 | 1587 | ||
1588 | p = xdr_inline_decode(xdr, 4 + 4 + 4); | 1588 | p = xdr_inline_decode(xdr, 4 + 4 + 4); |
1589 | if (unlikely(p == NULL)) | 1589 | if (unlikely(p == NULL)) |
1590 | goto out_overflow; | 1590 | goto out_overflow; |
1591 | count = be32_to_cpup(p++); | 1591 | count = be32_to_cpup(p++); |
1592 | eof = be32_to_cpup(p++); | 1592 | eof = be32_to_cpup(p++); |
1593 | ocount = be32_to_cpup(p++); | 1593 | ocount = be32_to_cpup(p++); |
1594 | if (unlikely(ocount != count)) | 1594 | if (unlikely(ocount != count)) |
1595 | goto out_mismatch; | 1595 | goto out_mismatch; |
1596 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 1596 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; |
1597 | recvd = xdr->buf->len - hdrlen; | 1597 | recvd = xdr->buf->len - hdrlen; |
1598 | if (unlikely(count > recvd)) | 1598 | if (unlikely(count > recvd)) |
1599 | goto out_cheating; | 1599 | goto out_cheating; |
1600 | 1600 | ||
1601 | out: | 1601 | out: |
1602 | xdr_read_pages(xdr, count); | 1602 | xdr_read_pages(xdr, count); |
1603 | result->eof = eof; | 1603 | result->eof = eof; |
1604 | result->count = count; | 1604 | result->count = count; |
1605 | return count; | 1605 | return count; |
1606 | out_mismatch: | 1606 | out_mismatch: |
1607 | dprintk("NFS: READ count doesn't match length of opaque: " | 1607 | dprintk("NFS: READ count doesn't match length of opaque: " |
1608 | "count %u != ocount %u\n", count, ocount); | 1608 | "count %u != ocount %u\n", count, ocount); |
1609 | return -EIO; | 1609 | return -EIO; |
1610 | out_cheating: | 1610 | out_cheating: |
1611 | dprintk("NFS: server cheating in read result: " | 1611 | dprintk("NFS: server cheating in read result: " |
1612 | "count %u > recvd %u\n", count, recvd); | 1612 | "count %u > recvd %u\n", count, recvd); |
1613 | count = recvd; | 1613 | count = recvd; |
1614 | eof = 0; | 1614 | eof = 0; |
1615 | goto out; | 1615 | goto out; |
1616 | out_overflow: | 1616 | out_overflow: |
1617 | print_overflow_msg(__func__, xdr); | 1617 | print_overflow_msg(__func__, xdr); |
1618 | return -EIO; | 1618 | return -EIO; |
1619 | } | 1619 | } |
1620 | 1620 | ||
1621 | static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr, | 1621 | static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr, |
1622 | struct nfs_readres *result) | 1622 | struct nfs_readres *result) |
1623 | { | 1623 | { |
1624 | enum nfs_stat status; | 1624 | enum nfs_stat status; |
1625 | int error; | 1625 | int error; |
1626 | 1626 | ||
1627 | error = decode_nfsstat3(xdr, &status); | 1627 | error = decode_nfsstat3(xdr, &status); |
1628 | if (unlikely(error)) | 1628 | if (unlikely(error)) |
1629 | goto out; | 1629 | goto out; |
1630 | error = decode_post_op_attr(xdr, result->fattr); | 1630 | error = decode_post_op_attr(xdr, result->fattr); |
1631 | if (unlikely(error)) | 1631 | if (unlikely(error)) |
1632 | goto out; | 1632 | goto out; |
1633 | if (status != NFS3_OK) | 1633 | if (status != NFS3_OK) |
1634 | goto out_status; | 1634 | goto out_status; |
1635 | error = decode_read3resok(xdr, result); | 1635 | error = decode_read3resok(xdr, result); |
1636 | out: | 1636 | out: |
1637 | return error; | 1637 | return error; |
1638 | out_status: | 1638 | out_status: |
1639 | return nfs_stat_to_errno(status); | 1639 | return nfs_stat_to_errno(status); |
1640 | } | 1640 | } |
1641 | 1641 | ||
1642 | /* | 1642 | /* |
1643 | * 3.3.7 WRITE3res | 1643 | * 3.3.7 WRITE3res |
1644 | * | 1644 | * |
1645 | * enum stable_how { | 1645 | * enum stable_how { |
1646 | * UNSTABLE = 0, | 1646 | * UNSTABLE = 0, |
1647 | * DATA_SYNC = 1, | 1647 | * DATA_SYNC = 1, |
1648 | * FILE_SYNC = 2 | 1648 | * FILE_SYNC = 2 |
1649 | * }; | 1649 | * }; |
1650 | * | 1650 | * |
1651 | * struct WRITE3resok { | 1651 | * struct WRITE3resok { |
1652 | * wcc_data file_wcc; | 1652 | * wcc_data file_wcc; |
1653 | * count3 count; | 1653 | * count3 count; |
1654 | * stable_how committed; | 1654 | * stable_how committed; |
1655 | * writeverf3 verf; | 1655 | * writeverf3 verf; |
1656 | * }; | 1656 | * }; |
1657 | * | 1657 | * |
1658 | * struct WRITE3resfail { | 1658 | * struct WRITE3resfail { |
1659 | * wcc_data file_wcc; | 1659 | * wcc_data file_wcc; |
1660 | * }; | 1660 | * }; |
1661 | * | 1661 | * |
1662 | * union WRITE3res switch (nfsstat3 status) { | 1662 | * union WRITE3res switch (nfsstat3 status) { |
1663 | * case NFS3_OK: | 1663 | * case NFS3_OK: |
1664 | * WRITE3resok resok; | 1664 | * WRITE3resok resok; |
1665 | * default: | 1665 | * default: |
1666 | * WRITE3resfail resfail; | 1666 | * WRITE3resfail resfail; |
1667 | * }; | 1667 | * }; |
1668 | */ | 1668 | */ |
1669 | static int decode_write3resok(struct xdr_stream *xdr, | 1669 | static int decode_write3resok(struct xdr_stream *xdr, |
1670 | struct nfs_writeres *result) | 1670 | struct nfs_writeres *result) |
1671 | { | 1671 | { |
1672 | __be32 *p; | 1672 | __be32 *p; |
1673 | 1673 | ||
1674 | p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE); | 1674 | p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE); |
1675 | if (unlikely(p == NULL)) | 1675 | if (unlikely(p == NULL)) |
1676 | goto out_overflow; | 1676 | goto out_overflow; |
1677 | result->count = be32_to_cpup(p++); | 1677 | result->count = be32_to_cpup(p++); |
1678 | result->verf->committed = be32_to_cpup(p++); | 1678 | result->verf->committed = be32_to_cpup(p++); |
1679 | if (unlikely(result->verf->committed > NFS_FILE_SYNC)) | 1679 | if (unlikely(result->verf->committed > NFS_FILE_SYNC)) |
1680 | goto out_badvalue; | 1680 | goto out_badvalue; |
1681 | memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE); | 1681 | memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE); |
1682 | return result->count; | 1682 | return result->count; |
1683 | out_badvalue: | 1683 | out_badvalue: |
1684 | dprintk("NFS: bad stable_how value: %u\n", result->verf->committed); | 1684 | dprintk("NFS: bad stable_how value: %u\n", result->verf->committed); |
1685 | return -EIO; | 1685 | return -EIO; |
1686 | out_overflow: | 1686 | out_overflow: |
1687 | print_overflow_msg(__func__, xdr); | 1687 | print_overflow_msg(__func__, xdr); |
1688 | return -EIO; | 1688 | return -EIO; |
1689 | } | 1689 | } |
1690 | 1690 | ||
1691 | static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr, | 1691 | static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr, |
1692 | struct nfs_writeres *result) | 1692 | struct nfs_writeres *result) |
1693 | { | 1693 | { |
1694 | enum nfs_stat status; | 1694 | enum nfs_stat status; |
1695 | int error; | 1695 | int error; |
1696 | 1696 | ||
1697 | error = decode_nfsstat3(xdr, &status); | 1697 | error = decode_nfsstat3(xdr, &status); |
1698 | if (unlikely(error)) | 1698 | if (unlikely(error)) |
1699 | goto out; | 1699 | goto out; |
1700 | error = decode_wcc_data(xdr, result->fattr); | 1700 | error = decode_wcc_data(xdr, result->fattr); |
1701 | if (unlikely(error)) | 1701 | if (unlikely(error)) |
1702 | goto out; | 1702 | goto out; |
1703 | if (status != NFS3_OK) | 1703 | if (status != NFS3_OK) |
1704 | goto out_status; | 1704 | goto out_status; |
1705 | error = decode_write3resok(xdr, result); | 1705 | error = decode_write3resok(xdr, result); |
1706 | out: | 1706 | out: |
1707 | return error; | 1707 | return error; |
1708 | out_status: | 1708 | out_status: |
1709 | return nfs_stat_to_errno(status); | 1709 | return nfs_stat_to_errno(status); |
1710 | } | 1710 | } |
1711 | 1711 | ||
1712 | /* | 1712 | /* |
1713 | * 3.3.8 CREATE3res | 1713 | * 3.3.8 CREATE3res |
1714 | * | 1714 | * |
1715 | * struct CREATE3resok { | 1715 | * struct CREATE3resok { |
1716 | * post_op_fh3 obj; | 1716 | * post_op_fh3 obj; |
1717 | * post_op_attr obj_attributes; | 1717 | * post_op_attr obj_attributes; |
1718 | * wcc_data dir_wcc; | 1718 | * wcc_data dir_wcc; |
1719 | * }; | 1719 | * }; |
1720 | * | 1720 | * |
1721 | * struct CREATE3resfail { | 1721 | * struct CREATE3resfail { |
1722 | * wcc_data dir_wcc; | 1722 | * wcc_data dir_wcc; |
1723 | * }; | 1723 | * }; |
1724 | * | 1724 | * |
1725 | * union CREATE3res switch (nfsstat3 status) { | 1725 | * union CREATE3res switch (nfsstat3 status) { |
1726 | * case NFS3_OK: | 1726 | * case NFS3_OK: |
1727 | * CREATE3resok resok; | 1727 | * CREATE3resok resok; |
1728 | * default: | 1728 | * default: |
1729 | * CREATE3resfail resfail; | 1729 | * CREATE3resfail resfail; |
1730 | * }; | 1730 | * }; |
1731 | */ | 1731 | */ |
1732 | static int decode_create3resok(struct xdr_stream *xdr, | 1732 | static int decode_create3resok(struct xdr_stream *xdr, |
1733 | struct nfs3_diropres *result) | 1733 | struct nfs3_diropres *result) |
1734 | { | 1734 | { |
1735 | int error; | 1735 | int error; |
1736 | 1736 | ||
1737 | error = decode_post_op_fh3(xdr, result->fh); | 1737 | error = decode_post_op_fh3(xdr, result->fh); |
1738 | if (unlikely(error)) | 1738 | if (unlikely(error)) |
1739 | goto out; | 1739 | goto out; |
1740 | error = decode_post_op_attr(xdr, result->fattr); | 1740 | error = decode_post_op_attr(xdr, result->fattr); |
1741 | if (unlikely(error)) | 1741 | if (unlikely(error)) |
1742 | goto out; | 1742 | goto out; |
1743 | /* The server isn't required to return a file handle. | 1743 | /* The server isn't required to return a file handle. |
1744 | * If it didn't, force the client to perform a LOOKUP | 1744 | * If it didn't, force the client to perform a LOOKUP |
1745 | * to determine the correct file handle and attribute | 1745 | * to determine the correct file handle and attribute |
1746 | * values for the new object. */ | 1746 | * values for the new object. */ |
1747 | if (result->fh->size == 0) | 1747 | if (result->fh->size == 0) |
1748 | result->fattr->valid = 0; | 1748 | result->fattr->valid = 0; |
1749 | error = decode_wcc_data(xdr, result->dir_attr); | 1749 | error = decode_wcc_data(xdr, result->dir_attr); |
1750 | out: | 1750 | out: |
1751 | return error; | 1751 | return error; |
1752 | } | 1752 | } |
1753 | 1753 | ||
1754 | static int nfs3_xdr_dec_create3res(struct rpc_rqst *req, | 1754 | static int nfs3_xdr_dec_create3res(struct rpc_rqst *req, |
1755 | struct xdr_stream *xdr, | 1755 | struct xdr_stream *xdr, |
1756 | struct nfs3_diropres *result) | 1756 | struct nfs3_diropres *result) |
1757 | { | 1757 | { |
1758 | enum nfs_stat status; | 1758 | enum nfs_stat status; |
1759 | int error; | 1759 | int error; |
1760 | 1760 | ||
1761 | error = decode_nfsstat3(xdr, &status); | 1761 | error = decode_nfsstat3(xdr, &status); |
1762 | if (unlikely(error)) | 1762 | if (unlikely(error)) |
1763 | goto out; | 1763 | goto out; |
1764 | if (status != NFS3_OK) | 1764 | if (status != NFS3_OK) |
1765 | goto out_default; | 1765 | goto out_default; |
1766 | error = decode_create3resok(xdr, result); | 1766 | error = decode_create3resok(xdr, result); |
1767 | out: | 1767 | out: |
1768 | return error; | 1768 | return error; |
1769 | out_default: | 1769 | out_default: |
1770 | error = decode_wcc_data(xdr, result->dir_attr); | 1770 | error = decode_wcc_data(xdr, result->dir_attr); |
1771 | if (unlikely(error)) | 1771 | if (unlikely(error)) |
1772 | goto out; | 1772 | goto out; |
1773 | return nfs_stat_to_errno(status); | 1773 | return nfs_stat_to_errno(status); |
1774 | } | 1774 | } |
1775 | 1775 | ||
1776 | /* | 1776 | /* |
1777 | * 3.3.12 REMOVE3res | 1777 | * 3.3.12 REMOVE3res |
1778 | * | 1778 | * |
1779 | * struct REMOVE3resok { | 1779 | * struct REMOVE3resok { |
1780 | * wcc_data dir_wcc; | 1780 | * wcc_data dir_wcc; |
1781 | * }; | 1781 | * }; |
1782 | * | 1782 | * |
1783 | * struct REMOVE3resfail { | 1783 | * struct REMOVE3resfail { |
1784 | * wcc_data dir_wcc; | 1784 | * wcc_data dir_wcc; |
1785 | * }; | 1785 | * }; |
1786 | * | 1786 | * |
1787 | * union REMOVE3res switch (nfsstat3 status) { | 1787 | * union REMOVE3res switch (nfsstat3 status) { |
1788 | * case NFS3_OK: | 1788 | * case NFS3_OK: |
1789 | * REMOVE3resok resok; | 1789 | * REMOVE3resok resok; |
1790 | * default: | 1790 | * default: |
1791 | * REMOVE3resfail resfail; | 1791 | * REMOVE3resfail resfail; |
1792 | * }; | 1792 | * }; |
1793 | */ | 1793 | */ |
1794 | static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req, | 1794 | static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req, |
1795 | struct xdr_stream *xdr, | 1795 | struct xdr_stream *xdr, |
1796 | struct nfs_removeres *result) | 1796 | struct nfs_removeres *result) |
1797 | { | 1797 | { |
1798 | enum nfs_stat status; | 1798 | enum nfs_stat status; |
1799 | int error; | 1799 | int error; |
1800 | 1800 | ||
1801 | error = decode_nfsstat3(xdr, &status); | 1801 | error = decode_nfsstat3(xdr, &status); |
1802 | if (unlikely(error)) | 1802 | if (unlikely(error)) |
1803 | goto out; | 1803 | goto out; |
1804 | error = decode_wcc_data(xdr, result->dir_attr); | 1804 | error = decode_wcc_data(xdr, result->dir_attr); |
1805 | if (unlikely(error)) | 1805 | if (unlikely(error)) |
1806 | goto out; | 1806 | goto out; |
1807 | if (status != NFS3_OK) | 1807 | if (status != NFS3_OK) |
1808 | goto out_status; | 1808 | goto out_status; |
1809 | out: | 1809 | out: |
1810 | return error; | 1810 | return error; |
1811 | out_status: | 1811 | out_status: |
1812 | return nfs_stat_to_errno(status); | 1812 | return nfs_stat_to_errno(status); |
1813 | } | 1813 | } |
1814 | 1814 | ||
1815 | /* | 1815 | /* |
1816 | * 3.3.14 RENAME3res | 1816 | * 3.3.14 RENAME3res |
1817 | * | 1817 | * |
1818 | * struct RENAME3resok { | 1818 | * struct RENAME3resok { |
1819 | * wcc_data fromdir_wcc; | 1819 | * wcc_data fromdir_wcc; |
1820 | * wcc_data todir_wcc; | 1820 | * wcc_data todir_wcc; |
1821 | * }; | 1821 | * }; |
1822 | * | 1822 | * |
1823 | * struct RENAME3resfail { | 1823 | * struct RENAME3resfail { |
1824 | * wcc_data fromdir_wcc; | 1824 | * wcc_data fromdir_wcc; |
1825 | * wcc_data todir_wcc; | 1825 | * wcc_data todir_wcc; |
1826 | * }; | 1826 | * }; |
1827 | * | 1827 | * |
1828 | * union RENAME3res switch (nfsstat3 status) { | 1828 | * union RENAME3res switch (nfsstat3 status) { |
1829 | * case NFS3_OK: | 1829 | * case NFS3_OK: |
1830 | * RENAME3resok resok; | 1830 | * RENAME3resok resok; |
1831 | * default: | 1831 | * default: |
1832 | * RENAME3resfail resfail; | 1832 | * RENAME3resfail resfail; |
1833 | * }; | 1833 | * }; |
1834 | */ | 1834 | */ |
1835 | static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req, | 1835 | static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req, |
1836 | struct xdr_stream *xdr, | 1836 | struct xdr_stream *xdr, |
1837 | struct nfs_renameres *result) | 1837 | struct nfs_renameres *result) |
1838 | { | 1838 | { |
1839 | enum nfs_stat status; | 1839 | enum nfs_stat status; |
1840 | int error; | 1840 | int error; |
1841 | 1841 | ||
1842 | error = decode_nfsstat3(xdr, &status); | 1842 | error = decode_nfsstat3(xdr, &status); |
1843 | if (unlikely(error)) | 1843 | if (unlikely(error)) |
1844 | goto out; | 1844 | goto out; |
1845 | error = decode_wcc_data(xdr, result->old_fattr); | 1845 | error = decode_wcc_data(xdr, result->old_fattr); |
1846 | if (unlikely(error)) | 1846 | if (unlikely(error)) |
1847 | goto out; | 1847 | goto out; |
1848 | error = decode_wcc_data(xdr, result->new_fattr); | 1848 | error = decode_wcc_data(xdr, result->new_fattr); |
1849 | if (unlikely(error)) | 1849 | if (unlikely(error)) |
1850 | goto out; | 1850 | goto out; |
1851 | if (status != NFS3_OK) | 1851 | if (status != NFS3_OK) |
1852 | goto out_status; | 1852 | goto out_status; |
1853 | out: | 1853 | out: |
1854 | return error; | 1854 | return error; |
1855 | out_status: | 1855 | out_status: |
1856 | return nfs_stat_to_errno(status); | 1856 | return nfs_stat_to_errno(status); |
1857 | } | 1857 | } |
1858 | 1858 | ||
1859 | /* | 1859 | /* |
1860 | * 3.3.15 LINK3res | 1860 | * 3.3.15 LINK3res |
1861 | * | 1861 | * |
1862 | * struct LINK3resok { | 1862 | * struct LINK3resok { |
1863 | * post_op_attr file_attributes; | 1863 | * post_op_attr file_attributes; |
1864 | * wcc_data linkdir_wcc; | 1864 | * wcc_data linkdir_wcc; |
1865 | * }; | 1865 | * }; |
1866 | * | 1866 | * |
1867 | * struct LINK3resfail { | 1867 | * struct LINK3resfail { |
1868 | * post_op_attr file_attributes; | 1868 | * post_op_attr file_attributes; |
1869 | * wcc_data linkdir_wcc; | 1869 | * wcc_data linkdir_wcc; |
1870 | * }; | 1870 | * }; |
1871 | * | 1871 | * |
1872 | * union LINK3res switch (nfsstat3 status) { | 1872 | * union LINK3res switch (nfsstat3 status) { |
1873 | * case NFS3_OK: | 1873 | * case NFS3_OK: |
1874 | * LINK3resok resok; | 1874 | * LINK3resok resok; |
1875 | * default: | 1875 | * default: |
1876 | * LINK3resfail resfail; | 1876 | * LINK3resfail resfail; |
1877 | * }; | 1877 | * }; |
1878 | */ | 1878 | */ |
1879 | static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr, | 1879 | static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr, |
1880 | struct nfs3_linkres *result) | 1880 | struct nfs3_linkres *result) |
1881 | { | 1881 | { |
1882 | enum nfs_stat status; | 1882 | enum nfs_stat status; |
1883 | int error; | 1883 | int error; |
1884 | 1884 | ||
1885 | error = decode_nfsstat3(xdr, &status); | 1885 | error = decode_nfsstat3(xdr, &status); |
1886 | if (unlikely(error)) | 1886 | if (unlikely(error)) |
1887 | goto out; | 1887 | goto out; |
1888 | error = decode_post_op_attr(xdr, result->fattr); | 1888 | error = decode_post_op_attr(xdr, result->fattr); |
1889 | if (unlikely(error)) | 1889 | if (unlikely(error)) |
1890 | goto out; | 1890 | goto out; |
1891 | error = decode_wcc_data(xdr, result->dir_attr); | 1891 | error = decode_wcc_data(xdr, result->dir_attr); |
1892 | if (unlikely(error)) | 1892 | if (unlikely(error)) |
1893 | goto out; | 1893 | goto out; |
1894 | if (status != NFS3_OK) | 1894 | if (status != NFS3_OK) |
1895 | goto out_status; | 1895 | goto out_status; |
1896 | out: | 1896 | out: |
1897 | return error; | 1897 | return error; |
1898 | out_status: | 1898 | out_status: |
1899 | return nfs_stat_to_errno(status); | 1899 | return nfs_stat_to_errno(status); |
1900 | } | 1900 | } |
1901 | 1901 | ||
1902 | /** | 1902 | /** |
1903 | * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in | 1903 | * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in |
1904 | * the local page cache | 1904 | * the local page cache |
1905 | * @xdr: XDR stream where entry resides | 1905 | * @xdr: XDR stream where entry resides |
1906 | * @entry: buffer to fill in with entry data | 1906 | * @entry: buffer to fill in with entry data |
1907 | * @plus: boolean indicating whether this should be a readdirplus entry | 1907 | * @plus: boolean indicating whether this should be a readdirplus entry |
1908 | * | 1908 | * |
1909 | * Returns zero if successful, otherwise a negative errno value is | 1909 | * Returns zero if successful, otherwise a negative errno value is |
1910 | * returned. | 1910 | * returned. |
1911 | * | 1911 | * |
1912 | * This function is not invoked during READDIR reply decoding, but | 1912 | * This function is not invoked during READDIR reply decoding, but |
1913 | * rather whenever an application invokes the getdents(2) system call | 1913 | * rather whenever an application invokes the getdents(2) system call |
1914 | * on a directory already in our cache. | 1914 | * on a directory already in our cache. |
1915 | * | 1915 | * |
1916 | * 3.3.16 entry3 | 1916 | * 3.3.16 entry3 |
1917 | * | 1917 | * |
1918 | * struct entry3 { | 1918 | * struct entry3 { |
1919 | * fileid3 fileid; | 1919 | * fileid3 fileid; |
1920 | * filename3 name; | 1920 | * filename3 name; |
1921 | * cookie3 cookie; | 1921 | * cookie3 cookie; |
1922 | * fhandle3 filehandle; | 1922 | * fhandle3 filehandle; |
1923 | * post_op_attr3 attributes; | 1923 | * post_op_attr3 attributes; |
1924 | * entry3 *nextentry; | 1924 | * entry3 *nextentry; |
1925 | * }; | 1925 | * }; |
1926 | * | 1926 | * |
1927 | * 3.3.17 entryplus3 | 1927 | * 3.3.17 entryplus3 |
1928 | * struct entryplus3 { | 1928 | * struct entryplus3 { |
1929 | * fileid3 fileid; | 1929 | * fileid3 fileid; |
1930 | * filename3 name; | 1930 | * filename3 name; |
1931 | * cookie3 cookie; | 1931 | * cookie3 cookie; |
1932 | * post_op_attr name_attributes; | 1932 | * post_op_attr name_attributes; |
1933 | * post_op_fh3 name_handle; | 1933 | * post_op_fh3 name_handle; |
1934 | * entryplus3 *nextentry; | 1934 | * entryplus3 *nextentry; |
1935 | * }; | 1935 | * }; |
1936 | */ | 1936 | */ |
1937 | int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 1937 | int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
1938 | int plus) | 1938 | int plus) |
1939 | { | 1939 | { |
1940 | struct nfs_entry old = *entry; | 1940 | struct nfs_entry old = *entry; |
1941 | __be32 *p; | 1941 | __be32 *p; |
1942 | int error; | 1942 | int error; |
1943 | 1943 | ||
1944 | p = xdr_inline_decode(xdr, 4); | 1944 | p = xdr_inline_decode(xdr, 4); |
1945 | if (unlikely(p == NULL)) | 1945 | if (unlikely(p == NULL)) |
1946 | goto out_overflow; | 1946 | goto out_overflow; |
1947 | if (*p == xdr_zero) { | 1947 | if (*p == xdr_zero) { |
1948 | p = xdr_inline_decode(xdr, 4); | 1948 | p = xdr_inline_decode(xdr, 4); |
1949 | if (unlikely(p == NULL)) | 1949 | if (unlikely(p == NULL)) |
1950 | goto out_overflow; | 1950 | goto out_overflow; |
1951 | if (*p == xdr_zero) | 1951 | if (*p == xdr_zero) |
1952 | return -EAGAIN; | 1952 | return -EAGAIN; |
1953 | entry->eof = 1; | 1953 | entry->eof = 1; |
1954 | return -EBADCOOKIE; | 1954 | return -EBADCOOKIE; |
1955 | } | 1955 | } |
1956 | 1956 | ||
1957 | error = decode_fileid3(xdr, &entry->ino); | 1957 | error = decode_fileid3(xdr, &entry->ino); |
1958 | if (unlikely(error)) | 1958 | if (unlikely(error)) |
1959 | return error; | 1959 | return error; |
1960 | 1960 | ||
1961 | error = decode_inline_filename3(xdr, &entry->name, &entry->len); | 1961 | error = decode_inline_filename3(xdr, &entry->name, &entry->len); |
1962 | if (unlikely(error)) | 1962 | if (unlikely(error)) |
1963 | return error; | 1963 | return error; |
1964 | 1964 | ||
1965 | entry->prev_cookie = entry->cookie; | 1965 | entry->prev_cookie = entry->cookie; |
1966 | error = decode_cookie3(xdr, &entry->cookie); | 1966 | error = decode_cookie3(xdr, &entry->cookie); |
1967 | if (unlikely(error)) | 1967 | if (unlikely(error)) |
1968 | return error; | 1968 | return error; |
1969 | 1969 | ||
1970 | entry->d_type = DT_UNKNOWN; | 1970 | entry->d_type = DT_UNKNOWN; |
1971 | 1971 | ||
1972 | if (plus) { | 1972 | if (plus) { |
1973 | entry->fattr->valid = 0; | 1973 | entry->fattr->valid = 0; |
1974 | error = decode_post_op_attr(xdr, entry->fattr); | 1974 | error = decode_post_op_attr(xdr, entry->fattr); |
1975 | if (unlikely(error)) | 1975 | if (unlikely(error)) |
1976 | return error; | 1976 | return error; |
1977 | if (entry->fattr->valid & NFS_ATTR_FATTR_V3) | 1977 | if (entry->fattr->valid & NFS_ATTR_FATTR_V3) |
1978 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); | 1978 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); |
1979 | 1979 | ||
1980 | /* In fact, a post_op_fh3: */ | 1980 | /* In fact, a post_op_fh3: */ |
1981 | p = xdr_inline_decode(xdr, 4); | 1981 | p = xdr_inline_decode(xdr, 4); |
1982 | if (unlikely(p == NULL)) | 1982 | if (unlikely(p == NULL)) |
1983 | goto out_overflow; | 1983 | goto out_overflow; |
1984 | if (*p != xdr_zero) { | 1984 | if (*p != xdr_zero) { |
1985 | error = decode_nfs_fh3(xdr, entry->fh); | 1985 | error = decode_nfs_fh3(xdr, entry->fh); |
1986 | if (unlikely(error)) { | 1986 | if (unlikely(error)) { |
1987 | if (error == -E2BIG) | 1987 | if (error == -E2BIG) |
1988 | goto out_truncated; | 1988 | goto out_truncated; |
1989 | return error; | 1989 | return error; |
1990 | } | 1990 | } |
1991 | } else | 1991 | } else |
1992 | zero_nfs_fh3(entry->fh); | 1992 | zero_nfs_fh3(entry->fh); |
1993 | } | 1993 | } |
1994 | 1994 | ||
1995 | return 0; | 1995 | return 0; |
1996 | 1996 | ||
1997 | out_overflow: | 1997 | out_overflow: |
1998 | print_overflow_msg(__func__, xdr); | 1998 | print_overflow_msg(__func__, xdr); |
1999 | return -EAGAIN; | 1999 | return -EAGAIN; |
2000 | out_truncated: | 2000 | out_truncated: |
2001 | dprintk("NFS: directory entry contains invalid file handle\n"); | 2001 | dprintk("NFS: directory entry contains invalid file handle\n"); |
2002 | *entry = old; | 2002 | *entry = old; |
2003 | return -EAGAIN; | 2003 | return -EAGAIN; |
2004 | } | 2004 | } |
2005 | 2005 | ||
2006 | /* | 2006 | /* |
2007 | * 3.3.16 READDIR3res | 2007 | * 3.3.16 READDIR3res |
2008 | * | 2008 | * |
2009 | * struct dirlist3 { | 2009 | * struct dirlist3 { |
2010 | * entry3 *entries; | 2010 | * entry3 *entries; |
2011 | * bool eof; | 2011 | * bool eof; |
2012 | * }; | 2012 | * }; |
2013 | * | 2013 | * |
2014 | * struct READDIR3resok { | 2014 | * struct READDIR3resok { |
2015 | * post_op_attr dir_attributes; | 2015 | * post_op_attr dir_attributes; |
2016 | * cookieverf3 cookieverf; | 2016 | * cookieverf3 cookieverf; |
2017 | * dirlist3 reply; | 2017 | * dirlist3 reply; |
2018 | * }; | 2018 | * }; |
2019 | * | 2019 | * |
2020 | * struct READDIR3resfail { | 2020 | * struct READDIR3resfail { |
2021 | * post_op_attr dir_attributes; | 2021 | * post_op_attr dir_attributes; |
2022 | * }; | 2022 | * }; |
2023 | * | 2023 | * |
2024 | * union READDIR3res switch (nfsstat3 status) { | 2024 | * union READDIR3res switch (nfsstat3 status) { |
2025 | * case NFS3_OK: | 2025 | * case NFS3_OK: |
2026 | * READDIR3resok resok; | 2026 | * READDIR3resok resok; |
2027 | * default: | 2027 | * default: |
2028 | * READDIR3resfail resfail; | 2028 | * READDIR3resfail resfail; |
2029 | * }; | 2029 | * }; |
2030 | * | 2030 | * |
2031 | * Read the directory contents into the page cache, but otherwise | 2031 | * Read the directory contents into the page cache, but otherwise |
2032 | * don't touch them. The actual decoding is done by nfs3_decode_entry() | 2032 | * don't touch them. The actual decoding is done by nfs3_decode_entry() |
2033 | * during subsequent nfs_readdir() calls. | 2033 | * during subsequent nfs_readdir() calls. |
2034 | */ | 2034 | */ |
2035 | static int decode_dirlist3(struct xdr_stream *xdr) | 2035 | static int decode_dirlist3(struct xdr_stream *xdr) |
2036 | { | 2036 | { |
2037 | u32 recvd, pglen; | 2037 | u32 recvd, pglen; |
2038 | size_t hdrlen; | 2038 | size_t hdrlen; |
2039 | 2039 | ||
2040 | pglen = xdr->buf->page_len; | 2040 | pglen = xdr->buf->page_len; |
2041 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 2041 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; |
2042 | recvd = xdr->buf->len - hdrlen; | 2042 | recvd = xdr->buf->len - hdrlen; |
2043 | if (unlikely(pglen > recvd)) | 2043 | if (unlikely(pglen > recvd)) |
2044 | goto out_cheating; | 2044 | goto out_cheating; |
2045 | out: | 2045 | out: |
2046 | xdr_read_pages(xdr, pglen); | 2046 | xdr_read_pages(xdr, pglen); |
2047 | return pglen; | 2047 | return pglen; |
2048 | out_cheating: | 2048 | out_cheating: |
2049 | dprintk("NFS: server cheating in readdir result: " | 2049 | dprintk("NFS: server cheating in readdir result: " |
2050 | "pglen %u > recvd %u\n", pglen, recvd); | 2050 | "pglen %u > recvd %u\n", pglen, recvd); |
2051 | pglen = recvd; | 2051 | pglen = recvd; |
2052 | goto out; | 2052 | goto out; |
2053 | } | 2053 | } |
2054 | 2054 | ||
2055 | static int decode_readdir3resok(struct xdr_stream *xdr, | 2055 | static int decode_readdir3resok(struct xdr_stream *xdr, |
2056 | struct nfs3_readdirres *result) | 2056 | struct nfs3_readdirres *result) |
2057 | { | 2057 | { |
2058 | int error; | 2058 | int error; |
2059 | 2059 | ||
2060 | error = decode_post_op_attr(xdr, result->dir_attr); | 2060 | error = decode_post_op_attr(xdr, result->dir_attr); |
2061 | if (unlikely(error)) | 2061 | if (unlikely(error)) |
2062 | goto out; | 2062 | goto out; |
2063 | /* XXX: do we need to check if result->verf != NULL ? */ | 2063 | /* XXX: do we need to check if result->verf != NULL ? */ |
2064 | error = decode_cookieverf3(xdr, result->verf); | 2064 | error = decode_cookieverf3(xdr, result->verf); |
2065 | if (unlikely(error)) | 2065 | if (unlikely(error)) |
2066 | goto out; | 2066 | goto out; |
2067 | error = decode_dirlist3(xdr); | 2067 | error = decode_dirlist3(xdr); |
2068 | out: | 2068 | out: |
2069 | return error; | 2069 | return error; |
2070 | } | 2070 | } |
2071 | 2071 | ||
2072 | static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req, | 2072 | static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req, |
2073 | struct xdr_stream *xdr, | 2073 | struct xdr_stream *xdr, |
2074 | struct nfs3_readdirres *result) | 2074 | struct nfs3_readdirres *result) |
2075 | { | 2075 | { |
2076 | enum nfs_stat status; | 2076 | enum nfs_stat status; |
2077 | int error; | 2077 | int error; |
2078 | 2078 | ||
2079 | error = decode_nfsstat3(xdr, &status); | 2079 | error = decode_nfsstat3(xdr, &status); |
2080 | if (unlikely(error)) | 2080 | if (unlikely(error)) |
2081 | goto out; | 2081 | goto out; |
2082 | if (status != NFS3_OK) | 2082 | if (status != NFS3_OK) |
2083 | goto out_default; | 2083 | goto out_default; |
2084 | error = decode_readdir3resok(xdr, result); | 2084 | error = decode_readdir3resok(xdr, result); |
2085 | out: | 2085 | out: |
2086 | return error; | 2086 | return error; |
2087 | out_default: | 2087 | out_default: |
2088 | error = decode_post_op_attr(xdr, result->dir_attr); | 2088 | error = decode_post_op_attr(xdr, result->dir_attr); |
2089 | if (unlikely(error)) | 2089 | if (unlikely(error)) |
2090 | goto out; | 2090 | goto out; |
2091 | return nfs_stat_to_errno(status); | 2091 | return nfs_stat_to_errno(status); |
2092 | } | 2092 | } |
2093 | 2093 | ||
2094 | /* | 2094 | /* |
2095 | * 3.3.18 FSSTAT3res | 2095 | * 3.3.18 FSSTAT3res |
2096 | * | 2096 | * |
2097 | * struct FSSTAT3resok { | 2097 | * struct FSSTAT3resok { |
2098 | * post_op_attr obj_attributes; | 2098 | * post_op_attr obj_attributes; |
2099 | * size3 tbytes; | 2099 | * size3 tbytes; |
2100 | * size3 fbytes; | 2100 | * size3 fbytes; |
2101 | * size3 abytes; | 2101 | * size3 abytes; |
2102 | * size3 tfiles; | 2102 | * size3 tfiles; |
2103 | * size3 ffiles; | 2103 | * size3 ffiles; |
2104 | * size3 afiles; | 2104 | * size3 afiles; |
2105 | * uint32 invarsec; | 2105 | * uint32 invarsec; |
2106 | * }; | 2106 | * }; |
2107 | * | 2107 | * |
2108 | * struct FSSTAT3resfail { | 2108 | * struct FSSTAT3resfail { |
2109 | * post_op_attr obj_attributes; | 2109 | * post_op_attr obj_attributes; |
2110 | * }; | 2110 | * }; |
2111 | * | 2111 | * |
2112 | * union FSSTAT3res switch (nfsstat3 status) { | 2112 | * union FSSTAT3res switch (nfsstat3 status) { |
2113 | * case NFS3_OK: | 2113 | * case NFS3_OK: |
2114 | * FSSTAT3resok resok; | 2114 | * FSSTAT3resok resok; |
2115 | * default: | 2115 | * default: |
2116 | * FSSTAT3resfail resfail; | 2116 | * FSSTAT3resfail resfail; |
2117 | * }; | 2117 | * }; |
2118 | */ | 2118 | */ |
2119 | static int decode_fsstat3resok(struct xdr_stream *xdr, | 2119 | static int decode_fsstat3resok(struct xdr_stream *xdr, |
2120 | struct nfs_fsstat *result) | 2120 | struct nfs_fsstat *result) |
2121 | { | 2121 | { |
2122 | __be32 *p; | 2122 | __be32 *p; |
2123 | 2123 | ||
2124 | p = xdr_inline_decode(xdr, 8 * 6 + 4); | 2124 | p = xdr_inline_decode(xdr, 8 * 6 + 4); |
2125 | if (unlikely(p == NULL)) | 2125 | if (unlikely(p == NULL)) |
2126 | goto out_overflow; | 2126 | goto out_overflow; |
2127 | p = xdr_decode_size3(p, &result->tbytes); | 2127 | p = xdr_decode_size3(p, &result->tbytes); |
2128 | p = xdr_decode_size3(p, &result->fbytes); | 2128 | p = xdr_decode_size3(p, &result->fbytes); |
2129 | p = xdr_decode_size3(p, &result->abytes); | 2129 | p = xdr_decode_size3(p, &result->abytes); |
2130 | p = xdr_decode_size3(p, &result->tfiles); | 2130 | p = xdr_decode_size3(p, &result->tfiles); |
2131 | p = xdr_decode_size3(p, &result->ffiles); | 2131 | p = xdr_decode_size3(p, &result->ffiles); |
2132 | xdr_decode_size3(p, &result->afiles); | 2132 | xdr_decode_size3(p, &result->afiles); |
2133 | /* ignore invarsec */ | 2133 | /* ignore invarsec */ |
2134 | return 0; | 2134 | return 0; |
2135 | out_overflow: | 2135 | out_overflow: |
2136 | print_overflow_msg(__func__, xdr); | 2136 | print_overflow_msg(__func__, xdr); |
2137 | return -EIO; | 2137 | return -EIO; |
2138 | } | 2138 | } |
2139 | 2139 | ||
2140 | static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, | 2140 | static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, |
2141 | struct xdr_stream *xdr, | 2141 | struct xdr_stream *xdr, |
2142 | struct nfs_fsstat *result) | 2142 | struct nfs_fsstat *result) |
2143 | { | 2143 | { |
2144 | enum nfs_stat status; | 2144 | enum nfs_stat status; |
2145 | int error; | 2145 | int error; |
2146 | 2146 | ||
2147 | error = decode_nfsstat3(xdr, &status); | 2147 | error = decode_nfsstat3(xdr, &status); |
2148 | if (unlikely(error)) | 2148 | if (unlikely(error)) |
2149 | goto out; | 2149 | goto out; |
2150 | error = decode_post_op_attr(xdr, result->fattr); | 2150 | error = decode_post_op_attr(xdr, result->fattr); |
2151 | if (unlikely(error)) | 2151 | if (unlikely(error)) |
2152 | goto out; | 2152 | goto out; |
2153 | if (status != NFS3_OK) | 2153 | if (status != NFS3_OK) |
2154 | goto out_status; | 2154 | goto out_status; |
2155 | error = decode_fsstat3resok(xdr, result); | 2155 | error = decode_fsstat3resok(xdr, result); |
2156 | out: | 2156 | out: |
2157 | return error; | 2157 | return error; |
2158 | out_status: | 2158 | out_status: |
2159 | return nfs_stat_to_errno(status); | 2159 | return nfs_stat_to_errno(status); |
2160 | } | 2160 | } |
2161 | 2161 | ||
2162 | /* | 2162 | /* |
2163 | * 3.3.19 FSINFO3res | 2163 | * 3.3.19 FSINFO3res |
2164 | * | 2164 | * |
2165 | * struct FSINFO3resok { | 2165 | * struct FSINFO3resok { |
2166 | * post_op_attr obj_attributes; | 2166 | * post_op_attr obj_attributes; |
2167 | * uint32 rtmax; | 2167 | * uint32 rtmax; |
2168 | * uint32 rtpref; | 2168 | * uint32 rtpref; |
2169 | * uint32 rtmult; | 2169 | * uint32 rtmult; |
2170 | * uint32 wtmax; | 2170 | * uint32 wtmax; |
2171 | * uint32 wtpref; | 2171 | * uint32 wtpref; |
2172 | * uint32 wtmult; | 2172 | * uint32 wtmult; |
2173 | * uint32 dtpref; | 2173 | * uint32 dtpref; |
2174 | * size3 maxfilesize; | 2174 | * size3 maxfilesize; |
2175 | * nfstime3 time_delta; | 2175 | * nfstime3 time_delta; |
2176 | * uint32 properties; | 2176 | * uint32 properties; |
2177 | * }; | 2177 | * }; |
2178 | * | 2178 | * |
2179 | * struct FSINFO3resfail { | 2179 | * struct FSINFO3resfail { |
2180 | * post_op_attr obj_attributes; | 2180 | * post_op_attr obj_attributes; |
2181 | * }; | 2181 | * }; |
2182 | * | 2182 | * |
2183 | * union FSINFO3res switch (nfsstat3 status) { | 2183 | * union FSINFO3res switch (nfsstat3 status) { |
2184 | * case NFS3_OK: | 2184 | * case NFS3_OK: |
2185 | * FSINFO3resok resok; | 2185 | * FSINFO3resok resok; |
2186 | * default: | 2186 | * default: |
2187 | * FSINFO3resfail resfail; | 2187 | * FSINFO3resfail resfail; |
2188 | * }; | 2188 | * }; |
2189 | */ | 2189 | */ |
2190 | static int decode_fsinfo3resok(struct xdr_stream *xdr, | 2190 | static int decode_fsinfo3resok(struct xdr_stream *xdr, |
2191 | struct nfs_fsinfo *result) | 2191 | struct nfs_fsinfo *result) |
2192 | { | 2192 | { |
2193 | __be32 *p; | 2193 | __be32 *p; |
2194 | 2194 | ||
2195 | p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4); | 2195 | p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4); |
2196 | if (unlikely(p == NULL)) | 2196 | if (unlikely(p == NULL)) |
2197 | goto out_overflow; | 2197 | goto out_overflow; |
2198 | result->rtmax = be32_to_cpup(p++); | 2198 | result->rtmax = be32_to_cpup(p++); |
2199 | result->rtpref = be32_to_cpup(p++); | 2199 | result->rtpref = be32_to_cpup(p++); |
2200 | result->rtmult = be32_to_cpup(p++); | 2200 | result->rtmult = be32_to_cpup(p++); |
2201 | result->wtmax = be32_to_cpup(p++); | 2201 | result->wtmax = be32_to_cpup(p++); |
2202 | result->wtpref = be32_to_cpup(p++); | 2202 | result->wtpref = be32_to_cpup(p++); |
2203 | result->wtmult = be32_to_cpup(p++); | 2203 | result->wtmult = be32_to_cpup(p++); |
2204 | result->dtpref = be32_to_cpup(p++); | 2204 | result->dtpref = be32_to_cpup(p++); |
2205 | p = xdr_decode_size3(p, &result->maxfilesize); | 2205 | p = xdr_decode_size3(p, &result->maxfilesize); |
2206 | xdr_decode_nfstime3(p, &result->time_delta); | 2206 | xdr_decode_nfstime3(p, &result->time_delta); |
2207 | 2207 | ||
2208 | /* ignore properties */ | 2208 | /* ignore properties */ |
2209 | result->lease_time = 0; | 2209 | result->lease_time = 0; |
2210 | return 0; | 2210 | return 0; |
2211 | out_overflow: | 2211 | out_overflow: |
2212 | print_overflow_msg(__func__, xdr); | 2212 | print_overflow_msg(__func__, xdr); |
2213 | return -EIO; | 2213 | return -EIO; |
2214 | } | 2214 | } |
2215 | 2215 | ||
2216 | static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, | 2216 | static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, |
2217 | struct xdr_stream *xdr, | 2217 | struct xdr_stream *xdr, |
2218 | struct nfs_fsinfo *result) | 2218 | struct nfs_fsinfo *result) |
2219 | { | 2219 | { |
2220 | enum nfs_stat status; | 2220 | enum nfs_stat status; |
2221 | int error; | 2221 | int error; |
2222 | 2222 | ||
2223 | error = decode_nfsstat3(xdr, &status); | 2223 | error = decode_nfsstat3(xdr, &status); |
2224 | if (unlikely(error)) | 2224 | if (unlikely(error)) |
2225 | goto out; | 2225 | goto out; |
2226 | error = decode_post_op_attr(xdr, result->fattr); | 2226 | error = decode_post_op_attr(xdr, result->fattr); |
2227 | if (unlikely(error)) | 2227 | if (unlikely(error)) |
2228 | goto out; | 2228 | goto out; |
2229 | if (status != NFS3_OK) | 2229 | if (status != NFS3_OK) |
2230 | goto out_status; | 2230 | goto out_status; |
2231 | error = decode_fsinfo3resok(xdr, result); | 2231 | error = decode_fsinfo3resok(xdr, result); |
2232 | out: | 2232 | out: |
2233 | return error; | 2233 | return error; |
2234 | out_status: | 2234 | out_status: |
2235 | return nfs_stat_to_errno(status); | 2235 | return nfs_stat_to_errno(status); |
2236 | } | 2236 | } |
2237 | 2237 | ||
2238 | /* | 2238 | /* |
2239 | * 3.3.20 PATHCONF3res | 2239 | * 3.3.20 PATHCONF3res |
2240 | * | 2240 | * |
2241 | * struct PATHCONF3resok { | 2241 | * struct PATHCONF3resok { |
2242 | * post_op_attr obj_attributes; | 2242 | * post_op_attr obj_attributes; |
2243 | * uint32 linkmax; | 2243 | * uint32 linkmax; |
2244 | * uint32 name_max; | 2244 | * uint32 name_max; |
2245 | * bool no_trunc; | 2245 | * bool no_trunc; |
2246 | * bool chown_restricted; | 2246 | * bool chown_restricted; |
2247 | * bool case_insensitive; | 2247 | * bool case_insensitive; |
2248 | * bool case_preserving; | 2248 | * bool case_preserving; |
2249 | * }; | 2249 | * }; |
2250 | * | 2250 | * |
2251 | * struct PATHCONF3resfail { | 2251 | * struct PATHCONF3resfail { |
2252 | * post_op_attr obj_attributes; | 2252 | * post_op_attr obj_attributes; |
2253 | * }; | 2253 | * }; |
2254 | * | 2254 | * |
2255 | * union PATHCONF3res switch (nfsstat3 status) { | 2255 | * union PATHCONF3res switch (nfsstat3 status) { |
2256 | * case NFS3_OK: | 2256 | * case NFS3_OK: |
2257 | * PATHCONF3resok resok; | 2257 | * PATHCONF3resok resok; |
2258 | * default: | 2258 | * default: |
2259 | * PATHCONF3resfail resfail; | 2259 | * PATHCONF3resfail resfail; |
2260 | * }; | 2260 | * }; |
2261 | */ | 2261 | */ |
2262 | static int decode_pathconf3resok(struct xdr_stream *xdr, | 2262 | static int decode_pathconf3resok(struct xdr_stream *xdr, |
2263 | struct nfs_pathconf *result) | 2263 | struct nfs_pathconf *result) |
2264 | { | 2264 | { |
2265 | __be32 *p; | 2265 | __be32 *p; |
2266 | 2266 | ||
2267 | p = xdr_inline_decode(xdr, 4 * 6); | 2267 | p = xdr_inline_decode(xdr, 4 * 6); |
2268 | if (unlikely(p == NULL)) | 2268 | if (unlikely(p == NULL)) |
2269 | goto out_overflow; | 2269 | goto out_overflow; |
2270 | result->max_link = be32_to_cpup(p++); | 2270 | result->max_link = be32_to_cpup(p++); |
2271 | result->max_namelen = be32_to_cpup(p); | 2271 | result->max_namelen = be32_to_cpup(p); |
2272 | /* ignore remaining fields */ | 2272 | /* ignore remaining fields */ |
2273 | return 0; | 2273 | return 0; |
2274 | out_overflow: | 2274 | out_overflow: |
2275 | print_overflow_msg(__func__, xdr); | 2275 | print_overflow_msg(__func__, xdr); |
2276 | return -EIO; | 2276 | return -EIO; |
2277 | } | 2277 | } |
2278 | 2278 | ||
2279 | static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, | 2279 | static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, |
2280 | struct xdr_stream *xdr, | 2280 | struct xdr_stream *xdr, |
2281 | struct nfs_pathconf *result) | 2281 | struct nfs_pathconf *result) |
2282 | { | 2282 | { |
2283 | enum nfs_stat status; | 2283 | enum nfs_stat status; |
2284 | int error; | 2284 | int error; |
2285 | 2285 | ||
2286 | error = decode_nfsstat3(xdr, &status); | 2286 | error = decode_nfsstat3(xdr, &status); |
2287 | if (unlikely(error)) | 2287 | if (unlikely(error)) |
2288 | goto out; | 2288 | goto out; |
2289 | error = decode_post_op_attr(xdr, result->fattr); | 2289 | error = decode_post_op_attr(xdr, result->fattr); |
2290 | if (unlikely(error)) | 2290 | if (unlikely(error)) |
2291 | goto out; | 2291 | goto out; |
2292 | if (status != NFS3_OK) | 2292 | if (status != NFS3_OK) |
2293 | goto out_status; | 2293 | goto out_status; |
2294 | error = decode_pathconf3resok(xdr, result); | 2294 | error = decode_pathconf3resok(xdr, result); |
2295 | out: | 2295 | out: |
2296 | return error; | 2296 | return error; |
2297 | out_status: | 2297 | out_status: |
2298 | return nfs_stat_to_errno(status); | 2298 | return nfs_stat_to_errno(status); |
2299 | } | 2299 | } |
2300 | 2300 | ||
2301 | /* | 2301 | /* |
2302 | * 3.3.21 COMMIT3res | 2302 | * 3.3.21 COMMIT3res |
2303 | * | 2303 | * |
2304 | * struct COMMIT3resok { | 2304 | * struct COMMIT3resok { |
2305 | * wcc_data file_wcc; | 2305 | * wcc_data file_wcc; |
2306 | * writeverf3 verf; | 2306 | * writeverf3 verf; |
2307 | * }; | 2307 | * }; |
2308 | * | 2308 | * |
2309 | * struct COMMIT3resfail { | 2309 | * struct COMMIT3resfail { |
2310 | * wcc_data file_wcc; | 2310 | * wcc_data file_wcc; |
2311 | * }; | 2311 | * }; |
2312 | * | 2312 | * |
2313 | * union COMMIT3res switch (nfsstat3 status) { | 2313 | * union COMMIT3res switch (nfsstat3 status) { |
2314 | * case NFS3_OK: | 2314 | * case NFS3_OK: |
2315 | * COMMIT3resok resok; | 2315 | * COMMIT3resok resok; |
2316 | * default: | 2316 | * default: |
2317 | * COMMIT3resfail resfail; | 2317 | * COMMIT3resfail resfail; |
2318 | * }; | 2318 | * }; |
2319 | */ | 2319 | */ |
2320 | static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, | 2320 | static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, |
2321 | struct xdr_stream *xdr, | 2321 | struct xdr_stream *xdr, |
2322 | struct nfs_writeres *result) | 2322 | struct nfs_writeres *result) |
2323 | { | 2323 | { |
2324 | enum nfs_stat status; | 2324 | enum nfs_stat status; |
2325 | int error; | 2325 | int error; |
2326 | 2326 | ||
2327 | error = decode_nfsstat3(xdr, &status); | 2327 | error = decode_nfsstat3(xdr, &status); |
2328 | if (unlikely(error)) | 2328 | if (unlikely(error)) |
2329 | goto out; | 2329 | goto out; |
2330 | error = decode_wcc_data(xdr, result->fattr); | 2330 | error = decode_wcc_data(xdr, result->fattr); |
2331 | if (unlikely(error)) | 2331 | if (unlikely(error)) |
2332 | goto out; | 2332 | goto out; |
2333 | if (status != NFS3_OK) | 2333 | if (status != NFS3_OK) |
2334 | goto out_status; | 2334 | goto out_status; |
2335 | error = decode_writeverf3(xdr, result->verf->verifier); | 2335 | error = decode_writeverf3(xdr, result->verf->verifier); |
2336 | out: | 2336 | out: |
2337 | return error; | 2337 | return error; |
2338 | out_status: | 2338 | out_status: |
2339 | return nfs_stat_to_errno(status); | 2339 | return nfs_stat_to_errno(status); |
2340 | } | 2340 | } |
2341 | 2341 | ||
2342 | #ifdef CONFIG_NFS_V3_ACL | 2342 | #ifdef CONFIG_NFS_V3_ACL |
2343 | 2343 | ||
2344 | static inline int decode_getacl3resok(struct xdr_stream *xdr, | 2344 | static inline int decode_getacl3resok(struct xdr_stream *xdr, |
2345 | struct nfs3_getaclres *result) | 2345 | struct nfs3_getaclres *result) |
2346 | { | 2346 | { |
2347 | struct posix_acl **acl; | 2347 | struct posix_acl **acl; |
2348 | unsigned int *aclcnt; | 2348 | unsigned int *aclcnt; |
2349 | size_t hdrlen; | 2349 | size_t hdrlen; |
2350 | int error; | 2350 | int error; |
2351 | 2351 | ||
2352 | error = decode_post_op_attr(xdr, result->fattr); | 2352 | error = decode_post_op_attr(xdr, result->fattr); |
2353 | if (unlikely(error)) | 2353 | if (unlikely(error)) |
2354 | goto out; | 2354 | goto out; |
2355 | error = decode_uint32(xdr, &result->mask); | 2355 | error = decode_uint32(xdr, &result->mask); |
2356 | if (unlikely(error)) | 2356 | if (unlikely(error)) |
2357 | goto out; | 2357 | goto out; |
2358 | error = -EINVAL; | 2358 | error = -EINVAL; |
2359 | if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) | 2359 | if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) |
2360 | goto out; | 2360 | goto out; |
2361 | 2361 | ||
2362 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 2362 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; |
2363 | 2363 | ||
2364 | acl = NULL; | 2364 | acl = NULL; |
2365 | if (result->mask & NFS_ACL) | 2365 | if (result->mask & NFS_ACL) |
2366 | acl = &result->acl_access; | 2366 | acl = &result->acl_access; |
2367 | aclcnt = NULL; | 2367 | aclcnt = NULL; |
2368 | if (result->mask & NFS_ACLCNT) | 2368 | if (result->mask & NFS_ACLCNT) |
2369 | aclcnt = &result->acl_access_count; | 2369 | aclcnt = &result->acl_access_count; |
2370 | error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl); | 2370 | error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl); |
2371 | if (unlikely(error <= 0)) | 2371 | if (unlikely(error <= 0)) |
2372 | goto out; | 2372 | goto out; |
2373 | 2373 | ||
2374 | acl = NULL; | 2374 | acl = NULL; |
2375 | if (result->mask & NFS_DFACL) | 2375 | if (result->mask & NFS_DFACL) |
2376 | acl = &result->acl_default; | 2376 | acl = &result->acl_default; |
2377 | aclcnt = NULL; | 2377 | aclcnt = NULL; |
2378 | if (result->mask & NFS_DFACLCNT) | 2378 | if (result->mask & NFS_DFACLCNT) |
2379 | aclcnt = &result->acl_default_count; | 2379 | aclcnt = &result->acl_default_count; |
2380 | error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl); | 2380 | error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl); |
2381 | if (unlikely(error <= 0)) | 2381 | if (unlikely(error <= 0)) |
2382 | return error; | 2382 | return error; |
2383 | error = 0; | 2383 | error = 0; |
2384 | out: | 2384 | out: |
2385 | return error; | 2385 | return error; |
2386 | } | 2386 | } |
2387 | 2387 | ||
2388 | static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req, | 2388 | static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req, |
2389 | struct xdr_stream *xdr, | 2389 | struct xdr_stream *xdr, |
2390 | struct nfs3_getaclres *result) | 2390 | struct nfs3_getaclres *result) |
2391 | { | 2391 | { |
2392 | enum nfs_stat status; | 2392 | enum nfs_stat status; |
2393 | int error; | 2393 | int error; |
2394 | 2394 | ||
2395 | error = decode_nfsstat3(xdr, &status); | 2395 | error = decode_nfsstat3(xdr, &status); |
2396 | if (unlikely(error)) | 2396 | if (unlikely(error)) |
2397 | goto out; | 2397 | goto out; |
2398 | if (status != NFS3_OK) | 2398 | if (status != NFS3_OK) |
2399 | goto out_default; | 2399 | goto out_default; |
2400 | error = decode_getacl3resok(xdr, result); | 2400 | error = decode_getacl3resok(xdr, result); |
2401 | out: | 2401 | out: |
2402 | return error; | 2402 | return error; |
2403 | out_default: | 2403 | out_default: |
2404 | return nfs_stat_to_errno(status); | 2404 | return nfs_stat_to_errno(status); |
2405 | } | 2405 | } |
2406 | 2406 | ||
2407 | static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req, | 2407 | static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req, |
2408 | struct xdr_stream *xdr, | 2408 | struct xdr_stream *xdr, |
2409 | struct nfs_fattr *result) | 2409 | struct nfs_fattr *result) |
2410 | { | 2410 | { |
2411 | enum nfs_stat status; | 2411 | enum nfs_stat status; |
2412 | int error; | 2412 | int error; |
2413 | 2413 | ||
2414 | error = decode_nfsstat3(xdr, &status); | 2414 | error = decode_nfsstat3(xdr, &status); |
2415 | if (unlikely(error)) | 2415 | if (unlikely(error)) |
2416 | goto out; | 2416 | goto out; |
2417 | if (status != NFS3_OK) | 2417 | if (status != NFS3_OK) |
2418 | goto out_default; | 2418 | goto out_default; |
2419 | error = decode_post_op_attr(xdr, result); | 2419 | error = decode_post_op_attr(xdr, result); |
2420 | out: | 2420 | out: |
2421 | return error; | 2421 | return error; |
2422 | out_default: | 2422 | out_default: |
2423 | return nfs_stat_to_errno(status); | 2423 | return nfs_stat_to_errno(status); |
2424 | } | 2424 | } |
2425 | 2425 | ||
2426 | #endif /* CONFIG_NFS_V3_ACL */ | 2426 | #endif /* CONFIG_NFS_V3_ACL */ |
2427 | 2427 | ||
2428 | #define PROC(proc, argtype, restype, timer) \ | 2428 | #define PROC(proc, argtype, restype, timer) \ |
2429 | [NFS3PROC_##proc] = { \ | 2429 | [NFS3PROC_##proc] = { \ |
2430 | .p_proc = NFS3PROC_##proc, \ | 2430 | .p_proc = NFS3PROC_##proc, \ |
2431 | .p_encode = (kxdreproc_t)nfs3_xdr_enc_##argtype##3args, \ | 2431 | .p_encode = (kxdreproc_t)nfs3_xdr_enc_##argtype##3args, \ |
2432 | .p_decode = (kxdrdproc_t)nfs3_xdr_dec_##restype##3res, \ | 2432 | .p_decode = (kxdrdproc_t)nfs3_xdr_dec_##restype##3res, \ |
2433 | .p_arglen = NFS3_##argtype##args_sz, \ | 2433 | .p_arglen = NFS3_##argtype##args_sz, \ |
2434 | .p_replen = NFS3_##restype##res_sz, \ | 2434 | .p_replen = NFS3_##restype##res_sz, \ |
2435 | .p_timer = timer, \ | 2435 | .p_timer = timer, \ |
2436 | .p_statidx = NFS3PROC_##proc, \ | 2436 | .p_statidx = NFS3PROC_##proc, \ |
2437 | .p_name = #proc, \ | 2437 | .p_name = #proc, \ |
2438 | } | 2438 | } |
2439 | 2439 | ||
2440 | struct rpc_procinfo nfs3_procedures[] = { | 2440 | struct rpc_procinfo nfs3_procedures[] = { |
2441 | PROC(GETATTR, getattr, getattr, 1), | 2441 | PROC(GETATTR, getattr, getattr, 1), |
2442 | PROC(SETATTR, setattr, setattr, 0), | 2442 | PROC(SETATTR, setattr, setattr, 0), |
2443 | PROC(LOOKUP, lookup, lookup, 2), | 2443 | PROC(LOOKUP, lookup, lookup, 2), |
2444 | PROC(ACCESS, access, access, 1), | 2444 | PROC(ACCESS, access, access, 1), |
2445 | PROC(READLINK, readlink, readlink, 3), | 2445 | PROC(READLINK, readlink, readlink, 3), |
2446 | PROC(READ, read, read, 3), | 2446 | PROC(READ, read, read, 3), |
2447 | PROC(WRITE, write, write, 4), | 2447 | PROC(WRITE, write, write, 4), |
2448 | PROC(CREATE, create, create, 0), | 2448 | PROC(CREATE, create, create, 0), |
2449 | PROC(MKDIR, mkdir, create, 0), | 2449 | PROC(MKDIR, mkdir, create, 0), |
2450 | PROC(SYMLINK, symlink, create, 0), | 2450 | PROC(SYMLINK, symlink, create, 0), |
2451 | PROC(MKNOD, mknod, create, 0), | 2451 | PROC(MKNOD, mknod, create, 0), |
2452 | PROC(REMOVE, remove, remove, 0), | 2452 | PROC(REMOVE, remove, remove, 0), |
2453 | PROC(RMDIR, lookup, setattr, 0), | 2453 | PROC(RMDIR, lookup, setattr, 0), |
2454 | PROC(RENAME, rename, rename, 0), | 2454 | PROC(RENAME, rename, rename, 0), |
2455 | PROC(LINK, link, link, 0), | 2455 | PROC(LINK, link, link, 0), |
2456 | PROC(READDIR, readdir, readdir, 3), | 2456 | PROC(READDIR, readdir, readdir, 3), |
2457 | PROC(READDIRPLUS, readdirplus, readdir, 3), | 2457 | PROC(READDIRPLUS, readdirplus, readdir, 3), |
2458 | PROC(FSSTAT, getattr, fsstat, 0), | 2458 | PROC(FSSTAT, getattr, fsstat, 0), |
2459 | PROC(FSINFO, getattr, fsinfo, 0), | 2459 | PROC(FSINFO, getattr, fsinfo, 0), |
2460 | PROC(PATHCONF, getattr, pathconf, 0), | 2460 | PROC(PATHCONF, getattr, pathconf, 0), |
2461 | PROC(COMMIT, commit, commit, 5), | 2461 | PROC(COMMIT, commit, commit, 5), |
2462 | }; | 2462 | }; |
2463 | 2463 | ||
2464 | struct rpc_version nfs_version3 = { | 2464 | const struct rpc_version nfs_version3 = { |
2465 | .number = 3, | 2465 | .number = 3, |
2466 | .nrprocs = ARRAY_SIZE(nfs3_procedures), | 2466 | .nrprocs = ARRAY_SIZE(nfs3_procedures), |
2467 | .procs = nfs3_procedures | 2467 | .procs = nfs3_procedures |
2468 | }; | 2468 | }; |
2469 | 2469 | ||
2470 | #ifdef CONFIG_NFS_V3_ACL | 2470 | #ifdef CONFIG_NFS_V3_ACL |
2471 | static struct rpc_procinfo nfs3_acl_procedures[] = { | 2471 | static struct rpc_procinfo nfs3_acl_procedures[] = { |
2472 | [ACLPROC3_GETACL] = { | 2472 | [ACLPROC3_GETACL] = { |
2473 | .p_proc = ACLPROC3_GETACL, | 2473 | .p_proc = ACLPROC3_GETACL, |
2474 | .p_encode = (kxdreproc_t)nfs3_xdr_enc_getacl3args, | 2474 | .p_encode = (kxdreproc_t)nfs3_xdr_enc_getacl3args, |
2475 | .p_decode = (kxdrdproc_t)nfs3_xdr_dec_getacl3res, | 2475 | .p_decode = (kxdrdproc_t)nfs3_xdr_dec_getacl3res, |
2476 | .p_arglen = ACL3_getaclargs_sz, | 2476 | .p_arglen = ACL3_getaclargs_sz, |
2477 | .p_replen = ACL3_getaclres_sz, | 2477 | .p_replen = ACL3_getaclres_sz, |
2478 | .p_timer = 1, | 2478 | .p_timer = 1, |
2479 | .p_name = "GETACL", | 2479 | .p_name = "GETACL", |
2480 | }, | 2480 | }, |
2481 | [ACLPROC3_SETACL] = { | 2481 | [ACLPROC3_SETACL] = { |
2482 | .p_proc = ACLPROC3_SETACL, | 2482 | .p_proc = ACLPROC3_SETACL, |
2483 | .p_encode = (kxdreproc_t)nfs3_xdr_enc_setacl3args, | 2483 | .p_encode = (kxdreproc_t)nfs3_xdr_enc_setacl3args, |
2484 | .p_decode = (kxdrdproc_t)nfs3_xdr_dec_setacl3res, | 2484 | .p_decode = (kxdrdproc_t)nfs3_xdr_dec_setacl3res, |
2485 | .p_arglen = ACL3_setaclargs_sz, | 2485 | .p_arglen = ACL3_setaclargs_sz, |
2486 | .p_replen = ACL3_setaclres_sz, | 2486 | .p_replen = ACL3_setaclres_sz, |
2487 | .p_timer = 0, | 2487 | .p_timer = 0, |
2488 | .p_name = "SETACL", | 2488 | .p_name = "SETACL", |
2489 | }, | 2489 | }, |
2490 | }; | 2490 | }; |
2491 | 2491 | ||
2492 | struct rpc_version nfsacl_version3 = { | 2492 | const struct rpc_version nfsacl_version3 = { |
2493 | .number = 3, | 2493 | .number = 3, |
2494 | .nrprocs = sizeof(nfs3_acl_procedures)/ | 2494 | .nrprocs = sizeof(nfs3_acl_procedures)/ |
2495 | sizeof(nfs3_acl_procedures[0]), | 2495 | sizeof(nfs3_acl_procedures[0]), |
2496 | .procs = nfs3_acl_procedures, | 2496 | .procs = nfs3_acl_procedures, |
2497 | }; | 2497 | }; |
2498 | #endif /* CONFIG_NFS_V3_ACL */ | 2498 | #endif /* CONFIG_NFS_V3_ACL */ |
2499 | 2499 |
fs/nfs/nfs4xdr.c
1 | /* | 1 | /* |
2 | * fs/nfs/nfs4xdr.c | 2 | * fs/nfs/nfs4xdr.c |
3 | * | 3 | * |
4 | * Client-side XDR for NFSv4. | 4 | * Client-side XDR for NFSv4. |
5 | * | 5 | * |
6 | * Copyright (c) 2002 The Regents of the University of Michigan. | 6 | * Copyright (c) 2002 The Regents of the University of Michigan. |
7 | * All rights reserved. | 7 | * All rights reserved. |
8 | * | 8 | * |
9 | * Kendrick Smith <kmsmith@umich.edu> | 9 | * Kendrick Smith <kmsmith@umich.edu> |
10 | * Andy Adamson <andros@umich.edu> | 10 | * Andy Adamson <andros@umich.edu> |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | 14 | * are met: |
15 | * | 15 | * |
16 | * 1. Redistributions of source code must retain the above copyright | 16 | * 1. Redistributions of source code must retain the above copyright |
17 | * notice, this list of conditions and the following disclaimer. | 17 | * notice, this list of conditions and the following disclaimer. |
18 | * 2. Redistributions in binary form must reproduce the above copyright | 18 | * 2. Redistributions in binary form must reproduce the above copyright |
19 | * notice, this list of conditions and the following disclaimer in the | 19 | * notice, this list of conditions and the following disclaimer in the |
20 | * documentation and/or other materials provided with the distribution. | 20 | * documentation and/or other materials provided with the distribution. |
21 | * 3. Neither the name of the University nor the names of its | 21 | * 3. Neither the name of the University nor the names of its |
22 | * contributors may be used to endorse or promote products derived | 22 | * contributors may be used to endorse or promote products derived |
23 | * from this software without specific prior written permission. | 23 | * from this software without specific prior written permission. |
24 | * | 24 | * |
25 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | 25 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
26 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 26 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
27 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 27 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
28 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 28 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
32 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 32 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include <linux/param.h> | 38 | #include <linux/param.h> |
39 | #include <linux/time.h> | 39 | #include <linux/time.h> |
40 | #include <linux/mm.h> | 40 | #include <linux/mm.h> |
41 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
42 | #include <linux/string.h> | 42 | #include <linux/string.h> |
43 | #include <linux/in.h> | 43 | #include <linux/in.h> |
44 | #include <linux/pagemap.h> | 44 | #include <linux/pagemap.h> |
45 | #include <linux/proc_fs.h> | 45 | #include <linux/proc_fs.h> |
46 | #include <linux/kdev_t.h> | 46 | #include <linux/kdev_t.h> |
47 | #include <linux/sunrpc/clnt.h> | 47 | #include <linux/sunrpc/clnt.h> |
48 | #include <linux/sunrpc/msg_prot.h> | 48 | #include <linux/sunrpc/msg_prot.h> |
49 | #include <linux/sunrpc/gss_api.h> | 49 | #include <linux/sunrpc/gss_api.h> |
50 | #include <linux/nfs.h> | 50 | #include <linux/nfs.h> |
51 | #include <linux/nfs4.h> | 51 | #include <linux/nfs4.h> |
52 | #include <linux/nfs_fs.h> | 52 | #include <linux/nfs_fs.h> |
53 | #include <linux/nfs_idmap.h> | 53 | #include <linux/nfs_idmap.h> |
54 | #include "nfs4_fs.h" | 54 | #include "nfs4_fs.h" |
55 | #include "internal.h" | 55 | #include "internal.h" |
56 | #include "pnfs.h" | 56 | #include "pnfs.h" |
57 | 57 | ||
58 | #define NFSDBG_FACILITY NFSDBG_XDR | 58 | #define NFSDBG_FACILITY NFSDBG_XDR |
59 | 59 | ||
60 | /* Mapping from NFS error code to "errno" error code. */ | 60 | /* Mapping from NFS error code to "errno" error code. */ |
61 | #define errno_NFSERR_IO EIO | 61 | #define errno_NFSERR_IO EIO |
62 | 62 | ||
63 | static int nfs4_stat_to_errno(int); | 63 | static int nfs4_stat_to_errno(int); |
64 | 64 | ||
65 | /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ | 65 | /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ |
66 | #ifdef DEBUG | 66 | #ifdef DEBUG |
67 | #define NFS4_MAXTAGLEN 20 | 67 | #define NFS4_MAXTAGLEN 20 |
68 | #else | 68 | #else |
69 | #define NFS4_MAXTAGLEN 0 | 69 | #define NFS4_MAXTAGLEN 0 |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | /* lock,open owner id: | 72 | /* lock,open owner id: |
73 | * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) | 73 | * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) |
74 | */ | 74 | */ |
75 | #define open_owner_id_maxsz (1 + 1 + 4) | 75 | #define open_owner_id_maxsz (1 + 1 + 4) |
76 | #define lock_owner_id_maxsz (1 + 1 + 4) | 76 | #define lock_owner_id_maxsz (1 + 1 + 4) |
77 | #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 77 | #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
78 | #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) | 78 | #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) |
79 | #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) | 79 | #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) |
80 | #define op_encode_hdr_maxsz (1) | 80 | #define op_encode_hdr_maxsz (1) |
81 | #define op_decode_hdr_maxsz (2) | 81 | #define op_decode_hdr_maxsz (2) |
82 | #define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) | 82 | #define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) |
83 | #define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) | 83 | #define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) |
84 | #define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) | 84 | #define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) |
85 | #define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) | 85 | #define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) |
86 | #define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \ | 86 | #define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \ |
87 | (NFS4_FHSIZE >> 2)) | 87 | (NFS4_FHSIZE >> 2)) |
88 | #define decode_putfh_maxsz (op_decode_hdr_maxsz) | 88 | #define decode_putfh_maxsz (op_decode_hdr_maxsz) |
89 | #define encode_putrootfh_maxsz (op_encode_hdr_maxsz) | 89 | #define encode_putrootfh_maxsz (op_encode_hdr_maxsz) |
90 | #define decode_putrootfh_maxsz (op_decode_hdr_maxsz) | 90 | #define decode_putrootfh_maxsz (op_decode_hdr_maxsz) |
91 | #define encode_getfh_maxsz (op_encode_hdr_maxsz) | 91 | #define encode_getfh_maxsz (op_encode_hdr_maxsz) |
92 | #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ | 92 | #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ |
93 | ((3+NFS4_FHSIZE) >> 2)) | 93 | ((3+NFS4_FHSIZE) >> 2)) |
94 | #define nfs4_fattr_bitmap_maxsz 4 | 94 | #define nfs4_fattr_bitmap_maxsz 4 |
95 | #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) | 95 | #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) |
96 | #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) | 96 | #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) |
97 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 97 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
98 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 98 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
99 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 99 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
100 | /* This is based on getfattr, which uses the most attributes: */ | 100 | /* This is based on getfattr, which uses the most attributes: */ |
101 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ | 101 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
102 | 3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz)) | 102 | 3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz)) |
103 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ | 103 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ |
104 | nfs4_fattr_value_maxsz) | 104 | nfs4_fattr_value_maxsz) |
105 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 105 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
106 | #define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \ | 106 | #define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \ |
107 | 1 + 2 + 1 + \ | 107 | 1 + 2 + 1 + \ |
108 | nfs4_owner_maxsz + \ | 108 | nfs4_owner_maxsz + \ |
109 | nfs4_group_maxsz + \ | 109 | nfs4_group_maxsz + \ |
110 | 4 + 4) | 110 | 4 + 4) |
111 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 111 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
112 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 112 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
113 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) | 113 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) |
114 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) | 114 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) |
115 | #define encode_fsinfo_maxsz (encode_getattr_maxsz) | 115 | #define encode_fsinfo_maxsz (encode_getattr_maxsz) |
116 | /* The 5 accounts for the PNFS attributes, and assumes that at most three | 116 | /* The 5 accounts for the PNFS attributes, and assumes that at most three |
117 | * layout types will be returned. | 117 | * layout types will be returned. |
118 | */ | 118 | */ |
119 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \ | 119 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \ |
120 | nfs4_fattr_bitmap_maxsz + 4 + 8 + 5) | 120 | nfs4_fattr_bitmap_maxsz + 4 + 8 + 5) |
121 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) | 121 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) |
122 | #define decode_renew_maxsz (op_decode_hdr_maxsz) | 122 | #define decode_renew_maxsz (op_decode_hdr_maxsz) |
123 | #define encode_setclientid_maxsz \ | 123 | #define encode_setclientid_maxsz \ |
124 | (op_encode_hdr_maxsz + \ | 124 | (op_encode_hdr_maxsz + \ |
125 | XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ | 125 | XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ |
126 | XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ | 126 | XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ |
127 | 1 /* sc_prog */ + \ | 127 | 1 /* sc_prog */ + \ |
128 | XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ | 128 | XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ |
129 | XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ | 129 | XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ |
130 | 1) /* sc_cb_ident */ | 130 | 1) /* sc_cb_ident */ |
131 | #define decode_setclientid_maxsz \ | 131 | #define decode_setclientid_maxsz \ |
132 | (op_decode_hdr_maxsz + \ | 132 | (op_decode_hdr_maxsz + \ |
133 | 2 + \ | 133 | 2 + \ |
134 | 1024) /* large value for CLID_INUSE */ | 134 | 1024) /* large value for CLID_INUSE */ |
135 | #define encode_setclientid_confirm_maxsz \ | 135 | #define encode_setclientid_confirm_maxsz \ |
136 | (op_encode_hdr_maxsz + \ | 136 | (op_encode_hdr_maxsz + \ |
137 | 3 + (NFS4_VERIFIER_SIZE >> 2)) | 137 | 3 + (NFS4_VERIFIER_SIZE >> 2)) |
138 | #define decode_setclientid_confirm_maxsz \ | 138 | #define decode_setclientid_confirm_maxsz \ |
139 | (op_decode_hdr_maxsz) | 139 | (op_decode_hdr_maxsz) |
140 | #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) | 140 | #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
141 | #define decode_lookup_maxsz (op_decode_hdr_maxsz) | 141 | #define decode_lookup_maxsz (op_decode_hdr_maxsz) |
142 | #define encode_share_access_maxsz \ | 142 | #define encode_share_access_maxsz \ |
143 | (2) | 143 | (2) |
144 | #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) | 144 | #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) |
145 | #define encode_opentype_maxsz (1 + encode_createmode_maxsz) | 145 | #define encode_opentype_maxsz (1 + encode_createmode_maxsz) |
146 | #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) | 146 | #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) |
147 | #define encode_open_maxsz (op_encode_hdr_maxsz + \ | 147 | #define encode_open_maxsz (op_encode_hdr_maxsz + \ |
148 | 2 + encode_share_access_maxsz + 2 + \ | 148 | 2 + encode_share_access_maxsz + 2 + \ |
149 | open_owner_id_maxsz + \ | 149 | open_owner_id_maxsz + \ |
150 | encode_opentype_maxsz + \ | 150 | encode_opentype_maxsz + \ |
151 | encode_claim_null_maxsz) | 151 | encode_claim_null_maxsz) |
152 | #define decode_ace_maxsz (3 + nfs4_owner_maxsz) | 152 | #define decode_ace_maxsz (3 + nfs4_owner_maxsz) |
153 | #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ | 153 | #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ |
154 | decode_ace_maxsz) | 154 | decode_ace_maxsz) |
155 | #define decode_change_info_maxsz (5) | 155 | #define decode_change_info_maxsz (5) |
156 | #define decode_open_maxsz (op_decode_hdr_maxsz + \ | 156 | #define decode_open_maxsz (op_decode_hdr_maxsz + \ |
157 | decode_stateid_maxsz + \ | 157 | decode_stateid_maxsz + \ |
158 | decode_change_info_maxsz + 1 + \ | 158 | decode_change_info_maxsz + 1 + \ |
159 | nfs4_fattr_bitmap_maxsz + \ | 159 | nfs4_fattr_bitmap_maxsz + \ |
160 | decode_delegation_maxsz) | 160 | decode_delegation_maxsz) |
161 | #define encode_open_confirm_maxsz \ | 161 | #define encode_open_confirm_maxsz \ |
162 | (op_encode_hdr_maxsz + \ | 162 | (op_encode_hdr_maxsz + \ |
163 | encode_stateid_maxsz + 1) | 163 | encode_stateid_maxsz + 1) |
164 | #define decode_open_confirm_maxsz \ | 164 | #define decode_open_confirm_maxsz \ |
165 | (op_decode_hdr_maxsz + \ | 165 | (op_decode_hdr_maxsz + \ |
166 | decode_stateid_maxsz) | 166 | decode_stateid_maxsz) |
167 | #define encode_open_downgrade_maxsz \ | 167 | #define encode_open_downgrade_maxsz \ |
168 | (op_encode_hdr_maxsz + \ | 168 | (op_encode_hdr_maxsz + \ |
169 | encode_stateid_maxsz + 1 + \ | 169 | encode_stateid_maxsz + 1 + \ |
170 | encode_share_access_maxsz) | 170 | encode_share_access_maxsz) |
171 | #define decode_open_downgrade_maxsz \ | 171 | #define decode_open_downgrade_maxsz \ |
172 | (op_decode_hdr_maxsz + \ | 172 | (op_decode_hdr_maxsz + \ |
173 | decode_stateid_maxsz) | 173 | decode_stateid_maxsz) |
174 | #define encode_close_maxsz (op_encode_hdr_maxsz + \ | 174 | #define encode_close_maxsz (op_encode_hdr_maxsz + \ |
175 | 1 + encode_stateid_maxsz) | 175 | 1 + encode_stateid_maxsz) |
176 | #define decode_close_maxsz (op_decode_hdr_maxsz + \ | 176 | #define decode_close_maxsz (op_decode_hdr_maxsz + \ |
177 | decode_stateid_maxsz) | 177 | decode_stateid_maxsz) |
178 | #define encode_setattr_maxsz (op_encode_hdr_maxsz + \ | 178 | #define encode_setattr_maxsz (op_encode_hdr_maxsz + \ |
179 | encode_stateid_maxsz + \ | 179 | encode_stateid_maxsz + \ |
180 | encode_attrs_maxsz) | 180 | encode_attrs_maxsz) |
181 | #define decode_setattr_maxsz (op_decode_hdr_maxsz + \ | 181 | #define decode_setattr_maxsz (op_decode_hdr_maxsz + \ |
182 | nfs4_fattr_bitmap_maxsz) | 182 | nfs4_fattr_bitmap_maxsz) |
183 | #define encode_read_maxsz (op_encode_hdr_maxsz + \ | 183 | #define encode_read_maxsz (op_encode_hdr_maxsz + \ |
184 | encode_stateid_maxsz + 3) | 184 | encode_stateid_maxsz + 3) |
185 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) | 185 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) |
186 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ | 186 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ |
187 | 2 + encode_verifier_maxsz + 5) | 187 | 2 + encode_verifier_maxsz + 5) |
188 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ | 188 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ |
189 | decode_verifier_maxsz) | 189 | decode_verifier_maxsz) |
190 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) | 190 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) |
191 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) | 191 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) |
192 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ | 192 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ |
193 | encode_stateid_maxsz + 4) | 193 | encode_stateid_maxsz + 4) |
194 | #define decode_write_maxsz (op_decode_hdr_maxsz + \ | 194 | #define decode_write_maxsz (op_decode_hdr_maxsz + \ |
195 | 2 + decode_verifier_maxsz) | 195 | 2 + decode_verifier_maxsz) |
196 | #define encode_commit_maxsz (op_encode_hdr_maxsz + 3) | 196 | #define encode_commit_maxsz (op_encode_hdr_maxsz + 3) |
197 | #define decode_commit_maxsz (op_decode_hdr_maxsz + \ | 197 | #define decode_commit_maxsz (op_decode_hdr_maxsz + \ |
198 | decode_verifier_maxsz) | 198 | decode_verifier_maxsz) |
199 | #define encode_remove_maxsz (op_encode_hdr_maxsz + \ | 199 | #define encode_remove_maxsz (op_encode_hdr_maxsz + \ |
200 | nfs4_name_maxsz) | 200 | nfs4_name_maxsz) |
201 | #define decode_remove_maxsz (op_decode_hdr_maxsz + \ | 201 | #define decode_remove_maxsz (op_decode_hdr_maxsz + \ |
202 | decode_change_info_maxsz) | 202 | decode_change_info_maxsz) |
203 | #define encode_rename_maxsz (op_encode_hdr_maxsz + \ | 203 | #define encode_rename_maxsz (op_encode_hdr_maxsz + \ |
204 | 2 * nfs4_name_maxsz) | 204 | 2 * nfs4_name_maxsz) |
205 | #define decode_rename_maxsz (op_decode_hdr_maxsz + \ | 205 | #define decode_rename_maxsz (op_decode_hdr_maxsz + \ |
206 | decode_change_info_maxsz + \ | 206 | decode_change_info_maxsz + \ |
207 | decode_change_info_maxsz) | 207 | decode_change_info_maxsz) |
208 | #define encode_link_maxsz (op_encode_hdr_maxsz + \ | 208 | #define encode_link_maxsz (op_encode_hdr_maxsz + \ |
209 | nfs4_name_maxsz) | 209 | nfs4_name_maxsz) |
210 | #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) | 210 | #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) |
211 | #define encode_lockowner_maxsz (7) | 211 | #define encode_lockowner_maxsz (7) |
212 | #define encode_lock_maxsz (op_encode_hdr_maxsz + \ | 212 | #define encode_lock_maxsz (op_encode_hdr_maxsz + \ |
213 | 7 + \ | 213 | 7 + \ |
214 | 1 + encode_stateid_maxsz + 1 + \ | 214 | 1 + encode_stateid_maxsz + 1 + \ |
215 | encode_lockowner_maxsz) | 215 | encode_lockowner_maxsz) |
216 | #define decode_lock_denied_maxsz \ | 216 | #define decode_lock_denied_maxsz \ |
217 | (8 + decode_lockowner_maxsz) | 217 | (8 + decode_lockowner_maxsz) |
218 | #define decode_lock_maxsz (op_decode_hdr_maxsz + \ | 218 | #define decode_lock_maxsz (op_decode_hdr_maxsz + \ |
219 | decode_lock_denied_maxsz) | 219 | decode_lock_denied_maxsz) |
220 | #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ | 220 | #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ |
221 | encode_lockowner_maxsz) | 221 | encode_lockowner_maxsz) |
222 | #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ | 222 | #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ |
223 | decode_lock_denied_maxsz) | 223 | decode_lock_denied_maxsz) |
224 | #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ | 224 | #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ |
225 | encode_stateid_maxsz + \ | 225 | encode_stateid_maxsz + \ |
226 | 4) | 226 | 4) |
227 | #define decode_locku_maxsz (op_decode_hdr_maxsz + \ | 227 | #define decode_locku_maxsz (op_decode_hdr_maxsz + \ |
228 | decode_stateid_maxsz) | 228 | decode_stateid_maxsz) |
229 | #define encode_release_lockowner_maxsz \ | 229 | #define encode_release_lockowner_maxsz \ |
230 | (op_encode_hdr_maxsz + \ | 230 | (op_encode_hdr_maxsz + \ |
231 | encode_lockowner_maxsz) | 231 | encode_lockowner_maxsz) |
232 | #define decode_release_lockowner_maxsz \ | 232 | #define decode_release_lockowner_maxsz \ |
233 | (op_decode_hdr_maxsz) | 233 | (op_decode_hdr_maxsz) |
234 | #define encode_access_maxsz (op_encode_hdr_maxsz + 1) | 234 | #define encode_access_maxsz (op_encode_hdr_maxsz + 1) |
235 | #define decode_access_maxsz (op_decode_hdr_maxsz + 2) | 235 | #define decode_access_maxsz (op_decode_hdr_maxsz + 2) |
236 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ | 236 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ |
237 | 1 + nfs4_name_maxsz + \ | 237 | 1 + nfs4_name_maxsz + \ |
238 | 1 + \ | 238 | 1 + \ |
239 | nfs4_fattr_maxsz) | 239 | nfs4_fattr_maxsz) |
240 | #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) | 240 | #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) |
241 | #define encode_create_maxsz (op_encode_hdr_maxsz + \ | 241 | #define encode_create_maxsz (op_encode_hdr_maxsz + \ |
242 | 1 + 2 + nfs4_name_maxsz + \ | 242 | 1 + 2 + nfs4_name_maxsz + \ |
243 | encode_attrs_maxsz) | 243 | encode_attrs_maxsz) |
244 | #define decode_create_maxsz (op_decode_hdr_maxsz + \ | 244 | #define decode_create_maxsz (op_decode_hdr_maxsz + \ |
245 | decode_change_info_maxsz + \ | 245 | decode_change_info_maxsz + \ |
246 | nfs4_fattr_bitmap_maxsz) | 246 | nfs4_fattr_bitmap_maxsz) |
247 | #define encode_statfs_maxsz (encode_getattr_maxsz) | 247 | #define encode_statfs_maxsz (encode_getattr_maxsz) |
248 | #define decode_statfs_maxsz (decode_getattr_maxsz) | 248 | #define decode_statfs_maxsz (decode_getattr_maxsz) |
249 | #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) | 249 | #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) |
250 | #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) | 250 | #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) |
251 | #define encode_getacl_maxsz (encode_getattr_maxsz) | 251 | #define encode_getacl_maxsz (encode_getattr_maxsz) |
252 | #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ | 252 | #define decode_getacl_maxsz (op_decode_hdr_maxsz + \ |
253 | nfs4_fattr_bitmap_maxsz + 1) | 253 | nfs4_fattr_bitmap_maxsz + 1) |
254 | #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ | 254 | #define encode_setacl_maxsz (op_encode_hdr_maxsz + \ |
255 | encode_stateid_maxsz + 3) | 255 | encode_stateid_maxsz + 3) |
256 | #define decode_setacl_maxsz (decode_setattr_maxsz) | 256 | #define decode_setacl_maxsz (decode_setattr_maxsz) |
257 | #define encode_fs_locations_maxsz \ | 257 | #define encode_fs_locations_maxsz \ |
258 | (encode_getattr_maxsz) | 258 | (encode_getattr_maxsz) |
259 | #define decode_fs_locations_maxsz \ | 259 | #define decode_fs_locations_maxsz \ |
260 | (0) | 260 | (0) |
261 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) | 261 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
262 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) | 262 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) |
263 | 263 | ||
264 | #if defined(CONFIG_NFS_V4_1) | 264 | #if defined(CONFIG_NFS_V4_1) |
265 | #define NFS4_MAX_MACHINE_NAME_LEN (64) | 265 | #define NFS4_MAX_MACHINE_NAME_LEN (64) |
266 | 266 | ||
267 | #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ | 267 | #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ |
268 | encode_verifier_maxsz + \ | 268 | encode_verifier_maxsz + \ |
269 | 1 /* co_ownerid.len */ + \ | 269 | 1 /* co_ownerid.len */ + \ |
270 | XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ | 270 | XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ |
271 | 1 /* flags */ + \ | 271 | 1 /* flags */ + \ |
272 | 1 /* spa_how */ + \ | 272 | 1 /* spa_how */ + \ |
273 | 0 /* SP4_NONE (for now) */ + \ | 273 | 0 /* SP4_NONE (for now) */ + \ |
274 | 1 /* zero implemetation id array */) | 274 | 1 /* zero implemetation id array */) |
275 | #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ | 275 | #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ |
276 | 2 /* eir_clientid */ + \ | 276 | 2 /* eir_clientid */ + \ |
277 | 1 /* eir_sequenceid */ + \ | 277 | 1 /* eir_sequenceid */ + \ |
278 | 1 /* eir_flags */ + \ | 278 | 1 /* eir_flags */ + \ |
279 | 1 /* spr_how */ + \ | 279 | 1 /* spr_how */ + \ |
280 | 0 /* SP4_NONE (for now) */ + \ | 280 | 0 /* SP4_NONE (for now) */ + \ |
281 | 2 /* eir_server_owner.so_minor_id */ + \ | 281 | 2 /* eir_server_owner.so_minor_id */ + \ |
282 | /* eir_server_owner.so_major_id<> */ \ | 282 | /* eir_server_owner.so_major_id<> */ \ |
283 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | 283 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
284 | /* eir_server_scope<> */ \ | 284 | /* eir_server_scope<> */ \ |
285 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | 285 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
286 | 1 /* eir_server_impl_id array length */ + \ | 286 | 1 /* eir_server_impl_id array length */ + \ |
287 | 0 /* ignored eir_server_impl_id contents */) | 287 | 0 /* ignored eir_server_impl_id contents */) |
288 | #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) | 288 | #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) |
289 | #define decode_channel_attrs_maxsz (6 + \ | 289 | #define decode_channel_attrs_maxsz (6 + \ |
290 | 1 /* ca_rdma_ird.len */ + \ | 290 | 1 /* ca_rdma_ird.len */ + \ |
291 | 1 /* ca_rdma_ird */) | 291 | 1 /* ca_rdma_ird */) |
292 | #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ | 292 | #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ |
293 | 2 /* csa_clientid */ + \ | 293 | 2 /* csa_clientid */ + \ |
294 | 1 /* csa_sequence */ + \ | 294 | 1 /* csa_sequence */ + \ |
295 | 1 /* csa_flags */ + \ | 295 | 1 /* csa_flags */ + \ |
296 | encode_channel_attrs_maxsz + \ | 296 | encode_channel_attrs_maxsz + \ |
297 | encode_channel_attrs_maxsz + \ | 297 | encode_channel_attrs_maxsz + \ |
298 | 1 /* csa_cb_program */ + \ | 298 | 1 /* csa_cb_program */ + \ |
299 | 1 /* csa_sec_parms.len (1) */ + \ | 299 | 1 /* csa_sec_parms.len (1) */ + \ |
300 | 1 /* cb_secflavor (AUTH_SYS) */ + \ | 300 | 1 /* cb_secflavor (AUTH_SYS) */ + \ |
301 | 1 /* stamp */ + \ | 301 | 1 /* stamp */ + \ |
302 | 1 /* machinename.len */ + \ | 302 | 1 /* machinename.len */ + \ |
303 | XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ | 303 | XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ |
304 | 1 /* uid */ + \ | 304 | 1 /* uid */ + \ |
305 | 1 /* gid */ + \ | 305 | 1 /* gid */ + \ |
306 | 1 /* gids.len (0) */) | 306 | 1 /* gids.len (0) */) |
307 | #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ | 307 | #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ |
308 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ | 308 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ |
309 | 1 /* csr_sequence */ + \ | 309 | 1 /* csr_sequence */ + \ |
310 | 1 /* csr_flags */ + \ | 310 | 1 /* csr_flags */ + \ |
311 | decode_channel_attrs_maxsz + \ | 311 | decode_channel_attrs_maxsz + \ |
312 | decode_channel_attrs_maxsz) | 312 | decode_channel_attrs_maxsz) |
313 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) | 313 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) |
314 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) | 314 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) |
315 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ | 315 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ |
316 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) | 316 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) |
317 | #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ | 317 | #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ |
318 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) | 318 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) |
319 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) | 319 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) |
320 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) | 320 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) |
321 | #define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 + \ | 321 | #define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 + \ |
322 | encode_verifier_maxsz) | 322 | encode_verifier_maxsz) |
323 | #define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + \ | 323 | #define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + \ |
324 | 2 /* nfs_cookie4 gdlr_cookie */ + \ | 324 | 2 /* nfs_cookie4 gdlr_cookie */ + \ |
325 | decode_verifier_maxsz \ | 325 | decode_verifier_maxsz \ |
326 | /* verifier4 gdlr_verifier */ + \ | 326 | /* verifier4 gdlr_verifier */ + \ |
327 | 1 /* gdlr_deviceid_list count */ + \ | 327 | 1 /* gdlr_deviceid_list count */ + \ |
328 | XDR_QUADLEN(NFS4_PNFS_GETDEVLIST_MAXNUM * \ | 328 | XDR_QUADLEN(NFS4_PNFS_GETDEVLIST_MAXNUM * \ |
329 | NFS4_DEVICEID4_SIZE) \ | 329 | NFS4_DEVICEID4_SIZE) \ |
330 | /* gdlr_deviceid_list */ + \ | 330 | /* gdlr_deviceid_list */ + \ |
331 | 1 /* bool gdlr_eof */) | 331 | 1 /* bool gdlr_eof */) |
332 | #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ | 332 | #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ |
333 | XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) | 333 | XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) |
334 | #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ | 334 | #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ |
335 | 1 /* layout type */ + \ | 335 | 1 /* layout type */ + \ |
336 | 1 /* opaque devaddr4 length */ + \ | 336 | 1 /* opaque devaddr4 length */ + \ |
337 | /* devaddr4 payload is read into page */ \ | 337 | /* devaddr4 payload is read into page */ \ |
338 | 1 /* notification bitmap length */ + \ | 338 | 1 /* notification bitmap length */ + \ |
339 | 1 /* notification bitmap */) | 339 | 1 /* notification bitmap */) |
340 | #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ | 340 | #define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \ |
341 | encode_stateid_maxsz) | 341 | encode_stateid_maxsz) |
342 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ | 342 | #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ |
343 | decode_stateid_maxsz + \ | 343 | decode_stateid_maxsz + \ |
344 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) | 344 | XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) |
345 | #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ | 345 | #define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ |
346 | 2 /* offset */ + \ | 346 | 2 /* offset */ + \ |
347 | 2 /* length */ + \ | 347 | 2 /* length */ + \ |
348 | 1 /* reclaim */ + \ | 348 | 1 /* reclaim */ + \ |
349 | encode_stateid_maxsz + \ | 349 | encode_stateid_maxsz + \ |
350 | 1 /* new offset (true) */ + \ | 350 | 1 /* new offset (true) */ + \ |
351 | 2 /* last byte written */ + \ | 351 | 2 /* last byte written */ + \ |
352 | 1 /* nt_timechanged (false) */ + \ | 352 | 1 /* nt_timechanged (false) */ + \ |
353 | 1 /* layoutupdate4 layout type */ + \ | 353 | 1 /* layoutupdate4 layout type */ + \ |
354 | 1 /* NULL filelayout layoutupdate4 payload */) | 354 | 1 /* NULL filelayout layoutupdate4 payload */) |
355 | #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) | 355 | #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) |
356 | #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ | 356 | #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ |
357 | encode_stateid_maxsz + \ | 357 | encode_stateid_maxsz + \ |
358 | 1 /* FIXME: opaque lrf_body always empty at the moment */) | 358 | 1 /* FIXME: opaque lrf_body always empty at the moment */) |
359 | #define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ | 359 | #define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ |
360 | 1 + decode_stateid_maxsz) | 360 | 1 + decode_stateid_maxsz) |
361 | #define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1) | 361 | #define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1) |
362 | #define decode_secinfo_no_name_maxsz decode_secinfo_maxsz | 362 | #define decode_secinfo_no_name_maxsz decode_secinfo_maxsz |
363 | #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ | 363 | #define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \ |
364 | XDR_QUADLEN(NFS4_STATEID_SIZE)) | 364 | XDR_QUADLEN(NFS4_STATEID_SIZE)) |
365 | #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) | 365 | #define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1) |
366 | #define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \ | 366 | #define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \ |
367 | XDR_QUADLEN(NFS4_STATEID_SIZE)) | 367 | XDR_QUADLEN(NFS4_STATEID_SIZE)) |
368 | #define decode_free_stateid_maxsz (op_decode_hdr_maxsz + 1) | 368 | #define decode_free_stateid_maxsz (op_decode_hdr_maxsz + 1) |
369 | #else /* CONFIG_NFS_V4_1 */ | 369 | #else /* CONFIG_NFS_V4_1 */ |
370 | #define encode_sequence_maxsz 0 | 370 | #define encode_sequence_maxsz 0 |
371 | #define decode_sequence_maxsz 0 | 371 | #define decode_sequence_maxsz 0 |
372 | #endif /* CONFIG_NFS_V4_1 */ | 372 | #endif /* CONFIG_NFS_V4_1 */ |
373 | 373 | ||
374 | #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ | 374 | #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ |
375 | #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ | 375 | #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ |
376 | #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ | 376 | #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ |
377 | encode_sequence_maxsz + \ | 377 | encode_sequence_maxsz + \ |
378 | encode_putfh_maxsz + \ | 378 | encode_putfh_maxsz + \ |
379 | encode_read_maxsz) | 379 | encode_read_maxsz) |
380 | #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ | 380 | #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ |
381 | decode_sequence_maxsz + \ | 381 | decode_sequence_maxsz + \ |
382 | decode_putfh_maxsz + \ | 382 | decode_putfh_maxsz + \ |
383 | decode_read_maxsz) | 383 | decode_read_maxsz) |
384 | #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ | 384 | #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ |
385 | encode_sequence_maxsz + \ | 385 | encode_sequence_maxsz + \ |
386 | encode_putfh_maxsz + \ | 386 | encode_putfh_maxsz + \ |
387 | encode_readlink_maxsz) | 387 | encode_readlink_maxsz) |
388 | #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ | 388 | #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ |
389 | decode_sequence_maxsz + \ | 389 | decode_sequence_maxsz + \ |
390 | decode_putfh_maxsz + \ | 390 | decode_putfh_maxsz + \ |
391 | decode_readlink_maxsz) | 391 | decode_readlink_maxsz) |
392 | #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ | 392 | #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ |
393 | encode_sequence_maxsz + \ | 393 | encode_sequence_maxsz + \ |
394 | encode_putfh_maxsz + \ | 394 | encode_putfh_maxsz + \ |
395 | encode_readdir_maxsz) | 395 | encode_readdir_maxsz) |
396 | #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ | 396 | #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ |
397 | decode_sequence_maxsz + \ | 397 | decode_sequence_maxsz + \ |
398 | decode_putfh_maxsz + \ | 398 | decode_putfh_maxsz + \ |
399 | decode_readdir_maxsz) | 399 | decode_readdir_maxsz) |
400 | #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ | 400 | #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ |
401 | encode_sequence_maxsz + \ | 401 | encode_sequence_maxsz + \ |
402 | encode_putfh_maxsz + \ | 402 | encode_putfh_maxsz + \ |
403 | encode_write_maxsz + \ | 403 | encode_write_maxsz + \ |
404 | encode_getattr_maxsz) | 404 | encode_getattr_maxsz) |
405 | #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ | 405 | #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ |
406 | decode_sequence_maxsz + \ | 406 | decode_sequence_maxsz + \ |
407 | decode_putfh_maxsz + \ | 407 | decode_putfh_maxsz + \ |
408 | decode_write_maxsz + \ | 408 | decode_write_maxsz + \ |
409 | decode_getattr_maxsz) | 409 | decode_getattr_maxsz) |
410 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ | 410 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ |
411 | encode_sequence_maxsz + \ | 411 | encode_sequence_maxsz + \ |
412 | encode_putfh_maxsz + \ | 412 | encode_putfh_maxsz + \ |
413 | encode_commit_maxsz + \ | 413 | encode_commit_maxsz + \ |
414 | encode_getattr_maxsz) | 414 | encode_getattr_maxsz) |
415 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ | 415 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ |
416 | decode_sequence_maxsz + \ | 416 | decode_sequence_maxsz + \ |
417 | decode_putfh_maxsz + \ | 417 | decode_putfh_maxsz + \ |
418 | decode_commit_maxsz + \ | 418 | decode_commit_maxsz + \ |
419 | decode_getattr_maxsz) | 419 | decode_getattr_maxsz) |
420 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ | 420 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ |
421 | encode_sequence_maxsz + \ | 421 | encode_sequence_maxsz + \ |
422 | encode_putfh_maxsz + \ | 422 | encode_putfh_maxsz + \ |
423 | encode_savefh_maxsz + \ | 423 | encode_savefh_maxsz + \ |
424 | encode_open_maxsz + \ | 424 | encode_open_maxsz + \ |
425 | encode_getfh_maxsz + \ | 425 | encode_getfh_maxsz + \ |
426 | encode_getattr_maxsz + \ | 426 | encode_getattr_maxsz + \ |
427 | encode_restorefh_maxsz + \ | 427 | encode_restorefh_maxsz + \ |
428 | encode_getattr_maxsz) | 428 | encode_getattr_maxsz) |
429 | #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ | 429 | #define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ |
430 | decode_sequence_maxsz + \ | 430 | decode_sequence_maxsz + \ |
431 | decode_putfh_maxsz + \ | 431 | decode_putfh_maxsz + \ |
432 | decode_savefh_maxsz + \ | 432 | decode_savefh_maxsz + \ |
433 | decode_open_maxsz + \ | 433 | decode_open_maxsz + \ |
434 | decode_getfh_maxsz + \ | 434 | decode_getfh_maxsz + \ |
435 | decode_getattr_maxsz + \ | 435 | decode_getattr_maxsz + \ |
436 | decode_restorefh_maxsz + \ | 436 | decode_restorefh_maxsz + \ |
437 | decode_getattr_maxsz) | 437 | decode_getattr_maxsz) |
438 | #define NFS4_enc_open_confirm_sz \ | 438 | #define NFS4_enc_open_confirm_sz \ |
439 | (compound_encode_hdr_maxsz + \ | 439 | (compound_encode_hdr_maxsz + \ |
440 | encode_putfh_maxsz + \ | 440 | encode_putfh_maxsz + \ |
441 | encode_open_confirm_maxsz) | 441 | encode_open_confirm_maxsz) |
442 | #define NFS4_dec_open_confirm_sz \ | 442 | #define NFS4_dec_open_confirm_sz \ |
443 | (compound_decode_hdr_maxsz + \ | 443 | (compound_decode_hdr_maxsz + \ |
444 | decode_putfh_maxsz + \ | 444 | decode_putfh_maxsz + \ |
445 | decode_open_confirm_maxsz) | 445 | decode_open_confirm_maxsz) |
446 | #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ | 446 | #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ |
447 | encode_sequence_maxsz + \ | 447 | encode_sequence_maxsz + \ |
448 | encode_putfh_maxsz + \ | 448 | encode_putfh_maxsz + \ |
449 | encode_open_maxsz + \ | 449 | encode_open_maxsz + \ |
450 | encode_getattr_maxsz) | 450 | encode_getattr_maxsz) |
451 | #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ | 451 | #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ |
452 | decode_sequence_maxsz + \ | 452 | decode_sequence_maxsz + \ |
453 | decode_putfh_maxsz + \ | 453 | decode_putfh_maxsz + \ |
454 | decode_open_maxsz + \ | 454 | decode_open_maxsz + \ |
455 | decode_getattr_maxsz) | 455 | decode_getattr_maxsz) |
456 | #define NFS4_enc_open_downgrade_sz \ | 456 | #define NFS4_enc_open_downgrade_sz \ |
457 | (compound_encode_hdr_maxsz + \ | 457 | (compound_encode_hdr_maxsz + \ |
458 | encode_sequence_maxsz + \ | 458 | encode_sequence_maxsz + \ |
459 | encode_putfh_maxsz + \ | 459 | encode_putfh_maxsz + \ |
460 | encode_open_downgrade_maxsz + \ | 460 | encode_open_downgrade_maxsz + \ |
461 | encode_getattr_maxsz) | 461 | encode_getattr_maxsz) |
462 | #define NFS4_dec_open_downgrade_sz \ | 462 | #define NFS4_dec_open_downgrade_sz \ |
463 | (compound_decode_hdr_maxsz + \ | 463 | (compound_decode_hdr_maxsz + \ |
464 | decode_sequence_maxsz + \ | 464 | decode_sequence_maxsz + \ |
465 | decode_putfh_maxsz + \ | 465 | decode_putfh_maxsz + \ |
466 | decode_open_downgrade_maxsz + \ | 466 | decode_open_downgrade_maxsz + \ |
467 | decode_getattr_maxsz) | 467 | decode_getattr_maxsz) |
468 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ | 468 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ |
469 | encode_sequence_maxsz + \ | 469 | encode_sequence_maxsz + \ |
470 | encode_putfh_maxsz + \ | 470 | encode_putfh_maxsz + \ |
471 | encode_close_maxsz + \ | 471 | encode_close_maxsz + \ |
472 | encode_getattr_maxsz) | 472 | encode_getattr_maxsz) |
473 | #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ | 473 | #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ |
474 | decode_sequence_maxsz + \ | 474 | decode_sequence_maxsz + \ |
475 | decode_putfh_maxsz + \ | 475 | decode_putfh_maxsz + \ |
476 | decode_close_maxsz + \ | 476 | decode_close_maxsz + \ |
477 | decode_getattr_maxsz) | 477 | decode_getattr_maxsz) |
478 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ | 478 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ |
479 | encode_sequence_maxsz + \ | 479 | encode_sequence_maxsz + \ |
480 | encode_putfh_maxsz + \ | 480 | encode_putfh_maxsz + \ |
481 | encode_setattr_maxsz + \ | 481 | encode_setattr_maxsz + \ |
482 | encode_getattr_maxsz) | 482 | encode_getattr_maxsz) |
483 | #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ | 483 | #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ |
484 | decode_sequence_maxsz + \ | 484 | decode_sequence_maxsz + \ |
485 | decode_putfh_maxsz + \ | 485 | decode_putfh_maxsz + \ |
486 | decode_setattr_maxsz + \ | 486 | decode_setattr_maxsz + \ |
487 | decode_getattr_maxsz) | 487 | decode_getattr_maxsz) |
488 | #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ | 488 | #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ |
489 | encode_sequence_maxsz + \ | 489 | encode_sequence_maxsz + \ |
490 | encode_putfh_maxsz + \ | 490 | encode_putfh_maxsz + \ |
491 | encode_fsinfo_maxsz) | 491 | encode_fsinfo_maxsz) |
492 | #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ | 492 | #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ |
493 | decode_sequence_maxsz + \ | 493 | decode_sequence_maxsz + \ |
494 | decode_putfh_maxsz + \ | 494 | decode_putfh_maxsz + \ |
495 | decode_fsinfo_maxsz) | 495 | decode_fsinfo_maxsz) |
496 | #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ | 496 | #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ |
497 | encode_renew_maxsz) | 497 | encode_renew_maxsz) |
498 | #define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \ | 498 | #define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \ |
499 | decode_renew_maxsz) | 499 | decode_renew_maxsz) |
500 | #define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \ | 500 | #define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \ |
501 | encode_setclientid_maxsz) | 501 | encode_setclientid_maxsz) |
502 | #define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \ | 502 | #define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \ |
503 | decode_setclientid_maxsz) | 503 | decode_setclientid_maxsz) |
504 | #define NFS4_enc_setclientid_confirm_sz \ | 504 | #define NFS4_enc_setclientid_confirm_sz \ |
505 | (compound_encode_hdr_maxsz + \ | 505 | (compound_encode_hdr_maxsz + \ |
506 | encode_setclientid_confirm_maxsz + \ | 506 | encode_setclientid_confirm_maxsz + \ |
507 | encode_putrootfh_maxsz + \ | 507 | encode_putrootfh_maxsz + \ |
508 | encode_fsinfo_maxsz) | 508 | encode_fsinfo_maxsz) |
509 | #define NFS4_dec_setclientid_confirm_sz \ | 509 | #define NFS4_dec_setclientid_confirm_sz \ |
510 | (compound_decode_hdr_maxsz + \ | 510 | (compound_decode_hdr_maxsz + \ |
511 | decode_setclientid_confirm_maxsz + \ | 511 | decode_setclientid_confirm_maxsz + \ |
512 | decode_putrootfh_maxsz + \ | 512 | decode_putrootfh_maxsz + \ |
513 | decode_fsinfo_maxsz) | 513 | decode_fsinfo_maxsz) |
514 | #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ | 514 | #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ |
515 | encode_sequence_maxsz + \ | 515 | encode_sequence_maxsz + \ |
516 | encode_putfh_maxsz + \ | 516 | encode_putfh_maxsz + \ |
517 | encode_lock_maxsz) | 517 | encode_lock_maxsz) |
518 | #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ | 518 | #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ |
519 | decode_sequence_maxsz + \ | 519 | decode_sequence_maxsz + \ |
520 | decode_putfh_maxsz + \ | 520 | decode_putfh_maxsz + \ |
521 | decode_lock_maxsz) | 521 | decode_lock_maxsz) |
522 | #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ | 522 | #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ |
523 | encode_sequence_maxsz + \ | 523 | encode_sequence_maxsz + \ |
524 | encode_putfh_maxsz + \ | 524 | encode_putfh_maxsz + \ |
525 | encode_lockt_maxsz) | 525 | encode_lockt_maxsz) |
526 | #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ | 526 | #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ |
527 | decode_sequence_maxsz + \ | 527 | decode_sequence_maxsz + \ |
528 | decode_putfh_maxsz + \ | 528 | decode_putfh_maxsz + \ |
529 | decode_lockt_maxsz) | 529 | decode_lockt_maxsz) |
530 | #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ | 530 | #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ |
531 | encode_sequence_maxsz + \ | 531 | encode_sequence_maxsz + \ |
532 | encode_putfh_maxsz + \ | 532 | encode_putfh_maxsz + \ |
533 | encode_locku_maxsz) | 533 | encode_locku_maxsz) |
534 | #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ | 534 | #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ |
535 | decode_sequence_maxsz + \ | 535 | decode_sequence_maxsz + \ |
536 | decode_putfh_maxsz + \ | 536 | decode_putfh_maxsz + \ |
537 | decode_locku_maxsz) | 537 | decode_locku_maxsz) |
538 | #define NFS4_enc_release_lockowner_sz \ | 538 | #define NFS4_enc_release_lockowner_sz \ |
539 | (compound_encode_hdr_maxsz + \ | 539 | (compound_encode_hdr_maxsz + \ |
540 | encode_lockowner_maxsz) | 540 | encode_lockowner_maxsz) |
541 | #define NFS4_dec_release_lockowner_sz \ | 541 | #define NFS4_dec_release_lockowner_sz \ |
542 | (compound_decode_hdr_maxsz + \ | 542 | (compound_decode_hdr_maxsz + \ |
543 | decode_lockowner_maxsz) | 543 | decode_lockowner_maxsz) |
544 | #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ | 544 | #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ |
545 | encode_sequence_maxsz + \ | 545 | encode_sequence_maxsz + \ |
546 | encode_putfh_maxsz + \ | 546 | encode_putfh_maxsz + \ |
547 | encode_access_maxsz + \ | 547 | encode_access_maxsz + \ |
548 | encode_getattr_maxsz) | 548 | encode_getattr_maxsz) |
549 | #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ | 549 | #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ |
550 | decode_sequence_maxsz + \ | 550 | decode_sequence_maxsz + \ |
551 | decode_putfh_maxsz + \ | 551 | decode_putfh_maxsz + \ |
552 | decode_access_maxsz + \ | 552 | decode_access_maxsz + \ |
553 | decode_getattr_maxsz) | 553 | decode_getattr_maxsz) |
554 | #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ | 554 | #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ |
555 | encode_sequence_maxsz + \ | 555 | encode_sequence_maxsz + \ |
556 | encode_putfh_maxsz + \ | 556 | encode_putfh_maxsz + \ |
557 | encode_getattr_maxsz) | 557 | encode_getattr_maxsz) |
558 | #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ | 558 | #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ |
559 | decode_sequence_maxsz + \ | 559 | decode_sequence_maxsz + \ |
560 | decode_putfh_maxsz + \ | 560 | decode_putfh_maxsz + \ |
561 | decode_getattr_maxsz) | 561 | decode_getattr_maxsz) |
562 | #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ | 562 | #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ |
563 | encode_sequence_maxsz + \ | 563 | encode_sequence_maxsz + \ |
564 | encode_putfh_maxsz + \ | 564 | encode_putfh_maxsz + \ |
565 | encode_lookup_maxsz + \ | 565 | encode_lookup_maxsz + \ |
566 | encode_getattr_maxsz + \ | 566 | encode_getattr_maxsz + \ |
567 | encode_getfh_maxsz) | 567 | encode_getfh_maxsz) |
568 | #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ | 568 | #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ |
569 | decode_sequence_maxsz + \ | 569 | decode_sequence_maxsz + \ |
570 | decode_putfh_maxsz + \ | 570 | decode_putfh_maxsz + \ |
571 | decode_lookup_maxsz + \ | 571 | decode_lookup_maxsz + \ |
572 | decode_getattr_maxsz + \ | 572 | decode_getattr_maxsz + \ |
573 | decode_getfh_maxsz) | 573 | decode_getfh_maxsz) |
574 | #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ | 574 | #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ |
575 | encode_sequence_maxsz + \ | 575 | encode_sequence_maxsz + \ |
576 | encode_putrootfh_maxsz + \ | 576 | encode_putrootfh_maxsz + \ |
577 | encode_getattr_maxsz + \ | 577 | encode_getattr_maxsz + \ |
578 | encode_getfh_maxsz) | 578 | encode_getfh_maxsz) |
579 | #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ | 579 | #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ |
580 | decode_sequence_maxsz + \ | 580 | decode_sequence_maxsz + \ |
581 | decode_putrootfh_maxsz + \ | 581 | decode_putrootfh_maxsz + \ |
582 | decode_getattr_maxsz + \ | 582 | decode_getattr_maxsz + \ |
583 | decode_getfh_maxsz) | 583 | decode_getfh_maxsz) |
584 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ | 584 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ |
585 | encode_sequence_maxsz + \ | 585 | encode_sequence_maxsz + \ |
586 | encode_putfh_maxsz + \ | 586 | encode_putfh_maxsz + \ |
587 | encode_remove_maxsz + \ | 587 | encode_remove_maxsz + \ |
588 | encode_getattr_maxsz) | 588 | encode_getattr_maxsz) |
589 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ | 589 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ |
590 | decode_sequence_maxsz + \ | 590 | decode_sequence_maxsz + \ |
591 | decode_putfh_maxsz + \ | 591 | decode_putfh_maxsz + \ |
592 | decode_remove_maxsz + \ | 592 | decode_remove_maxsz + \ |
593 | decode_getattr_maxsz) | 593 | decode_getattr_maxsz) |
594 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ | 594 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ |
595 | encode_sequence_maxsz + \ | 595 | encode_sequence_maxsz + \ |
596 | encode_putfh_maxsz + \ | 596 | encode_putfh_maxsz + \ |
597 | encode_savefh_maxsz + \ | 597 | encode_savefh_maxsz + \ |
598 | encode_putfh_maxsz + \ | 598 | encode_putfh_maxsz + \ |
599 | encode_rename_maxsz + \ | 599 | encode_rename_maxsz + \ |
600 | encode_getattr_maxsz + \ | 600 | encode_getattr_maxsz + \ |
601 | encode_restorefh_maxsz + \ | 601 | encode_restorefh_maxsz + \ |
602 | encode_getattr_maxsz) | 602 | encode_getattr_maxsz) |
603 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ | 603 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ |
604 | decode_sequence_maxsz + \ | 604 | decode_sequence_maxsz + \ |
605 | decode_putfh_maxsz + \ | 605 | decode_putfh_maxsz + \ |
606 | decode_savefh_maxsz + \ | 606 | decode_savefh_maxsz + \ |
607 | decode_putfh_maxsz + \ | 607 | decode_putfh_maxsz + \ |
608 | decode_rename_maxsz + \ | 608 | decode_rename_maxsz + \ |
609 | decode_getattr_maxsz + \ | 609 | decode_getattr_maxsz + \ |
610 | decode_restorefh_maxsz + \ | 610 | decode_restorefh_maxsz + \ |
611 | decode_getattr_maxsz) | 611 | decode_getattr_maxsz) |
612 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ | 612 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ |
613 | encode_sequence_maxsz + \ | 613 | encode_sequence_maxsz + \ |
614 | encode_putfh_maxsz + \ | 614 | encode_putfh_maxsz + \ |
615 | encode_savefh_maxsz + \ | 615 | encode_savefh_maxsz + \ |
616 | encode_putfh_maxsz + \ | 616 | encode_putfh_maxsz + \ |
617 | encode_link_maxsz + \ | 617 | encode_link_maxsz + \ |
618 | decode_getattr_maxsz + \ | 618 | decode_getattr_maxsz + \ |
619 | encode_restorefh_maxsz + \ | 619 | encode_restorefh_maxsz + \ |
620 | decode_getattr_maxsz) | 620 | decode_getattr_maxsz) |
621 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ | 621 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ |
622 | decode_sequence_maxsz + \ | 622 | decode_sequence_maxsz + \ |
623 | decode_putfh_maxsz + \ | 623 | decode_putfh_maxsz + \ |
624 | decode_savefh_maxsz + \ | 624 | decode_savefh_maxsz + \ |
625 | decode_putfh_maxsz + \ | 625 | decode_putfh_maxsz + \ |
626 | decode_link_maxsz + \ | 626 | decode_link_maxsz + \ |
627 | decode_getattr_maxsz + \ | 627 | decode_getattr_maxsz + \ |
628 | decode_restorefh_maxsz + \ | 628 | decode_restorefh_maxsz + \ |
629 | decode_getattr_maxsz) | 629 | decode_getattr_maxsz) |
630 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ | 630 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ |
631 | encode_sequence_maxsz + \ | 631 | encode_sequence_maxsz + \ |
632 | encode_putfh_maxsz + \ | 632 | encode_putfh_maxsz + \ |
633 | encode_symlink_maxsz + \ | 633 | encode_symlink_maxsz + \ |
634 | encode_getattr_maxsz + \ | 634 | encode_getattr_maxsz + \ |
635 | encode_getfh_maxsz) | 635 | encode_getfh_maxsz) |
636 | #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ | 636 | #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ |
637 | decode_sequence_maxsz + \ | 637 | decode_sequence_maxsz + \ |
638 | decode_putfh_maxsz + \ | 638 | decode_putfh_maxsz + \ |
639 | decode_symlink_maxsz + \ | 639 | decode_symlink_maxsz + \ |
640 | decode_getattr_maxsz + \ | 640 | decode_getattr_maxsz + \ |
641 | decode_getfh_maxsz) | 641 | decode_getfh_maxsz) |
642 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ | 642 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ |
643 | encode_sequence_maxsz + \ | 643 | encode_sequence_maxsz + \ |
644 | encode_putfh_maxsz + \ | 644 | encode_putfh_maxsz + \ |
645 | encode_savefh_maxsz + \ | 645 | encode_savefh_maxsz + \ |
646 | encode_create_maxsz + \ | 646 | encode_create_maxsz + \ |
647 | encode_getfh_maxsz + \ | 647 | encode_getfh_maxsz + \ |
648 | encode_getattr_maxsz + \ | 648 | encode_getattr_maxsz + \ |
649 | encode_restorefh_maxsz + \ | 649 | encode_restorefh_maxsz + \ |
650 | encode_getattr_maxsz) | 650 | encode_getattr_maxsz) |
651 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ | 651 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ |
652 | decode_sequence_maxsz + \ | 652 | decode_sequence_maxsz + \ |
653 | decode_putfh_maxsz + \ | 653 | decode_putfh_maxsz + \ |
654 | decode_savefh_maxsz + \ | 654 | decode_savefh_maxsz + \ |
655 | decode_create_maxsz + \ | 655 | decode_create_maxsz + \ |
656 | decode_getfh_maxsz + \ | 656 | decode_getfh_maxsz + \ |
657 | decode_getattr_maxsz + \ | 657 | decode_getattr_maxsz + \ |
658 | decode_restorefh_maxsz + \ | 658 | decode_restorefh_maxsz + \ |
659 | decode_getattr_maxsz) | 659 | decode_getattr_maxsz) |
660 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ | 660 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ |
661 | encode_sequence_maxsz + \ | 661 | encode_sequence_maxsz + \ |
662 | encode_putfh_maxsz + \ | 662 | encode_putfh_maxsz + \ |
663 | encode_getattr_maxsz) | 663 | encode_getattr_maxsz) |
664 | #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ | 664 | #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ |
665 | decode_sequence_maxsz + \ | 665 | decode_sequence_maxsz + \ |
666 | decode_putfh_maxsz + \ | 666 | decode_putfh_maxsz + \ |
667 | decode_getattr_maxsz) | 667 | decode_getattr_maxsz) |
668 | #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ | 668 | #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ |
669 | encode_sequence_maxsz + \ | 669 | encode_sequence_maxsz + \ |
670 | encode_putfh_maxsz + \ | 670 | encode_putfh_maxsz + \ |
671 | encode_statfs_maxsz) | 671 | encode_statfs_maxsz) |
672 | #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ | 672 | #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ |
673 | decode_sequence_maxsz + \ | 673 | decode_sequence_maxsz + \ |
674 | decode_putfh_maxsz + \ | 674 | decode_putfh_maxsz + \ |
675 | decode_statfs_maxsz) | 675 | decode_statfs_maxsz) |
676 | #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ | 676 | #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ |
677 | encode_sequence_maxsz + \ | 677 | encode_sequence_maxsz + \ |
678 | encode_putfh_maxsz + \ | 678 | encode_putfh_maxsz + \ |
679 | encode_getattr_maxsz) | 679 | encode_getattr_maxsz) |
680 | #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ | 680 | #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ |
681 | decode_sequence_maxsz + \ | 681 | decode_sequence_maxsz + \ |
682 | decode_putfh_maxsz + \ | 682 | decode_putfh_maxsz + \ |
683 | decode_getattr_maxsz) | 683 | decode_getattr_maxsz) |
684 | #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ | 684 | #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ |
685 | encode_sequence_maxsz + \ | 685 | encode_sequence_maxsz + \ |
686 | encode_putfh_maxsz + \ | 686 | encode_putfh_maxsz + \ |
687 | encode_delegreturn_maxsz + \ | 687 | encode_delegreturn_maxsz + \ |
688 | encode_getattr_maxsz) | 688 | encode_getattr_maxsz) |
689 | #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ | 689 | #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ |
690 | decode_sequence_maxsz + \ | 690 | decode_sequence_maxsz + \ |
691 | decode_delegreturn_maxsz + \ | 691 | decode_delegreturn_maxsz + \ |
692 | decode_getattr_maxsz) | 692 | decode_getattr_maxsz) |
693 | #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ | 693 | #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ |
694 | encode_sequence_maxsz + \ | 694 | encode_sequence_maxsz + \ |
695 | encode_putfh_maxsz + \ | 695 | encode_putfh_maxsz + \ |
696 | encode_getacl_maxsz) | 696 | encode_getacl_maxsz) |
697 | #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ | 697 | #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ |
698 | decode_sequence_maxsz + \ | 698 | decode_sequence_maxsz + \ |
699 | decode_putfh_maxsz + \ | 699 | decode_putfh_maxsz + \ |
700 | decode_getacl_maxsz) | 700 | decode_getacl_maxsz) |
701 | #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ | 701 | #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ |
702 | encode_sequence_maxsz + \ | 702 | encode_sequence_maxsz + \ |
703 | encode_putfh_maxsz + \ | 703 | encode_putfh_maxsz + \ |
704 | encode_setacl_maxsz) | 704 | encode_setacl_maxsz) |
705 | #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ | 705 | #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ |
706 | decode_sequence_maxsz + \ | 706 | decode_sequence_maxsz + \ |
707 | decode_putfh_maxsz + \ | 707 | decode_putfh_maxsz + \ |
708 | decode_setacl_maxsz) | 708 | decode_setacl_maxsz) |
709 | #define NFS4_enc_fs_locations_sz \ | 709 | #define NFS4_enc_fs_locations_sz \ |
710 | (compound_encode_hdr_maxsz + \ | 710 | (compound_encode_hdr_maxsz + \ |
711 | encode_sequence_maxsz + \ | 711 | encode_sequence_maxsz + \ |
712 | encode_putfh_maxsz + \ | 712 | encode_putfh_maxsz + \ |
713 | encode_lookup_maxsz + \ | 713 | encode_lookup_maxsz + \ |
714 | encode_fs_locations_maxsz) | 714 | encode_fs_locations_maxsz) |
715 | #define NFS4_dec_fs_locations_sz \ | 715 | #define NFS4_dec_fs_locations_sz \ |
716 | (compound_decode_hdr_maxsz + \ | 716 | (compound_decode_hdr_maxsz + \ |
717 | decode_sequence_maxsz + \ | 717 | decode_sequence_maxsz + \ |
718 | decode_putfh_maxsz + \ | 718 | decode_putfh_maxsz + \ |
719 | decode_lookup_maxsz + \ | 719 | decode_lookup_maxsz + \ |
720 | decode_fs_locations_maxsz) | 720 | decode_fs_locations_maxsz) |
721 | #define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ | 721 | #define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ |
722 | encode_sequence_maxsz + \ | 722 | encode_sequence_maxsz + \ |
723 | encode_putfh_maxsz + \ | 723 | encode_putfh_maxsz + \ |
724 | encode_secinfo_maxsz) | 724 | encode_secinfo_maxsz) |
725 | #define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ | 725 | #define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ |
726 | decode_sequence_maxsz + \ | 726 | decode_sequence_maxsz + \ |
727 | decode_putfh_maxsz + \ | 727 | decode_putfh_maxsz + \ |
728 | decode_secinfo_maxsz) | 728 | decode_secinfo_maxsz) |
729 | #if defined(CONFIG_NFS_V4_1) | 729 | #if defined(CONFIG_NFS_V4_1) |
730 | #define NFS4_enc_exchange_id_sz \ | 730 | #define NFS4_enc_exchange_id_sz \ |
731 | (compound_encode_hdr_maxsz + \ | 731 | (compound_encode_hdr_maxsz + \ |
732 | encode_exchange_id_maxsz) | 732 | encode_exchange_id_maxsz) |
733 | #define NFS4_dec_exchange_id_sz \ | 733 | #define NFS4_dec_exchange_id_sz \ |
734 | (compound_decode_hdr_maxsz + \ | 734 | (compound_decode_hdr_maxsz + \ |
735 | decode_exchange_id_maxsz) | 735 | decode_exchange_id_maxsz) |
736 | #define NFS4_enc_create_session_sz \ | 736 | #define NFS4_enc_create_session_sz \ |
737 | (compound_encode_hdr_maxsz + \ | 737 | (compound_encode_hdr_maxsz + \ |
738 | encode_create_session_maxsz) | 738 | encode_create_session_maxsz) |
739 | #define NFS4_dec_create_session_sz \ | 739 | #define NFS4_dec_create_session_sz \ |
740 | (compound_decode_hdr_maxsz + \ | 740 | (compound_decode_hdr_maxsz + \ |
741 | decode_create_session_maxsz) | 741 | decode_create_session_maxsz) |
742 | #define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \ | 742 | #define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \ |
743 | encode_destroy_session_maxsz) | 743 | encode_destroy_session_maxsz) |
744 | #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ | 744 | #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ |
745 | decode_destroy_session_maxsz) | 745 | decode_destroy_session_maxsz) |
746 | #define NFS4_enc_sequence_sz \ | 746 | #define NFS4_enc_sequence_sz \ |
747 | (compound_decode_hdr_maxsz + \ | 747 | (compound_decode_hdr_maxsz + \ |
748 | encode_sequence_maxsz) | 748 | encode_sequence_maxsz) |
749 | #define NFS4_dec_sequence_sz \ | 749 | #define NFS4_dec_sequence_sz \ |
750 | (compound_decode_hdr_maxsz + \ | 750 | (compound_decode_hdr_maxsz + \ |
751 | decode_sequence_maxsz) | 751 | decode_sequence_maxsz) |
752 | #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ | 752 | #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ |
753 | encode_sequence_maxsz + \ | 753 | encode_sequence_maxsz + \ |
754 | encode_putrootfh_maxsz + \ | 754 | encode_putrootfh_maxsz + \ |
755 | encode_fsinfo_maxsz) | 755 | encode_fsinfo_maxsz) |
756 | #define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \ | 756 | #define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \ |
757 | decode_sequence_maxsz + \ | 757 | decode_sequence_maxsz + \ |
758 | decode_putrootfh_maxsz + \ | 758 | decode_putrootfh_maxsz + \ |
759 | decode_fsinfo_maxsz) | 759 | decode_fsinfo_maxsz) |
760 | #define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ | 760 | #define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \ |
761 | encode_sequence_maxsz + \ | 761 | encode_sequence_maxsz + \ |
762 | encode_reclaim_complete_maxsz) | 762 | encode_reclaim_complete_maxsz) |
763 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ | 763 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ |
764 | decode_sequence_maxsz + \ | 764 | decode_sequence_maxsz + \ |
765 | decode_reclaim_complete_maxsz) | 765 | decode_reclaim_complete_maxsz) |
766 | #define NFS4_enc_getdevicelist_sz (compound_encode_hdr_maxsz + \ | 766 | #define NFS4_enc_getdevicelist_sz (compound_encode_hdr_maxsz + \ |
767 | encode_sequence_maxsz + \ | 767 | encode_sequence_maxsz + \ |
768 | encode_putfh_maxsz + \ | 768 | encode_putfh_maxsz + \ |
769 | encode_getdevicelist_maxsz) | 769 | encode_getdevicelist_maxsz) |
770 | #define NFS4_dec_getdevicelist_sz (compound_decode_hdr_maxsz + \ | 770 | #define NFS4_dec_getdevicelist_sz (compound_decode_hdr_maxsz + \ |
771 | decode_sequence_maxsz + \ | 771 | decode_sequence_maxsz + \ |
772 | decode_putfh_maxsz + \ | 772 | decode_putfh_maxsz + \ |
773 | decode_getdevicelist_maxsz) | 773 | decode_getdevicelist_maxsz) |
774 | #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ | 774 | #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ |
775 | encode_sequence_maxsz +\ | 775 | encode_sequence_maxsz +\ |
776 | encode_getdeviceinfo_maxsz) | 776 | encode_getdeviceinfo_maxsz) |
777 | #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ | 777 | #define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ |
778 | decode_sequence_maxsz + \ | 778 | decode_sequence_maxsz + \ |
779 | decode_getdeviceinfo_maxsz) | 779 | decode_getdeviceinfo_maxsz) |
780 | #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ | 780 | #define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \ |
781 | encode_sequence_maxsz + \ | 781 | encode_sequence_maxsz + \ |
782 | encode_putfh_maxsz + \ | 782 | encode_putfh_maxsz + \ |
783 | encode_layoutget_maxsz) | 783 | encode_layoutget_maxsz) |
784 | #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ | 784 | #define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \ |
785 | decode_sequence_maxsz + \ | 785 | decode_sequence_maxsz + \ |
786 | decode_putfh_maxsz + \ | 786 | decode_putfh_maxsz + \ |
787 | decode_layoutget_maxsz) | 787 | decode_layoutget_maxsz) |
788 | #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ | 788 | #define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ |
789 | encode_sequence_maxsz +\ | 789 | encode_sequence_maxsz +\ |
790 | encode_putfh_maxsz + \ | 790 | encode_putfh_maxsz + \ |
791 | encode_layoutcommit_maxsz + \ | 791 | encode_layoutcommit_maxsz + \ |
792 | encode_getattr_maxsz) | 792 | encode_getattr_maxsz) |
793 | #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ | 793 | #define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ |
794 | decode_sequence_maxsz + \ | 794 | decode_sequence_maxsz + \ |
795 | decode_putfh_maxsz + \ | 795 | decode_putfh_maxsz + \ |
796 | decode_layoutcommit_maxsz + \ | 796 | decode_layoutcommit_maxsz + \ |
797 | decode_getattr_maxsz) | 797 | decode_getattr_maxsz) |
798 | #define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \ | 798 | #define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \ |
799 | encode_sequence_maxsz + \ | 799 | encode_sequence_maxsz + \ |
800 | encode_putfh_maxsz + \ | 800 | encode_putfh_maxsz + \ |
801 | encode_layoutreturn_maxsz) | 801 | encode_layoutreturn_maxsz) |
802 | #define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \ | 802 | #define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \ |
803 | decode_sequence_maxsz + \ | 803 | decode_sequence_maxsz + \ |
804 | decode_putfh_maxsz + \ | 804 | decode_putfh_maxsz + \ |
805 | decode_layoutreturn_maxsz) | 805 | decode_layoutreturn_maxsz) |
806 | #define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \ | 806 | #define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \ |
807 | encode_sequence_maxsz + \ | 807 | encode_sequence_maxsz + \ |
808 | encode_putrootfh_maxsz +\ | 808 | encode_putrootfh_maxsz +\ |
809 | encode_secinfo_no_name_maxsz) | 809 | encode_secinfo_no_name_maxsz) |
810 | #define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \ | 810 | #define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \ |
811 | decode_sequence_maxsz + \ | 811 | decode_sequence_maxsz + \ |
812 | decode_putrootfh_maxsz + \ | 812 | decode_putrootfh_maxsz + \ |
813 | decode_secinfo_no_name_maxsz) | 813 | decode_secinfo_no_name_maxsz) |
814 | #define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \ | 814 | #define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \ |
815 | encode_sequence_maxsz + \ | 815 | encode_sequence_maxsz + \ |
816 | encode_test_stateid_maxsz) | 816 | encode_test_stateid_maxsz) |
817 | #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ | 817 | #define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \ |
818 | decode_sequence_maxsz + \ | 818 | decode_sequence_maxsz + \ |
819 | decode_test_stateid_maxsz) | 819 | decode_test_stateid_maxsz) |
820 | #define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \ | 820 | #define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \ |
821 | encode_sequence_maxsz + \ | 821 | encode_sequence_maxsz + \ |
822 | encode_free_stateid_maxsz) | 822 | encode_free_stateid_maxsz) |
823 | #define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \ | 823 | #define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \ |
824 | decode_sequence_maxsz + \ | 824 | decode_sequence_maxsz + \ |
825 | decode_free_stateid_maxsz) | 825 | decode_free_stateid_maxsz) |
826 | 826 | ||
827 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | 827 | const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
828 | compound_encode_hdr_maxsz + | 828 | compound_encode_hdr_maxsz + |
829 | encode_sequence_maxsz + | 829 | encode_sequence_maxsz + |
830 | encode_putfh_maxsz + | 830 | encode_putfh_maxsz + |
831 | encode_getattr_maxsz) * | 831 | encode_getattr_maxsz) * |
832 | XDR_UNIT); | 832 | XDR_UNIT); |
833 | 833 | ||
834 | const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | 834 | const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + |
835 | compound_decode_hdr_maxsz + | 835 | compound_decode_hdr_maxsz + |
836 | decode_sequence_maxsz + | 836 | decode_sequence_maxsz + |
837 | decode_putfh_maxsz) * | 837 | decode_putfh_maxsz) * |
838 | XDR_UNIT); | 838 | XDR_UNIT); |
839 | #endif /* CONFIG_NFS_V4_1 */ | 839 | #endif /* CONFIG_NFS_V4_1 */ |
840 | 840 | ||
841 | static const umode_t nfs_type2fmt[] = { | 841 | static const umode_t nfs_type2fmt[] = { |
842 | [NF4BAD] = 0, | 842 | [NF4BAD] = 0, |
843 | [NF4REG] = S_IFREG, | 843 | [NF4REG] = S_IFREG, |
844 | [NF4DIR] = S_IFDIR, | 844 | [NF4DIR] = S_IFDIR, |
845 | [NF4BLK] = S_IFBLK, | 845 | [NF4BLK] = S_IFBLK, |
846 | [NF4CHR] = S_IFCHR, | 846 | [NF4CHR] = S_IFCHR, |
847 | [NF4LNK] = S_IFLNK, | 847 | [NF4LNK] = S_IFLNK, |
848 | [NF4SOCK] = S_IFSOCK, | 848 | [NF4SOCK] = S_IFSOCK, |
849 | [NF4FIFO] = S_IFIFO, | 849 | [NF4FIFO] = S_IFIFO, |
850 | [NF4ATTRDIR] = 0, | 850 | [NF4ATTRDIR] = 0, |
851 | [NF4NAMEDATTR] = 0, | 851 | [NF4NAMEDATTR] = 0, |
852 | }; | 852 | }; |
853 | 853 | ||
854 | struct compound_hdr { | 854 | struct compound_hdr { |
855 | int32_t status; | 855 | int32_t status; |
856 | uint32_t nops; | 856 | uint32_t nops; |
857 | __be32 * nops_p; | 857 | __be32 * nops_p; |
858 | uint32_t taglen; | 858 | uint32_t taglen; |
859 | char * tag; | 859 | char * tag; |
860 | uint32_t replen; /* expected reply words */ | 860 | uint32_t replen; /* expected reply words */ |
861 | u32 minorversion; | 861 | u32 minorversion; |
862 | }; | 862 | }; |
863 | 863 | ||
864 | static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) | 864 | static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes) |
865 | { | 865 | { |
866 | __be32 *p = xdr_reserve_space(xdr, nbytes); | 866 | __be32 *p = xdr_reserve_space(xdr, nbytes); |
867 | BUG_ON(!p); | 867 | BUG_ON(!p); |
868 | return p; | 868 | return p; |
869 | } | 869 | } |
870 | 870 | ||
871 | static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) | 871 | static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) |
872 | { | 872 | { |
873 | __be32 *p; | 873 | __be32 *p; |
874 | 874 | ||
875 | p = xdr_reserve_space(xdr, 4 + len); | 875 | p = xdr_reserve_space(xdr, 4 + len); |
876 | BUG_ON(p == NULL); | 876 | BUG_ON(p == NULL); |
877 | xdr_encode_opaque(p, str, len); | 877 | xdr_encode_opaque(p, str, len); |
878 | } | 878 | } |
879 | 879 | ||
880 | static void encode_compound_hdr(struct xdr_stream *xdr, | 880 | static void encode_compound_hdr(struct xdr_stream *xdr, |
881 | struct rpc_rqst *req, | 881 | struct rpc_rqst *req, |
882 | struct compound_hdr *hdr) | 882 | struct compound_hdr *hdr) |
883 | { | 883 | { |
884 | __be32 *p; | 884 | __be32 *p; |
885 | struct rpc_auth *auth = req->rq_cred->cr_auth; | 885 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
886 | 886 | ||
887 | /* initialize running count of expected bytes in reply. | 887 | /* initialize running count of expected bytes in reply. |
888 | * NOTE: the replied tag SHOULD be the same is the one sent, | 888 | * NOTE: the replied tag SHOULD be the same is the one sent, |
889 | * but this is not required as a MUST for the server to do so. */ | 889 | * but this is not required as a MUST for the server to do so. */ |
890 | hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; | 890 | hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; |
891 | 891 | ||
892 | dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); | 892 | dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); |
893 | BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); | 893 | BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); |
894 | p = reserve_space(xdr, 4 + hdr->taglen + 8); | 894 | p = reserve_space(xdr, 4 + hdr->taglen + 8); |
895 | p = xdr_encode_opaque(p, hdr->tag, hdr->taglen); | 895 | p = xdr_encode_opaque(p, hdr->tag, hdr->taglen); |
896 | *p++ = cpu_to_be32(hdr->minorversion); | 896 | *p++ = cpu_to_be32(hdr->minorversion); |
897 | hdr->nops_p = p; | 897 | hdr->nops_p = p; |
898 | *p = cpu_to_be32(hdr->nops); | 898 | *p = cpu_to_be32(hdr->nops); |
899 | } | 899 | } |
900 | 900 | ||
901 | static void encode_nops(struct compound_hdr *hdr) | 901 | static void encode_nops(struct compound_hdr *hdr) |
902 | { | 902 | { |
903 | BUG_ON(hdr->nops > NFS4_MAX_OPS); | 903 | BUG_ON(hdr->nops > NFS4_MAX_OPS); |
904 | *hdr->nops_p = htonl(hdr->nops); | 904 | *hdr->nops_p = htonl(hdr->nops); |
905 | } | 905 | } |
906 | 906 | ||
907 | static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) | 907 | static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) |
908 | { | 908 | { |
909 | __be32 *p; | 909 | __be32 *p; |
910 | 910 | ||
911 | p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); | 911 | p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); |
912 | BUG_ON(p == NULL); | 912 | BUG_ON(p == NULL); |
913 | xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE); | 913 | xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE); |
914 | } | 914 | } |
915 | 915 | ||
916 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) | 916 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) |
917 | { | 917 | { |
918 | char owner_name[IDMAP_NAMESZ]; | 918 | char owner_name[IDMAP_NAMESZ]; |
919 | char owner_group[IDMAP_NAMESZ]; | 919 | char owner_group[IDMAP_NAMESZ]; |
920 | int owner_namelen = 0; | 920 | int owner_namelen = 0; |
921 | int owner_grouplen = 0; | 921 | int owner_grouplen = 0; |
922 | __be32 *p; | 922 | __be32 *p; |
923 | __be32 *q; | 923 | __be32 *q; |
924 | int len; | 924 | int len; |
925 | uint32_t bmval0 = 0; | 925 | uint32_t bmval0 = 0; |
926 | uint32_t bmval1 = 0; | 926 | uint32_t bmval1 = 0; |
927 | 927 | ||
928 | /* | 928 | /* |
929 | * We reserve enough space to write the entire attribute buffer at once. | 929 | * We reserve enough space to write the entire attribute buffer at once. |
930 | * In the worst-case, this would be | 930 | * In the worst-case, this would be |
931 | * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) | 931 | * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) |
932 | * = 36 bytes, plus any contribution from variable-length fields | 932 | * = 36 bytes, plus any contribution from variable-length fields |
933 | * such as owner/group. | 933 | * such as owner/group. |
934 | */ | 934 | */ |
935 | len = 16; | 935 | len = 16; |
936 | 936 | ||
937 | /* Sigh */ | 937 | /* Sigh */ |
938 | if (iap->ia_valid & ATTR_SIZE) | 938 | if (iap->ia_valid & ATTR_SIZE) |
939 | len += 8; | 939 | len += 8; |
940 | if (iap->ia_valid & ATTR_MODE) | 940 | if (iap->ia_valid & ATTR_MODE) |
941 | len += 4; | 941 | len += 4; |
942 | if (iap->ia_valid & ATTR_UID) { | 942 | if (iap->ia_valid & ATTR_UID) { |
943 | owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); | 943 | owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); |
944 | if (owner_namelen < 0) { | 944 | if (owner_namelen < 0) { |
945 | dprintk("nfs: couldn't resolve uid %d to string\n", | 945 | dprintk("nfs: couldn't resolve uid %d to string\n", |
946 | iap->ia_uid); | 946 | iap->ia_uid); |
947 | /* XXX */ | 947 | /* XXX */ |
948 | strcpy(owner_name, "nobody"); | 948 | strcpy(owner_name, "nobody"); |
949 | owner_namelen = sizeof("nobody") - 1; | 949 | owner_namelen = sizeof("nobody") - 1; |
950 | /* goto out; */ | 950 | /* goto out; */ |
951 | } | 951 | } |
952 | len += 4 + (XDR_QUADLEN(owner_namelen) << 2); | 952 | len += 4 + (XDR_QUADLEN(owner_namelen) << 2); |
953 | } | 953 | } |
954 | if (iap->ia_valid & ATTR_GID) { | 954 | if (iap->ia_valid & ATTR_GID) { |
955 | owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); | 955 | owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); |
956 | if (owner_grouplen < 0) { | 956 | if (owner_grouplen < 0) { |
957 | dprintk("nfs: couldn't resolve gid %d to string\n", | 957 | dprintk("nfs: couldn't resolve gid %d to string\n", |
958 | iap->ia_gid); | 958 | iap->ia_gid); |
959 | strcpy(owner_group, "nobody"); | 959 | strcpy(owner_group, "nobody"); |
960 | owner_grouplen = sizeof("nobody") - 1; | 960 | owner_grouplen = sizeof("nobody") - 1; |
961 | /* goto out; */ | 961 | /* goto out; */ |
962 | } | 962 | } |
963 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); | 963 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); |
964 | } | 964 | } |
965 | if (iap->ia_valid & ATTR_ATIME_SET) | 965 | if (iap->ia_valid & ATTR_ATIME_SET) |
966 | len += 16; | 966 | len += 16; |
967 | else if (iap->ia_valid & ATTR_ATIME) | 967 | else if (iap->ia_valid & ATTR_ATIME) |
968 | len += 4; | 968 | len += 4; |
969 | if (iap->ia_valid & ATTR_MTIME_SET) | 969 | if (iap->ia_valid & ATTR_MTIME_SET) |
970 | len += 16; | 970 | len += 16; |
971 | else if (iap->ia_valid & ATTR_MTIME) | 971 | else if (iap->ia_valid & ATTR_MTIME) |
972 | len += 4; | 972 | len += 4; |
973 | p = reserve_space(xdr, len); | 973 | p = reserve_space(xdr, len); |
974 | 974 | ||
975 | /* | 975 | /* |
976 | * We write the bitmap length now, but leave the bitmap and the attribute | 976 | * We write the bitmap length now, but leave the bitmap and the attribute |
977 | * buffer length to be backfilled at the end of this routine. | 977 | * buffer length to be backfilled at the end of this routine. |
978 | */ | 978 | */ |
979 | *p++ = cpu_to_be32(2); | 979 | *p++ = cpu_to_be32(2); |
980 | q = p; | 980 | q = p; |
981 | p += 3; | 981 | p += 3; |
982 | 982 | ||
983 | if (iap->ia_valid & ATTR_SIZE) { | 983 | if (iap->ia_valid & ATTR_SIZE) { |
984 | bmval0 |= FATTR4_WORD0_SIZE; | 984 | bmval0 |= FATTR4_WORD0_SIZE; |
985 | p = xdr_encode_hyper(p, iap->ia_size); | 985 | p = xdr_encode_hyper(p, iap->ia_size); |
986 | } | 986 | } |
987 | if (iap->ia_valid & ATTR_MODE) { | 987 | if (iap->ia_valid & ATTR_MODE) { |
988 | bmval1 |= FATTR4_WORD1_MODE; | 988 | bmval1 |= FATTR4_WORD1_MODE; |
989 | *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); | 989 | *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); |
990 | } | 990 | } |
991 | if (iap->ia_valid & ATTR_UID) { | 991 | if (iap->ia_valid & ATTR_UID) { |
992 | bmval1 |= FATTR4_WORD1_OWNER; | 992 | bmval1 |= FATTR4_WORD1_OWNER; |
993 | p = xdr_encode_opaque(p, owner_name, owner_namelen); | 993 | p = xdr_encode_opaque(p, owner_name, owner_namelen); |
994 | } | 994 | } |
995 | if (iap->ia_valid & ATTR_GID) { | 995 | if (iap->ia_valid & ATTR_GID) { |
996 | bmval1 |= FATTR4_WORD1_OWNER_GROUP; | 996 | bmval1 |= FATTR4_WORD1_OWNER_GROUP; |
997 | p = xdr_encode_opaque(p, owner_group, owner_grouplen); | 997 | p = xdr_encode_opaque(p, owner_group, owner_grouplen); |
998 | } | 998 | } |
999 | if (iap->ia_valid & ATTR_ATIME_SET) { | 999 | if (iap->ia_valid & ATTR_ATIME_SET) { |
1000 | bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; | 1000 | bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; |
1001 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); | 1001 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); |
1002 | *p++ = cpu_to_be32(0); | 1002 | *p++ = cpu_to_be32(0); |
1003 | *p++ = cpu_to_be32(iap->ia_atime.tv_sec); | 1003 | *p++ = cpu_to_be32(iap->ia_atime.tv_sec); |
1004 | *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); | 1004 | *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); |
1005 | } | 1005 | } |
1006 | else if (iap->ia_valid & ATTR_ATIME) { | 1006 | else if (iap->ia_valid & ATTR_ATIME) { |
1007 | bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; | 1007 | bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; |
1008 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | 1008 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
1009 | } | 1009 | } |
1010 | if (iap->ia_valid & ATTR_MTIME_SET) { | 1010 | if (iap->ia_valid & ATTR_MTIME_SET) { |
1011 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | 1011 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; |
1012 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); | 1012 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); |
1013 | *p++ = cpu_to_be32(0); | 1013 | *p++ = cpu_to_be32(0); |
1014 | *p++ = cpu_to_be32(iap->ia_mtime.tv_sec); | 1014 | *p++ = cpu_to_be32(iap->ia_mtime.tv_sec); |
1015 | *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec); | 1015 | *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec); |
1016 | } | 1016 | } |
1017 | else if (iap->ia_valid & ATTR_MTIME) { | 1017 | else if (iap->ia_valid & ATTR_MTIME) { |
1018 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | 1018 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; |
1019 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | 1019 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | /* | 1022 | /* |
1023 | * Now we backfill the bitmap and the attribute buffer length. | 1023 | * Now we backfill the bitmap and the attribute buffer length. |
1024 | */ | 1024 | */ |
1025 | if (len != ((char *)p - (char *)q) + 4) { | 1025 | if (len != ((char *)p - (char *)q) + 4) { |
1026 | printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n", | 1026 | printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n", |
1027 | len, ((char *)p - (char *)q) + 4); | 1027 | len, ((char *)p - (char *)q) + 4); |
1028 | BUG(); | 1028 | BUG(); |
1029 | } | 1029 | } |
1030 | len = (char *)p - (char *)q - 12; | 1030 | len = (char *)p - (char *)q - 12; |
1031 | *q++ = htonl(bmval0); | 1031 | *q++ = htonl(bmval0); |
1032 | *q++ = htonl(bmval1); | 1032 | *q++ = htonl(bmval1); |
1033 | *q = htonl(len); | 1033 | *q = htonl(len); |
1034 | 1034 | ||
1035 | /* out: */ | 1035 | /* out: */ |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr) | 1038 | static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr) |
1039 | { | 1039 | { |
1040 | __be32 *p; | 1040 | __be32 *p; |
1041 | 1041 | ||
1042 | p = reserve_space(xdr, 8); | 1042 | p = reserve_space(xdr, 8); |
1043 | *p++ = cpu_to_be32(OP_ACCESS); | 1043 | *p++ = cpu_to_be32(OP_ACCESS); |
1044 | *p = cpu_to_be32(access); | 1044 | *p = cpu_to_be32(access); |
1045 | hdr->nops++; | 1045 | hdr->nops++; |
1046 | hdr->replen += decode_access_maxsz; | 1046 | hdr->replen += decode_access_maxsz; |
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) | 1049 | static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) |
1050 | { | 1050 | { |
1051 | __be32 *p; | 1051 | __be32 *p; |
1052 | 1052 | ||
1053 | p = reserve_space(xdr, 8+NFS4_STATEID_SIZE); | 1053 | p = reserve_space(xdr, 8+NFS4_STATEID_SIZE); |
1054 | *p++ = cpu_to_be32(OP_CLOSE); | 1054 | *p++ = cpu_to_be32(OP_CLOSE); |
1055 | *p++ = cpu_to_be32(arg->seqid->sequence->counter); | 1055 | *p++ = cpu_to_be32(arg->seqid->sequence->counter); |
1056 | xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); | 1056 | xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); |
1057 | hdr->nops++; | 1057 | hdr->nops++; |
1058 | hdr->replen += decode_close_maxsz; | 1058 | hdr->replen += decode_close_maxsz; |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) | 1061 | static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) |
1062 | { | 1062 | { |
1063 | __be32 *p; | 1063 | __be32 *p; |
1064 | 1064 | ||
1065 | p = reserve_space(xdr, 16); | 1065 | p = reserve_space(xdr, 16); |
1066 | *p++ = cpu_to_be32(OP_COMMIT); | 1066 | *p++ = cpu_to_be32(OP_COMMIT); |
1067 | p = xdr_encode_hyper(p, args->offset); | 1067 | p = xdr_encode_hyper(p, args->offset); |
1068 | *p = cpu_to_be32(args->count); | 1068 | *p = cpu_to_be32(args->count); |
1069 | hdr->nops++; | 1069 | hdr->nops++; |
1070 | hdr->replen += decode_commit_maxsz; | 1070 | hdr->replen += decode_commit_maxsz; |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) | 1073 | static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) |
1074 | { | 1074 | { |
1075 | __be32 *p; | 1075 | __be32 *p; |
1076 | 1076 | ||
1077 | p = reserve_space(xdr, 8); | 1077 | p = reserve_space(xdr, 8); |
1078 | *p++ = cpu_to_be32(OP_CREATE); | 1078 | *p++ = cpu_to_be32(OP_CREATE); |
1079 | *p = cpu_to_be32(create->ftype); | 1079 | *p = cpu_to_be32(create->ftype); |
1080 | 1080 | ||
1081 | switch (create->ftype) { | 1081 | switch (create->ftype) { |
1082 | case NF4LNK: | 1082 | case NF4LNK: |
1083 | p = reserve_space(xdr, 4); | 1083 | p = reserve_space(xdr, 4); |
1084 | *p = cpu_to_be32(create->u.symlink.len); | 1084 | *p = cpu_to_be32(create->u.symlink.len); |
1085 | xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); | 1085 | xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); |
1086 | break; | 1086 | break; |
1087 | 1087 | ||
1088 | case NF4BLK: case NF4CHR: | 1088 | case NF4BLK: case NF4CHR: |
1089 | p = reserve_space(xdr, 8); | 1089 | p = reserve_space(xdr, 8); |
1090 | *p++ = cpu_to_be32(create->u.device.specdata1); | 1090 | *p++ = cpu_to_be32(create->u.device.specdata1); |
1091 | *p = cpu_to_be32(create->u.device.specdata2); | 1091 | *p = cpu_to_be32(create->u.device.specdata2); |
1092 | break; | 1092 | break; |
1093 | 1093 | ||
1094 | default: | 1094 | default: |
1095 | break; | 1095 | break; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | encode_string(xdr, create->name->len, create->name->name); | 1098 | encode_string(xdr, create->name->len, create->name->name); |
1099 | hdr->nops++; | 1099 | hdr->nops++; |
1100 | hdr->replen += decode_create_maxsz; | 1100 | hdr->replen += decode_create_maxsz; |
1101 | 1101 | ||
1102 | encode_attrs(xdr, create->attrs, create->server); | 1102 | encode_attrs(xdr, create->attrs, create->server); |
1103 | } | 1103 | } |
1104 | 1104 | ||
1105 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) | 1105 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) |
1106 | { | 1106 | { |
1107 | __be32 *p; | 1107 | __be32 *p; |
1108 | 1108 | ||
1109 | p = reserve_space(xdr, 12); | 1109 | p = reserve_space(xdr, 12); |
1110 | *p++ = cpu_to_be32(OP_GETATTR); | 1110 | *p++ = cpu_to_be32(OP_GETATTR); |
1111 | *p++ = cpu_to_be32(1); | 1111 | *p++ = cpu_to_be32(1); |
1112 | *p = cpu_to_be32(bitmap); | 1112 | *p = cpu_to_be32(bitmap); |
1113 | hdr->nops++; | 1113 | hdr->nops++; |
1114 | hdr->replen += decode_getattr_maxsz; | 1114 | hdr->replen += decode_getattr_maxsz; |
1115 | } | 1115 | } |
1116 | 1116 | ||
1117 | static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr) | 1117 | static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr) |
1118 | { | 1118 | { |
1119 | __be32 *p; | 1119 | __be32 *p; |
1120 | 1120 | ||
1121 | p = reserve_space(xdr, 16); | 1121 | p = reserve_space(xdr, 16); |
1122 | *p++ = cpu_to_be32(OP_GETATTR); | 1122 | *p++ = cpu_to_be32(OP_GETATTR); |
1123 | *p++ = cpu_to_be32(2); | 1123 | *p++ = cpu_to_be32(2); |
1124 | *p++ = cpu_to_be32(bm0); | 1124 | *p++ = cpu_to_be32(bm0); |
1125 | *p = cpu_to_be32(bm1); | 1125 | *p = cpu_to_be32(bm1); |
1126 | hdr->nops++; | 1126 | hdr->nops++; |
1127 | hdr->replen += decode_getattr_maxsz; | 1127 | hdr->replen += decode_getattr_maxsz; |
1128 | } | 1128 | } |
1129 | 1129 | ||
1130 | static void | 1130 | static void |
1131 | encode_getattr_three(struct xdr_stream *xdr, | 1131 | encode_getattr_three(struct xdr_stream *xdr, |
1132 | uint32_t bm0, uint32_t bm1, uint32_t bm2, | 1132 | uint32_t bm0, uint32_t bm1, uint32_t bm2, |
1133 | struct compound_hdr *hdr) | 1133 | struct compound_hdr *hdr) |
1134 | { | 1134 | { |
1135 | __be32 *p; | 1135 | __be32 *p; |
1136 | 1136 | ||
1137 | p = reserve_space(xdr, 4); | 1137 | p = reserve_space(xdr, 4); |
1138 | *p = cpu_to_be32(OP_GETATTR); | 1138 | *p = cpu_to_be32(OP_GETATTR); |
1139 | if (bm2) { | 1139 | if (bm2) { |
1140 | p = reserve_space(xdr, 16); | 1140 | p = reserve_space(xdr, 16); |
1141 | *p++ = cpu_to_be32(3); | 1141 | *p++ = cpu_to_be32(3); |
1142 | *p++ = cpu_to_be32(bm0); | 1142 | *p++ = cpu_to_be32(bm0); |
1143 | *p++ = cpu_to_be32(bm1); | 1143 | *p++ = cpu_to_be32(bm1); |
1144 | *p = cpu_to_be32(bm2); | 1144 | *p = cpu_to_be32(bm2); |
1145 | } else if (bm1) { | 1145 | } else if (bm1) { |
1146 | p = reserve_space(xdr, 12); | 1146 | p = reserve_space(xdr, 12); |
1147 | *p++ = cpu_to_be32(2); | 1147 | *p++ = cpu_to_be32(2); |
1148 | *p++ = cpu_to_be32(bm0); | 1148 | *p++ = cpu_to_be32(bm0); |
1149 | *p = cpu_to_be32(bm1); | 1149 | *p = cpu_to_be32(bm1); |
1150 | } else { | 1150 | } else { |
1151 | p = reserve_space(xdr, 8); | 1151 | p = reserve_space(xdr, 8); |
1152 | *p++ = cpu_to_be32(1); | 1152 | *p++ = cpu_to_be32(1); |
1153 | *p = cpu_to_be32(bm0); | 1153 | *p = cpu_to_be32(bm0); |
1154 | } | 1154 | } |
1155 | hdr->nops++; | 1155 | hdr->nops++; |
1156 | hdr->replen += decode_getattr_maxsz; | 1156 | hdr->replen += decode_getattr_maxsz; |
1157 | } | 1157 | } |
1158 | 1158 | ||
1159 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1159 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1160 | { | 1160 | { |
1161 | encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], | 1161 | encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], |
1162 | bitmask[1] & nfs4_fattr_bitmap[1], hdr); | 1162 | bitmask[1] & nfs4_fattr_bitmap[1], hdr); |
1163 | } | 1163 | } |
1164 | 1164 | ||
1165 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1165 | static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1166 | { | 1166 | { |
1167 | encode_getattr_three(xdr, | 1167 | encode_getattr_three(xdr, |
1168 | bitmask[0] & nfs4_fsinfo_bitmap[0], | 1168 | bitmask[0] & nfs4_fsinfo_bitmap[0], |
1169 | bitmask[1] & nfs4_fsinfo_bitmap[1], | 1169 | bitmask[1] & nfs4_fsinfo_bitmap[1], |
1170 | bitmask[2] & nfs4_fsinfo_bitmap[2], | 1170 | bitmask[2] & nfs4_fsinfo_bitmap[2], |
1171 | hdr); | 1171 | hdr); |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1174 | static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1175 | { | 1175 | { |
1176 | encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0], | 1176 | encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0], |
1177 | bitmask[1] & nfs4_fs_locations_bitmap[1], hdr); | 1177 | bitmask[1] & nfs4_fs_locations_bitmap[1], hdr); |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) | 1180 | static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
1181 | { | 1181 | { |
1182 | __be32 *p; | 1182 | __be32 *p; |
1183 | 1183 | ||
1184 | p = reserve_space(xdr, 4); | 1184 | p = reserve_space(xdr, 4); |
1185 | *p = cpu_to_be32(OP_GETFH); | 1185 | *p = cpu_to_be32(OP_GETFH); |
1186 | hdr->nops++; | 1186 | hdr->nops++; |
1187 | hdr->replen += decode_getfh_maxsz; | 1187 | hdr->replen += decode_getfh_maxsz; |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) | 1190 | static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
1191 | { | 1191 | { |
1192 | __be32 *p; | 1192 | __be32 *p; |
1193 | 1193 | ||
1194 | p = reserve_space(xdr, 8 + name->len); | 1194 | p = reserve_space(xdr, 8 + name->len); |
1195 | *p++ = cpu_to_be32(OP_LINK); | 1195 | *p++ = cpu_to_be32(OP_LINK); |
1196 | xdr_encode_opaque(p, name->name, name->len); | 1196 | xdr_encode_opaque(p, name->name, name->len); |
1197 | hdr->nops++; | 1197 | hdr->nops++; |
1198 | hdr->replen += decode_link_maxsz; | 1198 | hdr->replen += decode_link_maxsz; |
1199 | } | 1199 | } |
1200 | 1200 | ||
1201 | static inline int nfs4_lock_type(struct file_lock *fl, int block) | 1201 | static inline int nfs4_lock_type(struct file_lock *fl, int block) |
1202 | { | 1202 | { |
1203 | if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) | 1203 | if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) |
1204 | return block ? NFS4_READW_LT : NFS4_READ_LT; | 1204 | return block ? NFS4_READW_LT : NFS4_READ_LT; |
1205 | return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; | 1205 | return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | static inline uint64_t nfs4_lock_length(struct file_lock *fl) | 1208 | static inline uint64_t nfs4_lock_length(struct file_lock *fl) |
1209 | { | 1209 | { |
1210 | if (fl->fl_end == OFFSET_MAX) | 1210 | if (fl->fl_end == OFFSET_MAX) |
1211 | return ~(uint64_t)0; | 1211 | return ~(uint64_t)0; |
1212 | return fl->fl_end - fl->fl_start + 1; | 1212 | return fl->fl_end - fl->fl_start + 1; |
1213 | } | 1213 | } |
1214 | 1214 | ||
1215 | static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) | 1215 | static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) |
1216 | { | 1216 | { |
1217 | __be32 *p; | 1217 | __be32 *p; |
1218 | 1218 | ||
1219 | p = reserve_space(xdr, 32); | 1219 | p = reserve_space(xdr, 32); |
1220 | p = xdr_encode_hyper(p, lowner->clientid); | 1220 | p = xdr_encode_hyper(p, lowner->clientid); |
1221 | *p++ = cpu_to_be32(20); | 1221 | *p++ = cpu_to_be32(20); |
1222 | p = xdr_encode_opaque_fixed(p, "lock id:", 8); | 1222 | p = xdr_encode_opaque_fixed(p, "lock id:", 8); |
1223 | *p++ = cpu_to_be32(lowner->s_dev); | 1223 | *p++ = cpu_to_be32(lowner->s_dev); |
1224 | xdr_encode_hyper(p, lowner->id); | 1224 | xdr_encode_hyper(p, lowner->id); |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | /* | 1227 | /* |
1228 | * opcode,type,reclaim,offset,length,new_lock_owner = 32 | 1228 | * opcode,type,reclaim,offset,length,new_lock_owner = 32 |
1229 | * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 | 1229 | * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 |
1230 | */ | 1230 | */ |
1231 | static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr) | 1231 | static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr) |
1232 | { | 1232 | { |
1233 | __be32 *p; | 1233 | __be32 *p; |
1234 | 1234 | ||
1235 | p = reserve_space(xdr, 32); | 1235 | p = reserve_space(xdr, 32); |
1236 | *p++ = cpu_to_be32(OP_LOCK); | 1236 | *p++ = cpu_to_be32(OP_LOCK); |
1237 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block)); | 1237 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block)); |
1238 | *p++ = cpu_to_be32(args->reclaim); | 1238 | *p++ = cpu_to_be32(args->reclaim); |
1239 | p = xdr_encode_hyper(p, args->fl->fl_start); | 1239 | p = xdr_encode_hyper(p, args->fl->fl_start); |
1240 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); | 1240 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
1241 | *p = cpu_to_be32(args->new_lock_owner); | 1241 | *p = cpu_to_be32(args->new_lock_owner); |
1242 | if (args->new_lock_owner){ | 1242 | if (args->new_lock_owner){ |
1243 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); | 1243 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); |
1244 | *p++ = cpu_to_be32(args->open_seqid->sequence->counter); | 1244 | *p++ = cpu_to_be32(args->open_seqid->sequence->counter); |
1245 | p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE); | 1245 | p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE); |
1246 | *p++ = cpu_to_be32(args->lock_seqid->sequence->counter); | 1246 | *p++ = cpu_to_be32(args->lock_seqid->sequence->counter); |
1247 | encode_lockowner(xdr, &args->lock_owner); | 1247 | encode_lockowner(xdr, &args->lock_owner); |
1248 | } | 1248 | } |
1249 | else { | 1249 | else { |
1250 | p = reserve_space(xdr, NFS4_STATEID_SIZE+4); | 1250 | p = reserve_space(xdr, NFS4_STATEID_SIZE+4); |
1251 | p = xdr_encode_opaque_fixed(p, args->lock_stateid->data, NFS4_STATEID_SIZE); | 1251 | p = xdr_encode_opaque_fixed(p, args->lock_stateid->data, NFS4_STATEID_SIZE); |
1252 | *p = cpu_to_be32(args->lock_seqid->sequence->counter); | 1252 | *p = cpu_to_be32(args->lock_seqid->sequence->counter); |
1253 | } | 1253 | } |
1254 | hdr->nops++; | 1254 | hdr->nops++; |
1255 | hdr->replen += decode_lock_maxsz; | 1255 | hdr->replen += decode_lock_maxsz; |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) | 1258 | static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) |
1259 | { | 1259 | { |
1260 | __be32 *p; | 1260 | __be32 *p; |
1261 | 1261 | ||
1262 | p = reserve_space(xdr, 24); | 1262 | p = reserve_space(xdr, 24); |
1263 | *p++ = cpu_to_be32(OP_LOCKT); | 1263 | *p++ = cpu_to_be32(OP_LOCKT); |
1264 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); | 1264 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); |
1265 | p = xdr_encode_hyper(p, args->fl->fl_start); | 1265 | p = xdr_encode_hyper(p, args->fl->fl_start); |
1266 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); | 1266 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
1267 | encode_lockowner(xdr, &args->lock_owner); | 1267 | encode_lockowner(xdr, &args->lock_owner); |
1268 | hdr->nops++; | 1268 | hdr->nops++; |
1269 | hdr->replen += decode_lockt_maxsz; | 1269 | hdr->replen += decode_lockt_maxsz; |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) | 1272 | static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) |
1273 | { | 1273 | { |
1274 | __be32 *p; | 1274 | __be32 *p; |
1275 | 1275 | ||
1276 | p = reserve_space(xdr, 12+NFS4_STATEID_SIZE+16); | 1276 | p = reserve_space(xdr, 12+NFS4_STATEID_SIZE+16); |
1277 | *p++ = cpu_to_be32(OP_LOCKU); | 1277 | *p++ = cpu_to_be32(OP_LOCKU); |
1278 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); | 1278 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); |
1279 | *p++ = cpu_to_be32(args->seqid->sequence->counter); | 1279 | *p++ = cpu_to_be32(args->seqid->sequence->counter); |
1280 | p = xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); | 1280 | p = xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); |
1281 | p = xdr_encode_hyper(p, args->fl->fl_start); | 1281 | p = xdr_encode_hyper(p, args->fl->fl_start); |
1282 | xdr_encode_hyper(p, nfs4_lock_length(args->fl)); | 1282 | xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
1283 | hdr->nops++; | 1283 | hdr->nops++; |
1284 | hdr->replen += decode_locku_maxsz; | 1284 | hdr->replen += decode_locku_maxsz; |
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) | 1287 | static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) |
1288 | { | 1288 | { |
1289 | __be32 *p; | 1289 | __be32 *p; |
1290 | 1290 | ||
1291 | p = reserve_space(xdr, 4); | 1291 | p = reserve_space(xdr, 4); |
1292 | *p = cpu_to_be32(OP_RELEASE_LOCKOWNER); | 1292 | *p = cpu_to_be32(OP_RELEASE_LOCKOWNER); |
1293 | encode_lockowner(xdr, lowner); | 1293 | encode_lockowner(xdr, lowner); |
1294 | hdr->nops++; | 1294 | hdr->nops++; |
1295 | hdr->replen += decode_release_lockowner_maxsz; | 1295 | hdr->replen += decode_release_lockowner_maxsz; |
1296 | } | 1296 | } |
1297 | 1297 | ||
1298 | static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) | 1298 | static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
1299 | { | 1299 | { |
1300 | int len = name->len; | 1300 | int len = name->len; |
1301 | __be32 *p; | 1301 | __be32 *p; |
1302 | 1302 | ||
1303 | p = reserve_space(xdr, 8 + len); | 1303 | p = reserve_space(xdr, 8 + len); |
1304 | *p++ = cpu_to_be32(OP_LOOKUP); | 1304 | *p++ = cpu_to_be32(OP_LOOKUP); |
1305 | xdr_encode_opaque(p, name->name, len); | 1305 | xdr_encode_opaque(p, name->name, len); |
1306 | hdr->nops++; | 1306 | hdr->nops++; |
1307 | hdr->replen += decode_lookup_maxsz; | 1307 | hdr->replen += decode_lookup_maxsz; |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode) | 1310 | static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode) |
1311 | { | 1311 | { |
1312 | __be32 *p; | 1312 | __be32 *p; |
1313 | 1313 | ||
1314 | p = reserve_space(xdr, 8); | 1314 | p = reserve_space(xdr, 8); |
1315 | switch (fmode & (FMODE_READ|FMODE_WRITE)) { | 1315 | switch (fmode & (FMODE_READ|FMODE_WRITE)) { |
1316 | case FMODE_READ: | 1316 | case FMODE_READ: |
1317 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ); | 1317 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ); |
1318 | break; | 1318 | break; |
1319 | case FMODE_WRITE: | 1319 | case FMODE_WRITE: |
1320 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE); | 1320 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE); |
1321 | break; | 1321 | break; |
1322 | case FMODE_READ|FMODE_WRITE: | 1322 | case FMODE_READ|FMODE_WRITE: |
1323 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH); | 1323 | *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH); |
1324 | break; | 1324 | break; |
1325 | default: | 1325 | default: |
1326 | *p++ = cpu_to_be32(0); | 1326 | *p++ = cpu_to_be32(0); |
1327 | } | 1327 | } |
1328 | *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ | 1328 | *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) | 1331 | static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
1332 | { | 1332 | { |
1333 | __be32 *p; | 1333 | __be32 *p; |
1334 | /* | 1334 | /* |
1335 | * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, | 1335 | * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, |
1336 | * owner 4 = 32 | 1336 | * owner 4 = 32 |
1337 | */ | 1337 | */ |
1338 | p = reserve_space(xdr, 8); | 1338 | p = reserve_space(xdr, 8); |
1339 | *p++ = cpu_to_be32(OP_OPEN); | 1339 | *p++ = cpu_to_be32(OP_OPEN); |
1340 | *p = cpu_to_be32(arg->seqid->sequence->counter); | 1340 | *p = cpu_to_be32(arg->seqid->sequence->counter); |
1341 | encode_share_access(xdr, arg->fmode); | 1341 | encode_share_access(xdr, arg->fmode); |
1342 | p = reserve_space(xdr, 32); | 1342 | p = reserve_space(xdr, 32); |
1343 | p = xdr_encode_hyper(p, arg->clientid); | 1343 | p = xdr_encode_hyper(p, arg->clientid); |
1344 | *p++ = cpu_to_be32(20); | 1344 | *p++ = cpu_to_be32(20); |
1345 | p = xdr_encode_opaque_fixed(p, "open id:", 8); | 1345 | p = xdr_encode_opaque_fixed(p, "open id:", 8); |
1346 | *p++ = cpu_to_be32(arg->server->s_dev); | 1346 | *p++ = cpu_to_be32(arg->server->s_dev); |
1347 | xdr_encode_hyper(p, arg->id); | 1347 | xdr_encode_hyper(p, arg->id); |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) | 1350 | static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
1351 | { | 1351 | { |
1352 | __be32 *p; | 1352 | __be32 *p; |
1353 | struct nfs_client *clp; | 1353 | struct nfs_client *clp; |
1354 | 1354 | ||
1355 | p = reserve_space(xdr, 4); | 1355 | p = reserve_space(xdr, 4); |
1356 | switch(arg->open_flags & O_EXCL) { | 1356 | switch(arg->open_flags & O_EXCL) { |
1357 | case 0: | 1357 | case 0: |
1358 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); | 1358 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); |
1359 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1359 | encode_attrs(xdr, arg->u.attrs, arg->server); |
1360 | break; | 1360 | break; |
1361 | default: | 1361 | default: |
1362 | clp = arg->server->nfs_client; | 1362 | clp = arg->server->nfs_client; |
1363 | if (clp->cl_mvops->minor_version > 0) { | 1363 | if (clp->cl_mvops->minor_version > 0) { |
1364 | if (nfs4_has_persistent_session(clp)) { | 1364 | if (nfs4_has_persistent_session(clp)) { |
1365 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); | 1365 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); |
1366 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1366 | encode_attrs(xdr, arg->u.attrs, arg->server); |
1367 | } else { | 1367 | } else { |
1368 | struct iattr dummy; | 1368 | struct iattr dummy; |
1369 | 1369 | ||
1370 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); | 1370 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); |
1371 | encode_nfs4_verifier(xdr, &arg->u.verifier); | 1371 | encode_nfs4_verifier(xdr, &arg->u.verifier); |
1372 | dummy.ia_valid = 0; | 1372 | dummy.ia_valid = 0; |
1373 | encode_attrs(xdr, &dummy, arg->server); | 1373 | encode_attrs(xdr, &dummy, arg->server); |
1374 | } | 1374 | } |
1375 | } else { | 1375 | } else { |
1376 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); | 1376 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); |
1377 | encode_nfs4_verifier(xdr, &arg->u.verifier); | 1377 | encode_nfs4_verifier(xdr, &arg->u.verifier); |
1378 | } | 1378 | } |
1379 | } | 1379 | } |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) | 1382 | static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) |
1383 | { | 1383 | { |
1384 | __be32 *p; | 1384 | __be32 *p; |
1385 | 1385 | ||
1386 | p = reserve_space(xdr, 4); | 1386 | p = reserve_space(xdr, 4); |
1387 | switch (arg->open_flags & O_CREAT) { | 1387 | switch (arg->open_flags & O_CREAT) { |
1388 | case 0: | 1388 | case 0: |
1389 | *p = cpu_to_be32(NFS4_OPEN_NOCREATE); | 1389 | *p = cpu_to_be32(NFS4_OPEN_NOCREATE); |
1390 | break; | 1390 | break; |
1391 | default: | 1391 | default: |
1392 | BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL); | 1392 | BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL); |
1393 | *p = cpu_to_be32(NFS4_OPEN_CREATE); | 1393 | *p = cpu_to_be32(NFS4_OPEN_CREATE); |
1394 | encode_createmode(xdr, arg); | 1394 | encode_createmode(xdr, arg); |
1395 | } | 1395 | } |
1396 | } | 1396 | } |
1397 | 1397 | ||
1398 | static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type) | 1398 | static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type) |
1399 | { | 1399 | { |
1400 | __be32 *p; | 1400 | __be32 *p; |
1401 | 1401 | ||
1402 | p = reserve_space(xdr, 4); | 1402 | p = reserve_space(xdr, 4); |
1403 | switch (delegation_type) { | 1403 | switch (delegation_type) { |
1404 | case 0: | 1404 | case 0: |
1405 | *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE); | 1405 | *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE); |
1406 | break; | 1406 | break; |
1407 | case FMODE_READ: | 1407 | case FMODE_READ: |
1408 | *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ); | 1408 | *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ); |
1409 | break; | 1409 | break; |
1410 | case FMODE_WRITE|FMODE_READ: | 1410 | case FMODE_WRITE|FMODE_READ: |
1411 | *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE); | 1411 | *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE); |
1412 | break; | 1412 | break; |
1413 | default: | 1413 | default: |
1414 | BUG(); | 1414 | BUG(); |
1415 | } | 1415 | } |
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) | 1418 | static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) |
1419 | { | 1419 | { |
1420 | __be32 *p; | 1420 | __be32 *p; |
1421 | 1421 | ||
1422 | p = reserve_space(xdr, 4); | 1422 | p = reserve_space(xdr, 4); |
1423 | *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL); | 1423 | *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL); |
1424 | encode_string(xdr, name->len, name->name); | 1424 | encode_string(xdr, name->len, name->name); |
1425 | } | 1425 | } |
1426 | 1426 | ||
1427 | static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type) | 1427 | static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type) |
1428 | { | 1428 | { |
1429 | __be32 *p; | 1429 | __be32 *p; |
1430 | 1430 | ||
1431 | p = reserve_space(xdr, 4); | 1431 | p = reserve_space(xdr, 4); |
1432 | *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS); | 1432 | *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS); |
1433 | encode_delegation_type(xdr, type); | 1433 | encode_delegation_type(xdr, type); |
1434 | } | 1434 | } |
1435 | 1435 | ||
1436 | static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) | 1436 | static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) |
1437 | { | 1437 | { |
1438 | __be32 *p; | 1438 | __be32 *p; |
1439 | 1439 | ||
1440 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); | 1440 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); |
1441 | *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR); | 1441 | *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR); |
1442 | xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); | 1442 | xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); |
1443 | encode_string(xdr, name->len, name->name); | 1443 | encode_string(xdr, name->len, name->name); |
1444 | } | 1444 | } |
1445 | 1445 | ||
1446 | static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr) | 1446 | static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr) |
1447 | { | 1447 | { |
1448 | encode_openhdr(xdr, arg); | 1448 | encode_openhdr(xdr, arg); |
1449 | encode_opentype(xdr, arg); | 1449 | encode_opentype(xdr, arg); |
1450 | switch (arg->claim) { | 1450 | switch (arg->claim) { |
1451 | case NFS4_OPEN_CLAIM_NULL: | 1451 | case NFS4_OPEN_CLAIM_NULL: |
1452 | encode_claim_null(xdr, arg->name); | 1452 | encode_claim_null(xdr, arg->name); |
1453 | break; | 1453 | break; |
1454 | case NFS4_OPEN_CLAIM_PREVIOUS: | 1454 | case NFS4_OPEN_CLAIM_PREVIOUS: |
1455 | encode_claim_previous(xdr, arg->u.delegation_type); | 1455 | encode_claim_previous(xdr, arg->u.delegation_type); |
1456 | break; | 1456 | break; |
1457 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: | 1457 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: |
1458 | encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); | 1458 | encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); |
1459 | break; | 1459 | break; |
1460 | default: | 1460 | default: |
1461 | BUG(); | 1461 | BUG(); |
1462 | } | 1462 | } |
1463 | hdr->nops++; | 1463 | hdr->nops++; |
1464 | hdr->replen += decode_open_maxsz; | 1464 | hdr->replen += decode_open_maxsz; |
1465 | } | 1465 | } |
1466 | 1466 | ||
1467 | static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) | 1467 | static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) |
1468 | { | 1468 | { |
1469 | __be32 *p; | 1469 | __be32 *p; |
1470 | 1470 | ||
1471 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); | 1471 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); |
1472 | *p++ = cpu_to_be32(OP_OPEN_CONFIRM); | 1472 | *p++ = cpu_to_be32(OP_OPEN_CONFIRM); |
1473 | p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); | 1473 | p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); |
1474 | *p = cpu_to_be32(arg->seqid->sequence->counter); | 1474 | *p = cpu_to_be32(arg->seqid->sequence->counter); |
1475 | hdr->nops++; | 1475 | hdr->nops++; |
1476 | hdr->replen += decode_open_confirm_maxsz; | 1476 | hdr->replen += decode_open_confirm_maxsz; |
1477 | } | 1477 | } |
1478 | 1478 | ||
1479 | static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) | 1479 | static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) |
1480 | { | 1480 | { |
1481 | __be32 *p; | 1481 | __be32 *p; |
1482 | 1482 | ||
1483 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); | 1483 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); |
1484 | *p++ = cpu_to_be32(OP_OPEN_DOWNGRADE); | 1484 | *p++ = cpu_to_be32(OP_OPEN_DOWNGRADE); |
1485 | p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); | 1485 | p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE); |
1486 | *p = cpu_to_be32(arg->seqid->sequence->counter); | 1486 | *p = cpu_to_be32(arg->seqid->sequence->counter); |
1487 | encode_share_access(xdr, arg->fmode); | 1487 | encode_share_access(xdr, arg->fmode); |
1488 | hdr->nops++; | 1488 | hdr->nops++; |
1489 | hdr->replen += decode_open_downgrade_maxsz; | 1489 | hdr->replen += decode_open_downgrade_maxsz; |
1490 | } | 1490 | } |
1491 | 1491 | ||
1492 | static void | 1492 | static void |
1493 | encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr) | 1493 | encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr) |
1494 | { | 1494 | { |
1495 | int len = fh->size; | 1495 | int len = fh->size; |
1496 | __be32 *p; | 1496 | __be32 *p; |
1497 | 1497 | ||
1498 | p = reserve_space(xdr, 8 + len); | 1498 | p = reserve_space(xdr, 8 + len); |
1499 | *p++ = cpu_to_be32(OP_PUTFH); | 1499 | *p++ = cpu_to_be32(OP_PUTFH); |
1500 | xdr_encode_opaque(p, fh->data, len); | 1500 | xdr_encode_opaque(p, fh->data, len); |
1501 | hdr->nops++; | 1501 | hdr->nops++; |
1502 | hdr->replen += decode_putfh_maxsz; | 1502 | hdr->replen += decode_putfh_maxsz; |
1503 | } | 1503 | } |
1504 | 1504 | ||
1505 | static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) | 1505 | static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
1506 | { | 1506 | { |
1507 | __be32 *p; | 1507 | __be32 *p; |
1508 | 1508 | ||
1509 | p = reserve_space(xdr, 4); | 1509 | p = reserve_space(xdr, 4); |
1510 | *p = cpu_to_be32(OP_PUTROOTFH); | 1510 | *p = cpu_to_be32(OP_PUTROOTFH); |
1511 | hdr->nops++; | 1511 | hdr->nops++; |
1512 | hdr->replen += decode_putrootfh_maxsz; | 1512 | hdr->replen += decode_putrootfh_maxsz; |
1513 | } | 1513 | } |
1514 | 1514 | ||
1515 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx, int zero_seqid) | 1515 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx, int zero_seqid) |
1516 | { | 1516 | { |
1517 | nfs4_stateid stateid; | 1517 | nfs4_stateid stateid; |
1518 | __be32 *p; | 1518 | __be32 *p; |
1519 | 1519 | ||
1520 | p = reserve_space(xdr, NFS4_STATEID_SIZE); | 1520 | p = reserve_space(xdr, NFS4_STATEID_SIZE); |
1521 | if (ctx->state != NULL) { | 1521 | if (ctx->state != NULL) { |
1522 | nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid); | 1522 | nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid); |
1523 | if (zero_seqid) | 1523 | if (zero_seqid) |
1524 | stateid.stateid.seqid = 0; | 1524 | stateid.stateid.seqid = 0; |
1525 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); | 1525 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); |
1526 | } else | 1526 | } else |
1527 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); | 1527 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); |
1528 | } | 1528 | } |
1529 | 1529 | ||
1530 | static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr) | 1530 | static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr) |
1531 | { | 1531 | { |
1532 | __be32 *p; | 1532 | __be32 *p; |
1533 | 1533 | ||
1534 | p = reserve_space(xdr, 4); | 1534 | p = reserve_space(xdr, 4); |
1535 | *p = cpu_to_be32(OP_READ); | 1535 | *p = cpu_to_be32(OP_READ); |
1536 | 1536 | ||
1537 | encode_stateid(xdr, args->context, args->lock_context, | 1537 | encode_stateid(xdr, args->context, args->lock_context, |
1538 | hdr->minorversion); | 1538 | hdr->minorversion); |
1539 | 1539 | ||
1540 | p = reserve_space(xdr, 12); | 1540 | p = reserve_space(xdr, 12); |
1541 | p = xdr_encode_hyper(p, args->offset); | 1541 | p = xdr_encode_hyper(p, args->offset); |
1542 | *p = cpu_to_be32(args->count); | 1542 | *p = cpu_to_be32(args->count); |
1543 | hdr->nops++; | 1543 | hdr->nops++; |
1544 | hdr->replen += decode_read_maxsz; | 1544 | hdr->replen += decode_read_maxsz; |
1545 | } | 1545 | } |
1546 | 1546 | ||
1547 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1547 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
1548 | { | 1548 | { |
1549 | uint32_t attrs[2] = { | 1549 | uint32_t attrs[2] = { |
1550 | FATTR4_WORD0_RDATTR_ERROR, | 1550 | FATTR4_WORD0_RDATTR_ERROR, |
1551 | FATTR4_WORD1_MOUNTED_ON_FILEID, | 1551 | FATTR4_WORD1_MOUNTED_ON_FILEID, |
1552 | }; | 1552 | }; |
1553 | uint32_t dircount = readdir->count >> 1; | 1553 | uint32_t dircount = readdir->count >> 1; |
1554 | __be32 *p; | 1554 | __be32 *p; |
1555 | 1555 | ||
1556 | if (readdir->plus) { | 1556 | if (readdir->plus) { |
1557 | attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| | 1557 | attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| |
1558 | FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID; | 1558 | FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID; |
1559 | attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| | 1559 | attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| |
1560 | FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| | 1560 | FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| |
1561 | FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| | 1561 | FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| |
1562 | FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | 1562 | FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
1563 | dircount >>= 1; | 1563 | dircount >>= 1; |
1564 | } | 1564 | } |
1565 | /* Use mounted_on_fileid only if the server supports it */ | 1565 | /* Use mounted_on_fileid only if the server supports it */ |
1566 | if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) | 1566 | if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) |
1567 | attrs[0] |= FATTR4_WORD0_FILEID; | 1567 | attrs[0] |= FATTR4_WORD0_FILEID; |
1568 | 1568 | ||
1569 | p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); | 1569 | p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); |
1570 | *p++ = cpu_to_be32(OP_READDIR); | 1570 | *p++ = cpu_to_be32(OP_READDIR); |
1571 | p = xdr_encode_hyper(p, readdir->cookie); | 1571 | p = xdr_encode_hyper(p, readdir->cookie); |
1572 | p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE); | 1572 | p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE); |
1573 | *p++ = cpu_to_be32(dircount); | 1573 | *p++ = cpu_to_be32(dircount); |
1574 | *p++ = cpu_to_be32(readdir->count); | 1574 | *p++ = cpu_to_be32(readdir->count); |
1575 | *p++ = cpu_to_be32(2); | 1575 | *p++ = cpu_to_be32(2); |
1576 | 1576 | ||
1577 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); | 1577 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); |
1578 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); | 1578 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); |
1579 | hdr->nops++; | 1579 | hdr->nops++; |
1580 | hdr->replen += decode_readdir_maxsz; | 1580 | hdr->replen += decode_readdir_maxsz; |
1581 | dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", | 1581 | dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", |
1582 | __func__, | 1582 | __func__, |
1583 | (unsigned long long)readdir->cookie, | 1583 | (unsigned long long)readdir->cookie, |
1584 | ((u32 *)readdir->verifier.data)[0], | 1584 | ((u32 *)readdir->verifier.data)[0], |
1585 | ((u32 *)readdir->verifier.data)[1], | 1585 | ((u32 *)readdir->verifier.data)[1], |
1586 | attrs[0] & readdir->bitmask[0], | 1586 | attrs[0] & readdir->bitmask[0], |
1587 | attrs[1] & readdir->bitmask[1]); | 1587 | attrs[1] & readdir->bitmask[1]); |
1588 | } | 1588 | } |
1589 | 1589 | ||
1590 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) | 1590 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) |
1591 | { | 1591 | { |
1592 | __be32 *p; | 1592 | __be32 *p; |
1593 | 1593 | ||
1594 | p = reserve_space(xdr, 4); | 1594 | p = reserve_space(xdr, 4); |
1595 | *p = cpu_to_be32(OP_READLINK); | 1595 | *p = cpu_to_be32(OP_READLINK); |
1596 | hdr->nops++; | 1596 | hdr->nops++; |
1597 | hdr->replen += decode_readlink_maxsz; | 1597 | hdr->replen += decode_readlink_maxsz; |
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) | 1600 | static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
1601 | { | 1601 | { |
1602 | __be32 *p; | 1602 | __be32 *p; |
1603 | 1603 | ||
1604 | p = reserve_space(xdr, 8 + name->len); | 1604 | p = reserve_space(xdr, 8 + name->len); |
1605 | *p++ = cpu_to_be32(OP_REMOVE); | 1605 | *p++ = cpu_to_be32(OP_REMOVE); |
1606 | xdr_encode_opaque(p, name->name, name->len); | 1606 | xdr_encode_opaque(p, name->name, name->len); |
1607 | hdr->nops++; | 1607 | hdr->nops++; |
1608 | hdr->replen += decode_remove_maxsz; | 1608 | hdr->replen += decode_remove_maxsz; |
1609 | } | 1609 | } |
1610 | 1610 | ||
1611 | static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) | 1611 | static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) |
1612 | { | 1612 | { |
1613 | __be32 *p; | 1613 | __be32 *p; |
1614 | 1614 | ||
1615 | p = reserve_space(xdr, 4); | 1615 | p = reserve_space(xdr, 4); |
1616 | *p = cpu_to_be32(OP_RENAME); | 1616 | *p = cpu_to_be32(OP_RENAME); |
1617 | encode_string(xdr, oldname->len, oldname->name); | 1617 | encode_string(xdr, oldname->len, oldname->name); |
1618 | encode_string(xdr, newname->len, newname->name); | 1618 | encode_string(xdr, newname->len, newname->name); |
1619 | hdr->nops++; | 1619 | hdr->nops++; |
1620 | hdr->replen += decode_rename_maxsz; | 1620 | hdr->replen += decode_rename_maxsz; |
1621 | } | 1621 | } |
1622 | 1622 | ||
1623 | static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr) | 1623 | static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr) |
1624 | { | 1624 | { |
1625 | __be32 *p; | 1625 | __be32 *p; |
1626 | 1626 | ||
1627 | p = reserve_space(xdr, 12); | 1627 | p = reserve_space(xdr, 12); |
1628 | *p++ = cpu_to_be32(OP_RENEW); | 1628 | *p++ = cpu_to_be32(OP_RENEW); |
1629 | xdr_encode_hyper(p, client_stateid->cl_clientid); | 1629 | xdr_encode_hyper(p, client_stateid->cl_clientid); |
1630 | hdr->nops++; | 1630 | hdr->nops++; |
1631 | hdr->replen += decode_renew_maxsz; | 1631 | hdr->replen += decode_renew_maxsz; |
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | static void | 1634 | static void |
1635 | encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr) | 1635 | encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
1636 | { | 1636 | { |
1637 | __be32 *p; | 1637 | __be32 *p; |
1638 | 1638 | ||
1639 | p = reserve_space(xdr, 4); | 1639 | p = reserve_space(xdr, 4); |
1640 | *p = cpu_to_be32(OP_RESTOREFH); | 1640 | *p = cpu_to_be32(OP_RESTOREFH); |
1641 | hdr->nops++; | 1641 | hdr->nops++; |
1642 | hdr->replen += decode_restorefh_maxsz; | 1642 | hdr->replen += decode_restorefh_maxsz; |
1643 | } | 1643 | } |
1644 | 1644 | ||
1645 | static void | 1645 | static void |
1646 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr) | 1646 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr) |
1647 | { | 1647 | { |
1648 | __be32 *p; | 1648 | __be32 *p; |
1649 | 1649 | ||
1650 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); | 1650 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); |
1651 | *p++ = cpu_to_be32(OP_SETATTR); | 1651 | *p++ = cpu_to_be32(OP_SETATTR); |
1652 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); | 1652 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); |
1653 | p = reserve_space(xdr, 2*4); | 1653 | p = reserve_space(xdr, 2*4); |
1654 | *p++ = cpu_to_be32(1); | 1654 | *p++ = cpu_to_be32(1); |
1655 | *p = cpu_to_be32(FATTR4_WORD0_ACL); | 1655 | *p = cpu_to_be32(FATTR4_WORD0_ACL); |
1656 | BUG_ON(arg->acl_len % 4); | 1656 | BUG_ON(arg->acl_len % 4); |
1657 | p = reserve_space(xdr, 4); | 1657 | p = reserve_space(xdr, 4); |
1658 | *p = cpu_to_be32(arg->acl_len); | 1658 | *p = cpu_to_be32(arg->acl_len); |
1659 | xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); | 1659 | xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); |
1660 | hdr->nops++; | 1660 | hdr->nops++; |
1661 | hdr->replen += decode_setacl_maxsz; | 1661 | hdr->replen += decode_setacl_maxsz; |
1662 | } | 1662 | } |
1663 | 1663 | ||
1664 | static void | 1664 | static void |
1665 | encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr) | 1665 | encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr) |
1666 | { | 1666 | { |
1667 | __be32 *p; | 1667 | __be32 *p; |
1668 | 1668 | ||
1669 | p = reserve_space(xdr, 4); | 1669 | p = reserve_space(xdr, 4); |
1670 | *p = cpu_to_be32(OP_SAVEFH); | 1670 | *p = cpu_to_be32(OP_SAVEFH); |
1671 | hdr->nops++; | 1671 | hdr->nops++; |
1672 | hdr->replen += decode_savefh_maxsz; | 1672 | hdr->replen += decode_savefh_maxsz; |
1673 | } | 1673 | } |
1674 | 1674 | ||
1675 | static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) | 1675 | static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) |
1676 | { | 1676 | { |
1677 | __be32 *p; | 1677 | __be32 *p; |
1678 | 1678 | ||
1679 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); | 1679 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); |
1680 | *p++ = cpu_to_be32(OP_SETATTR); | 1680 | *p++ = cpu_to_be32(OP_SETATTR); |
1681 | xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE); | 1681 | xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE); |
1682 | hdr->nops++; | 1682 | hdr->nops++; |
1683 | hdr->replen += decode_setattr_maxsz; | 1683 | hdr->replen += decode_setattr_maxsz; |
1684 | encode_attrs(xdr, arg->iap, server); | 1684 | encode_attrs(xdr, arg->iap, server); |
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) | 1687 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) |
1688 | { | 1688 | { |
1689 | __be32 *p; | 1689 | __be32 *p; |
1690 | 1690 | ||
1691 | p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE); | 1691 | p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE); |
1692 | *p++ = cpu_to_be32(OP_SETCLIENTID); | 1692 | *p++ = cpu_to_be32(OP_SETCLIENTID); |
1693 | xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE); | 1693 | xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE); |
1694 | 1694 | ||
1695 | encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name); | 1695 | encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name); |
1696 | p = reserve_space(xdr, 4); | 1696 | p = reserve_space(xdr, 4); |
1697 | *p = cpu_to_be32(setclientid->sc_prog); | 1697 | *p = cpu_to_be32(setclientid->sc_prog); |
1698 | encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid); | 1698 | encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid); |
1699 | encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr); | 1699 | encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr); |
1700 | p = reserve_space(xdr, 4); | 1700 | p = reserve_space(xdr, 4); |
1701 | *p = cpu_to_be32(setclientid->sc_cb_ident); | 1701 | *p = cpu_to_be32(setclientid->sc_cb_ident); |
1702 | hdr->nops++; | 1702 | hdr->nops++; |
1703 | hdr->replen += decode_setclientid_maxsz; | 1703 | hdr->replen += decode_setclientid_maxsz; |
1704 | } | 1704 | } |
1705 | 1705 | ||
1706 | static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) | 1706 | static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr) |
1707 | { | 1707 | { |
1708 | __be32 *p; | 1708 | __be32 *p; |
1709 | 1709 | ||
1710 | p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE); | 1710 | p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE); |
1711 | *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM); | 1711 | *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM); |
1712 | p = xdr_encode_hyper(p, arg->clientid); | 1712 | p = xdr_encode_hyper(p, arg->clientid); |
1713 | xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE); | 1713 | xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE); |
1714 | hdr->nops++; | 1714 | hdr->nops++; |
1715 | hdr->replen += decode_setclientid_confirm_maxsz; | 1715 | hdr->replen += decode_setclientid_confirm_maxsz; |
1716 | } | 1716 | } |
1717 | 1717 | ||
1718 | static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) | 1718 | static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) |
1719 | { | 1719 | { |
1720 | __be32 *p; | 1720 | __be32 *p; |
1721 | 1721 | ||
1722 | p = reserve_space(xdr, 4); | 1722 | p = reserve_space(xdr, 4); |
1723 | *p = cpu_to_be32(OP_WRITE); | 1723 | *p = cpu_to_be32(OP_WRITE); |
1724 | 1724 | ||
1725 | encode_stateid(xdr, args->context, args->lock_context, | 1725 | encode_stateid(xdr, args->context, args->lock_context, |
1726 | hdr->minorversion); | 1726 | hdr->minorversion); |
1727 | 1727 | ||
1728 | p = reserve_space(xdr, 16); | 1728 | p = reserve_space(xdr, 16); |
1729 | p = xdr_encode_hyper(p, args->offset); | 1729 | p = xdr_encode_hyper(p, args->offset); |
1730 | *p++ = cpu_to_be32(args->stable); | 1730 | *p++ = cpu_to_be32(args->stable); |
1731 | *p = cpu_to_be32(args->count); | 1731 | *p = cpu_to_be32(args->count); |
1732 | 1732 | ||
1733 | xdr_write_pages(xdr, args->pages, args->pgbase, args->count); | 1733 | xdr_write_pages(xdr, args->pages, args->pgbase, args->count); |
1734 | hdr->nops++; | 1734 | hdr->nops++; |
1735 | hdr->replen += decode_write_maxsz; | 1735 | hdr->replen += decode_write_maxsz; |
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) | 1738 | static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) |
1739 | { | 1739 | { |
1740 | __be32 *p; | 1740 | __be32 *p; |
1741 | 1741 | ||
1742 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); | 1742 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE); |
1743 | 1743 | ||
1744 | *p++ = cpu_to_be32(OP_DELEGRETURN); | 1744 | *p++ = cpu_to_be32(OP_DELEGRETURN); |
1745 | xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); | 1745 | xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE); |
1746 | hdr->nops++; | 1746 | hdr->nops++; |
1747 | hdr->replen += decode_delegreturn_maxsz; | 1747 | hdr->replen += decode_delegreturn_maxsz; |
1748 | } | 1748 | } |
1749 | 1749 | ||
1750 | static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) | 1750 | static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
1751 | { | 1751 | { |
1752 | int len = name->len; | 1752 | int len = name->len; |
1753 | __be32 *p; | 1753 | __be32 *p; |
1754 | 1754 | ||
1755 | p = reserve_space(xdr, 8 + len); | 1755 | p = reserve_space(xdr, 8 + len); |
1756 | *p++ = cpu_to_be32(OP_SECINFO); | 1756 | *p++ = cpu_to_be32(OP_SECINFO); |
1757 | xdr_encode_opaque(p, name->name, len); | 1757 | xdr_encode_opaque(p, name->name, len); |
1758 | hdr->nops++; | 1758 | hdr->nops++; |
1759 | hdr->replen += decode_secinfo_maxsz; | 1759 | hdr->replen += decode_secinfo_maxsz; |
1760 | } | 1760 | } |
1761 | 1761 | ||
1762 | #if defined(CONFIG_NFS_V4_1) | 1762 | #if defined(CONFIG_NFS_V4_1) |
1763 | /* NFSv4.1 operations */ | 1763 | /* NFSv4.1 operations */ |
1764 | static void encode_exchange_id(struct xdr_stream *xdr, | 1764 | static void encode_exchange_id(struct xdr_stream *xdr, |
1765 | struct nfs41_exchange_id_args *args, | 1765 | struct nfs41_exchange_id_args *args, |
1766 | struct compound_hdr *hdr) | 1766 | struct compound_hdr *hdr) |
1767 | { | 1767 | { |
1768 | __be32 *p; | 1768 | __be32 *p; |
1769 | 1769 | ||
1770 | p = reserve_space(xdr, 4 + sizeof(args->verifier->data)); | 1770 | p = reserve_space(xdr, 4 + sizeof(args->verifier->data)); |
1771 | *p++ = cpu_to_be32(OP_EXCHANGE_ID); | 1771 | *p++ = cpu_to_be32(OP_EXCHANGE_ID); |
1772 | xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data)); | 1772 | xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data)); |
1773 | 1773 | ||
1774 | encode_string(xdr, args->id_len, args->id); | 1774 | encode_string(xdr, args->id_len, args->id); |
1775 | 1775 | ||
1776 | p = reserve_space(xdr, 12); | 1776 | p = reserve_space(xdr, 12); |
1777 | *p++ = cpu_to_be32(args->flags); | 1777 | *p++ = cpu_to_be32(args->flags); |
1778 | *p++ = cpu_to_be32(0); /* zero length state_protect4_a */ | 1778 | *p++ = cpu_to_be32(0); /* zero length state_protect4_a */ |
1779 | *p = cpu_to_be32(0); /* zero length implementation id array */ | 1779 | *p = cpu_to_be32(0); /* zero length implementation id array */ |
1780 | hdr->nops++; | 1780 | hdr->nops++; |
1781 | hdr->replen += decode_exchange_id_maxsz; | 1781 | hdr->replen += decode_exchange_id_maxsz; |
1782 | } | 1782 | } |
1783 | 1783 | ||
1784 | static void encode_create_session(struct xdr_stream *xdr, | 1784 | static void encode_create_session(struct xdr_stream *xdr, |
1785 | struct nfs41_create_session_args *args, | 1785 | struct nfs41_create_session_args *args, |
1786 | struct compound_hdr *hdr) | 1786 | struct compound_hdr *hdr) |
1787 | { | 1787 | { |
1788 | __be32 *p; | 1788 | __be32 *p; |
1789 | char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; | 1789 | char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; |
1790 | uint32_t len; | 1790 | uint32_t len; |
1791 | struct nfs_client *clp = args->client; | 1791 | struct nfs_client *clp = args->client; |
1792 | u32 max_resp_sz_cached; | 1792 | u32 max_resp_sz_cached; |
1793 | 1793 | ||
1794 | /* | 1794 | /* |
1795 | * Assumes OPEN is the biggest non-idempotent compound. | 1795 | * Assumes OPEN is the biggest non-idempotent compound. |
1796 | * 2 is the verifier. | 1796 | * 2 is the verifier. |
1797 | */ | 1797 | */ |
1798 | max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + | 1798 | max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + |
1799 | RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT; | 1799 | RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT; |
1800 | 1800 | ||
1801 | len = scnprintf(machine_name, sizeof(machine_name), "%s", | 1801 | len = scnprintf(machine_name, sizeof(machine_name), "%s", |
1802 | clp->cl_ipaddr); | 1802 | clp->cl_ipaddr); |
1803 | 1803 | ||
1804 | p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); | 1804 | p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); |
1805 | *p++ = cpu_to_be32(OP_CREATE_SESSION); | 1805 | *p++ = cpu_to_be32(OP_CREATE_SESSION); |
1806 | p = xdr_encode_hyper(p, clp->cl_clientid); | 1806 | p = xdr_encode_hyper(p, clp->cl_clientid); |
1807 | *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ | 1807 | *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ |
1808 | *p++ = cpu_to_be32(args->flags); /*flags */ | 1808 | *p++ = cpu_to_be32(args->flags); /*flags */ |
1809 | 1809 | ||
1810 | /* Fore Channel */ | 1810 | /* Fore Channel */ |
1811 | *p++ = cpu_to_be32(0); /* header padding size */ | 1811 | *p++ = cpu_to_be32(0); /* header padding size */ |
1812 | *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ | 1812 | *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ |
1813 | *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ | 1813 | *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ |
1814 | *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ | 1814 | *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ |
1815 | *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ | 1815 | *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ |
1816 | *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ | 1816 | *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ |
1817 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ | 1817 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ |
1818 | 1818 | ||
1819 | /* Back Channel */ | 1819 | /* Back Channel */ |
1820 | *p++ = cpu_to_be32(0); /* header padding size */ | 1820 | *p++ = cpu_to_be32(0); /* header padding size */ |
1821 | *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ | 1821 | *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ |
1822 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ | 1822 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ |
1823 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ | 1823 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ |
1824 | *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */ | 1824 | *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */ |
1825 | *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */ | 1825 | *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */ |
1826 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ | 1826 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ |
1827 | 1827 | ||
1828 | *p++ = cpu_to_be32(args->cb_program); /* cb_program */ | 1828 | *p++ = cpu_to_be32(args->cb_program); /* cb_program */ |
1829 | *p++ = cpu_to_be32(1); | 1829 | *p++ = cpu_to_be32(1); |
1830 | *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ | 1830 | *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ |
1831 | 1831 | ||
1832 | /* authsys_parms rfc1831 */ | 1832 | /* authsys_parms rfc1831 */ |
1833 | *p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec); /* stamp */ | 1833 | *p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec); /* stamp */ |
1834 | p = xdr_encode_opaque(p, machine_name, len); | 1834 | p = xdr_encode_opaque(p, machine_name, len); |
1835 | *p++ = cpu_to_be32(0); /* UID */ | 1835 | *p++ = cpu_to_be32(0); /* UID */ |
1836 | *p++ = cpu_to_be32(0); /* GID */ | 1836 | *p++ = cpu_to_be32(0); /* GID */ |
1837 | *p = cpu_to_be32(0); /* No more gids */ | 1837 | *p = cpu_to_be32(0); /* No more gids */ |
1838 | hdr->nops++; | 1838 | hdr->nops++; |
1839 | hdr->replen += decode_create_session_maxsz; | 1839 | hdr->replen += decode_create_session_maxsz; |
1840 | } | 1840 | } |
1841 | 1841 | ||
1842 | static void encode_destroy_session(struct xdr_stream *xdr, | 1842 | static void encode_destroy_session(struct xdr_stream *xdr, |
1843 | struct nfs4_session *session, | 1843 | struct nfs4_session *session, |
1844 | struct compound_hdr *hdr) | 1844 | struct compound_hdr *hdr) |
1845 | { | 1845 | { |
1846 | __be32 *p; | 1846 | __be32 *p; |
1847 | p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN); | 1847 | p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN); |
1848 | *p++ = cpu_to_be32(OP_DESTROY_SESSION); | 1848 | *p++ = cpu_to_be32(OP_DESTROY_SESSION); |
1849 | xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); | 1849 | xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); |
1850 | hdr->nops++; | 1850 | hdr->nops++; |
1851 | hdr->replen += decode_destroy_session_maxsz; | 1851 | hdr->replen += decode_destroy_session_maxsz; |
1852 | } | 1852 | } |
1853 | 1853 | ||
1854 | static void encode_reclaim_complete(struct xdr_stream *xdr, | 1854 | static void encode_reclaim_complete(struct xdr_stream *xdr, |
1855 | struct nfs41_reclaim_complete_args *args, | 1855 | struct nfs41_reclaim_complete_args *args, |
1856 | struct compound_hdr *hdr) | 1856 | struct compound_hdr *hdr) |
1857 | { | 1857 | { |
1858 | __be32 *p; | 1858 | __be32 *p; |
1859 | 1859 | ||
1860 | p = reserve_space(xdr, 8); | 1860 | p = reserve_space(xdr, 8); |
1861 | *p++ = cpu_to_be32(OP_RECLAIM_COMPLETE); | 1861 | *p++ = cpu_to_be32(OP_RECLAIM_COMPLETE); |
1862 | *p++ = cpu_to_be32(args->one_fs); | 1862 | *p++ = cpu_to_be32(args->one_fs); |
1863 | hdr->nops++; | 1863 | hdr->nops++; |
1864 | hdr->replen += decode_reclaim_complete_maxsz; | 1864 | hdr->replen += decode_reclaim_complete_maxsz; |
1865 | } | 1865 | } |
1866 | #endif /* CONFIG_NFS_V4_1 */ | 1866 | #endif /* CONFIG_NFS_V4_1 */ |
1867 | 1867 | ||
1868 | static void encode_sequence(struct xdr_stream *xdr, | 1868 | static void encode_sequence(struct xdr_stream *xdr, |
1869 | const struct nfs4_sequence_args *args, | 1869 | const struct nfs4_sequence_args *args, |
1870 | struct compound_hdr *hdr) | 1870 | struct compound_hdr *hdr) |
1871 | { | 1871 | { |
1872 | #if defined(CONFIG_NFS_V4_1) | 1872 | #if defined(CONFIG_NFS_V4_1) |
1873 | struct nfs4_session *session = args->sa_session; | 1873 | struct nfs4_session *session = args->sa_session; |
1874 | struct nfs4_slot_table *tp; | 1874 | struct nfs4_slot_table *tp; |
1875 | struct nfs4_slot *slot; | 1875 | struct nfs4_slot *slot; |
1876 | __be32 *p; | 1876 | __be32 *p; |
1877 | 1877 | ||
1878 | if (!session) | 1878 | if (!session) |
1879 | return; | 1879 | return; |
1880 | 1880 | ||
1881 | tp = &session->fc_slot_table; | 1881 | tp = &session->fc_slot_table; |
1882 | 1882 | ||
1883 | WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE); | 1883 | WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE); |
1884 | slot = tp->slots + args->sa_slotid; | 1884 | slot = tp->slots + args->sa_slotid; |
1885 | 1885 | ||
1886 | p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16); | 1886 | p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16); |
1887 | *p++ = cpu_to_be32(OP_SEQUENCE); | 1887 | *p++ = cpu_to_be32(OP_SEQUENCE); |
1888 | 1888 | ||
1889 | /* | 1889 | /* |
1890 | * Sessionid + seqid + slotid + max slotid + cache_this | 1890 | * Sessionid + seqid + slotid + max slotid + cache_this |
1891 | */ | 1891 | */ |
1892 | dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d " | 1892 | dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d " |
1893 | "max_slotid=%d cache_this=%d\n", | 1893 | "max_slotid=%d cache_this=%d\n", |
1894 | __func__, | 1894 | __func__, |
1895 | ((u32 *)session->sess_id.data)[0], | 1895 | ((u32 *)session->sess_id.data)[0], |
1896 | ((u32 *)session->sess_id.data)[1], | 1896 | ((u32 *)session->sess_id.data)[1], |
1897 | ((u32 *)session->sess_id.data)[2], | 1897 | ((u32 *)session->sess_id.data)[2], |
1898 | ((u32 *)session->sess_id.data)[3], | 1898 | ((u32 *)session->sess_id.data)[3], |
1899 | slot->seq_nr, args->sa_slotid, | 1899 | slot->seq_nr, args->sa_slotid, |
1900 | tp->highest_used_slotid, args->sa_cache_this); | 1900 | tp->highest_used_slotid, args->sa_cache_this); |
1901 | p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); | 1901 | p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); |
1902 | *p++ = cpu_to_be32(slot->seq_nr); | 1902 | *p++ = cpu_to_be32(slot->seq_nr); |
1903 | *p++ = cpu_to_be32(args->sa_slotid); | 1903 | *p++ = cpu_to_be32(args->sa_slotid); |
1904 | *p++ = cpu_to_be32(tp->highest_used_slotid); | 1904 | *p++ = cpu_to_be32(tp->highest_used_slotid); |
1905 | *p = cpu_to_be32(args->sa_cache_this); | 1905 | *p = cpu_to_be32(args->sa_cache_this); |
1906 | hdr->nops++; | 1906 | hdr->nops++; |
1907 | hdr->replen += decode_sequence_maxsz; | 1907 | hdr->replen += decode_sequence_maxsz; |
1908 | #endif /* CONFIG_NFS_V4_1 */ | 1908 | #endif /* CONFIG_NFS_V4_1 */ |
1909 | } | 1909 | } |
1910 | 1910 | ||
1911 | #ifdef CONFIG_NFS_V4_1 | 1911 | #ifdef CONFIG_NFS_V4_1 |
1912 | static void | 1912 | static void |
1913 | encode_getdevicelist(struct xdr_stream *xdr, | 1913 | encode_getdevicelist(struct xdr_stream *xdr, |
1914 | const struct nfs4_getdevicelist_args *args, | 1914 | const struct nfs4_getdevicelist_args *args, |
1915 | struct compound_hdr *hdr) | 1915 | struct compound_hdr *hdr) |
1916 | { | 1916 | { |
1917 | __be32 *p; | 1917 | __be32 *p; |
1918 | nfs4_verifier dummy = { | 1918 | nfs4_verifier dummy = { |
1919 | .data = "dummmmmy", | 1919 | .data = "dummmmmy", |
1920 | }; | 1920 | }; |
1921 | 1921 | ||
1922 | p = reserve_space(xdr, 20); | 1922 | p = reserve_space(xdr, 20); |
1923 | *p++ = cpu_to_be32(OP_GETDEVICELIST); | 1923 | *p++ = cpu_to_be32(OP_GETDEVICELIST); |
1924 | *p++ = cpu_to_be32(args->layoutclass); | 1924 | *p++ = cpu_to_be32(args->layoutclass); |
1925 | *p++ = cpu_to_be32(NFS4_PNFS_GETDEVLIST_MAXNUM); | 1925 | *p++ = cpu_to_be32(NFS4_PNFS_GETDEVLIST_MAXNUM); |
1926 | xdr_encode_hyper(p, 0ULL); /* cookie */ | 1926 | xdr_encode_hyper(p, 0ULL); /* cookie */ |
1927 | encode_nfs4_verifier(xdr, &dummy); | 1927 | encode_nfs4_verifier(xdr, &dummy); |
1928 | hdr->nops++; | 1928 | hdr->nops++; |
1929 | hdr->replen += decode_getdevicelist_maxsz; | 1929 | hdr->replen += decode_getdevicelist_maxsz; |
1930 | } | 1930 | } |
1931 | 1931 | ||
1932 | static void | 1932 | static void |
1933 | encode_getdeviceinfo(struct xdr_stream *xdr, | 1933 | encode_getdeviceinfo(struct xdr_stream *xdr, |
1934 | const struct nfs4_getdeviceinfo_args *args, | 1934 | const struct nfs4_getdeviceinfo_args *args, |
1935 | struct compound_hdr *hdr) | 1935 | struct compound_hdr *hdr) |
1936 | { | 1936 | { |
1937 | __be32 *p; | 1937 | __be32 *p; |
1938 | 1938 | ||
1939 | p = reserve_space(xdr, 16 + NFS4_DEVICEID4_SIZE); | 1939 | p = reserve_space(xdr, 16 + NFS4_DEVICEID4_SIZE); |
1940 | *p++ = cpu_to_be32(OP_GETDEVICEINFO); | 1940 | *p++ = cpu_to_be32(OP_GETDEVICEINFO); |
1941 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, | 1941 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, |
1942 | NFS4_DEVICEID4_SIZE); | 1942 | NFS4_DEVICEID4_SIZE); |
1943 | *p++ = cpu_to_be32(args->pdev->layout_type); | 1943 | *p++ = cpu_to_be32(args->pdev->layout_type); |
1944 | *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ | 1944 | *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ |
1945 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ | 1945 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ |
1946 | hdr->nops++; | 1946 | hdr->nops++; |
1947 | hdr->replen += decode_getdeviceinfo_maxsz; | 1947 | hdr->replen += decode_getdeviceinfo_maxsz; |
1948 | } | 1948 | } |
1949 | 1949 | ||
1950 | static void | 1950 | static void |
1951 | encode_layoutget(struct xdr_stream *xdr, | 1951 | encode_layoutget(struct xdr_stream *xdr, |
1952 | const struct nfs4_layoutget_args *args, | 1952 | const struct nfs4_layoutget_args *args, |
1953 | struct compound_hdr *hdr) | 1953 | struct compound_hdr *hdr) |
1954 | { | 1954 | { |
1955 | __be32 *p; | 1955 | __be32 *p; |
1956 | 1956 | ||
1957 | p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); | 1957 | p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); |
1958 | *p++ = cpu_to_be32(OP_LAYOUTGET); | 1958 | *p++ = cpu_to_be32(OP_LAYOUTGET); |
1959 | *p++ = cpu_to_be32(0); /* Signal layout available */ | 1959 | *p++ = cpu_to_be32(0); /* Signal layout available */ |
1960 | *p++ = cpu_to_be32(args->type); | 1960 | *p++ = cpu_to_be32(args->type); |
1961 | *p++ = cpu_to_be32(args->range.iomode); | 1961 | *p++ = cpu_to_be32(args->range.iomode); |
1962 | p = xdr_encode_hyper(p, args->range.offset); | 1962 | p = xdr_encode_hyper(p, args->range.offset); |
1963 | p = xdr_encode_hyper(p, args->range.length); | 1963 | p = xdr_encode_hyper(p, args->range.length); |
1964 | p = xdr_encode_hyper(p, args->minlength); | 1964 | p = xdr_encode_hyper(p, args->minlength); |
1965 | p = xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); | 1965 | p = xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); |
1966 | *p = cpu_to_be32(args->maxcount); | 1966 | *p = cpu_to_be32(args->maxcount); |
1967 | 1967 | ||
1968 | dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", | 1968 | dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", |
1969 | __func__, | 1969 | __func__, |
1970 | args->type, | 1970 | args->type, |
1971 | args->range.iomode, | 1971 | args->range.iomode, |
1972 | (unsigned long)args->range.offset, | 1972 | (unsigned long)args->range.offset, |
1973 | (unsigned long)args->range.length, | 1973 | (unsigned long)args->range.length, |
1974 | args->maxcount); | 1974 | args->maxcount); |
1975 | hdr->nops++; | 1975 | hdr->nops++; |
1976 | hdr->replen += decode_layoutget_maxsz; | 1976 | hdr->replen += decode_layoutget_maxsz; |
1977 | } | 1977 | } |
1978 | 1978 | ||
1979 | static int | 1979 | static int |
1980 | encode_layoutcommit(struct xdr_stream *xdr, | 1980 | encode_layoutcommit(struct xdr_stream *xdr, |
1981 | struct inode *inode, | 1981 | struct inode *inode, |
1982 | const struct nfs4_layoutcommit_args *args, | 1982 | const struct nfs4_layoutcommit_args *args, |
1983 | struct compound_hdr *hdr) | 1983 | struct compound_hdr *hdr) |
1984 | { | 1984 | { |
1985 | __be32 *p; | 1985 | __be32 *p; |
1986 | 1986 | ||
1987 | dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, | 1987 | dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, |
1988 | NFS_SERVER(args->inode)->pnfs_curr_ld->id); | 1988 | NFS_SERVER(args->inode)->pnfs_curr_ld->id); |
1989 | 1989 | ||
1990 | p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); | 1990 | p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); |
1991 | *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); | 1991 | *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); |
1992 | /* Only whole file layouts */ | 1992 | /* Only whole file layouts */ |
1993 | p = xdr_encode_hyper(p, 0); /* offset */ | 1993 | p = xdr_encode_hyper(p, 0); /* offset */ |
1994 | p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */ | 1994 | p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */ |
1995 | *p++ = cpu_to_be32(0); /* reclaim */ | 1995 | *p++ = cpu_to_be32(0); /* reclaim */ |
1996 | p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); | 1996 | p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); |
1997 | *p++ = cpu_to_be32(1); /* newoffset = TRUE */ | 1997 | *p++ = cpu_to_be32(1); /* newoffset = TRUE */ |
1998 | p = xdr_encode_hyper(p, args->lastbytewritten); | 1998 | p = xdr_encode_hyper(p, args->lastbytewritten); |
1999 | *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ | 1999 | *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ |
2000 | *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ | 2000 | *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ |
2001 | 2001 | ||
2002 | if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) | 2002 | if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) |
2003 | NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit( | 2003 | NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit( |
2004 | NFS_I(inode)->layout, xdr, args); | 2004 | NFS_I(inode)->layout, xdr, args); |
2005 | else { | 2005 | else { |
2006 | p = reserve_space(xdr, 4); | 2006 | p = reserve_space(xdr, 4); |
2007 | *p = cpu_to_be32(0); /* no layout-type payload */ | 2007 | *p = cpu_to_be32(0); /* no layout-type payload */ |
2008 | } | 2008 | } |
2009 | 2009 | ||
2010 | hdr->nops++; | 2010 | hdr->nops++; |
2011 | hdr->replen += decode_layoutcommit_maxsz; | 2011 | hdr->replen += decode_layoutcommit_maxsz; |
2012 | return 0; | 2012 | return 0; |
2013 | } | 2013 | } |
2014 | 2014 | ||
2015 | static void | 2015 | static void |
2016 | encode_layoutreturn(struct xdr_stream *xdr, | 2016 | encode_layoutreturn(struct xdr_stream *xdr, |
2017 | const struct nfs4_layoutreturn_args *args, | 2017 | const struct nfs4_layoutreturn_args *args, |
2018 | struct compound_hdr *hdr) | 2018 | struct compound_hdr *hdr) |
2019 | { | 2019 | { |
2020 | __be32 *p; | 2020 | __be32 *p; |
2021 | 2021 | ||
2022 | p = reserve_space(xdr, 20); | 2022 | p = reserve_space(xdr, 20); |
2023 | *p++ = cpu_to_be32(OP_LAYOUTRETURN); | 2023 | *p++ = cpu_to_be32(OP_LAYOUTRETURN); |
2024 | *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ | 2024 | *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */ |
2025 | *p++ = cpu_to_be32(args->layout_type); | 2025 | *p++ = cpu_to_be32(args->layout_type); |
2026 | *p++ = cpu_to_be32(IOMODE_ANY); | 2026 | *p++ = cpu_to_be32(IOMODE_ANY); |
2027 | *p = cpu_to_be32(RETURN_FILE); | 2027 | *p = cpu_to_be32(RETURN_FILE); |
2028 | p = reserve_space(xdr, 16 + NFS4_STATEID_SIZE); | 2028 | p = reserve_space(xdr, 16 + NFS4_STATEID_SIZE); |
2029 | p = xdr_encode_hyper(p, 0); | 2029 | p = xdr_encode_hyper(p, 0); |
2030 | p = xdr_encode_hyper(p, NFS4_MAX_UINT64); | 2030 | p = xdr_encode_hyper(p, NFS4_MAX_UINT64); |
2031 | spin_lock(&args->inode->i_lock); | 2031 | spin_lock(&args->inode->i_lock); |
2032 | xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); | 2032 | xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); |
2033 | spin_unlock(&args->inode->i_lock); | 2033 | spin_unlock(&args->inode->i_lock); |
2034 | if (NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn) { | 2034 | if (NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn) { |
2035 | NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn( | 2035 | NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn( |
2036 | NFS_I(args->inode)->layout, xdr, args); | 2036 | NFS_I(args->inode)->layout, xdr, args); |
2037 | } else { | 2037 | } else { |
2038 | p = reserve_space(xdr, 4); | 2038 | p = reserve_space(xdr, 4); |
2039 | *p = cpu_to_be32(0); | 2039 | *p = cpu_to_be32(0); |
2040 | } | 2040 | } |
2041 | hdr->nops++; | 2041 | hdr->nops++; |
2042 | hdr->replen += decode_layoutreturn_maxsz; | 2042 | hdr->replen += decode_layoutreturn_maxsz; |
2043 | } | 2043 | } |
2044 | 2044 | ||
2045 | static int | 2045 | static int |
2046 | encode_secinfo_no_name(struct xdr_stream *xdr, | 2046 | encode_secinfo_no_name(struct xdr_stream *xdr, |
2047 | const struct nfs41_secinfo_no_name_args *args, | 2047 | const struct nfs41_secinfo_no_name_args *args, |
2048 | struct compound_hdr *hdr) | 2048 | struct compound_hdr *hdr) |
2049 | { | 2049 | { |
2050 | __be32 *p; | 2050 | __be32 *p; |
2051 | p = reserve_space(xdr, 8); | 2051 | p = reserve_space(xdr, 8); |
2052 | *p++ = cpu_to_be32(OP_SECINFO_NO_NAME); | 2052 | *p++ = cpu_to_be32(OP_SECINFO_NO_NAME); |
2053 | *p++ = cpu_to_be32(args->style); | 2053 | *p++ = cpu_to_be32(args->style); |
2054 | hdr->nops++; | 2054 | hdr->nops++; |
2055 | hdr->replen += decode_secinfo_no_name_maxsz; | 2055 | hdr->replen += decode_secinfo_no_name_maxsz; |
2056 | return 0; | 2056 | return 0; |
2057 | } | 2057 | } |
2058 | 2058 | ||
2059 | static void encode_test_stateid(struct xdr_stream *xdr, | 2059 | static void encode_test_stateid(struct xdr_stream *xdr, |
2060 | struct nfs41_test_stateid_args *args, | 2060 | struct nfs41_test_stateid_args *args, |
2061 | struct compound_hdr *hdr) | 2061 | struct compound_hdr *hdr) |
2062 | { | 2062 | { |
2063 | __be32 *p; | 2063 | __be32 *p; |
2064 | 2064 | ||
2065 | p = reserve_space(xdr, 8 + NFS4_STATEID_SIZE); | 2065 | p = reserve_space(xdr, 8 + NFS4_STATEID_SIZE); |
2066 | *p++ = cpu_to_be32(OP_TEST_STATEID); | 2066 | *p++ = cpu_to_be32(OP_TEST_STATEID); |
2067 | *p++ = cpu_to_be32(1); | 2067 | *p++ = cpu_to_be32(1); |
2068 | xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); | 2068 | xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); |
2069 | hdr->nops++; | 2069 | hdr->nops++; |
2070 | hdr->replen += decode_test_stateid_maxsz; | 2070 | hdr->replen += decode_test_stateid_maxsz; |
2071 | } | 2071 | } |
2072 | 2072 | ||
2073 | static void encode_free_stateid(struct xdr_stream *xdr, | 2073 | static void encode_free_stateid(struct xdr_stream *xdr, |
2074 | struct nfs41_free_stateid_args *args, | 2074 | struct nfs41_free_stateid_args *args, |
2075 | struct compound_hdr *hdr) | 2075 | struct compound_hdr *hdr) |
2076 | { | 2076 | { |
2077 | __be32 *p; | 2077 | __be32 *p; |
2078 | p = reserve_space(xdr, 4 + NFS4_STATEID_SIZE); | 2078 | p = reserve_space(xdr, 4 + NFS4_STATEID_SIZE); |
2079 | *p++ = cpu_to_be32(OP_FREE_STATEID); | 2079 | *p++ = cpu_to_be32(OP_FREE_STATEID); |
2080 | xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); | 2080 | xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE); |
2081 | hdr->nops++; | 2081 | hdr->nops++; |
2082 | hdr->replen += decode_free_stateid_maxsz; | 2082 | hdr->replen += decode_free_stateid_maxsz; |
2083 | } | 2083 | } |
2084 | #endif /* CONFIG_NFS_V4_1 */ | 2084 | #endif /* CONFIG_NFS_V4_1 */ |
2085 | 2085 | ||
2086 | /* | 2086 | /* |
2087 | * END OF "GENERIC" ENCODE ROUTINES. | 2087 | * END OF "GENERIC" ENCODE ROUTINES. |
2088 | */ | 2088 | */ |
2089 | 2089 | ||
2090 | static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) | 2090 | static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) |
2091 | { | 2091 | { |
2092 | #if defined(CONFIG_NFS_V4_1) | 2092 | #if defined(CONFIG_NFS_V4_1) |
2093 | if (args->sa_session) | 2093 | if (args->sa_session) |
2094 | return args->sa_session->clp->cl_mvops->minor_version; | 2094 | return args->sa_session->clp->cl_mvops->minor_version; |
2095 | #endif /* CONFIG_NFS_V4_1 */ | 2095 | #endif /* CONFIG_NFS_V4_1 */ |
2096 | return 0; | 2096 | return 0; |
2097 | } | 2097 | } |
2098 | 2098 | ||
2099 | /* | 2099 | /* |
2100 | * Encode an ACCESS request | 2100 | * Encode an ACCESS request |
2101 | */ | 2101 | */ |
2102 | static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr, | 2102 | static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr, |
2103 | const struct nfs4_accessargs *args) | 2103 | const struct nfs4_accessargs *args) |
2104 | { | 2104 | { |
2105 | struct compound_hdr hdr = { | 2105 | struct compound_hdr hdr = { |
2106 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2106 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2107 | }; | 2107 | }; |
2108 | 2108 | ||
2109 | encode_compound_hdr(xdr, req, &hdr); | 2109 | encode_compound_hdr(xdr, req, &hdr); |
2110 | encode_sequence(xdr, &args->seq_args, &hdr); | 2110 | encode_sequence(xdr, &args->seq_args, &hdr); |
2111 | encode_putfh(xdr, args->fh, &hdr); | 2111 | encode_putfh(xdr, args->fh, &hdr); |
2112 | encode_access(xdr, args->access, &hdr); | 2112 | encode_access(xdr, args->access, &hdr); |
2113 | encode_getfattr(xdr, args->bitmask, &hdr); | 2113 | encode_getfattr(xdr, args->bitmask, &hdr); |
2114 | encode_nops(&hdr); | 2114 | encode_nops(&hdr); |
2115 | } | 2115 | } |
2116 | 2116 | ||
2117 | /* | 2117 | /* |
2118 | * Encode LOOKUP request | 2118 | * Encode LOOKUP request |
2119 | */ | 2119 | */ |
2120 | static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, | 2120 | static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, |
2121 | const struct nfs4_lookup_arg *args) | 2121 | const struct nfs4_lookup_arg *args) |
2122 | { | 2122 | { |
2123 | struct compound_hdr hdr = { | 2123 | struct compound_hdr hdr = { |
2124 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2124 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2125 | }; | 2125 | }; |
2126 | 2126 | ||
2127 | encode_compound_hdr(xdr, req, &hdr); | 2127 | encode_compound_hdr(xdr, req, &hdr); |
2128 | encode_sequence(xdr, &args->seq_args, &hdr); | 2128 | encode_sequence(xdr, &args->seq_args, &hdr); |
2129 | encode_putfh(xdr, args->dir_fh, &hdr); | 2129 | encode_putfh(xdr, args->dir_fh, &hdr); |
2130 | encode_lookup(xdr, args->name, &hdr); | 2130 | encode_lookup(xdr, args->name, &hdr); |
2131 | encode_getfh(xdr, &hdr); | 2131 | encode_getfh(xdr, &hdr); |
2132 | encode_getfattr(xdr, args->bitmask, &hdr); | 2132 | encode_getfattr(xdr, args->bitmask, &hdr); |
2133 | encode_nops(&hdr); | 2133 | encode_nops(&hdr); |
2134 | } | 2134 | } |
2135 | 2135 | ||
2136 | /* | 2136 | /* |
2137 | * Encode LOOKUP_ROOT request | 2137 | * Encode LOOKUP_ROOT request |
2138 | */ | 2138 | */ |
2139 | static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, | 2139 | static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, |
2140 | struct xdr_stream *xdr, | 2140 | struct xdr_stream *xdr, |
2141 | const struct nfs4_lookup_root_arg *args) | 2141 | const struct nfs4_lookup_root_arg *args) |
2142 | { | 2142 | { |
2143 | struct compound_hdr hdr = { | 2143 | struct compound_hdr hdr = { |
2144 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2144 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2145 | }; | 2145 | }; |
2146 | 2146 | ||
2147 | encode_compound_hdr(xdr, req, &hdr); | 2147 | encode_compound_hdr(xdr, req, &hdr); |
2148 | encode_sequence(xdr, &args->seq_args, &hdr); | 2148 | encode_sequence(xdr, &args->seq_args, &hdr); |
2149 | encode_putrootfh(xdr, &hdr); | 2149 | encode_putrootfh(xdr, &hdr); |
2150 | encode_getfh(xdr, &hdr); | 2150 | encode_getfh(xdr, &hdr); |
2151 | encode_getfattr(xdr, args->bitmask, &hdr); | 2151 | encode_getfattr(xdr, args->bitmask, &hdr); |
2152 | encode_nops(&hdr); | 2152 | encode_nops(&hdr); |
2153 | } | 2153 | } |
2154 | 2154 | ||
2155 | /* | 2155 | /* |
2156 | * Encode REMOVE request | 2156 | * Encode REMOVE request |
2157 | */ | 2157 | */ |
2158 | static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, | 2158 | static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr, |
2159 | const struct nfs_removeargs *args) | 2159 | const struct nfs_removeargs *args) |
2160 | { | 2160 | { |
2161 | struct compound_hdr hdr = { | 2161 | struct compound_hdr hdr = { |
2162 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2162 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2163 | }; | 2163 | }; |
2164 | 2164 | ||
2165 | encode_compound_hdr(xdr, req, &hdr); | 2165 | encode_compound_hdr(xdr, req, &hdr); |
2166 | encode_sequence(xdr, &args->seq_args, &hdr); | 2166 | encode_sequence(xdr, &args->seq_args, &hdr); |
2167 | encode_putfh(xdr, args->fh, &hdr); | 2167 | encode_putfh(xdr, args->fh, &hdr); |
2168 | encode_remove(xdr, &args->name, &hdr); | 2168 | encode_remove(xdr, &args->name, &hdr); |
2169 | encode_getfattr(xdr, args->bitmask, &hdr); | 2169 | encode_getfattr(xdr, args->bitmask, &hdr); |
2170 | encode_nops(&hdr); | 2170 | encode_nops(&hdr); |
2171 | } | 2171 | } |
2172 | 2172 | ||
2173 | /* | 2173 | /* |
2174 | * Encode RENAME request | 2174 | * Encode RENAME request |
2175 | */ | 2175 | */ |
2176 | static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, | 2176 | static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr, |
2177 | const struct nfs_renameargs *args) | 2177 | const struct nfs_renameargs *args) |
2178 | { | 2178 | { |
2179 | struct compound_hdr hdr = { | 2179 | struct compound_hdr hdr = { |
2180 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2180 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2181 | }; | 2181 | }; |
2182 | 2182 | ||
2183 | encode_compound_hdr(xdr, req, &hdr); | 2183 | encode_compound_hdr(xdr, req, &hdr); |
2184 | encode_sequence(xdr, &args->seq_args, &hdr); | 2184 | encode_sequence(xdr, &args->seq_args, &hdr); |
2185 | encode_putfh(xdr, args->old_dir, &hdr); | 2185 | encode_putfh(xdr, args->old_dir, &hdr); |
2186 | encode_savefh(xdr, &hdr); | 2186 | encode_savefh(xdr, &hdr); |
2187 | encode_putfh(xdr, args->new_dir, &hdr); | 2187 | encode_putfh(xdr, args->new_dir, &hdr); |
2188 | encode_rename(xdr, args->old_name, args->new_name, &hdr); | 2188 | encode_rename(xdr, args->old_name, args->new_name, &hdr); |
2189 | encode_getfattr(xdr, args->bitmask, &hdr); | 2189 | encode_getfattr(xdr, args->bitmask, &hdr); |
2190 | encode_restorefh(xdr, &hdr); | 2190 | encode_restorefh(xdr, &hdr); |
2191 | encode_getfattr(xdr, args->bitmask, &hdr); | 2191 | encode_getfattr(xdr, args->bitmask, &hdr); |
2192 | encode_nops(&hdr); | 2192 | encode_nops(&hdr); |
2193 | } | 2193 | } |
2194 | 2194 | ||
2195 | /* | 2195 | /* |
2196 | * Encode LINK request | 2196 | * Encode LINK request |
2197 | */ | 2197 | */ |
2198 | static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, | 2198 | static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr, |
2199 | const struct nfs4_link_arg *args) | 2199 | const struct nfs4_link_arg *args) |
2200 | { | 2200 | { |
2201 | struct compound_hdr hdr = { | 2201 | struct compound_hdr hdr = { |
2202 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2202 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2203 | }; | 2203 | }; |
2204 | 2204 | ||
2205 | encode_compound_hdr(xdr, req, &hdr); | 2205 | encode_compound_hdr(xdr, req, &hdr); |
2206 | encode_sequence(xdr, &args->seq_args, &hdr); | 2206 | encode_sequence(xdr, &args->seq_args, &hdr); |
2207 | encode_putfh(xdr, args->fh, &hdr); | 2207 | encode_putfh(xdr, args->fh, &hdr); |
2208 | encode_savefh(xdr, &hdr); | 2208 | encode_savefh(xdr, &hdr); |
2209 | encode_putfh(xdr, args->dir_fh, &hdr); | 2209 | encode_putfh(xdr, args->dir_fh, &hdr); |
2210 | encode_link(xdr, args->name, &hdr); | 2210 | encode_link(xdr, args->name, &hdr); |
2211 | encode_getfattr(xdr, args->bitmask, &hdr); | 2211 | encode_getfattr(xdr, args->bitmask, &hdr); |
2212 | encode_restorefh(xdr, &hdr); | 2212 | encode_restorefh(xdr, &hdr); |
2213 | encode_getfattr(xdr, args->bitmask, &hdr); | 2213 | encode_getfattr(xdr, args->bitmask, &hdr); |
2214 | encode_nops(&hdr); | 2214 | encode_nops(&hdr); |
2215 | } | 2215 | } |
2216 | 2216 | ||
2217 | /* | 2217 | /* |
2218 | * Encode CREATE request | 2218 | * Encode CREATE request |
2219 | */ | 2219 | */ |
2220 | static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, | 2220 | static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr, |
2221 | const struct nfs4_create_arg *args) | 2221 | const struct nfs4_create_arg *args) |
2222 | { | 2222 | { |
2223 | struct compound_hdr hdr = { | 2223 | struct compound_hdr hdr = { |
2224 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2224 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2225 | }; | 2225 | }; |
2226 | 2226 | ||
2227 | encode_compound_hdr(xdr, req, &hdr); | 2227 | encode_compound_hdr(xdr, req, &hdr); |
2228 | encode_sequence(xdr, &args->seq_args, &hdr); | 2228 | encode_sequence(xdr, &args->seq_args, &hdr); |
2229 | encode_putfh(xdr, args->dir_fh, &hdr); | 2229 | encode_putfh(xdr, args->dir_fh, &hdr); |
2230 | encode_savefh(xdr, &hdr); | 2230 | encode_savefh(xdr, &hdr); |
2231 | encode_create(xdr, args, &hdr); | 2231 | encode_create(xdr, args, &hdr); |
2232 | encode_getfh(xdr, &hdr); | 2232 | encode_getfh(xdr, &hdr); |
2233 | encode_getfattr(xdr, args->bitmask, &hdr); | 2233 | encode_getfattr(xdr, args->bitmask, &hdr); |
2234 | encode_restorefh(xdr, &hdr); | 2234 | encode_restorefh(xdr, &hdr); |
2235 | encode_getfattr(xdr, args->bitmask, &hdr); | 2235 | encode_getfattr(xdr, args->bitmask, &hdr); |
2236 | encode_nops(&hdr); | 2236 | encode_nops(&hdr); |
2237 | } | 2237 | } |
2238 | 2238 | ||
2239 | /* | 2239 | /* |
2240 | * Encode SYMLINK request | 2240 | * Encode SYMLINK request |
2241 | */ | 2241 | */ |
2242 | static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr, | 2242 | static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr, |
2243 | const struct nfs4_create_arg *args) | 2243 | const struct nfs4_create_arg *args) |
2244 | { | 2244 | { |
2245 | nfs4_xdr_enc_create(req, xdr, args); | 2245 | nfs4_xdr_enc_create(req, xdr, args); |
2246 | } | 2246 | } |
2247 | 2247 | ||
2248 | /* | 2248 | /* |
2249 | * Encode GETATTR request | 2249 | * Encode GETATTR request |
2250 | */ | 2250 | */ |
2251 | static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr, | 2251 | static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr, |
2252 | const struct nfs4_getattr_arg *args) | 2252 | const struct nfs4_getattr_arg *args) |
2253 | { | 2253 | { |
2254 | struct compound_hdr hdr = { | 2254 | struct compound_hdr hdr = { |
2255 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2255 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2256 | }; | 2256 | }; |
2257 | 2257 | ||
2258 | encode_compound_hdr(xdr, req, &hdr); | 2258 | encode_compound_hdr(xdr, req, &hdr); |
2259 | encode_sequence(xdr, &args->seq_args, &hdr); | 2259 | encode_sequence(xdr, &args->seq_args, &hdr); |
2260 | encode_putfh(xdr, args->fh, &hdr); | 2260 | encode_putfh(xdr, args->fh, &hdr); |
2261 | encode_getfattr(xdr, args->bitmask, &hdr); | 2261 | encode_getfattr(xdr, args->bitmask, &hdr); |
2262 | encode_nops(&hdr); | 2262 | encode_nops(&hdr); |
2263 | } | 2263 | } |
2264 | 2264 | ||
2265 | /* | 2265 | /* |
2266 | * Encode a CLOSE request | 2266 | * Encode a CLOSE request |
2267 | */ | 2267 | */ |
2268 | static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, | 2268 | static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, |
2269 | struct nfs_closeargs *args) | 2269 | struct nfs_closeargs *args) |
2270 | { | 2270 | { |
2271 | struct compound_hdr hdr = { | 2271 | struct compound_hdr hdr = { |
2272 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2272 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2273 | }; | 2273 | }; |
2274 | 2274 | ||
2275 | encode_compound_hdr(xdr, req, &hdr); | 2275 | encode_compound_hdr(xdr, req, &hdr); |
2276 | encode_sequence(xdr, &args->seq_args, &hdr); | 2276 | encode_sequence(xdr, &args->seq_args, &hdr); |
2277 | encode_putfh(xdr, args->fh, &hdr); | 2277 | encode_putfh(xdr, args->fh, &hdr); |
2278 | encode_close(xdr, args, &hdr); | 2278 | encode_close(xdr, args, &hdr); |
2279 | encode_getfattr(xdr, args->bitmask, &hdr); | 2279 | encode_getfattr(xdr, args->bitmask, &hdr); |
2280 | encode_nops(&hdr); | 2280 | encode_nops(&hdr); |
2281 | } | 2281 | } |
2282 | 2282 | ||
2283 | /* | 2283 | /* |
2284 | * Encode an OPEN request | 2284 | * Encode an OPEN request |
2285 | */ | 2285 | */ |
2286 | static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, | 2286 | static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, |
2287 | struct nfs_openargs *args) | 2287 | struct nfs_openargs *args) |
2288 | { | 2288 | { |
2289 | struct compound_hdr hdr = { | 2289 | struct compound_hdr hdr = { |
2290 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2290 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2291 | }; | 2291 | }; |
2292 | 2292 | ||
2293 | encode_compound_hdr(xdr, req, &hdr); | 2293 | encode_compound_hdr(xdr, req, &hdr); |
2294 | encode_sequence(xdr, &args->seq_args, &hdr); | 2294 | encode_sequence(xdr, &args->seq_args, &hdr); |
2295 | encode_putfh(xdr, args->fh, &hdr); | 2295 | encode_putfh(xdr, args->fh, &hdr); |
2296 | encode_savefh(xdr, &hdr); | 2296 | encode_savefh(xdr, &hdr); |
2297 | encode_open(xdr, args, &hdr); | 2297 | encode_open(xdr, args, &hdr); |
2298 | encode_getfh(xdr, &hdr); | 2298 | encode_getfh(xdr, &hdr); |
2299 | encode_getfattr(xdr, args->bitmask, &hdr); | 2299 | encode_getfattr(xdr, args->bitmask, &hdr); |
2300 | encode_restorefh(xdr, &hdr); | 2300 | encode_restorefh(xdr, &hdr); |
2301 | encode_getfattr(xdr, args->dir_bitmask, &hdr); | 2301 | encode_getfattr(xdr, args->dir_bitmask, &hdr); |
2302 | encode_nops(&hdr); | 2302 | encode_nops(&hdr); |
2303 | } | 2303 | } |
2304 | 2304 | ||
2305 | /* | 2305 | /* |
2306 | * Encode an OPEN_CONFIRM request | 2306 | * Encode an OPEN_CONFIRM request |
2307 | */ | 2307 | */ |
2308 | static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, | 2308 | static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, |
2309 | struct xdr_stream *xdr, | 2309 | struct xdr_stream *xdr, |
2310 | struct nfs_open_confirmargs *args) | 2310 | struct nfs_open_confirmargs *args) |
2311 | { | 2311 | { |
2312 | struct compound_hdr hdr = { | 2312 | struct compound_hdr hdr = { |
2313 | .nops = 0, | 2313 | .nops = 0, |
2314 | }; | 2314 | }; |
2315 | 2315 | ||
2316 | encode_compound_hdr(xdr, req, &hdr); | 2316 | encode_compound_hdr(xdr, req, &hdr); |
2317 | encode_putfh(xdr, args->fh, &hdr); | 2317 | encode_putfh(xdr, args->fh, &hdr); |
2318 | encode_open_confirm(xdr, args, &hdr); | 2318 | encode_open_confirm(xdr, args, &hdr); |
2319 | encode_nops(&hdr); | 2319 | encode_nops(&hdr); |
2320 | } | 2320 | } |
2321 | 2321 | ||
2322 | /* | 2322 | /* |
2323 | * Encode an OPEN request with no attributes. | 2323 | * Encode an OPEN request with no attributes. |
2324 | */ | 2324 | */ |
2325 | static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, | 2325 | static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, |
2326 | struct xdr_stream *xdr, | 2326 | struct xdr_stream *xdr, |
2327 | struct nfs_openargs *args) | 2327 | struct nfs_openargs *args) |
2328 | { | 2328 | { |
2329 | struct compound_hdr hdr = { | 2329 | struct compound_hdr hdr = { |
2330 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2330 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2331 | }; | 2331 | }; |
2332 | 2332 | ||
2333 | encode_compound_hdr(xdr, req, &hdr); | 2333 | encode_compound_hdr(xdr, req, &hdr); |
2334 | encode_sequence(xdr, &args->seq_args, &hdr); | 2334 | encode_sequence(xdr, &args->seq_args, &hdr); |
2335 | encode_putfh(xdr, args->fh, &hdr); | 2335 | encode_putfh(xdr, args->fh, &hdr); |
2336 | encode_open(xdr, args, &hdr); | 2336 | encode_open(xdr, args, &hdr); |
2337 | encode_getfattr(xdr, args->bitmask, &hdr); | 2337 | encode_getfattr(xdr, args->bitmask, &hdr); |
2338 | encode_nops(&hdr); | 2338 | encode_nops(&hdr); |
2339 | } | 2339 | } |
2340 | 2340 | ||
2341 | /* | 2341 | /* |
2342 | * Encode an OPEN_DOWNGRADE request | 2342 | * Encode an OPEN_DOWNGRADE request |
2343 | */ | 2343 | */ |
2344 | static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, | 2344 | static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, |
2345 | struct xdr_stream *xdr, | 2345 | struct xdr_stream *xdr, |
2346 | struct nfs_closeargs *args) | 2346 | struct nfs_closeargs *args) |
2347 | { | 2347 | { |
2348 | struct compound_hdr hdr = { | 2348 | struct compound_hdr hdr = { |
2349 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2349 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2350 | }; | 2350 | }; |
2351 | 2351 | ||
2352 | encode_compound_hdr(xdr, req, &hdr); | 2352 | encode_compound_hdr(xdr, req, &hdr); |
2353 | encode_sequence(xdr, &args->seq_args, &hdr); | 2353 | encode_sequence(xdr, &args->seq_args, &hdr); |
2354 | encode_putfh(xdr, args->fh, &hdr); | 2354 | encode_putfh(xdr, args->fh, &hdr); |
2355 | encode_open_downgrade(xdr, args, &hdr); | 2355 | encode_open_downgrade(xdr, args, &hdr); |
2356 | encode_getfattr(xdr, args->bitmask, &hdr); | 2356 | encode_getfattr(xdr, args->bitmask, &hdr); |
2357 | encode_nops(&hdr); | 2357 | encode_nops(&hdr); |
2358 | } | 2358 | } |
2359 | 2359 | ||
2360 | /* | 2360 | /* |
2361 | * Encode a LOCK request | 2361 | * Encode a LOCK request |
2362 | */ | 2362 | */ |
2363 | static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr, | 2363 | static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr, |
2364 | struct nfs_lock_args *args) | 2364 | struct nfs_lock_args *args) |
2365 | { | 2365 | { |
2366 | struct compound_hdr hdr = { | 2366 | struct compound_hdr hdr = { |
2367 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2367 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2368 | }; | 2368 | }; |
2369 | 2369 | ||
2370 | encode_compound_hdr(xdr, req, &hdr); | 2370 | encode_compound_hdr(xdr, req, &hdr); |
2371 | encode_sequence(xdr, &args->seq_args, &hdr); | 2371 | encode_sequence(xdr, &args->seq_args, &hdr); |
2372 | encode_putfh(xdr, args->fh, &hdr); | 2372 | encode_putfh(xdr, args->fh, &hdr); |
2373 | encode_lock(xdr, args, &hdr); | 2373 | encode_lock(xdr, args, &hdr); |
2374 | encode_nops(&hdr); | 2374 | encode_nops(&hdr); |
2375 | } | 2375 | } |
2376 | 2376 | ||
2377 | /* | 2377 | /* |
2378 | * Encode a LOCKT request | 2378 | * Encode a LOCKT request |
2379 | */ | 2379 | */ |
2380 | static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr, | 2380 | static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr, |
2381 | struct nfs_lockt_args *args) | 2381 | struct nfs_lockt_args *args) |
2382 | { | 2382 | { |
2383 | struct compound_hdr hdr = { | 2383 | struct compound_hdr hdr = { |
2384 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2384 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2385 | }; | 2385 | }; |
2386 | 2386 | ||
2387 | encode_compound_hdr(xdr, req, &hdr); | 2387 | encode_compound_hdr(xdr, req, &hdr); |
2388 | encode_sequence(xdr, &args->seq_args, &hdr); | 2388 | encode_sequence(xdr, &args->seq_args, &hdr); |
2389 | encode_putfh(xdr, args->fh, &hdr); | 2389 | encode_putfh(xdr, args->fh, &hdr); |
2390 | encode_lockt(xdr, args, &hdr); | 2390 | encode_lockt(xdr, args, &hdr); |
2391 | encode_nops(&hdr); | 2391 | encode_nops(&hdr); |
2392 | } | 2392 | } |
2393 | 2393 | ||
2394 | /* | 2394 | /* |
2395 | * Encode a LOCKU request | 2395 | * Encode a LOCKU request |
2396 | */ | 2396 | */ |
2397 | static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, | 2397 | static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, |
2398 | struct nfs_locku_args *args) | 2398 | struct nfs_locku_args *args) |
2399 | { | 2399 | { |
2400 | struct compound_hdr hdr = { | 2400 | struct compound_hdr hdr = { |
2401 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2401 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2402 | }; | 2402 | }; |
2403 | 2403 | ||
2404 | encode_compound_hdr(xdr, req, &hdr); | 2404 | encode_compound_hdr(xdr, req, &hdr); |
2405 | encode_sequence(xdr, &args->seq_args, &hdr); | 2405 | encode_sequence(xdr, &args->seq_args, &hdr); |
2406 | encode_putfh(xdr, args->fh, &hdr); | 2406 | encode_putfh(xdr, args->fh, &hdr); |
2407 | encode_locku(xdr, args, &hdr); | 2407 | encode_locku(xdr, args, &hdr); |
2408 | encode_nops(&hdr); | 2408 | encode_nops(&hdr); |
2409 | } | 2409 | } |
2410 | 2410 | ||
2411 | static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, | 2411 | static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, |
2412 | struct xdr_stream *xdr, | 2412 | struct xdr_stream *xdr, |
2413 | struct nfs_release_lockowner_args *args) | 2413 | struct nfs_release_lockowner_args *args) |
2414 | { | 2414 | { |
2415 | struct compound_hdr hdr = { | 2415 | struct compound_hdr hdr = { |
2416 | .minorversion = 0, | 2416 | .minorversion = 0, |
2417 | }; | 2417 | }; |
2418 | 2418 | ||
2419 | encode_compound_hdr(xdr, req, &hdr); | 2419 | encode_compound_hdr(xdr, req, &hdr); |
2420 | encode_release_lockowner(xdr, &args->lock_owner, &hdr); | 2420 | encode_release_lockowner(xdr, &args->lock_owner, &hdr); |
2421 | encode_nops(&hdr); | 2421 | encode_nops(&hdr); |
2422 | } | 2422 | } |
2423 | 2423 | ||
2424 | /* | 2424 | /* |
2425 | * Encode a READLINK request | 2425 | * Encode a READLINK request |
2426 | */ | 2426 | */ |
2427 | static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, | 2427 | static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr, |
2428 | const struct nfs4_readlink *args) | 2428 | const struct nfs4_readlink *args) |
2429 | { | 2429 | { |
2430 | struct compound_hdr hdr = { | 2430 | struct compound_hdr hdr = { |
2431 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2431 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2432 | }; | 2432 | }; |
2433 | 2433 | ||
2434 | encode_compound_hdr(xdr, req, &hdr); | 2434 | encode_compound_hdr(xdr, req, &hdr); |
2435 | encode_sequence(xdr, &args->seq_args, &hdr); | 2435 | encode_sequence(xdr, &args->seq_args, &hdr); |
2436 | encode_putfh(xdr, args->fh, &hdr); | 2436 | encode_putfh(xdr, args->fh, &hdr); |
2437 | encode_readlink(xdr, args, req, &hdr); | 2437 | encode_readlink(xdr, args, req, &hdr); |
2438 | 2438 | ||
2439 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, | 2439 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, |
2440 | args->pgbase, args->pglen); | 2440 | args->pgbase, args->pglen); |
2441 | encode_nops(&hdr); | 2441 | encode_nops(&hdr); |
2442 | } | 2442 | } |
2443 | 2443 | ||
2444 | /* | 2444 | /* |
2445 | * Encode a READDIR request | 2445 | * Encode a READDIR request |
2446 | */ | 2446 | */ |
2447 | static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, | 2447 | static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr, |
2448 | const struct nfs4_readdir_arg *args) | 2448 | const struct nfs4_readdir_arg *args) |
2449 | { | 2449 | { |
2450 | struct compound_hdr hdr = { | 2450 | struct compound_hdr hdr = { |
2451 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2451 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2452 | }; | 2452 | }; |
2453 | 2453 | ||
2454 | encode_compound_hdr(xdr, req, &hdr); | 2454 | encode_compound_hdr(xdr, req, &hdr); |
2455 | encode_sequence(xdr, &args->seq_args, &hdr); | 2455 | encode_sequence(xdr, &args->seq_args, &hdr); |
2456 | encode_putfh(xdr, args->fh, &hdr); | 2456 | encode_putfh(xdr, args->fh, &hdr); |
2457 | encode_readdir(xdr, args, req, &hdr); | 2457 | encode_readdir(xdr, args, req, &hdr); |
2458 | 2458 | ||
2459 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, | 2459 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages, |
2460 | args->pgbase, args->count); | 2460 | args->pgbase, args->count); |
2461 | dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", | 2461 | dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", |
2462 | __func__, hdr.replen << 2, args->pages, | 2462 | __func__, hdr.replen << 2, args->pages, |
2463 | args->pgbase, args->count); | 2463 | args->pgbase, args->count); |
2464 | encode_nops(&hdr); | 2464 | encode_nops(&hdr); |
2465 | } | 2465 | } |
2466 | 2466 | ||
2467 | /* | 2467 | /* |
2468 | * Encode a READ request | 2468 | * Encode a READ request |
2469 | */ | 2469 | */ |
2470 | static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, | 2470 | static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr, |
2471 | struct nfs_readargs *args) | 2471 | struct nfs_readargs *args) |
2472 | { | 2472 | { |
2473 | struct compound_hdr hdr = { | 2473 | struct compound_hdr hdr = { |
2474 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2474 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2475 | }; | 2475 | }; |
2476 | 2476 | ||
2477 | encode_compound_hdr(xdr, req, &hdr); | 2477 | encode_compound_hdr(xdr, req, &hdr); |
2478 | encode_sequence(xdr, &args->seq_args, &hdr); | 2478 | encode_sequence(xdr, &args->seq_args, &hdr); |
2479 | encode_putfh(xdr, args->fh, &hdr); | 2479 | encode_putfh(xdr, args->fh, &hdr); |
2480 | encode_read(xdr, args, &hdr); | 2480 | encode_read(xdr, args, &hdr); |
2481 | 2481 | ||
2482 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, | 2482 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, |
2483 | args->pages, args->pgbase, args->count); | 2483 | args->pages, args->pgbase, args->count); |
2484 | req->rq_rcv_buf.flags |= XDRBUF_READ; | 2484 | req->rq_rcv_buf.flags |= XDRBUF_READ; |
2485 | encode_nops(&hdr); | 2485 | encode_nops(&hdr); |
2486 | } | 2486 | } |
2487 | 2487 | ||
2488 | /* | 2488 | /* |
2489 | * Encode an SETATTR request | 2489 | * Encode an SETATTR request |
2490 | */ | 2490 | */ |
2491 | static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr, | 2491 | static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr, |
2492 | struct nfs_setattrargs *args) | 2492 | struct nfs_setattrargs *args) |
2493 | { | 2493 | { |
2494 | struct compound_hdr hdr = { | 2494 | struct compound_hdr hdr = { |
2495 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2495 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2496 | }; | 2496 | }; |
2497 | 2497 | ||
2498 | encode_compound_hdr(xdr, req, &hdr); | 2498 | encode_compound_hdr(xdr, req, &hdr); |
2499 | encode_sequence(xdr, &args->seq_args, &hdr); | 2499 | encode_sequence(xdr, &args->seq_args, &hdr); |
2500 | encode_putfh(xdr, args->fh, &hdr); | 2500 | encode_putfh(xdr, args->fh, &hdr); |
2501 | encode_setattr(xdr, args, args->server, &hdr); | 2501 | encode_setattr(xdr, args, args->server, &hdr); |
2502 | encode_getfattr(xdr, args->bitmask, &hdr); | 2502 | encode_getfattr(xdr, args->bitmask, &hdr); |
2503 | encode_nops(&hdr); | 2503 | encode_nops(&hdr); |
2504 | } | 2504 | } |
2505 | 2505 | ||
2506 | /* | 2506 | /* |
2507 | * Encode a GETACL request | 2507 | * Encode a GETACL request |
2508 | */ | 2508 | */ |
2509 | static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, | 2509 | static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, |
2510 | struct nfs_getaclargs *args) | 2510 | struct nfs_getaclargs *args) |
2511 | { | 2511 | { |
2512 | struct compound_hdr hdr = { | 2512 | struct compound_hdr hdr = { |
2513 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2513 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2514 | }; | 2514 | }; |
2515 | uint32_t replen; | 2515 | uint32_t replen; |
2516 | 2516 | ||
2517 | encode_compound_hdr(xdr, req, &hdr); | 2517 | encode_compound_hdr(xdr, req, &hdr); |
2518 | encode_sequence(xdr, &args->seq_args, &hdr); | 2518 | encode_sequence(xdr, &args->seq_args, &hdr); |
2519 | encode_putfh(xdr, args->fh, &hdr); | 2519 | encode_putfh(xdr, args->fh, &hdr); |
2520 | replen = hdr.replen + op_decode_hdr_maxsz + 1; | 2520 | replen = hdr.replen + op_decode_hdr_maxsz + 1; |
2521 | encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); | 2521 | encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); |
2522 | 2522 | ||
2523 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, | 2523 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, |
2524 | args->acl_pages, args->acl_pgbase, args->acl_len); | 2524 | args->acl_pages, args->acl_pgbase, args->acl_len); |
2525 | xdr_set_scratch_buffer(xdr, page_address(args->acl_scratch), PAGE_SIZE); | 2525 | xdr_set_scratch_buffer(xdr, page_address(args->acl_scratch), PAGE_SIZE); |
2526 | 2526 | ||
2527 | encode_nops(&hdr); | 2527 | encode_nops(&hdr); |
2528 | } | 2528 | } |
2529 | 2529 | ||
2530 | /* | 2530 | /* |
2531 | * Encode a WRITE request | 2531 | * Encode a WRITE request |
2532 | */ | 2532 | */ |
2533 | static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, | 2533 | static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr, |
2534 | struct nfs_writeargs *args) | 2534 | struct nfs_writeargs *args) |
2535 | { | 2535 | { |
2536 | struct compound_hdr hdr = { | 2536 | struct compound_hdr hdr = { |
2537 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2537 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2538 | }; | 2538 | }; |
2539 | 2539 | ||
2540 | encode_compound_hdr(xdr, req, &hdr); | 2540 | encode_compound_hdr(xdr, req, &hdr); |
2541 | encode_sequence(xdr, &args->seq_args, &hdr); | 2541 | encode_sequence(xdr, &args->seq_args, &hdr); |
2542 | encode_putfh(xdr, args->fh, &hdr); | 2542 | encode_putfh(xdr, args->fh, &hdr); |
2543 | encode_write(xdr, args, &hdr); | 2543 | encode_write(xdr, args, &hdr); |
2544 | req->rq_snd_buf.flags |= XDRBUF_WRITE; | 2544 | req->rq_snd_buf.flags |= XDRBUF_WRITE; |
2545 | if (args->bitmask) | 2545 | if (args->bitmask) |
2546 | encode_getfattr(xdr, args->bitmask, &hdr); | 2546 | encode_getfattr(xdr, args->bitmask, &hdr); |
2547 | encode_nops(&hdr); | 2547 | encode_nops(&hdr); |
2548 | } | 2548 | } |
2549 | 2549 | ||
2550 | /* | 2550 | /* |
2551 | * a COMMIT request | 2551 | * a COMMIT request |
2552 | */ | 2552 | */ |
2553 | static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, | 2553 | static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, |
2554 | struct nfs_writeargs *args) | 2554 | struct nfs_writeargs *args) |
2555 | { | 2555 | { |
2556 | struct compound_hdr hdr = { | 2556 | struct compound_hdr hdr = { |
2557 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2557 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2558 | }; | 2558 | }; |
2559 | 2559 | ||
2560 | encode_compound_hdr(xdr, req, &hdr); | 2560 | encode_compound_hdr(xdr, req, &hdr); |
2561 | encode_sequence(xdr, &args->seq_args, &hdr); | 2561 | encode_sequence(xdr, &args->seq_args, &hdr); |
2562 | encode_putfh(xdr, args->fh, &hdr); | 2562 | encode_putfh(xdr, args->fh, &hdr); |
2563 | encode_commit(xdr, args, &hdr); | 2563 | encode_commit(xdr, args, &hdr); |
2564 | if (args->bitmask) | 2564 | if (args->bitmask) |
2565 | encode_getfattr(xdr, args->bitmask, &hdr); | 2565 | encode_getfattr(xdr, args->bitmask, &hdr); |
2566 | encode_nops(&hdr); | 2566 | encode_nops(&hdr); |
2567 | } | 2567 | } |
2568 | 2568 | ||
2569 | /* | 2569 | /* |
2570 | * FSINFO request | 2570 | * FSINFO request |
2571 | */ | 2571 | */ |
2572 | static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, | 2572 | static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, |
2573 | struct nfs4_fsinfo_arg *args) | 2573 | struct nfs4_fsinfo_arg *args) |
2574 | { | 2574 | { |
2575 | struct compound_hdr hdr = { | 2575 | struct compound_hdr hdr = { |
2576 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2576 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2577 | }; | 2577 | }; |
2578 | 2578 | ||
2579 | encode_compound_hdr(xdr, req, &hdr); | 2579 | encode_compound_hdr(xdr, req, &hdr); |
2580 | encode_sequence(xdr, &args->seq_args, &hdr); | 2580 | encode_sequence(xdr, &args->seq_args, &hdr); |
2581 | encode_putfh(xdr, args->fh, &hdr); | 2581 | encode_putfh(xdr, args->fh, &hdr); |
2582 | encode_fsinfo(xdr, args->bitmask, &hdr); | 2582 | encode_fsinfo(xdr, args->bitmask, &hdr); |
2583 | encode_nops(&hdr); | 2583 | encode_nops(&hdr); |
2584 | } | 2584 | } |
2585 | 2585 | ||
2586 | /* | 2586 | /* |
2587 | * a PATHCONF request | 2587 | * a PATHCONF request |
2588 | */ | 2588 | */ |
2589 | static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, | 2589 | static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, |
2590 | const struct nfs4_pathconf_arg *args) | 2590 | const struct nfs4_pathconf_arg *args) |
2591 | { | 2591 | { |
2592 | struct compound_hdr hdr = { | 2592 | struct compound_hdr hdr = { |
2593 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2593 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2594 | }; | 2594 | }; |
2595 | 2595 | ||
2596 | encode_compound_hdr(xdr, req, &hdr); | 2596 | encode_compound_hdr(xdr, req, &hdr); |
2597 | encode_sequence(xdr, &args->seq_args, &hdr); | 2597 | encode_sequence(xdr, &args->seq_args, &hdr); |
2598 | encode_putfh(xdr, args->fh, &hdr); | 2598 | encode_putfh(xdr, args->fh, &hdr); |
2599 | encode_getattr_one(xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0], | 2599 | encode_getattr_one(xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0], |
2600 | &hdr); | 2600 | &hdr); |
2601 | encode_nops(&hdr); | 2601 | encode_nops(&hdr); |
2602 | } | 2602 | } |
2603 | 2603 | ||
2604 | /* | 2604 | /* |
2605 | * a STATFS request | 2605 | * a STATFS request |
2606 | */ | 2606 | */ |
2607 | static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, | 2607 | static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, |
2608 | const struct nfs4_statfs_arg *args) | 2608 | const struct nfs4_statfs_arg *args) |
2609 | { | 2609 | { |
2610 | struct compound_hdr hdr = { | 2610 | struct compound_hdr hdr = { |
2611 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2611 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2612 | }; | 2612 | }; |
2613 | 2613 | ||
2614 | encode_compound_hdr(xdr, req, &hdr); | 2614 | encode_compound_hdr(xdr, req, &hdr); |
2615 | encode_sequence(xdr, &args->seq_args, &hdr); | 2615 | encode_sequence(xdr, &args->seq_args, &hdr); |
2616 | encode_putfh(xdr, args->fh, &hdr); | 2616 | encode_putfh(xdr, args->fh, &hdr); |
2617 | encode_getattr_two(xdr, args->bitmask[0] & nfs4_statfs_bitmap[0], | 2617 | encode_getattr_two(xdr, args->bitmask[0] & nfs4_statfs_bitmap[0], |
2618 | args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr); | 2618 | args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr); |
2619 | encode_nops(&hdr); | 2619 | encode_nops(&hdr); |
2620 | } | 2620 | } |
2621 | 2621 | ||
2622 | /* | 2622 | /* |
2623 | * GETATTR_BITMAP request | 2623 | * GETATTR_BITMAP request |
2624 | */ | 2624 | */ |
2625 | static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, | 2625 | static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, |
2626 | struct xdr_stream *xdr, | 2626 | struct xdr_stream *xdr, |
2627 | struct nfs4_server_caps_arg *args) | 2627 | struct nfs4_server_caps_arg *args) |
2628 | { | 2628 | { |
2629 | struct compound_hdr hdr = { | 2629 | struct compound_hdr hdr = { |
2630 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2630 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2631 | }; | 2631 | }; |
2632 | 2632 | ||
2633 | encode_compound_hdr(xdr, req, &hdr); | 2633 | encode_compound_hdr(xdr, req, &hdr); |
2634 | encode_sequence(xdr, &args->seq_args, &hdr); | 2634 | encode_sequence(xdr, &args->seq_args, &hdr); |
2635 | encode_putfh(xdr, args->fhandle, &hdr); | 2635 | encode_putfh(xdr, args->fhandle, &hdr); |
2636 | encode_getattr_one(xdr, FATTR4_WORD0_SUPPORTED_ATTRS| | 2636 | encode_getattr_one(xdr, FATTR4_WORD0_SUPPORTED_ATTRS| |
2637 | FATTR4_WORD0_LINK_SUPPORT| | 2637 | FATTR4_WORD0_LINK_SUPPORT| |
2638 | FATTR4_WORD0_SYMLINK_SUPPORT| | 2638 | FATTR4_WORD0_SYMLINK_SUPPORT| |
2639 | FATTR4_WORD0_ACLSUPPORT, &hdr); | 2639 | FATTR4_WORD0_ACLSUPPORT, &hdr); |
2640 | encode_nops(&hdr); | 2640 | encode_nops(&hdr); |
2641 | } | 2641 | } |
2642 | 2642 | ||
2643 | /* | 2643 | /* |
2644 | * a RENEW request | 2644 | * a RENEW request |
2645 | */ | 2645 | */ |
2646 | static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, | 2646 | static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, |
2647 | struct nfs_client *clp) | 2647 | struct nfs_client *clp) |
2648 | { | 2648 | { |
2649 | struct compound_hdr hdr = { | 2649 | struct compound_hdr hdr = { |
2650 | .nops = 0, | 2650 | .nops = 0, |
2651 | }; | 2651 | }; |
2652 | 2652 | ||
2653 | encode_compound_hdr(xdr, req, &hdr); | 2653 | encode_compound_hdr(xdr, req, &hdr); |
2654 | encode_renew(xdr, clp, &hdr); | 2654 | encode_renew(xdr, clp, &hdr); |
2655 | encode_nops(&hdr); | 2655 | encode_nops(&hdr); |
2656 | } | 2656 | } |
2657 | 2657 | ||
2658 | /* | 2658 | /* |
2659 | * a SETCLIENTID request | 2659 | * a SETCLIENTID request |
2660 | */ | 2660 | */ |
2661 | static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req, | 2661 | static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req, |
2662 | struct xdr_stream *xdr, | 2662 | struct xdr_stream *xdr, |
2663 | struct nfs4_setclientid *sc) | 2663 | struct nfs4_setclientid *sc) |
2664 | { | 2664 | { |
2665 | struct compound_hdr hdr = { | 2665 | struct compound_hdr hdr = { |
2666 | .nops = 0, | 2666 | .nops = 0, |
2667 | }; | 2667 | }; |
2668 | 2668 | ||
2669 | encode_compound_hdr(xdr, req, &hdr); | 2669 | encode_compound_hdr(xdr, req, &hdr); |
2670 | encode_setclientid(xdr, sc, &hdr); | 2670 | encode_setclientid(xdr, sc, &hdr); |
2671 | encode_nops(&hdr); | 2671 | encode_nops(&hdr); |
2672 | } | 2672 | } |
2673 | 2673 | ||
2674 | /* | 2674 | /* |
2675 | * a SETCLIENTID_CONFIRM request | 2675 | * a SETCLIENTID_CONFIRM request |
2676 | */ | 2676 | */ |
2677 | static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, | 2677 | static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, |
2678 | struct xdr_stream *xdr, | 2678 | struct xdr_stream *xdr, |
2679 | struct nfs4_setclientid_res *arg) | 2679 | struct nfs4_setclientid_res *arg) |
2680 | { | 2680 | { |
2681 | struct compound_hdr hdr = { | 2681 | struct compound_hdr hdr = { |
2682 | .nops = 0, | 2682 | .nops = 0, |
2683 | }; | 2683 | }; |
2684 | const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; | 2684 | const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; |
2685 | 2685 | ||
2686 | encode_compound_hdr(xdr, req, &hdr); | 2686 | encode_compound_hdr(xdr, req, &hdr); |
2687 | encode_setclientid_confirm(xdr, arg, &hdr); | 2687 | encode_setclientid_confirm(xdr, arg, &hdr); |
2688 | encode_putrootfh(xdr, &hdr); | 2688 | encode_putrootfh(xdr, &hdr); |
2689 | encode_fsinfo(xdr, lease_bitmap, &hdr); | 2689 | encode_fsinfo(xdr, lease_bitmap, &hdr); |
2690 | encode_nops(&hdr); | 2690 | encode_nops(&hdr); |
2691 | } | 2691 | } |
2692 | 2692 | ||
2693 | /* | 2693 | /* |
2694 | * DELEGRETURN request | 2694 | * DELEGRETURN request |
2695 | */ | 2695 | */ |
2696 | static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, | 2696 | static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, |
2697 | struct xdr_stream *xdr, | 2697 | struct xdr_stream *xdr, |
2698 | const struct nfs4_delegreturnargs *args) | 2698 | const struct nfs4_delegreturnargs *args) |
2699 | { | 2699 | { |
2700 | struct compound_hdr hdr = { | 2700 | struct compound_hdr hdr = { |
2701 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2701 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2702 | }; | 2702 | }; |
2703 | 2703 | ||
2704 | encode_compound_hdr(xdr, req, &hdr); | 2704 | encode_compound_hdr(xdr, req, &hdr); |
2705 | encode_sequence(xdr, &args->seq_args, &hdr); | 2705 | encode_sequence(xdr, &args->seq_args, &hdr); |
2706 | encode_putfh(xdr, args->fhandle, &hdr); | 2706 | encode_putfh(xdr, args->fhandle, &hdr); |
2707 | encode_delegreturn(xdr, args->stateid, &hdr); | 2707 | encode_delegreturn(xdr, args->stateid, &hdr); |
2708 | encode_getfattr(xdr, args->bitmask, &hdr); | 2708 | encode_getfattr(xdr, args->bitmask, &hdr); |
2709 | encode_nops(&hdr); | 2709 | encode_nops(&hdr); |
2710 | } | 2710 | } |
2711 | 2711 | ||
2712 | /* | 2712 | /* |
2713 | * Encode FS_LOCATIONS request | 2713 | * Encode FS_LOCATIONS request |
2714 | */ | 2714 | */ |
2715 | static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, | 2715 | static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, |
2716 | struct xdr_stream *xdr, | 2716 | struct xdr_stream *xdr, |
2717 | struct nfs4_fs_locations_arg *args) | 2717 | struct nfs4_fs_locations_arg *args) |
2718 | { | 2718 | { |
2719 | struct compound_hdr hdr = { | 2719 | struct compound_hdr hdr = { |
2720 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2720 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2721 | }; | 2721 | }; |
2722 | uint32_t replen; | 2722 | uint32_t replen; |
2723 | 2723 | ||
2724 | encode_compound_hdr(xdr, req, &hdr); | 2724 | encode_compound_hdr(xdr, req, &hdr); |
2725 | encode_sequence(xdr, &args->seq_args, &hdr); | 2725 | encode_sequence(xdr, &args->seq_args, &hdr); |
2726 | encode_putfh(xdr, args->dir_fh, &hdr); | 2726 | encode_putfh(xdr, args->dir_fh, &hdr); |
2727 | encode_lookup(xdr, args->name, &hdr); | 2727 | encode_lookup(xdr, args->name, &hdr); |
2728 | replen = hdr.replen; /* get the attribute into args->page */ | 2728 | replen = hdr.replen; /* get the attribute into args->page */ |
2729 | encode_fs_locations(xdr, args->bitmask, &hdr); | 2729 | encode_fs_locations(xdr, args->bitmask, &hdr); |
2730 | 2730 | ||
2731 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page, | 2731 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page, |
2732 | 0, PAGE_SIZE); | 2732 | 0, PAGE_SIZE); |
2733 | encode_nops(&hdr); | 2733 | encode_nops(&hdr); |
2734 | } | 2734 | } |
2735 | 2735 | ||
2736 | /* | 2736 | /* |
2737 | * Encode SECINFO request | 2737 | * Encode SECINFO request |
2738 | */ | 2738 | */ |
2739 | static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, | 2739 | static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, |
2740 | struct xdr_stream *xdr, | 2740 | struct xdr_stream *xdr, |
2741 | struct nfs4_secinfo_arg *args) | 2741 | struct nfs4_secinfo_arg *args) |
2742 | { | 2742 | { |
2743 | struct compound_hdr hdr = { | 2743 | struct compound_hdr hdr = { |
2744 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2744 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2745 | }; | 2745 | }; |
2746 | 2746 | ||
2747 | encode_compound_hdr(xdr, req, &hdr); | 2747 | encode_compound_hdr(xdr, req, &hdr); |
2748 | encode_sequence(xdr, &args->seq_args, &hdr); | 2748 | encode_sequence(xdr, &args->seq_args, &hdr); |
2749 | encode_putfh(xdr, args->dir_fh, &hdr); | 2749 | encode_putfh(xdr, args->dir_fh, &hdr); |
2750 | encode_secinfo(xdr, args->name, &hdr); | 2750 | encode_secinfo(xdr, args->name, &hdr); |
2751 | encode_nops(&hdr); | 2751 | encode_nops(&hdr); |
2752 | } | 2752 | } |
2753 | 2753 | ||
2754 | #if defined(CONFIG_NFS_V4_1) | 2754 | #if defined(CONFIG_NFS_V4_1) |
2755 | /* | 2755 | /* |
2756 | * EXCHANGE_ID request | 2756 | * EXCHANGE_ID request |
2757 | */ | 2757 | */ |
2758 | static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, | 2758 | static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, |
2759 | struct xdr_stream *xdr, | 2759 | struct xdr_stream *xdr, |
2760 | struct nfs41_exchange_id_args *args) | 2760 | struct nfs41_exchange_id_args *args) |
2761 | { | 2761 | { |
2762 | struct compound_hdr hdr = { | 2762 | struct compound_hdr hdr = { |
2763 | .minorversion = args->client->cl_mvops->minor_version, | 2763 | .minorversion = args->client->cl_mvops->minor_version, |
2764 | }; | 2764 | }; |
2765 | 2765 | ||
2766 | encode_compound_hdr(xdr, req, &hdr); | 2766 | encode_compound_hdr(xdr, req, &hdr); |
2767 | encode_exchange_id(xdr, args, &hdr); | 2767 | encode_exchange_id(xdr, args, &hdr); |
2768 | encode_nops(&hdr); | 2768 | encode_nops(&hdr); |
2769 | } | 2769 | } |
2770 | 2770 | ||
2771 | /* | 2771 | /* |
2772 | * a CREATE_SESSION request | 2772 | * a CREATE_SESSION request |
2773 | */ | 2773 | */ |
2774 | static void nfs4_xdr_enc_create_session(struct rpc_rqst *req, | 2774 | static void nfs4_xdr_enc_create_session(struct rpc_rqst *req, |
2775 | struct xdr_stream *xdr, | 2775 | struct xdr_stream *xdr, |
2776 | struct nfs41_create_session_args *args) | 2776 | struct nfs41_create_session_args *args) |
2777 | { | 2777 | { |
2778 | struct compound_hdr hdr = { | 2778 | struct compound_hdr hdr = { |
2779 | .minorversion = args->client->cl_mvops->minor_version, | 2779 | .minorversion = args->client->cl_mvops->minor_version, |
2780 | }; | 2780 | }; |
2781 | 2781 | ||
2782 | encode_compound_hdr(xdr, req, &hdr); | 2782 | encode_compound_hdr(xdr, req, &hdr); |
2783 | encode_create_session(xdr, args, &hdr); | 2783 | encode_create_session(xdr, args, &hdr); |
2784 | encode_nops(&hdr); | 2784 | encode_nops(&hdr); |
2785 | } | 2785 | } |
2786 | 2786 | ||
2787 | /* | 2787 | /* |
2788 | * a DESTROY_SESSION request | 2788 | * a DESTROY_SESSION request |
2789 | */ | 2789 | */ |
2790 | static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, | 2790 | static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, |
2791 | struct xdr_stream *xdr, | 2791 | struct xdr_stream *xdr, |
2792 | struct nfs4_session *session) | 2792 | struct nfs4_session *session) |
2793 | { | 2793 | { |
2794 | struct compound_hdr hdr = { | 2794 | struct compound_hdr hdr = { |
2795 | .minorversion = session->clp->cl_mvops->minor_version, | 2795 | .minorversion = session->clp->cl_mvops->minor_version, |
2796 | }; | 2796 | }; |
2797 | 2797 | ||
2798 | encode_compound_hdr(xdr, req, &hdr); | 2798 | encode_compound_hdr(xdr, req, &hdr); |
2799 | encode_destroy_session(xdr, session, &hdr); | 2799 | encode_destroy_session(xdr, session, &hdr); |
2800 | encode_nops(&hdr); | 2800 | encode_nops(&hdr); |
2801 | } | 2801 | } |
2802 | 2802 | ||
2803 | /* | 2803 | /* |
2804 | * a SEQUENCE request | 2804 | * a SEQUENCE request |
2805 | */ | 2805 | */ |
2806 | static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, | 2806 | static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, |
2807 | struct nfs4_sequence_args *args) | 2807 | struct nfs4_sequence_args *args) |
2808 | { | 2808 | { |
2809 | struct compound_hdr hdr = { | 2809 | struct compound_hdr hdr = { |
2810 | .minorversion = nfs4_xdr_minorversion(args), | 2810 | .minorversion = nfs4_xdr_minorversion(args), |
2811 | }; | 2811 | }; |
2812 | 2812 | ||
2813 | encode_compound_hdr(xdr, req, &hdr); | 2813 | encode_compound_hdr(xdr, req, &hdr); |
2814 | encode_sequence(xdr, args, &hdr); | 2814 | encode_sequence(xdr, args, &hdr); |
2815 | encode_nops(&hdr); | 2815 | encode_nops(&hdr); |
2816 | } | 2816 | } |
2817 | 2817 | ||
2818 | /* | 2818 | /* |
2819 | * a GET_LEASE_TIME request | 2819 | * a GET_LEASE_TIME request |
2820 | */ | 2820 | */ |
2821 | static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, | 2821 | static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, |
2822 | struct xdr_stream *xdr, | 2822 | struct xdr_stream *xdr, |
2823 | struct nfs4_get_lease_time_args *args) | 2823 | struct nfs4_get_lease_time_args *args) |
2824 | { | 2824 | { |
2825 | struct compound_hdr hdr = { | 2825 | struct compound_hdr hdr = { |
2826 | .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), | 2826 | .minorversion = nfs4_xdr_minorversion(&args->la_seq_args), |
2827 | }; | 2827 | }; |
2828 | const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; | 2828 | const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME }; |
2829 | 2829 | ||
2830 | encode_compound_hdr(xdr, req, &hdr); | 2830 | encode_compound_hdr(xdr, req, &hdr); |
2831 | encode_sequence(xdr, &args->la_seq_args, &hdr); | 2831 | encode_sequence(xdr, &args->la_seq_args, &hdr); |
2832 | encode_putrootfh(xdr, &hdr); | 2832 | encode_putrootfh(xdr, &hdr); |
2833 | encode_fsinfo(xdr, lease_bitmap, &hdr); | 2833 | encode_fsinfo(xdr, lease_bitmap, &hdr); |
2834 | encode_nops(&hdr); | 2834 | encode_nops(&hdr); |
2835 | } | 2835 | } |
2836 | 2836 | ||
2837 | /* | 2837 | /* |
2838 | * a RECLAIM_COMPLETE request | 2838 | * a RECLAIM_COMPLETE request |
2839 | */ | 2839 | */ |
2840 | static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, | 2840 | static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, |
2841 | struct xdr_stream *xdr, | 2841 | struct xdr_stream *xdr, |
2842 | struct nfs41_reclaim_complete_args *args) | 2842 | struct nfs41_reclaim_complete_args *args) |
2843 | { | 2843 | { |
2844 | struct compound_hdr hdr = { | 2844 | struct compound_hdr hdr = { |
2845 | .minorversion = nfs4_xdr_minorversion(&args->seq_args) | 2845 | .minorversion = nfs4_xdr_minorversion(&args->seq_args) |
2846 | }; | 2846 | }; |
2847 | 2847 | ||
2848 | encode_compound_hdr(xdr, req, &hdr); | 2848 | encode_compound_hdr(xdr, req, &hdr); |
2849 | encode_sequence(xdr, &args->seq_args, &hdr); | 2849 | encode_sequence(xdr, &args->seq_args, &hdr); |
2850 | encode_reclaim_complete(xdr, args, &hdr); | 2850 | encode_reclaim_complete(xdr, args, &hdr); |
2851 | encode_nops(&hdr); | 2851 | encode_nops(&hdr); |
2852 | } | 2852 | } |
2853 | 2853 | ||
2854 | /* | 2854 | /* |
2855 | * Encode GETDEVICELIST request | 2855 | * Encode GETDEVICELIST request |
2856 | */ | 2856 | */ |
2857 | static void nfs4_xdr_enc_getdevicelist(struct rpc_rqst *req, | 2857 | static void nfs4_xdr_enc_getdevicelist(struct rpc_rqst *req, |
2858 | struct xdr_stream *xdr, | 2858 | struct xdr_stream *xdr, |
2859 | struct nfs4_getdevicelist_args *args) | 2859 | struct nfs4_getdevicelist_args *args) |
2860 | { | 2860 | { |
2861 | struct compound_hdr hdr = { | 2861 | struct compound_hdr hdr = { |
2862 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2862 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2863 | }; | 2863 | }; |
2864 | 2864 | ||
2865 | encode_compound_hdr(xdr, req, &hdr); | 2865 | encode_compound_hdr(xdr, req, &hdr); |
2866 | encode_sequence(xdr, &args->seq_args, &hdr); | 2866 | encode_sequence(xdr, &args->seq_args, &hdr); |
2867 | encode_putfh(xdr, args->fh, &hdr); | 2867 | encode_putfh(xdr, args->fh, &hdr); |
2868 | encode_getdevicelist(xdr, args, &hdr); | 2868 | encode_getdevicelist(xdr, args, &hdr); |
2869 | encode_nops(&hdr); | 2869 | encode_nops(&hdr); |
2870 | } | 2870 | } |
2871 | 2871 | ||
2872 | /* | 2872 | /* |
2873 | * Encode GETDEVICEINFO request | 2873 | * Encode GETDEVICEINFO request |
2874 | */ | 2874 | */ |
2875 | static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, | 2875 | static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, |
2876 | struct xdr_stream *xdr, | 2876 | struct xdr_stream *xdr, |
2877 | struct nfs4_getdeviceinfo_args *args) | 2877 | struct nfs4_getdeviceinfo_args *args) |
2878 | { | 2878 | { |
2879 | struct compound_hdr hdr = { | 2879 | struct compound_hdr hdr = { |
2880 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2880 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2881 | }; | 2881 | }; |
2882 | 2882 | ||
2883 | encode_compound_hdr(xdr, req, &hdr); | 2883 | encode_compound_hdr(xdr, req, &hdr); |
2884 | encode_sequence(xdr, &args->seq_args, &hdr); | 2884 | encode_sequence(xdr, &args->seq_args, &hdr); |
2885 | encode_getdeviceinfo(xdr, args, &hdr); | 2885 | encode_getdeviceinfo(xdr, args, &hdr); |
2886 | 2886 | ||
2887 | /* set up reply kvec. Subtract notification bitmap max size (2) | 2887 | /* set up reply kvec. Subtract notification bitmap max size (2) |
2888 | * so that notification bitmap is put in xdr_buf tail */ | 2888 | * so that notification bitmap is put in xdr_buf tail */ |
2889 | xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2, | 2889 | xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2, |
2890 | args->pdev->pages, args->pdev->pgbase, | 2890 | args->pdev->pages, args->pdev->pgbase, |
2891 | args->pdev->pglen); | 2891 | args->pdev->pglen); |
2892 | 2892 | ||
2893 | encode_nops(&hdr); | 2893 | encode_nops(&hdr); |
2894 | } | 2894 | } |
2895 | 2895 | ||
2896 | /* | 2896 | /* |
2897 | * Encode LAYOUTGET request | 2897 | * Encode LAYOUTGET request |
2898 | */ | 2898 | */ |
2899 | static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, | 2899 | static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, |
2900 | struct xdr_stream *xdr, | 2900 | struct xdr_stream *xdr, |
2901 | struct nfs4_layoutget_args *args) | 2901 | struct nfs4_layoutget_args *args) |
2902 | { | 2902 | { |
2903 | struct compound_hdr hdr = { | 2903 | struct compound_hdr hdr = { |
2904 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2904 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2905 | }; | 2905 | }; |
2906 | 2906 | ||
2907 | encode_compound_hdr(xdr, req, &hdr); | 2907 | encode_compound_hdr(xdr, req, &hdr); |
2908 | encode_sequence(xdr, &args->seq_args, &hdr); | 2908 | encode_sequence(xdr, &args->seq_args, &hdr); |
2909 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | 2909 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); |
2910 | encode_layoutget(xdr, args, &hdr); | 2910 | encode_layoutget(xdr, args, &hdr); |
2911 | 2911 | ||
2912 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, | 2912 | xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, |
2913 | args->layout.pages, 0, args->layout.pglen); | 2913 | args->layout.pages, 0, args->layout.pglen); |
2914 | 2914 | ||
2915 | encode_nops(&hdr); | 2915 | encode_nops(&hdr); |
2916 | } | 2916 | } |
2917 | 2917 | ||
2918 | /* | 2918 | /* |
2919 | * Encode LAYOUTCOMMIT request | 2919 | * Encode LAYOUTCOMMIT request |
2920 | */ | 2920 | */ |
2921 | static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, | 2921 | static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, |
2922 | struct xdr_stream *xdr, | 2922 | struct xdr_stream *xdr, |
2923 | struct nfs4_layoutcommit_args *args) | 2923 | struct nfs4_layoutcommit_args *args) |
2924 | { | 2924 | { |
2925 | struct nfs4_layoutcommit_data *data = | 2925 | struct nfs4_layoutcommit_data *data = |
2926 | container_of(args, struct nfs4_layoutcommit_data, args); | 2926 | container_of(args, struct nfs4_layoutcommit_data, args); |
2927 | struct compound_hdr hdr = { | 2927 | struct compound_hdr hdr = { |
2928 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2928 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2929 | }; | 2929 | }; |
2930 | 2930 | ||
2931 | encode_compound_hdr(xdr, req, &hdr); | 2931 | encode_compound_hdr(xdr, req, &hdr); |
2932 | encode_sequence(xdr, &args->seq_args, &hdr); | 2932 | encode_sequence(xdr, &args->seq_args, &hdr); |
2933 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | 2933 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); |
2934 | encode_layoutcommit(xdr, data->args.inode, args, &hdr); | 2934 | encode_layoutcommit(xdr, data->args.inode, args, &hdr); |
2935 | encode_getfattr(xdr, args->bitmask, &hdr); | 2935 | encode_getfattr(xdr, args->bitmask, &hdr); |
2936 | encode_nops(&hdr); | 2936 | encode_nops(&hdr); |
2937 | } | 2937 | } |
2938 | 2938 | ||
2939 | /* | 2939 | /* |
2940 | * Encode LAYOUTRETURN request | 2940 | * Encode LAYOUTRETURN request |
2941 | */ | 2941 | */ |
2942 | static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req, | 2942 | static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req, |
2943 | struct xdr_stream *xdr, | 2943 | struct xdr_stream *xdr, |
2944 | struct nfs4_layoutreturn_args *args) | 2944 | struct nfs4_layoutreturn_args *args) |
2945 | { | 2945 | { |
2946 | struct compound_hdr hdr = { | 2946 | struct compound_hdr hdr = { |
2947 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2947 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2948 | }; | 2948 | }; |
2949 | 2949 | ||
2950 | encode_compound_hdr(xdr, req, &hdr); | 2950 | encode_compound_hdr(xdr, req, &hdr); |
2951 | encode_sequence(xdr, &args->seq_args, &hdr); | 2951 | encode_sequence(xdr, &args->seq_args, &hdr); |
2952 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | 2952 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); |
2953 | encode_layoutreturn(xdr, args, &hdr); | 2953 | encode_layoutreturn(xdr, args, &hdr); |
2954 | encode_nops(&hdr); | 2954 | encode_nops(&hdr); |
2955 | } | 2955 | } |
2956 | 2956 | ||
2957 | /* | 2957 | /* |
2958 | * Encode SECINFO_NO_NAME request | 2958 | * Encode SECINFO_NO_NAME request |
2959 | */ | 2959 | */ |
2960 | static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req, | 2960 | static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req, |
2961 | struct xdr_stream *xdr, | 2961 | struct xdr_stream *xdr, |
2962 | struct nfs41_secinfo_no_name_args *args) | 2962 | struct nfs41_secinfo_no_name_args *args) |
2963 | { | 2963 | { |
2964 | struct compound_hdr hdr = { | 2964 | struct compound_hdr hdr = { |
2965 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2965 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2966 | }; | 2966 | }; |
2967 | 2967 | ||
2968 | encode_compound_hdr(xdr, req, &hdr); | 2968 | encode_compound_hdr(xdr, req, &hdr); |
2969 | encode_sequence(xdr, &args->seq_args, &hdr); | 2969 | encode_sequence(xdr, &args->seq_args, &hdr); |
2970 | encode_putrootfh(xdr, &hdr); | 2970 | encode_putrootfh(xdr, &hdr); |
2971 | encode_secinfo_no_name(xdr, args, &hdr); | 2971 | encode_secinfo_no_name(xdr, args, &hdr); |
2972 | encode_nops(&hdr); | 2972 | encode_nops(&hdr); |
2973 | return 0; | 2973 | return 0; |
2974 | } | 2974 | } |
2975 | 2975 | ||
2976 | /* | 2976 | /* |
2977 | * Encode TEST_STATEID request | 2977 | * Encode TEST_STATEID request |
2978 | */ | 2978 | */ |
2979 | static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req, | 2979 | static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req, |
2980 | struct xdr_stream *xdr, | 2980 | struct xdr_stream *xdr, |
2981 | struct nfs41_test_stateid_args *args) | 2981 | struct nfs41_test_stateid_args *args) |
2982 | { | 2982 | { |
2983 | struct compound_hdr hdr = { | 2983 | struct compound_hdr hdr = { |
2984 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 2984 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
2985 | }; | 2985 | }; |
2986 | 2986 | ||
2987 | encode_compound_hdr(xdr, req, &hdr); | 2987 | encode_compound_hdr(xdr, req, &hdr); |
2988 | encode_sequence(xdr, &args->seq_args, &hdr); | 2988 | encode_sequence(xdr, &args->seq_args, &hdr); |
2989 | encode_test_stateid(xdr, args, &hdr); | 2989 | encode_test_stateid(xdr, args, &hdr); |
2990 | encode_nops(&hdr); | 2990 | encode_nops(&hdr); |
2991 | } | 2991 | } |
2992 | 2992 | ||
2993 | /* | 2993 | /* |
2994 | * Encode FREE_STATEID request | 2994 | * Encode FREE_STATEID request |
2995 | */ | 2995 | */ |
2996 | static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req, | 2996 | static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req, |
2997 | struct xdr_stream *xdr, | 2997 | struct xdr_stream *xdr, |
2998 | struct nfs41_free_stateid_args *args) | 2998 | struct nfs41_free_stateid_args *args) |
2999 | { | 2999 | { |
3000 | struct compound_hdr hdr = { | 3000 | struct compound_hdr hdr = { |
3001 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 3001 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
3002 | }; | 3002 | }; |
3003 | 3003 | ||
3004 | encode_compound_hdr(xdr, req, &hdr); | 3004 | encode_compound_hdr(xdr, req, &hdr); |
3005 | encode_sequence(xdr, &args->seq_args, &hdr); | 3005 | encode_sequence(xdr, &args->seq_args, &hdr); |
3006 | encode_free_stateid(xdr, args, &hdr); | 3006 | encode_free_stateid(xdr, args, &hdr); |
3007 | encode_nops(&hdr); | 3007 | encode_nops(&hdr); |
3008 | } | 3008 | } |
3009 | #endif /* CONFIG_NFS_V4_1 */ | 3009 | #endif /* CONFIG_NFS_V4_1 */ |
3010 | 3010 | ||
3011 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 3011 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
3012 | { | 3012 | { |
3013 | dprintk("nfs: %s: prematurely hit end of receive buffer. " | 3013 | dprintk("nfs: %s: prematurely hit end of receive buffer. " |
3014 | "Remaining buffer length is %tu words.\n", | 3014 | "Remaining buffer length is %tu words.\n", |
3015 | func, xdr->end - xdr->p); | 3015 | func, xdr->end - xdr->p); |
3016 | } | 3016 | } |
3017 | 3017 | ||
3018 | static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) | 3018 | static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) |
3019 | { | 3019 | { |
3020 | __be32 *p; | 3020 | __be32 *p; |
3021 | 3021 | ||
3022 | p = xdr_inline_decode(xdr, 4); | 3022 | p = xdr_inline_decode(xdr, 4); |
3023 | if (unlikely(!p)) | 3023 | if (unlikely(!p)) |
3024 | goto out_overflow; | 3024 | goto out_overflow; |
3025 | *len = be32_to_cpup(p); | 3025 | *len = be32_to_cpup(p); |
3026 | p = xdr_inline_decode(xdr, *len); | 3026 | p = xdr_inline_decode(xdr, *len); |
3027 | if (unlikely(!p)) | 3027 | if (unlikely(!p)) |
3028 | goto out_overflow; | 3028 | goto out_overflow; |
3029 | *string = (char *)p; | 3029 | *string = (char *)p; |
3030 | return 0; | 3030 | return 0; |
3031 | out_overflow: | 3031 | out_overflow: |
3032 | print_overflow_msg(__func__, xdr); | 3032 | print_overflow_msg(__func__, xdr); |
3033 | return -EIO; | 3033 | return -EIO; |
3034 | } | 3034 | } |
3035 | 3035 | ||
3036 | static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) | 3036 | static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) |
3037 | { | 3037 | { |
3038 | __be32 *p; | 3038 | __be32 *p; |
3039 | 3039 | ||
3040 | p = xdr_inline_decode(xdr, 8); | 3040 | p = xdr_inline_decode(xdr, 8); |
3041 | if (unlikely(!p)) | 3041 | if (unlikely(!p)) |
3042 | goto out_overflow; | 3042 | goto out_overflow; |
3043 | hdr->status = be32_to_cpup(p++); | 3043 | hdr->status = be32_to_cpup(p++); |
3044 | hdr->taglen = be32_to_cpup(p); | 3044 | hdr->taglen = be32_to_cpup(p); |
3045 | 3045 | ||
3046 | p = xdr_inline_decode(xdr, hdr->taglen + 4); | 3046 | p = xdr_inline_decode(xdr, hdr->taglen + 4); |
3047 | if (unlikely(!p)) | 3047 | if (unlikely(!p)) |
3048 | goto out_overflow; | 3048 | goto out_overflow; |
3049 | hdr->tag = (char *)p; | 3049 | hdr->tag = (char *)p; |
3050 | p += XDR_QUADLEN(hdr->taglen); | 3050 | p += XDR_QUADLEN(hdr->taglen); |
3051 | hdr->nops = be32_to_cpup(p); | 3051 | hdr->nops = be32_to_cpup(p); |
3052 | if (unlikely(hdr->nops < 1)) | 3052 | if (unlikely(hdr->nops < 1)) |
3053 | return nfs4_stat_to_errno(hdr->status); | 3053 | return nfs4_stat_to_errno(hdr->status); |
3054 | return 0; | 3054 | return 0; |
3055 | out_overflow: | 3055 | out_overflow: |
3056 | print_overflow_msg(__func__, xdr); | 3056 | print_overflow_msg(__func__, xdr); |
3057 | return -EIO; | 3057 | return -EIO; |
3058 | } | 3058 | } |
3059 | 3059 | ||
3060 | static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) | 3060 | static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) |
3061 | { | 3061 | { |
3062 | __be32 *p; | 3062 | __be32 *p; |
3063 | uint32_t opnum; | 3063 | uint32_t opnum; |
3064 | int32_t nfserr; | 3064 | int32_t nfserr; |
3065 | 3065 | ||
3066 | p = xdr_inline_decode(xdr, 8); | 3066 | p = xdr_inline_decode(xdr, 8); |
3067 | if (unlikely(!p)) | 3067 | if (unlikely(!p)) |
3068 | goto out_overflow; | 3068 | goto out_overflow; |
3069 | opnum = be32_to_cpup(p++); | 3069 | opnum = be32_to_cpup(p++); |
3070 | if (opnum != expected) { | 3070 | if (opnum != expected) { |
3071 | dprintk("nfs: Server returned operation" | 3071 | dprintk("nfs: Server returned operation" |
3072 | " %d but we issued a request for %d\n", | 3072 | " %d but we issued a request for %d\n", |
3073 | opnum, expected); | 3073 | opnum, expected); |
3074 | return -EIO; | 3074 | return -EIO; |
3075 | } | 3075 | } |
3076 | nfserr = be32_to_cpup(p); | 3076 | nfserr = be32_to_cpup(p); |
3077 | if (nfserr != NFS_OK) | 3077 | if (nfserr != NFS_OK) |
3078 | return nfs4_stat_to_errno(nfserr); | 3078 | return nfs4_stat_to_errno(nfserr); |
3079 | return 0; | 3079 | return 0; |
3080 | out_overflow: | 3080 | out_overflow: |
3081 | print_overflow_msg(__func__, xdr); | 3081 | print_overflow_msg(__func__, xdr); |
3082 | return -EIO; | 3082 | return -EIO; |
3083 | } | 3083 | } |
3084 | 3084 | ||
3085 | /* Dummy routine */ | 3085 | /* Dummy routine */ |
3086 | static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) | 3086 | static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) |
3087 | { | 3087 | { |
3088 | __be32 *p; | 3088 | __be32 *p; |
3089 | unsigned int strlen; | 3089 | unsigned int strlen; |
3090 | char *str; | 3090 | char *str; |
3091 | 3091 | ||
3092 | p = xdr_inline_decode(xdr, 12); | 3092 | p = xdr_inline_decode(xdr, 12); |
3093 | if (likely(p)) | 3093 | if (likely(p)) |
3094 | return decode_opaque_inline(xdr, &strlen, &str); | 3094 | return decode_opaque_inline(xdr, &strlen, &str); |
3095 | print_overflow_msg(__func__, xdr); | 3095 | print_overflow_msg(__func__, xdr); |
3096 | return -EIO; | 3096 | return -EIO; |
3097 | } | 3097 | } |
3098 | 3098 | ||
3099 | static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) | 3099 | static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) |
3100 | { | 3100 | { |
3101 | uint32_t bmlen; | 3101 | uint32_t bmlen; |
3102 | __be32 *p; | 3102 | __be32 *p; |
3103 | 3103 | ||
3104 | p = xdr_inline_decode(xdr, 4); | 3104 | p = xdr_inline_decode(xdr, 4); |
3105 | if (unlikely(!p)) | 3105 | if (unlikely(!p)) |
3106 | goto out_overflow; | 3106 | goto out_overflow; |
3107 | bmlen = be32_to_cpup(p); | 3107 | bmlen = be32_to_cpup(p); |
3108 | 3108 | ||
3109 | bitmap[0] = bitmap[1] = bitmap[2] = 0; | 3109 | bitmap[0] = bitmap[1] = bitmap[2] = 0; |
3110 | p = xdr_inline_decode(xdr, (bmlen << 2)); | 3110 | p = xdr_inline_decode(xdr, (bmlen << 2)); |
3111 | if (unlikely(!p)) | 3111 | if (unlikely(!p)) |
3112 | goto out_overflow; | 3112 | goto out_overflow; |
3113 | if (bmlen > 0) { | 3113 | if (bmlen > 0) { |
3114 | bitmap[0] = be32_to_cpup(p++); | 3114 | bitmap[0] = be32_to_cpup(p++); |
3115 | if (bmlen > 1) { | 3115 | if (bmlen > 1) { |
3116 | bitmap[1] = be32_to_cpup(p++); | 3116 | bitmap[1] = be32_to_cpup(p++); |
3117 | if (bmlen > 2) | 3117 | if (bmlen > 2) |
3118 | bitmap[2] = be32_to_cpup(p); | 3118 | bitmap[2] = be32_to_cpup(p); |
3119 | } | 3119 | } |
3120 | } | 3120 | } |
3121 | return 0; | 3121 | return 0; |
3122 | out_overflow: | 3122 | out_overflow: |
3123 | print_overflow_msg(__func__, xdr); | 3123 | print_overflow_msg(__func__, xdr); |
3124 | return -EIO; | 3124 | return -EIO; |
3125 | } | 3125 | } |
3126 | 3126 | ||
3127 | static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) | 3127 | static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) |
3128 | { | 3128 | { |
3129 | __be32 *p; | 3129 | __be32 *p; |
3130 | 3130 | ||
3131 | p = xdr_inline_decode(xdr, 4); | 3131 | p = xdr_inline_decode(xdr, 4); |
3132 | if (unlikely(!p)) | 3132 | if (unlikely(!p)) |
3133 | goto out_overflow; | 3133 | goto out_overflow; |
3134 | *attrlen = be32_to_cpup(p); | 3134 | *attrlen = be32_to_cpup(p); |
3135 | *savep = xdr->p; | 3135 | *savep = xdr->p; |
3136 | return 0; | 3136 | return 0; |
3137 | out_overflow: | 3137 | out_overflow: |
3138 | print_overflow_msg(__func__, xdr); | 3138 | print_overflow_msg(__func__, xdr); |
3139 | return -EIO; | 3139 | return -EIO; |
3140 | } | 3140 | } |
3141 | 3141 | ||
3142 | static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) | 3142 | static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask) |
3143 | { | 3143 | { |
3144 | if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) { | 3144 | if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) { |
3145 | int ret; | 3145 | int ret; |
3146 | ret = decode_attr_bitmap(xdr, bitmask); | 3146 | ret = decode_attr_bitmap(xdr, bitmask); |
3147 | if (unlikely(ret < 0)) | 3147 | if (unlikely(ret < 0)) |
3148 | return ret; | 3148 | return ret; |
3149 | bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; | 3149 | bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; |
3150 | } else | 3150 | } else |
3151 | bitmask[0] = bitmask[1] = bitmask[2] = 0; | 3151 | bitmask[0] = bitmask[1] = bitmask[2] = 0; |
3152 | dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__, | 3152 | dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__, |
3153 | bitmask[0], bitmask[1], bitmask[2]); | 3153 | bitmask[0], bitmask[1], bitmask[2]); |
3154 | return 0; | 3154 | return 0; |
3155 | } | 3155 | } |
3156 | 3156 | ||
3157 | static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) | 3157 | static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) |
3158 | { | 3158 | { |
3159 | __be32 *p; | 3159 | __be32 *p; |
3160 | int ret = 0; | 3160 | int ret = 0; |
3161 | 3161 | ||
3162 | *type = 0; | 3162 | *type = 0; |
3163 | if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) | 3163 | if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) |
3164 | return -EIO; | 3164 | return -EIO; |
3165 | if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { | 3165 | if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) { |
3166 | p = xdr_inline_decode(xdr, 4); | 3166 | p = xdr_inline_decode(xdr, 4); |
3167 | if (unlikely(!p)) | 3167 | if (unlikely(!p)) |
3168 | goto out_overflow; | 3168 | goto out_overflow; |
3169 | *type = be32_to_cpup(p); | 3169 | *type = be32_to_cpup(p); |
3170 | if (*type < NF4REG || *type > NF4NAMEDATTR) { | 3170 | if (*type < NF4REG || *type > NF4NAMEDATTR) { |
3171 | dprintk("%s: bad type %d\n", __func__, *type); | 3171 | dprintk("%s: bad type %d\n", __func__, *type); |
3172 | return -EIO; | 3172 | return -EIO; |
3173 | } | 3173 | } |
3174 | bitmap[0] &= ~FATTR4_WORD0_TYPE; | 3174 | bitmap[0] &= ~FATTR4_WORD0_TYPE; |
3175 | ret = NFS_ATTR_FATTR_TYPE; | 3175 | ret = NFS_ATTR_FATTR_TYPE; |
3176 | } | 3176 | } |
3177 | dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); | 3177 | dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]); |
3178 | return ret; | 3178 | return ret; |
3179 | out_overflow: | 3179 | out_overflow: |
3180 | print_overflow_msg(__func__, xdr); | 3180 | print_overflow_msg(__func__, xdr); |
3181 | return -EIO; | 3181 | return -EIO; |
3182 | } | 3182 | } |
3183 | 3183 | ||
3184 | static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) | 3184 | static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) |
3185 | { | 3185 | { |
3186 | __be32 *p; | 3186 | __be32 *p; |
3187 | int ret = 0; | 3187 | int ret = 0; |
3188 | 3188 | ||
3189 | *change = 0; | 3189 | *change = 0; |
3190 | if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) | 3190 | if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) |
3191 | return -EIO; | 3191 | return -EIO; |
3192 | if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { | 3192 | if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) { |
3193 | p = xdr_inline_decode(xdr, 8); | 3193 | p = xdr_inline_decode(xdr, 8); |
3194 | if (unlikely(!p)) | 3194 | if (unlikely(!p)) |
3195 | goto out_overflow; | 3195 | goto out_overflow; |
3196 | xdr_decode_hyper(p, change); | 3196 | xdr_decode_hyper(p, change); |
3197 | bitmap[0] &= ~FATTR4_WORD0_CHANGE; | 3197 | bitmap[0] &= ~FATTR4_WORD0_CHANGE; |
3198 | ret = NFS_ATTR_FATTR_CHANGE; | 3198 | ret = NFS_ATTR_FATTR_CHANGE; |
3199 | } | 3199 | } |
3200 | dprintk("%s: change attribute=%Lu\n", __func__, | 3200 | dprintk("%s: change attribute=%Lu\n", __func__, |
3201 | (unsigned long long)*change); | 3201 | (unsigned long long)*change); |
3202 | return ret; | 3202 | return ret; |
3203 | out_overflow: | 3203 | out_overflow: |
3204 | print_overflow_msg(__func__, xdr); | 3204 | print_overflow_msg(__func__, xdr); |
3205 | return -EIO; | 3205 | return -EIO; |
3206 | } | 3206 | } |
3207 | 3207 | ||
3208 | static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) | 3208 | static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) |
3209 | { | 3209 | { |
3210 | __be32 *p; | 3210 | __be32 *p; |
3211 | int ret = 0; | 3211 | int ret = 0; |
3212 | 3212 | ||
3213 | *size = 0; | 3213 | *size = 0; |
3214 | if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) | 3214 | if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) |
3215 | return -EIO; | 3215 | return -EIO; |
3216 | if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { | 3216 | if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) { |
3217 | p = xdr_inline_decode(xdr, 8); | 3217 | p = xdr_inline_decode(xdr, 8); |
3218 | if (unlikely(!p)) | 3218 | if (unlikely(!p)) |
3219 | goto out_overflow; | 3219 | goto out_overflow; |
3220 | xdr_decode_hyper(p, size); | 3220 | xdr_decode_hyper(p, size); |
3221 | bitmap[0] &= ~FATTR4_WORD0_SIZE; | 3221 | bitmap[0] &= ~FATTR4_WORD0_SIZE; |
3222 | ret = NFS_ATTR_FATTR_SIZE; | 3222 | ret = NFS_ATTR_FATTR_SIZE; |
3223 | } | 3223 | } |
3224 | dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); | 3224 | dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size); |
3225 | return ret; | 3225 | return ret; |
3226 | out_overflow: | 3226 | out_overflow: |
3227 | print_overflow_msg(__func__, xdr); | 3227 | print_overflow_msg(__func__, xdr); |
3228 | return -EIO; | 3228 | return -EIO; |
3229 | } | 3229 | } |
3230 | 3230 | ||
3231 | static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3231 | static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
3232 | { | 3232 | { |
3233 | __be32 *p; | 3233 | __be32 *p; |
3234 | 3234 | ||
3235 | *res = 0; | 3235 | *res = 0; |
3236 | if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U))) | 3236 | if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U))) |
3237 | return -EIO; | 3237 | return -EIO; |
3238 | if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { | 3238 | if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) { |
3239 | p = xdr_inline_decode(xdr, 4); | 3239 | p = xdr_inline_decode(xdr, 4); |
3240 | if (unlikely(!p)) | 3240 | if (unlikely(!p)) |
3241 | goto out_overflow; | 3241 | goto out_overflow; |
3242 | *res = be32_to_cpup(p); | 3242 | *res = be32_to_cpup(p); |
3243 | bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; | 3243 | bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT; |
3244 | } | 3244 | } |
3245 | dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); | 3245 | dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true"); |
3246 | return 0; | 3246 | return 0; |
3247 | out_overflow: | 3247 | out_overflow: |
3248 | print_overflow_msg(__func__, xdr); | 3248 | print_overflow_msg(__func__, xdr); |
3249 | return -EIO; | 3249 | return -EIO; |
3250 | } | 3250 | } |
3251 | 3251 | ||
3252 | static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3252 | static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
3253 | { | 3253 | { |
3254 | __be32 *p; | 3254 | __be32 *p; |
3255 | 3255 | ||
3256 | *res = 0; | 3256 | *res = 0; |
3257 | if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U))) | 3257 | if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U))) |
3258 | return -EIO; | 3258 | return -EIO; |
3259 | if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { | 3259 | if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) { |
3260 | p = xdr_inline_decode(xdr, 4); | 3260 | p = xdr_inline_decode(xdr, 4); |
3261 | if (unlikely(!p)) | 3261 | if (unlikely(!p)) |
3262 | goto out_overflow; | 3262 | goto out_overflow; |
3263 | *res = be32_to_cpup(p); | 3263 | *res = be32_to_cpup(p); |
3264 | bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; | 3264 | bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT; |
3265 | } | 3265 | } |
3266 | dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); | 3266 | dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true"); |
3267 | return 0; | 3267 | return 0; |
3268 | out_overflow: | 3268 | out_overflow: |
3269 | print_overflow_msg(__func__, xdr); | 3269 | print_overflow_msg(__func__, xdr); |
3270 | return -EIO; | 3270 | return -EIO; |
3271 | } | 3271 | } |
3272 | 3272 | ||
3273 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) | 3273 | static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) |
3274 | { | 3274 | { |
3275 | __be32 *p; | 3275 | __be32 *p; |
3276 | int ret = 0; | 3276 | int ret = 0; |
3277 | 3277 | ||
3278 | fsid->major = 0; | 3278 | fsid->major = 0; |
3279 | fsid->minor = 0; | 3279 | fsid->minor = 0; |
3280 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U))) | 3280 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U))) |
3281 | return -EIO; | 3281 | return -EIO; |
3282 | if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { | 3282 | if (likely(bitmap[0] & FATTR4_WORD0_FSID)) { |
3283 | p = xdr_inline_decode(xdr, 16); | 3283 | p = xdr_inline_decode(xdr, 16); |
3284 | if (unlikely(!p)) | 3284 | if (unlikely(!p)) |
3285 | goto out_overflow; | 3285 | goto out_overflow; |
3286 | p = xdr_decode_hyper(p, &fsid->major); | 3286 | p = xdr_decode_hyper(p, &fsid->major); |
3287 | xdr_decode_hyper(p, &fsid->minor); | 3287 | xdr_decode_hyper(p, &fsid->minor); |
3288 | bitmap[0] &= ~FATTR4_WORD0_FSID; | 3288 | bitmap[0] &= ~FATTR4_WORD0_FSID; |
3289 | ret = NFS_ATTR_FATTR_FSID; | 3289 | ret = NFS_ATTR_FATTR_FSID; |
3290 | } | 3290 | } |
3291 | dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, | 3291 | dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__, |
3292 | (unsigned long long)fsid->major, | 3292 | (unsigned long long)fsid->major, |
3293 | (unsigned long long)fsid->minor); | 3293 | (unsigned long long)fsid->minor); |
3294 | return ret; | 3294 | return ret; |
3295 | out_overflow: | 3295 | out_overflow: |
3296 | print_overflow_msg(__func__, xdr); | 3296 | print_overflow_msg(__func__, xdr); |
3297 | return -EIO; | 3297 | return -EIO; |
3298 | } | 3298 | } |
3299 | 3299 | ||
3300 | static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3300 | static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
3301 | { | 3301 | { |
3302 | __be32 *p; | 3302 | __be32 *p; |
3303 | 3303 | ||
3304 | *res = 60; | 3304 | *res = 60; |
3305 | if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U))) | 3305 | if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U))) |
3306 | return -EIO; | 3306 | return -EIO; |
3307 | if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { | 3307 | if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) { |
3308 | p = xdr_inline_decode(xdr, 4); | 3308 | p = xdr_inline_decode(xdr, 4); |
3309 | if (unlikely(!p)) | 3309 | if (unlikely(!p)) |
3310 | goto out_overflow; | 3310 | goto out_overflow; |
3311 | *res = be32_to_cpup(p); | 3311 | *res = be32_to_cpup(p); |
3312 | bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; | 3312 | bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME; |
3313 | } | 3313 | } |
3314 | dprintk("%s: file size=%u\n", __func__, (unsigned int)*res); | 3314 | dprintk("%s: file size=%u\n", __func__, (unsigned int)*res); |
3315 | return 0; | 3315 | return 0; |
3316 | out_overflow: | 3316 | out_overflow: |
3317 | print_overflow_msg(__func__, xdr); | 3317 | print_overflow_msg(__func__, xdr); |
3318 | return -EIO; | 3318 | return -EIO; |
3319 | } | 3319 | } |
3320 | 3320 | ||
3321 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) | 3321 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) |
3322 | { | 3322 | { |
3323 | __be32 *p; | 3323 | __be32 *p; |
3324 | 3324 | ||
3325 | if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U))) | 3325 | if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U))) |
3326 | return -EIO; | 3326 | return -EIO; |
3327 | if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { | 3327 | if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) { |
3328 | p = xdr_inline_decode(xdr, 4); | 3328 | p = xdr_inline_decode(xdr, 4); |
3329 | if (unlikely(!p)) | 3329 | if (unlikely(!p)) |
3330 | goto out_overflow; | 3330 | goto out_overflow; |
3331 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | 3331 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; |
3332 | *res = -be32_to_cpup(p); | 3332 | *res = -be32_to_cpup(p); |
3333 | } | 3333 | } |
3334 | return 0; | 3334 | return 0; |
3335 | out_overflow: | 3335 | out_overflow: |
3336 | print_overflow_msg(__func__, xdr); | 3336 | print_overflow_msg(__func__, xdr); |
3337 | return -EIO; | 3337 | return -EIO; |
3338 | } | 3338 | } |
3339 | 3339 | ||
3340 | static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh) | 3340 | static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh) |
3341 | { | 3341 | { |
3342 | __be32 *p; | 3342 | __be32 *p; |
3343 | int len; | 3343 | int len; |
3344 | 3344 | ||
3345 | if (fh != NULL) | 3345 | if (fh != NULL) |
3346 | memset(fh, 0, sizeof(*fh)); | 3346 | memset(fh, 0, sizeof(*fh)); |
3347 | 3347 | ||
3348 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U))) | 3348 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U))) |
3349 | return -EIO; | 3349 | return -EIO; |
3350 | if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { | 3350 | if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) { |
3351 | p = xdr_inline_decode(xdr, 4); | 3351 | p = xdr_inline_decode(xdr, 4); |
3352 | if (unlikely(!p)) | 3352 | if (unlikely(!p)) |
3353 | goto out_overflow; | 3353 | goto out_overflow; |
3354 | len = be32_to_cpup(p); | 3354 | len = be32_to_cpup(p); |
3355 | if (len > NFS4_FHSIZE) | 3355 | if (len > NFS4_FHSIZE) |
3356 | return -EIO; | 3356 | return -EIO; |
3357 | p = xdr_inline_decode(xdr, len); | 3357 | p = xdr_inline_decode(xdr, len); |
3358 | if (unlikely(!p)) | 3358 | if (unlikely(!p)) |
3359 | goto out_overflow; | 3359 | goto out_overflow; |
3360 | if (fh != NULL) { | 3360 | if (fh != NULL) { |
3361 | memcpy(fh->data, p, len); | 3361 | memcpy(fh->data, p, len); |
3362 | fh->size = len; | 3362 | fh->size = len; |
3363 | } | 3363 | } |
3364 | bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; | 3364 | bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE; |
3365 | } | 3365 | } |
3366 | return 0; | 3366 | return 0; |
3367 | out_overflow: | 3367 | out_overflow: |
3368 | print_overflow_msg(__func__, xdr); | 3368 | print_overflow_msg(__func__, xdr); |
3369 | return -EIO; | 3369 | return -EIO; |
3370 | } | 3370 | } |
3371 | 3371 | ||
3372 | static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3372 | static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
3373 | { | 3373 | { |
3374 | __be32 *p; | 3374 | __be32 *p; |
3375 | 3375 | ||
3376 | *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL; | 3376 | *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL; |
3377 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) | 3377 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) |
3378 | return -EIO; | 3378 | return -EIO; |
3379 | if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { | 3379 | if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { |
3380 | p = xdr_inline_decode(xdr, 4); | 3380 | p = xdr_inline_decode(xdr, 4); |
3381 | if (unlikely(!p)) | 3381 | if (unlikely(!p)) |
3382 | goto out_overflow; | 3382 | goto out_overflow; |
3383 | *res = be32_to_cpup(p); | 3383 | *res = be32_to_cpup(p); |
3384 | bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; | 3384 | bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT; |
3385 | } | 3385 | } |
3386 | dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); | 3386 | dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res); |
3387 | return 0; | 3387 | return 0; |
3388 | out_overflow: | 3388 | out_overflow: |
3389 | print_overflow_msg(__func__, xdr); | 3389 | print_overflow_msg(__func__, xdr); |
3390 | return -EIO; | 3390 | return -EIO; |
3391 | } | 3391 | } |
3392 | 3392 | ||
3393 | static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) | 3393 | static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) |
3394 | { | 3394 | { |
3395 | __be32 *p; | 3395 | __be32 *p; |
3396 | int ret = 0; | 3396 | int ret = 0; |
3397 | 3397 | ||
3398 | *fileid = 0; | 3398 | *fileid = 0; |
3399 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) | 3399 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) |
3400 | return -EIO; | 3400 | return -EIO; |
3401 | if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { | 3401 | if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) { |
3402 | p = xdr_inline_decode(xdr, 8); | 3402 | p = xdr_inline_decode(xdr, 8); |
3403 | if (unlikely(!p)) | 3403 | if (unlikely(!p)) |
3404 | goto out_overflow; | 3404 | goto out_overflow; |
3405 | xdr_decode_hyper(p, fileid); | 3405 | xdr_decode_hyper(p, fileid); |
3406 | bitmap[0] &= ~FATTR4_WORD0_FILEID; | 3406 | bitmap[0] &= ~FATTR4_WORD0_FILEID; |
3407 | ret = NFS_ATTR_FATTR_FILEID; | 3407 | ret = NFS_ATTR_FATTR_FILEID; |
3408 | } | 3408 | } |
3409 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 3409 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
3410 | return ret; | 3410 | return ret; |
3411 | out_overflow: | 3411 | out_overflow: |
3412 | print_overflow_msg(__func__, xdr); | 3412 | print_overflow_msg(__func__, xdr); |
3413 | return -EIO; | 3413 | return -EIO; |
3414 | } | 3414 | } |
3415 | 3415 | ||
3416 | static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) | 3416 | static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) |
3417 | { | 3417 | { |
3418 | __be32 *p; | 3418 | __be32 *p; |
3419 | int ret = 0; | 3419 | int ret = 0; |
3420 | 3420 | ||
3421 | *fileid = 0; | 3421 | *fileid = 0; |
3422 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) | 3422 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) |
3423 | return -EIO; | 3423 | return -EIO; |
3424 | if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { | 3424 | if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) { |
3425 | p = xdr_inline_decode(xdr, 8); | 3425 | p = xdr_inline_decode(xdr, 8); |
3426 | if (unlikely(!p)) | 3426 | if (unlikely(!p)) |
3427 | goto out_overflow; | 3427 | goto out_overflow; |
3428 | xdr_decode_hyper(p, fileid); | 3428 | xdr_decode_hyper(p, fileid); |
3429 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | 3429 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; |
3430 | ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; | 3430 | ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; |
3431 | } | 3431 | } |
3432 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 3432 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
3433 | return ret; | 3433 | return ret; |
3434 | out_overflow: | 3434 | out_overflow: |
3435 | print_overflow_msg(__func__, xdr); | 3435 | print_overflow_msg(__func__, xdr); |
3436 | return -EIO; | 3436 | return -EIO; |
3437 | } | 3437 | } |
3438 | 3438 | ||
3439 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3439 | static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
3440 | { | 3440 | { |
3441 | __be32 *p; | 3441 | __be32 *p; |
3442 | int status = 0; | 3442 | int status = 0; |
3443 | 3443 | ||
3444 | *res = 0; | 3444 | *res = 0; |
3445 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U))) | 3445 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U))) |
3446 | return -EIO; | 3446 | return -EIO; |
3447 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { | 3447 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) { |
3448 | p = xdr_inline_decode(xdr, 8); | 3448 | p = xdr_inline_decode(xdr, 8); |
3449 | if (unlikely(!p)) | 3449 | if (unlikely(!p)) |
3450 | goto out_overflow; | 3450 | goto out_overflow; |
3451 | xdr_decode_hyper(p, res); | 3451 | xdr_decode_hyper(p, res); |
3452 | bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; | 3452 | bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL; |
3453 | } | 3453 | } |
3454 | dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); | 3454 | dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res); |
3455 | return status; | 3455 | return status; |
3456 | out_overflow: | 3456 | out_overflow: |
3457 | print_overflow_msg(__func__, xdr); | 3457 | print_overflow_msg(__func__, xdr); |
3458 | return -EIO; | 3458 | return -EIO; |
3459 | } | 3459 | } |
3460 | 3460 | ||
3461 | static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3461 | static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
3462 | { | 3462 | { |
3463 | __be32 *p; | 3463 | __be32 *p; |
3464 | int status = 0; | 3464 | int status = 0; |
3465 | 3465 | ||
3466 | *res = 0; | 3466 | *res = 0; |
3467 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U))) | 3467 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U))) |
3468 | return -EIO; | 3468 | return -EIO; |
3469 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { | 3469 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) { |
3470 | p = xdr_inline_decode(xdr, 8); | 3470 | p = xdr_inline_decode(xdr, 8); |
3471 | if (unlikely(!p)) | 3471 | if (unlikely(!p)) |
3472 | goto out_overflow; | 3472 | goto out_overflow; |
3473 | xdr_decode_hyper(p, res); | 3473 | xdr_decode_hyper(p, res); |
3474 | bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; | 3474 | bitmap[0] &= ~FATTR4_WORD0_FILES_FREE; |
3475 | } | 3475 | } |
3476 | dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); | 3476 | dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res); |
3477 | return status; | 3477 | return status; |
3478 | out_overflow: | 3478 | out_overflow: |
3479 | print_overflow_msg(__func__, xdr); | 3479 | print_overflow_msg(__func__, xdr); |
3480 | return -EIO; | 3480 | return -EIO; |
3481 | } | 3481 | } |
3482 | 3482 | ||
3483 | static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3483 | static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
3484 | { | 3484 | { |
3485 | __be32 *p; | 3485 | __be32 *p; |
3486 | int status = 0; | 3486 | int status = 0; |
3487 | 3487 | ||
3488 | *res = 0; | 3488 | *res = 0; |
3489 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U))) | 3489 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U))) |
3490 | return -EIO; | 3490 | return -EIO; |
3491 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { | 3491 | if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) { |
3492 | p = xdr_inline_decode(xdr, 8); | 3492 | p = xdr_inline_decode(xdr, 8); |
3493 | if (unlikely(!p)) | 3493 | if (unlikely(!p)) |
3494 | goto out_overflow; | 3494 | goto out_overflow; |
3495 | xdr_decode_hyper(p, res); | 3495 | xdr_decode_hyper(p, res); |
3496 | bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; | 3496 | bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL; |
3497 | } | 3497 | } |
3498 | dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); | 3498 | dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res); |
3499 | return status; | 3499 | return status; |
3500 | out_overflow: | 3500 | out_overflow: |
3501 | print_overflow_msg(__func__, xdr); | 3501 | print_overflow_msg(__func__, xdr); |
3502 | return -EIO; | 3502 | return -EIO; |
3503 | } | 3503 | } |
3504 | 3504 | ||
3505 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) | 3505 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) |
3506 | { | 3506 | { |
3507 | u32 n; | 3507 | u32 n; |
3508 | __be32 *p; | 3508 | __be32 *p; |
3509 | int status = 0; | 3509 | int status = 0; |
3510 | 3510 | ||
3511 | p = xdr_inline_decode(xdr, 4); | 3511 | p = xdr_inline_decode(xdr, 4); |
3512 | if (unlikely(!p)) | 3512 | if (unlikely(!p)) |
3513 | goto out_overflow; | 3513 | goto out_overflow; |
3514 | n = be32_to_cpup(p); | 3514 | n = be32_to_cpup(p); |
3515 | if (n == 0) | 3515 | if (n == 0) |
3516 | goto root_path; | 3516 | goto root_path; |
3517 | dprintk("path "); | 3517 | dprintk("path "); |
3518 | path->ncomponents = 0; | 3518 | path->ncomponents = 0; |
3519 | while (path->ncomponents < n) { | 3519 | while (path->ncomponents < n) { |
3520 | struct nfs4_string *component = &path->components[path->ncomponents]; | 3520 | struct nfs4_string *component = &path->components[path->ncomponents]; |
3521 | status = decode_opaque_inline(xdr, &component->len, &component->data); | 3521 | status = decode_opaque_inline(xdr, &component->len, &component->data); |
3522 | if (unlikely(status != 0)) | 3522 | if (unlikely(status != 0)) |
3523 | goto out_eio; | 3523 | goto out_eio; |
3524 | if (path->ncomponents != n) | 3524 | if (path->ncomponents != n) |
3525 | dprintk("/"); | 3525 | dprintk("/"); |
3526 | dprintk("%s", component->data); | 3526 | dprintk("%s", component->data); |
3527 | if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS) | 3527 | if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS) |
3528 | path->ncomponents++; | 3528 | path->ncomponents++; |
3529 | else { | 3529 | else { |
3530 | dprintk("cannot parse %d components in path\n", n); | 3530 | dprintk("cannot parse %d components in path\n", n); |
3531 | goto out_eio; | 3531 | goto out_eio; |
3532 | } | 3532 | } |
3533 | } | 3533 | } |
3534 | out: | 3534 | out: |
3535 | dprintk("\n"); | 3535 | dprintk("\n"); |
3536 | return status; | 3536 | return status; |
3537 | root_path: | 3537 | root_path: |
3538 | /* a root pathname is sent as a zero component4 */ | 3538 | /* a root pathname is sent as a zero component4 */ |
3539 | path->ncomponents = 1; | 3539 | path->ncomponents = 1; |
3540 | path->components[0].len=0; | 3540 | path->components[0].len=0; |
3541 | path->components[0].data=NULL; | 3541 | path->components[0].data=NULL; |
3542 | dprintk("path /\n"); | 3542 | dprintk("path /\n"); |
3543 | goto out; | 3543 | goto out; |
3544 | out_eio: | 3544 | out_eio: |
3545 | dprintk(" status %d", status); | 3545 | dprintk(" status %d", status); |
3546 | status = -EIO; | 3546 | status = -EIO; |
3547 | goto out; | 3547 | goto out; |
3548 | out_overflow: | 3548 | out_overflow: |
3549 | print_overflow_msg(__func__, xdr); | 3549 | print_overflow_msg(__func__, xdr); |
3550 | return -EIO; | 3550 | return -EIO; |
3551 | } | 3551 | } |
3552 | 3552 | ||
3553 | static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) | 3553 | static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) |
3554 | { | 3554 | { |
3555 | int n; | 3555 | int n; |
3556 | __be32 *p; | 3556 | __be32 *p; |
3557 | int status = -EIO; | 3557 | int status = -EIO; |
3558 | 3558 | ||
3559 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) | 3559 | if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) |
3560 | goto out; | 3560 | goto out; |
3561 | status = 0; | 3561 | status = 0; |
3562 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) | 3562 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) |
3563 | goto out; | 3563 | goto out; |
3564 | dprintk("%s: fsroot ", __func__); | 3564 | dprintk("%s: fsroot ", __func__); |
3565 | status = decode_pathname(xdr, &res->fs_path); | 3565 | status = decode_pathname(xdr, &res->fs_path); |
3566 | if (unlikely(status != 0)) | 3566 | if (unlikely(status != 0)) |
3567 | goto out; | 3567 | goto out; |
3568 | p = xdr_inline_decode(xdr, 4); | 3568 | p = xdr_inline_decode(xdr, 4); |
3569 | if (unlikely(!p)) | 3569 | if (unlikely(!p)) |
3570 | goto out_overflow; | 3570 | goto out_overflow; |
3571 | n = be32_to_cpup(p); | 3571 | n = be32_to_cpup(p); |
3572 | if (n <= 0) | 3572 | if (n <= 0) |
3573 | goto out_eio; | 3573 | goto out_eio; |
3574 | res->nlocations = 0; | 3574 | res->nlocations = 0; |
3575 | while (res->nlocations < n) { | 3575 | while (res->nlocations < n) { |
3576 | u32 m; | 3576 | u32 m; |
3577 | struct nfs4_fs_location *loc = &res->locations[res->nlocations]; | 3577 | struct nfs4_fs_location *loc = &res->locations[res->nlocations]; |
3578 | 3578 | ||
3579 | p = xdr_inline_decode(xdr, 4); | 3579 | p = xdr_inline_decode(xdr, 4); |
3580 | if (unlikely(!p)) | 3580 | if (unlikely(!p)) |
3581 | goto out_overflow; | 3581 | goto out_overflow; |
3582 | m = be32_to_cpup(p); | 3582 | m = be32_to_cpup(p); |
3583 | 3583 | ||
3584 | loc->nservers = 0; | 3584 | loc->nservers = 0; |
3585 | dprintk("%s: servers ", __func__); | 3585 | dprintk("%s: servers ", __func__); |
3586 | while (loc->nservers < m) { | 3586 | while (loc->nservers < m) { |
3587 | struct nfs4_string *server = &loc->servers[loc->nservers]; | 3587 | struct nfs4_string *server = &loc->servers[loc->nservers]; |
3588 | status = decode_opaque_inline(xdr, &server->len, &server->data); | 3588 | status = decode_opaque_inline(xdr, &server->len, &server->data); |
3589 | if (unlikely(status != 0)) | 3589 | if (unlikely(status != 0)) |
3590 | goto out_eio; | 3590 | goto out_eio; |
3591 | dprintk("%s ", server->data); | 3591 | dprintk("%s ", server->data); |
3592 | if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) | 3592 | if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) |
3593 | loc->nservers++; | 3593 | loc->nservers++; |
3594 | else { | 3594 | else { |
3595 | unsigned int i; | 3595 | unsigned int i; |
3596 | dprintk("%s: using first %u of %u servers " | 3596 | dprintk("%s: using first %u of %u servers " |
3597 | "returned for location %u\n", | 3597 | "returned for location %u\n", |
3598 | __func__, | 3598 | __func__, |
3599 | NFS4_FS_LOCATION_MAXSERVERS, | 3599 | NFS4_FS_LOCATION_MAXSERVERS, |
3600 | m, res->nlocations); | 3600 | m, res->nlocations); |
3601 | for (i = loc->nservers; i < m; i++) { | 3601 | for (i = loc->nservers; i < m; i++) { |
3602 | unsigned int len; | 3602 | unsigned int len; |
3603 | char *data; | 3603 | char *data; |
3604 | status = decode_opaque_inline(xdr, &len, &data); | 3604 | status = decode_opaque_inline(xdr, &len, &data); |
3605 | if (unlikely(status != 0)) | 3605 | if (unlikely(status != 0)) |
3606 | goto out_eio; | 3606 | goto out_eio; |
3607 | } | 3607 | } |
3608 | } | 3608 | } |
3609 | } | 3609 | } |
3610 | status = decode_pathname(xdr, &loc->rootpath); | 3610 | status = decode_pathname(xdr, &loc->rootpath); |
3611 | if (unlikely(status != 0)) | 3611 | if (unlikely(status != 0)) |
3612 | goto out_eio; | 3612 | goto out_eio; |
3613 | if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) | 3613 | if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES) |
3614 | res->nlocations++; | 3614 | res->nlocations++; |
3615 | } | 3615 | } |
3616 | if (res->nlocations != 0) | 3616 | if (res->nlocations != 0) |
3617 | status = NFS_ATTR_FATTR_V4_REFERRAL; | 3617 | status = NFS_ATTR_FATTR_V4_REFERRAL; |
3618 | out: | 3618 | out: |
3619 | dprintk("%s: fs_locations done, error = %d\n", __func__, status); | 3619 | dprintk("%s: fs_locations done, error = %d\n", __func__, status); |
3620 | return status; | 3620 | return status; |
3621 | out_overflow: | 3621 | out_overflow: |
3622 | print_overflow_msg(__func__, xdr); | 3622 | print_overflow_msg(__func__, xdr); |
3623 | out_eio: | 3623 | out_eio: |
3624 | status = -EIO; | 3624 | status = -EIO; |
3625 | goto out; | 3625 | goto out; |
3626 | } | 3626 | } |
3627 | 3627 | ||
3628 | static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3628 | static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
3629 | { | 3629 | { |
3630 | __be32 *p; | 3630 | __be32 *p; |
3631 | int status = 0; | 3631 | int status = 0; |
3632 | 3632 | ||
3633 | *res = 0; | 3633 | *res = 0; |
3634 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U))) | 3634 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U))) |
3635 | return -EIO; | 3635 | return -EIO; |
3636 | if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { | 3636 | if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) { |
3637 | p = xdr_inline_decode(xdr, 8); | 3637 | p = xdr_inline_decode(xdr, 8); |
3638 | if (unlikely(!p)) | 3638 | if (unlikely(!p)) |
3639 | goto out_overflow; | 3639 | goto out_overflow; |
3640 | xdr_decode_hyper(p, res); | 3640 | xdr_decode_hyper(p, res); |
3641 | bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; | 3641 | bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE; |
3642 | } | 3642 | } |
3643 | dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); | 3643 | dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res); |
3644 | return status; | 3644 | return status; |
3645 | out_overflow: | 3645 | out_overflow: |
3646 | print_overflow_msg(__func__, xdr); | 3646 | print_overflow_msg(__func__, xdr); |
3647 | return -EIO; | 3647 | return -EIO; |
3648 | } | 3648 | } |
3649 | 3649 | ||
3650 | static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) | 3650 | static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) |
3651 | { | 3651 | { |
3652 | __be32 *p; | 3652 | __be32 *p; |
3653 | int status = 0; | 3653 | int status = 0; |
3654 | 3654 | ||
3655 | *maxlink = 1; | 3655 | *maxlink = 1; |
3656 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U))) | 3656 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U))) |
3657 | return -EIO; | 3657 | return -EIO; |
3658 | if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { | 3658 | if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) { |
3659 | p = xdr_inline_decode(xdr, 4); | 3659 | p = xdr_inline_decode(xdr, 4); |
3660 | if (unlikely(!p)) | 3660 | if (unlikely(!p)) |
3661 | goto out_overflow; | 3661 | goto out_overflow; |
3662 | *maxlink = be32_to_cpup(p); | 3662 | *maxlink = be32_to_cpup(p); |
3663 | bitmap[0] &= ~FATTR4_WORD0_MAXLINK; | 3663 | bitmap[0] &= ~FATTR4_WORD0_MAXLINK; |
3664 | } | 3664 | } |
3665 | dprintk("%s: maxlink=%u\n", __func__, *maxlink); | 3665 | dprintk("%s: maxlink=%u\n", __func__, *maxlink); |
3666 | return status; | 3666 | return status; |
3667 | out_overflow: | 3667 | out_overflow: |
3668 | print_overflow_msg(__func__, xdr); | 3668 | print_overflow_msg(__func__, xdr); |
3669 | return -EIO; | 3669 | return -EIO; |
3670 | } | 3670 | } |
3671 | 3671 | ||
3672 | static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) | 3672 | static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) |
3673 | { | 3673 | { |
3674 | __be32 *p; | 3674 | __be32 *p; |
3675 | int status = 0; | 3675 | int status = 0; |
3676 | 3676 | ||
3677 | *maxname = 1024; | 3677 | *maxname = 1024; |
3678 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U))) | 3678 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U))) |
3679 | return -EIO; | 3679 | return -EIO; |
3680 | if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { | 3680 | if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) { |
3681 | p = xdr_inline_decode(xdr, 4); | 3681 | p = xdr_inline_decode(xdr, 4); |
3682 | if (unlikely(!p)) | 3682 | if (unlikely(!p)) |
3683 | goto out_overflow; | 3683 | goto out_overflow; |
3684 | *maxname = be32_to_cpup(p); | 3684 | *maxname = be32_to_cpup(p); |
3685 | bitmap[0] &= ~FATTR4_WORD0_MAXNAME; | 3685 | bitmap[0] &= ~FATTR4_WORD0_MAXNAME; |
3686 | } | 3686 | } |
3687 | dprintk("%s: maxname=%u\n", __func__, *maxname); | 3687 | dprintk("%s: maxname=%u\n", __func__, *maxname); |
3688 | return status; | 3688 | return status; |
3689 | out_overflow: | 3689 | out_overflow: |
3690 | print_overflow_msg(__func__, xdr); | 3690 | print_overflow_msg(__func__, xdr); |
3691 | return -EIO; | 3691 | return -EIO; |
3692 | } | 3692 | } |
3693 | 3693 | ||
3694 | static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3694 | static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
3695 | { | 3695 | { |
3696 | __be32 *p; | 3696 | __be32 *p; |
3697 | int status = 0; | 3697 | int status = 0; |
3698 | 3698 | ||
3699 | *res = 1024; | 3699 | *res = 1024; |
3700 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U))) | 3700 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U))) |
3701 | return -EIO; | 3701 | return -EIO; |
3702 | if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) { | 3702 | if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) { |
3703 | uint64_t maxread; | 3703 | uint64_t maxread; |
3704 | p = xdr_inline_decode(xdr, 8); | 3704 | p = xdr_inline_decode(xdr, 8); |
3705 | if (unlikely(!p)) | 3705 | if (unlikely(!p)) |
3706 | goto out_overflow; | 3706 | goto out_overflow; |
3707 | xdr_decode_hyper(p, &maxread); | 3707 | xdr_decode_hyper(p, &maxread); |
3708 | if (maxread > 0x7FFFFFFF) | 3708 | if (maxread > 0x7FFFFFFF) |
3709 | maxread = 0x7FFFFFFF; | 3709 | maxread = 0x7FFFFFFF; |
3710 | *res = (uint32_t)maxread; | 3710 | *res = (uint32_t)maxread; |
3711 | bitmap[0] &= ~FATTR4_WORD0_MAXREAD; | 3711 | bitmap[0] &= ~FATTR4_WORD0_MAXREAD; |
3712 | } | 3712 | } |
3713 | dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); | 3713 | dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res); |
3714 | return status; | 3714 | return status; |
3715 | out_overflow: | 3715 | out_overflow: |
3716 | print_overflow_msg(__func__, xdr); | 3716 | print_overflow_msg(__func__, xdr); |
3717 | return -EIO; | 3717 | return -EIO; |
3718 | } | 3718 | } |
3719 | 3719 | ||
3720 | static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) | 3720 | static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) |
3721 | { | 3721 | { |
3722 | __be32 *p; | 3722 | __be32 *p; |
3723 | int status = 0; | 3723 | int status = 0; |
3724 | 3724 | ||
3725 | *res = 1024; | 3725 | *res = 1024; |
3726 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U))) | 3726 | if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U))) |
3727 | return -EIO; | 3727 | return -EIO; |
3728 | if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) { | 3728 | if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) { |
3729 | uint64_t maxwrite; | 3729 | uint64_t maxwrite; |
3730 | p = xdr_inline_decode(xdr, 8); | 3730 | p = xdr_inline_decode(xdr, 8); |
3731 | if (unlikely(!p)) | 3731 | if (unlikely(!p)) |
3732 | goto out_overflow; | 3732 | goto out_overflow; |
3733 | xdr_decode_hyper(p, &maxwrite); | 3733 | xdr_decode_hyper(p, &maxwrite); |
3734 | if (maxwrite > 0x7FFFFFFF) | 3734 | if (maxwrite > 0x7FFFFFFF) |
3735 | maxwrite = 0x7FFFFFFF; | 3735 | maxwrite = 0x7FFFFFFF; |
3736 | *res = (uint32_t)maxwrite; | 3736 | *res = (uint32_t)maxwrite; |
3737 | bitmap[0] &= ~FATTR4_WORD0_MAXWRITE; | 3737 | bitmap[0] &= ~FATTR4_WORD0_MAXWRITE; |
3738 | } | 3738 | } |
3739 | dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); | 3739 | dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res); |
3740 | return status; | 3740 | return status; |
3741 | out_overflow: | 3741 | out_overflow: |
3742 | print_overflow_msg(__func__, xdr); | 3742 | print_overflow_msg(__func__, xdr); |
3743 | return -EIO; | 3743 | return -EIO; |
3744 | } | 3744 | } |
3745 | 3745 | ||
3746 | static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) | 3746 | static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode) |
3747 | { | 3747 | { |
3748 | uint32_t tmp; | 3748 | uint32_t tmp; |
3749 | __be32 *p; | 3749 | __be32 *p; |
3750 | int ret = 0; | 3750 | int ret = 0; |
3751 | 3751 | ||
3752 | *mode = 0; | 3752 | *mode = 0; |
3753 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) | 3753 | if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) |
3754 | return -EIO; | 3754 | return -EIO; |
3755 | if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { | 3755 | if (likely(bitmap[1] & FATTR4_WORD1_MODE)) { |
3756 | p = xdr_inline_decode(xdr, 4); | 3756 | p = xdr_inline_decode(xdr, 4); |
3757 | if (unlikely(!p)) | 3757 | if (unlikely(!p)) |
3758 | goto out_overflow; | 3758 | goto out_overflow; |
3759 | tmp = be32_to_cpup(p); | 3759 | tmp = be32_to_cpup(p); |
3760 | *mode = tmp & ~S_IFMT; | 3760 | *mode = tmp & ~S_IFMT; |
3761 | bitmap[1] &= ~FATTR4_WORD1_MODE; | 3761 | bitmap[1] &= ~FATTR4_WORD1_MODE; |
3762 | ret = NFS_ATTR_FATTR_MODE; | 3762 | ret = NFS_ATTR_FATTR_MODE; |
3763 | } | 3763 | } |
3764 | dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); | 3764 | dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode); |
3765 | return ret; | 3765 | return ret; |
3766 | out_overflow: | 3766 | out_overflow: |
3767 | print_overflow_msg(__func__, xdr); | 3767 | print_overflow_msg(__func__, xdr); |
3768 | return -EIO; | 3768 | return -EIO; |
3769 | } | 3769 | } |
3770 | 3770 | ||
3771 | static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) | 3771 | static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) |
3772 | { | 3772 | { |
3773 | __be32 *p; | 3773 | __be32 *p; |
3774 | int ret = 0; | 3774 | int ret = 0; |
3775 | 3775 | ||
3776 | *nlink = 1; | 3776 | *nlink = 1; |
3777 | if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) | 3777 | if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) |
3778 | return -EIO; | 3778 | return -EIO; |
3779 | if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { | 3779 | if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) { |
3780 | p = xdr_inline_decode(xdr, 4); | 3780 | p = xdr_inline_decode(xdr, 4); |
3781 | if (unlikely(!p)) | 3781 | if (unlikely(!p)) |
3782 | goto out_overflow; | 3782 | goto out_overflow; |
3783 | *nlink = be32_to_cpup(p); | 3783 | *nlink = be32_to_cpup(p); |
3784 | bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; | 3784 | bitmap[1] &= ~FATTR4_WORD1_NUMLINKS; |
3785 | ret = NFS_ATTR_FATTR_NLINK; | 3785 | ret = NFS_ATTR_FATTR_NLINK; |
3786 | } | 3786 | } |
3787 | dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); | 3787 | dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink); |
3788 | return ret; | 3788 | return ret; |
3789 | out_overflow: | 3789 | out_overflow: |
3790 | print_overflow_msg(__func__, xdr); | 3790 | print_overflow_msg(__func__, xdr); |
3791 | return -EIO; | 3791 | return -EIO; |
3792 | } | 3792 | } |
3793 | 3793 | ||
3794 | static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, | 3794 | static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, |
3795 | const struct nfs_server *server, uint32_t *uid, | 3795 | const struct nfs_server *server, uint32_t *uid, |
3796 | struct nfs4_string *owner_name) | 3796 | struct nfs4_string *owner_name) |
3797 | { | 3797 | { |
3798 | uint32_t len; | 3798 | uint32_t len; |
3799 | __be32 *p; | 3799 | __be32 *p; |
3800 | int ret = 0; | 3800 | int ret = 0; |
3801 | 3801 | ||
3802 | *uid = -2; | 3802 | *uid = -2; |
3803 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) | 3803 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) |
3804 | return -EIO; | 3804 | return -EIO; |
3805 | if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) { | 3805 | if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) { |
3806 | p = xdr_inline_decode(xdr, 4); | 3806 | p = xdr_inline_decode(xdr, 4); |
3807 | if (unlikely(!p)) | 3807 | if (unlikely(!p)) |
3808 | goto out_overflow; | 3808 | goto out_overflow; |
3809 | len = be32_to_cpup(p); | 3809 | len = be32_to_cpup(p); |
3810 | p = xdr_inline_decode(xdr, len); | 3810 | p = xdr_inline_decode(xdr, len); |
3811 | if (unlikely(!p)) | 3811 | if (unlikely(!p)) |
3812 | goto out_overflow; | 3812 | goto out_overflow; |
3813 | if (owner_name != NULL) { | 3813 | if (owner_name != NULL) { |
3814 | owner_name->data = kmemdup(p, len, GFP_NOWAIT); | 3814 | owner_name->data = kmemdup(p, len, GFP_NOWAIT); |
3815 | if (owner_name->data != NULL) { | 3815 | if (owner_name->data != NULL) { |
3816 | owner_name->len = len; | 3816 | owner_name->len = len; |
3817 | ret = NFS_ATTR_FATTR_OWNER_NAME; | 3817 | ret = NFS_ATTR_FATTR_OWNER_NAME; |
3818 | } | 3818 | } |
3819 | } else if (len < XDR_MAX_NETOBJ) { | 3819 | } else if (len < XDR_MAX_NETOBJ) { |
3820 | if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) | 3820 | if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) |
3821 | ret = NFS_ATTR_FATTR_OWNER; | 3821 | ret = NFS_ATTR_FATTR_OWNER; |
3822 | else | 3822 | else |
3823 | dprintk("%s: nfs_map_name_to_uid failed!\n", | 3823 | dprintk("%s: nfs_map_name_to_uid failed!\n", |
3824 | __func__); | 3824 | __func__); |
3825 | } else | 3825 | } else |
3826 | dprintk("%s: name too long (%u)!\n", | 3826 | dprintk("%s: name too long (%u)!\n", |
3827 | __func__, len); | 3827 | __func__, len); |
3828 | bitmap[1] &= ~FATTR4_WORD1_OWNER; | 3828 | bitmap[1] &= ~FATTR4_WORD1_OWNER; |
3829 | } | 3829 | } |
3830 | dprintk("%s: uid=%d\n", __func__, (int)*uid); | 3830 | dprintk("%s: uid=%d\n", __func__, (int)*uid); |
3831 | return ret; | 3831 | return ret; |
3832 | out_overflow: | 3832 | out_overflow: |
3833 | print_overflow_msg(__func__, xdr); | 3833 | print_overflow_msg(__func__, xdr); |
3834 | return -EIO; | 3834 | return -EIO; |
3835 | } | 3835 | } |
3836 | 3836 | ||
3837 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, | 3837 | static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, |
3838 | const struct nfs_server *server, uint32_t *gid, | 3838 | const struct nfs_server *server, uint32_t *gid, |
3839 | struct nfs4_string *group_name) | 3839 | struct nfs4_string *group_name) |
3840 | { | 3840 | { |
3841 | uint32_t len; | 3841 | uint32_t len; |
3842 | __be32 *p; | 3842 | __be32 *p; |
3843 | int ret = 0; | 3843 | int ret = 0; |
3844 | 3844 | ||
3845 | *gid = -2; | 3845 | *gid = -2; |
3846 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) | 3846 | if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) |
3847 | return -EIO; | 3847 | return -EIO; |
3848 | if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) { | 3848 | if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) { |
3849 | p = xdr_inline_decode(xdr, 4); | 3849 | p = xdr_inline_decode(xdr, 4); |
3850 | if (unlikely(!p)) | 3850 | if (unlikely(!p)) |
3851 | goto out_overflow; | 3851 | goto out_overflow; |
3852 | len = be32_to_cpup(p); | 3852 | len = be32_to_cpup(p); |
3853 | p = xdr_inline_decode(xdr, len); | 3853 | p = xdr_inline_decode(xdr, len); |
3854 | if (unlikely(!p)) | 3854 | if (unlikely(!p)) |
3855 | goto out_overflow; | 3855 | goto out_overflow; |
3856 | if (group_name != NULL) { | 3856 | if (group_name != NULL) { |
3857 | group_name->data = kmemdup(p, len, GFP_NOWAIT); | 3857 | group_name->data = kmemdup(p, len, GFP_NOWAIT); |
3858 | if (group_name->data != NULL) { | 3858 | if (group_name->data != NULL) { |
3859 | group_name->len = len; | 3859 | group_name->len = len; |
3860 | ret = NFS_ATTR_FATTR_GROUP_NAME; | 3860 | ret = NFS_ATTR_FATTR_GROUP_NAME; |
3861 | } | 3861 | } |
3862 | } else if (len < XDR_MAX_NETOBJ) { | 3862 | } else if (len < XDR_MAX_NETOBJ) { |
3863 | if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) | 3863 | if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) |
3864 | ret = NFS_ATTR_FATTR_GROUP; | 3864 | ret = NFS_ATTR_FATTR_GROUP; |
3865 | else | 3865 | else |
3866 | dprintk("%s: nfs_map_group_to_gid failed!\n", | 3866 | dprintk("%s: nfs_map_group_to_gid failed!\n", |
3867 | __func__); | 3867 | __func__); |
3868 | } else | 3868 | } else |
3869 | dprintk("%s: name too long (%u)!\n", | 3869 | dprintk("%s: name too long (%u)!\n", |
3870 | __func__, len); | 3870 | __func__, len); |
3871 | bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; | 3871 | bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; |
3872 | } | 3872 | } |
3873 | dprintk("%s: gid=%d\n", __func__, (int)*gid); | 3873 | dprintk("%s: gid=%d\n", __func__, (int)*gid); |
3874 | return ret; | 3874 | return ret; |
3875 | out_overflow: | 3875 | out_overflow: |
3876 | print_overflow_msg(__func__, xdr); | 3876 | print_overflow_msg(__func__, xdr); |
3877 | return -EIO; | 3877 | return -EIO; |
3878 | } | 3878 | } |
3879 | 3879 | ||
3880 | static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) | 3880 | static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) |
3881 | { | 3881 | { |
3882 | uint32_t major = 0, minor = 0; | 3882 | uint32_t major = 0, minor = 0; |
3883 | __be32 *p; | 3883 | __be32 *p; |
3884 | int ret = 0; | 3884 | int ret = 0; |
3885 | 3885 | ||
3886 | *rdev = MKDEV(0,0); | 3886 | *rdev = MKDEV(0,0); |
3887 | if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) | 3887 | if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) |
3888 | return -EIO; | 3888 | return -EIO; |
3889 | if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) { | 3889 | if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) { |
3890 | dev_t tmp; | 3890 | dev_t tmp; |
3891 | 3891 | ||
3892 | p = xdr_inline_decode(xdr, 8); | 3892 | p = xdr_inline_decode(xdr, 8); |
3893 | if (unlikely(!p)) | 3893 | if (unlikely(!p)) |
3894 | goto out_overflow; | 3894 | goto out_overflow; |
3895 | major = be32_to_cpup(p++); | 3895 | major = be32_to_cpup(p++); |
3896 | minor = be32_to_cpup(p); | 3896 | minor = be32_to_cpup(p); |
3897 | tmp = MKDEV(major, minor); | 3897 | tmp = MKDEV(major, minor); |
3898 | if (MAJOR(tmp) == major && MINOR(tmp) == minor) | 3898 | if (MAJOR(tmp) == major && MINOR(tmp) == minor) |
3899 | *rdev = tmp; | 3899 | *rdev = tmp; |
3900 | bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; | 3900 | bitmap[1] &= ~ FATTR4_WORD1_RAWDEV; |
3901 | ret = NFS_ATTR_FATTR_RDEV; | 3901 | ret = NFS_ATTR_FATTR_RDEV; |
3902 | } | 3902 | } |
3903 | dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); | 3903 | dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor); |
3904 | return ret; | 3904 | return ret; |
3905 | out_overflow: | 3905 | out_overflow: |
3906 | print_overflow_msg(__func__, xdr); | 3906 | print_overflow_msg(__func__, xdr); |
3907 | return -EIO; | 3907 | return -EIO; |
3908 | } | 3908 | } |
3909 | 3909 | ||
3910 | static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3910 | static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
3911 | { | 3911 | { |
3912 | __be32 *p; | 3912 | __be32 *p; |
3913 | int status = 0; | 3913 | int status = 0; |
3914 | 3914 | ||
3915 | *res = 0; | 3915 | *res = 0; |
3916 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U))) | 3916 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U))) |
3917 | return -EIO; | 3917 | return -EIO; |
3918 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { | 3918 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) { |
3919 | p = xdr_inline_decode(xdr, 8); | 3919 | p = xdr_inline_decode(xdr, 8); |
3920 | if (unlikely(!p)) | 3920 | if (unlikely(!p)) |
3921 | goto out_overflow; | 3921 | goto out_overflow; |
3922 | xdr_decode_hyper(p, res); | 3922 | xdr_decode_hyper(p, res); |
3923 | bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; | 3923 | bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL; |
3924 | } | 3924 | } |
3925 | dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); | 3925 | dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res); |
3926 | return status; | 3926 | return status; |
3927 | out_overflow: | 3927 | out_overflow: |
3928 | print_overflow_msg(__func__, xdr); | 3928 | print_overflow_msg(__func__, xdr); |
3929 | return -EIO; | 3929 | return -EIO; |
3930 | } | 3930 | } |
3931 | 3931 | ||
3932 | static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3932 | static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
3933 | { | 3933 | { |
3934 | __be32 *p; | 3934 | __be32 *p; |
3935 | int status = 0; | 3935 | int status = 0; |
3936 | 3936 | ||
3937 | *res = 0; | 3937 | *res = 0; |
3938 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U))) | 3938 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U))) |
3939 | return -EIO; | 3939 | return -EIO; |
3940 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { | 3940 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) { |
3941 | p = xdr_inline_decode(xdr, 8); | 3941 | p = xdr_inline_decode(xdr, 8); |
3942 | if (unlikely(!p)) | 3942 | if (unlikely(!p)) |
3943 | goto out_overflow; | 3943 | goto out_overflow; |
3944 | xdr_decode_hyper(p, res); | 3944 | xdr_decode_hyper(p, res); |
3945 | bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; | 3945 | bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE; |
3946 | } | 3946 | } |
3947 | dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); | 3947 | dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res); |
3948 | return status; | 3948 | return status; |
3949 | out_overflow: | 3949 | out_overflow: |
3950 | print_overflow_msg(__func__, xdr); | 3950 | print_overflow_msg(__func__, xdr); |
3951 | return -EIO; | 3951 | return -EIO; |
3952 | } | 3952 | } |
3953 | 3953 | ||
3954 | static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) | 3954 | static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) |
3955 | { | 3955 | { |
3956 | __be32 *p; | 3956 | __be32 *p; |
3957 | int status = 0; | 3957 | int status = 0; |
3958 | 3958 | ||
3959 | *res = 0; | 3959 | *res = 0; |
3960 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U))) | 3960 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U))) |
3961 | return -EIO; | 3961 | return -EIO; |
3962 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { | 3962 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) { |
3963 | p = xdr_inline_decode(xdr, 8); | 3963 | p = xdr_inline_decode(xdr, 8); |
3964 | if (unlikely(!p)) | 3964 | if (unlikely(!p)) |
3965 | goto out_overflow; | 3965 | goto out_overflow; |
3966 | xdr_decode_hyper(p, res); | 3966 | xdr_decode_hyper(p, res); |
3967 | bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; | 3967 | bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL; |
3968 | } | 3968 | } |
3969 | dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); | 3969 | dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res); |
3970 | return status; | 3970 | return status; |
3971 | out_overflow: | 3971 | out_overflow: |
3972 | print_overflow_msg(__func__, xdr); | 3972 | print_overflow_msg(__func__, xdr); |
3973 | return -EIO; | 3973 | return -EIO; |
3974 | } | 3974 | } |
3975 | 3975 | ||
3976 | static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) | 3976 | static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) |
3977 | { | 3977 | { |
3978 | __be32 *p; | 3978 | __be32 *p; |
3979 | int ret = 0; | 3979 | int ret = 0; |
3980 | 3980 | ||
3981 | *used = 0; | 3981 | *used = 0; |
3982 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) | 3982 | if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) |
3983 | return -EIO; | 3983 | return -EIO; |
3984 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { | 3984 | if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) { |
3985 | p = xdr_inline_decode(xdr, 8); | 3985 | p = xdr_inline_decode(xdr, 8); |
3986 | if (unlikely(!p)) | 3986 | if (unlikely(!p)) |
3987 | goto out_overflow; | 3987 | goto out_overflow; |
3988 | xdr_decode_hyper(p, used); | 3988 | xdr_decode_hyper(p, used); |
3989 | bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; | 3989 | bitmap[1] &= ~FATTR4_WORD1_SPACE_USED; |
3990 | ret = NFS_ATTR_FATTR_SPACE_USED; | 3990 | ret = NFS_ATTR_FATTR_SPACE_USED; |
3991 | } | 3991 | } |
3992 | dprintk("%s: space used=%Lu\n", __func__, | 3992 | dprintk("%s: space used=%Lu\n", __func__, |
3993 | (unsigned long long)*used); | 3993 | (unsigned long long)*used); |
3994 | return ret; | 3994 | return ret; |
3995 | out_overflow: | 3995 | out_overflow: |
3996 | print_overflow_msg(__func__, xdr); | 3996 | print_overflow_msg(__func__, xdr); |
3997 | return -EIO; | 3997 | return -EIO; |
3998 | } | 3998 | } |
3999 | 3999 | ||
4000 | static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) | 4000 | static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) |
4001 | { | 4001 | { |
4002 | __be32 *p; | 4002 | __be32 *p; |
4003 | uint64_t sec; | 4003 | uint64_t sec; |
4004 | uint32_t nsec; | 4004 | uint32_t nsec; |
4005 | 4005 | ||
4006 | p = xdr_inline_decode(xdr, 12); | 4006 | p = xdr_inline_decode(xdr, 12); |
4007 | if (unlikely(!p)) | 4007 | if (unlikely(!p)) |
4008 | goto out_overflow; | 4008 | goto out_overflow; |
4009 | p = xdr_decode_hyper(p, &sec); | 4009 | p = xdr_decode_hyper(p, &sec); |
4010 | nsec = be32_to_cpup(p); | 4010 | nsec = be32_to_cpup(p); |
4011 | time->tv_sec = (time_t)sec; | 4011 | time->tv_sec = (time_t)sec; |
4012 | time->tv_nsec = (long)nsec; | 4012 | time->tv_nsec = (long)nsec; |
4013 | return 0; | 4013 | return 0; |
4014 | out_overflow: | 4014 | out_overflow: |
4015 | print_overflow_msg(__func__, xdr); | 4015 | print_overflow_msg(__func__, xdr); |
4016 | return -EIO; | 4016 | return -EIO; |
4017 | } | 4017 | } |
4018 | 4018 | ||
4019 | static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4019 | static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
4020 | { | 4020 | { |
4021 | int status = 0; | 4021 | int status = 0; |
4022 | 4022 | ||
4023 | time->tv_sec = 0; | 4023 | time->tv_sec = 0; |
4024 | time->tv_nsec = 0; | 4024 | time->tv_nsec = 0; |
4025 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U))) | 4025 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U))) |
4026 | return -EIO; | 4026 | return -EIO; |
4027 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { | 4027 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) { |
4028 | status = decode_attr_time(xdr, time); | 4028 | status = decode_attr_time(xdr, time); |
4029 | if (status == 0) | 4029 | if (status == 0) |
4030 | status = NFS_ATTR_FATTR_ATIME; | 4030 | status = NFS_ATTR_FATTR_ATIME; |
4031 | bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; | 4031 | bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; |
4032 | } | 4032 | } |
4033 | dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec); | 4033 | dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec); |
4034 | return status; | 4034 | return status; |
4035 | } | 4035 | } |
4036 | 4036 | ||
4037 | static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4037 | static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
4038 | { | 4038 | { |
4039 | int status = 0; | 4039 | int status = 0; |
4040 | 4040 | ||
4041 | time->tv_sec = 0; | 4041 | time->tv_sec = 0; |
4042 | time->tv_nsec = 0; | 4042 | time->tv_nsec = 0; |
4043 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U))) | 4043 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U))) |
4044 | return -EIO; | 4044 | return -EIO; |
4045 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { | 4045 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) { |
4046 | status = decode_attr_time(xdr, time); | 4046 | status = decode_attr_time(xdr, time); |
4047 | if (status == 0) | 4047 | if (status == 0) |
4048 | status = NFS_ATTR_FATTR_CTIME; | 4048 | status = NFS_ATTR_FATTR_CTIME; |
4049 | bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; | 4049 | bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; |
4050 | } | 4050 | } |
4051 | dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec); | 4051 | dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec); |
4052 | return status; | 4052 | return status; |
4053 | } | 4053 | } |
4054 | 4054 | ||
4055 | static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, | 4055 | static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, |
4056 | struct timespec *time) | 4056 | struct timespec *time) |
4057 | { | 4057 | { |
4058 | int status = 0; | 4058 | int status = 0; |
4059 | 4059 | ||
4060 | time->tv_sec = 0; | 4060 | time->tv_sec = 0; |
4061 | time->tv_nsec = 0; | 4061 | time->tv_nsec = 0; |
4062 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U))) | 4062 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U))) |
4063 | return -EIO; | 4063 | return -EIO; |
4064 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) { | 4064 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) { |
4065 | status = decode_attr_time(xdr, time); | 4065 | status = decode_attr_time(xdr, time); |
4066 | bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA; | 4066 | bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA; |
4067 | } | 4067 | } |
4068 | dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec, | 4068 | dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec, |
4069 | (long)time->tv_nsec); | 4069 | (long)time->tv_nsec); |
4070 | return status; | 4070 | return status; |
4071 | } | 4071 | } |
4072 | 4072 | ||
4073 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4073 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
4074 | { | 4074 | { |
4075 | int status = 0; | 4075 | int status = 0; |
4076 | 4076 | ||
4077 | time->tv_sec = 0; | 4077 | time->tv_sec = 0; |
4078 | time->tv_nsec = 0; | 4078 | time->tv_nsec = 0; |
4079 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U))) | 4079 | if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U))) |
4080 | return -EIO; | 4080 | return -EIO; |
4081 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { | 4081 | if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) { |
4082 | status = decode_attr_time(xdr, time); | 4082 | status = decode_attr_time(xdr, time); |
4083 | if (status == 0) | 4083 | if (status == 0) |
4084 | status = NFS_ATTR_FATTR_MTIME; | 4084 | status = NFS_ATTR_FATTR_MTIME; |
4085 | bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; | 4085 | bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; |
4086 | } | 4086 | } |
4087 | dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec); | 4087 | dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec); |
4088 | return status; | 4088 | return status; |
4089 | } | 4089 | } |
4090 | 4090 | ||
4091 | static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) | 4091 | static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) |
4092 | { | 4092 | { |
4093 | unsigned int attrwords = XDR_QUADLEN(attrlen); | 4093 | unsigned int attrwords = XDR_QUADLEN(attrlen); |
4094 | unsigned int nwords = xdr->p - savep; | 4094 | unsigned int nwords = xdr->p - savep; |
4095 | 4095 | ||
4096 | if (unlikely(attrwords != nwords)) { | 4096 | if (unlikely(attrwords != nwords)) { |
4097 | dprintk("%s: server returned incorrect attribute length: " | 4097 | dprintk("%s: server returned incorrect attribute length: " |
4098 | "%u %c %u\n", | 4098 | "%u %c %u\n", |
4099 | __func__, | 4099 | __func__, |
4100 | attrwords << 2, | 4100 | attrwords << 2, |
4101 | (attrwords < nwords) ? '<' : '>', | 4101 | (attrwords < nwords) ? '<' : '>', |
4102 | nwords << 2); | 4102 | nwords << 2); |
4103 | return -EIO; | 4103 | return -EIO; |
4104 | } | 4104 | } |
4105 | return 0; | 4105 | return 0; |
4106 | } | 4106 | } |
4107 | 4107 | ||
4108 | static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | 4108 | static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) |
4109 | { | 4109 | { |
4110 | __be32 *p; | 4110 | __be32 *p; |
4111 | 4111 | ||
4112 | p = xdr_inline_decode(xdr, 20); | 4112 | p = xdr_inline_decode(xdr, 20); |
4113 | if (unlikely(!p)) | 4113 | if (unlikely(!p)) |
4114 | goto out_overflow; | 4114 | goto out_overflow; |
4115 | cinfo->atomic = be32_to_cpup(p++); | 4115 | cinfo->atomic = be32_to_cpup(p++); |
4116 | p = xdr_decode_hyper(p, &cinfo->before); | 4116 | p = xdr_decode_hyper(p, &cinfo->before); |
4117 | xdr_decode_hyper(p, &cinfo->after); | 4117 | xdr_decode_hyper(p, &cinfo->after); |
4118 | return 0; | 4118 | return 0; |
4119 | out_overflow: | 4119 | out_overflow: |
4120 | print_overflow_msg(__func__, xdr); | 4120 | print_overflow_msg(__func__, xdr); |
4121 | return -EIO; | 4121 | return -EIO; |
4122 | } | 4122 | } |
4123 | 4123 | ||
4124 | static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access) | 4124 | static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access) |
4125 | { | 4125 | { |
4126 | __be32 *p; | 4126 | __be32 *p; |
4127 | uint32_t supp, acc; | 4127 | uint32_t supp, acc; |
4128 | int status; | 4128 | int status; |
4129 | 4129 | ||
4130 | status = decode_op_hdr(xdr, OP_ACCESS); | 4130 | status = decode_op_hdr(xdr, OP_ACCESS); |
4131 | if (status) | 4131 | if (status) |
4132 | return status; | 4132 | return status; |
4133 | p = xdr_inline_decode(xdr, 8); | 4133 | p = xdr_inline_decode(xdr, 8); |
4134 | if (unlikely(!p)) | 4134 | if (unlikely(!p)) |
4135 | goto out_overflow; | 4135 | goto out_overflow; |
4136 | supp = be32_to_cpup(p++); | 4136 | supp = be32_to_cpup(p++); |
4137 | acc = be32_to_cpup(p); | 4137 | acc = be32_to_cpup(p); |
4138 | access->supported = supp; | 4138 | access->supported = supp; |
4139 | access->access = acc; | 4139 | access->access = acc; |
4140 | return 0; | 4140 | return 0; |
4141 | out_overflow: | 4141 | out_overflow: |
4142 | print_overflow_msg(__func__, xdr); | 4142 | print_overflow_msg(__func__, xdr); |
4143 | return -EIO; | 4143 | return -EIO; |
4144 | } | 4144 | } |
4145 | 4145 | ||
4146 | static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) | 4146 | static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len) |
4147 | { | 4147 | { |
4148 | __be32 *p; | 4148 | __be32 *p; |
4149 | 4149 | ||
4150 | p = xdr_inline_decode(xdr, len); | 4150 | p = xdr_inline_decode(xdr, len); |
4151 | if (likely(p)) { | 4151 | if (likely(p)) { |
4152 | memcpy(buf, p, len); | 4152 | memcpy(buf, p, len); |
4153 | return 0; | 4153 | return 0; |
4154 | } | 4154 | } |
4155 | print_overflow_msg(__func__, xdr); | 4155 | print_overflow_msg(__func__, xdr); |
4156 | return -EIO; | 4156 | return -EIO; |
4157 | } | 4157 | } |
4158 | 4158 | ||
4159 | static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) | 4159 | static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) |
4160 | { | 4160 | { |
4161 | return decode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE); | 4161 | return decode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE); |
4162 | } | 4162 | } |
4163 | 4163 | ||
4164 | static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) | 4164 | static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) |
4165 | { | 4165 | { |
4166 | int status; | 4166 | int status; |
4167 | 4167 | ||
4168 | status = decode_op_hdr(xdr, OP_CLOSE); | 4168 | status = decode_op_hdr(xdr, OP_CLOSE); |
4169 | if (status != -EIO) | 4169 | if (status != -EIO) |
4170 | nfs_increment_open_seqid(status, res->seqid); | 4170 | nfs_increment_open_seqid(status, res->seqid); |
4171 | if (!status) | 4171 | if (!status) |
4172 | status = decode_stateid(xdr, &res->stateid); | 4172 | status = decode_stateid(xdr, &res->stateid); |
4173 | return status; | 4173 | return status; |
4174 | } | 4174 | } |
4175 | 4175 | ||
4176 | static int decode_verifier(struct xdr_stream *xdr, void *verifier) | 4176 | static int decode_verifier(struct xdr_stream *xdr, void *verifier) |
4177 | { | 4177 | { |
4178 | return decode_opaque_fixed(xdr, verifier, 8); | 4178 | return decode_opaque_fixed(xdr, verifier, 8); |
4179 | } | 4179 | } |
4180 | 4180 | ||
4181 | static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) | 4181 | static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) |
4182 | { | 4182 | { |
4183 | int status; | 4183 | int status; |
4184 | 4184 | ||
4185 | status = decode_op_hdr(xdr, OP_COMMIT); | 4185 | status = decode_op_hdr(xdr, OP_COMMIT); |
4186 | if (!status) | 4186 | if (!status) |
4187 | status = decode_verifier(xdr, res->verf->verifier); | 4187 | status = decode_verifier(xdr, res->verf->verifier); |
4188 | return status; | 4188 | return status; |
4189 | } | 4189 | } |
4190 | 4190 | ||
4191 | static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | 4191 | static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) |
4192 | { | 4192 | { |
4193 | __be32 *p; | 4193 | __be32 *p; |
4194 | uint32_t bmlen; | 4194 | uint32_t bmlen; |
4195 | int status; | 4195 | int status; |
4196 | 4196 | ||
4197 | status = decode_op_hdr(xdr, OP_CREATE); | 4197 | status = decode_op_hdr(xdr, OP_CREATE); |
4198 | if (status) | 4198 | if (status) |
4199 | return status; | 4199 | return status; |
4200 | if ((status = decode_change_info(xdr, cinfo))) | 4200 | if ((status = decode_change_info(xdr, cinfo))) |
4201 | return status; | 4201 | return status; |
4202 | p = xdr_inline_decode(xdr, 4); | 4202 | p = xdr_inline_decode(xdr, 4); |
4203 | if (unlikely(!p)) | 4203 | if (unlikely(!p)) |
4204 | goto out_overflow; | 4204 | goto out_overflow; |
4205 | bmlen = be32_to_cpup(p); | 4205 | bmlen = be32_to_cpup(p); |
4206 | p = xdr_inline_decode(xdr, bmlen << 2); | 4206 | p = xdr_inline_decode(xdr, bmlen << 2); |
4207 | if (likely(p)) | 4207 | if (likely(p)) |
4208 | return 0; | 4208 | return 0; |
4209 | out_overflow: | 4209 | out_overflow: |
4210 | print_overflow_msg(__func__, xdr); | 4210 | print_overflow_msg(__func__, xdr); |
4211 | return -EIO; | 4211 | return -EIO; |
4212 | } | 4212 | } |
4213 | 4213 | ||
4214 | static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) | 4214 | static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) |
4215 | { | 4215 | { |
4216 | __be32 *savep; | 4216 | __be32 *savep; |
4217 | uint32_t attrlen, bitmap[3] = {0}; | 4217 | uint32_t attrlen, bitmap[3] = {0}; |
4218 | int status; | 4218 | int status; |
4219 | 4219 | ||
4220 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4220 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
4221 | goto xdr_error; | 4221 | goto xdr_error; |
4222 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 4222 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
4223 | goto xdr_error; | 4223 | goto xdr_error; |
4224 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 4224 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
4225 | goto xdr_error; | 4225 | goto xdr_error; |
4226 | if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0) | 4226 | if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0) |
4227 | goto xdr_error; | 4227 | goto xdr_error; |
4228 | if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0) | 4228 | if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0) |
4229 | goto xdr_error; | 4229 | goto xdr_error; |
4230 | if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0) | 4230 | if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0) |
4231 | goto xdr_error; | 4231 | goto xdr_error; |
4232 | if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0) | 4232 | if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0) |
4233 | goto xdr_error; | 4233 | goto xdr_error; |
4234 | status = verify_attr_len(xdr, savep, attrlen); | 4234 | status = verify_attr_len(xdr, savep, attrlen); |
4235 | xdr_error: | 4235 | xdr_error: |
4236 | dprintk("%s: xdr returned %d!\n", __func__, -status); | 4236 | dprintk("%s: xdr returned %d!\n", __func__, -status); |
4237 | return status; | 4237 | return status; |
4238 | } | 4238 | } |
4239 | 4239 | ||
4240 | static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) | 4240 | static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) |
4241 | { | 4241 | { |
4242 | __be32 *savep; | 4242 | __be32 *savep; |
4243 | uint32_t attrlen, bitmap[3] = {0}; | 4243 | uint32_t attrlen, bitmap[3] = {0}; |
4244 | int status; | 4244 | int status; |
4245 | 4245 | ||
4246 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4246 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
4247 | goto xdr_error; | 4247 | goto xdr_error; |
4248 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 4248 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
4249 | goto xdr_error; | 4249 | goto xdr_error; |
4250 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 4250 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
4251 | goto xdr_error; | 4251 | goto xdr_error; |
4252 | 4252 | ||
4253 | if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0) | 4253 | if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0) |
4254 | goto xdr_error; | 4254 | goto xdr_error; |
4255 | if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0) | 4255 | if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0) |
4256 | goto xdr_error; | 4256 | goto xdr_error; |
4257 | if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0) | 4257 | if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0) |
4258 | goto xdr_error; | 4258 | goto xdr_error; |
4259 | if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0) | 4259 | if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0) |
4260 | goto xdr_error; | 4260 | goto xdr_error; |
4261 | if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0) | 4261 | if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0) |
4262 | goto xdr_error; | 4262 | goto xdr_error; |
4263 | if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0) | 4263 | if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0) |
4264 | goto xdr_error; | 4264 | goto xdr_error; |
4265 | 4265 | ||
4266 | status = verify_attr_len(xdr, savep, attrlen); | 4266 | status = verify_attr_len(xdr, savep, attrlen); |
4267 | xdr_error: | 4267 | xdr_error: |
4268 | dprintk("%s: xdr returned %d!\n", __func__, -status); | 4268 | dprintk("%s: xdr returned %d!\n", __func__, -status); |
4269 | return status; | 4269 | return status; |
4270 | } | 4270 | } |
4271 | 4271 | ||
4272 | static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) | 4272 | static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) |
4273 | { | 4273 | { |
4274 | __be32 *savep; | 4274 | __be32 *savep; |
4275 | uint32_t attrlen, bitmap[3] = {0}; | 4275 | uint32_t attrlen, bitmap[3] = {0}; |
4276 | int status; | 4276 | int status; |
4277 | 4277 | ||
4278 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4278 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
4279 | goto xdr_error; | 4279 | goto xdr_error; |
4280 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 4280 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
4281 | goto xdr_error; | 4281 | goto xdr_error; |
4282 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 4282 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
4283 | goto xdr_error; | 4283 | goto xdr_error; |
4284 | 4284 | ||
4285 | if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0) | 4285 | if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0) |
4286 | goto xdr_error; | 4286 | goto xdr_error; |
4287 | if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0) | 4287 | if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0) |
4288 | goto xdr_error; | 4288 | goto xdr_error; |
4289 | 4289 | ||
4290 | status = verify_attr_len(xdr, savep, attrlen); | 4290 | status = verify_attr_len(xdr, savep, attrlen); |
4291 | xdr_error: | 4291 | xdr_error: |
4292 | dprintk("%s: xdr returned %d!\n", __func__, -status); | 4292 | dprintk("%s: xdr returned %d!\n", __func__, -status); |
4293 | return status; | 4293 | return status; |
4294 | } | 4294 | } |
4295 | 4295 | ||
4296 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4296 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
4297 | struct nfs_fattr *fattr, struct nfs_fh *fh, | 4297 | struct nfs_fattr *fattr, struct nfs_fh *fh, |
4298 | const struct nfs_server *server) | 4298 | const struct nfs_server *server) |
4299 | { | 4299 | { |
4300 | int status; | 4300 | int status; |
4301 | umode_t fmode = 0; | 4301 | umode_t fmode = 0; |
4302 | uint32_t type; | 4302 | uint32_t type; |
4303 | int32_t err; | 4303 | int32_t err; |
4304 | 4304 | ||
4305 | status = decode_attr_type(xdr, bitmap, &type); | 4305 | status = decode_attr_type(xdr, bitmap, &type); |
4306 | if (status < 0) | 4306 | if (status < 0) |
4307 | goto xdr_error; | 4307 | goto xdr_error; |
4308 | fattr->mode = 0; | 4308 | fattr->mode = 0; |
4309 | if (status != 0) { | 4309 | if (status != 0) { |
4310 | fattr->mode |= nfs_type2fmt[type]; | 4310 | fattr->mode |= nfs_type2fmt[type]; |
4311 | fattr->valid |= status; | 4311 | fattr->valid |= status; |
4312 | } | 4312 | } |
4313 | 4313 | ||
4314 | status = decode_attr_change(xdr, bitmap, &fattr->change_attr); | 4314 | status = decode_attr_change(xdr, bitmap, &fattr->change_attr); |
4315 | if (status < 0) | 4315 | if (status < 0) |
4316 | goto xdr_error; | 4316 | goto xdr_error; |
4317 | fattr->valid |= status; | 4317 | fattr->valid |= status; |
4318 | 4318 | ||
4319 | status = decode_attr_size(xdr, bitmap, &fattr->size); | 4319 | status = decode_attr_size(xdr, bitmap, &fattr->size); |
4320 | if (status < 0) | 4320 | if (status < 0) |
4321 | goto xdr_error; | 4321 | goto xdr_error; |
4322 | fattr->valid |= status; | 4322 | fattr->valid |= status; |
4323 | 4323 | ||
4324 | status = decode_attr_fsid(xdr, bitmap, &fattr->fsid); | 4324 | status = decode_attr_fsid(xdr, bitmap, &fattr->fsid); |
4325 | if (status < 0) | 4325 | if (status < 0) |
4326 | goto xdr_error; | 4326 | goto xdr_error; |
4327 | fattr->valid |= status; | 4327 | fattr->valid |= status; |
4328 | 4328 | ||
4329 | err = 0; | 4329 | err = 0; |
4330 | status = decode_attr_error(xdr, bitmap, &err); | 4330 | status = decode_attr_error(xdr, bitmap, &err); |
4331 | if (status < 0) | 4331 | if (status < 0) |
4332 | goto xdr_error; | 4332 | goto xdr_error; |
4333 | if (err == -NFS4ERR_WRONGSEC) | 4333 | if (err == -NFS4ERR_WRONGSEC) |
4334 | nfs_fixup_secinfo_attributes(fattr, fh); | 4334 | nfs_fixup_secinfo_attributes(fattr, fh); |
4335 | 4335 | ||
4336 | status = decode_attr_filehandle(xdr, bitmap, fh); | 4336 | status = decode_attr_filehandle(xdr, bitmap, fh); |
4337 | if (status < 0) | 4337 | if (status < 0) |
4338 | goto xdr_error; | 4338 | goto xdr_error; |
4339 | 4339 | ||
4340 | status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); | 4340 | status = decode_attr_fileid(xdr, bitmap, &fattr->fileid); |
4341 | if (status < 0) | 4341 | if (status < 0) |
4342 | goto xdr_error; | 4342 | goto xdr_error; |
4343 | fattr->valid |= status; | 4343 | fattr->valid |= status; |
4344 | 4344 | ||
4345 | status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, | 4345 | status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, |
4346 | struct nfs4_fs_locations, | 4346 | struct nfs4_fs_locations, |
4347 | fattr)); | 4347 | fattr)); |
4348 | if (status < 0) | 4348 | if (status < 0) |
4349 | goto xdr_error; | 4349 | goto xdr_error; |
4350 | fattr->valid |= status; | 4350 | fattr->valid |= status; |
4351 | 4351 | ||
4352 | status = decode_attr_mode(xdr, bitmap, &fmode); | 4352 | status = decode_attr_mode(xdr, bitmap, &fmode); |
4353 | if (status < 0) | 4353 | if (status < 0) |
4354 | goto xdr_error; | 4354 | goto xdr_error; |
4355 | if (status != 0) { | 4355 | if (status != 0) { |
4356 | fattr->mode |= fmode; | 4356 | fattr->mode |= fmode; |
4357 | fattr->valid |= status; | 4357 | fattr->valid |= status; |
4358 | } | 4358 | } |
4359 | 4359 | ||
4360 | status = decode_attr_nlink(xdr, bitmap, &fattr->nlink); | 4360 | status = decode_attr_nlink(xdr, bitmap, &fattr->nlink); |
4361 | if (status < 0) | 4361 | if (status < 0) |
4362 | goto xdr_error; | 4362 | goto xdr_error; |
4363 | fattr->valid |= status; | 4363 | fattr->valid |= status; |
4364 | 4364 | ||
4365 | status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name); | 4365 | status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name); |
4366 | if (status < 0) | 4366 | if (status < 0) |
4367 | goto xdr_error; | 4367 | goto xdr_error; |
4368 | fattr->valid |= status; | 4368 | fattr->valid |= status; |
4369 | 4369 | ||
4370 | status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name); | 4370 | status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name); |
4371 | if (status < 0) | 4371 | if (status < 0) |
4372 | goto xdr_error; | 4372 | goto xdr_error; |
4373 | fattr->valid |= status; | 4373 | fattr->valid |= status; |
4374 | 4374 | ||
4375 | status = decode_attr_rdev(xdr, bitmap, &fattr->rdev); | 4375 | status = decode_attr_rdev(xdr, bitmap, &fattr->rdev); |
4376 | if (status < 0) | 4376 | if (status < 0) |
4377 | goto xdr_error; | 4377 | goto xdr_error; |
4378 | fattr->valid |= status; | 4378 | fattr->valid |= status; |
4379 | 4379 | ||
4380 | status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used); | 4380 | status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used); |
4381 | if (status < 0) | 4381 | if (status < 0) |
4382 | goto xdr_error; | 4382 | goto xdr_error; |
4383 | fattr->valid |= status; | 4383 | fattr->valid |= status; |
4384 | 4384 | ||
4385 | status = decode_attr_time_access(xdr, bitmap, &fattr->atime); | 4385 | status = decode_attr_time_access(xdr, bitmap, &fattr->atime); |
4386 | if (status < 0) | 4386 | if (status < 0) |
4387 | goto xdr_error; | 4387 | goto xdr_error; |
4388 | fattr->valid |= status; | 4388 | fattr->valid |= status; |
4389 | 4389 | ||
4390 | status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime); | 4390 | status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime); |
4391 | if (status < 0) | 4391 | if (status < 0) |
4392 | goto xdr_error; | 4392 | goto xdr_error; |
4393 | fattr->valid |= status; | 4393 | fattr->valid |= status; |
4394 | 4394 | ||
4395 | status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime); | 4395 | status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime); |
4396 | if (status < 0) | 4396 | if (status < 0) |
4397 | goto xdr_error; | 4397 | goto xdr_error; |
4398 | fattr->valid |= status; | 4398 | fattr->valid |= status; |
4399 | 4399 | ||
4400 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid); | 4400 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid); |
4401 | if (status < 0) | 4401 | if (status < 0) |
4402 | goto xdr_error; | 4402 | goto xdr_error; |
4403 | fattr->valid |= status; | 4403 | fattr->valid |= status; |
4404 | 4404 | ||
4405 | xdr_error: | 4405 | xdr_error: |
4406 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4406 | dprintk("%s: xdr returned %d\n", __func__, -status); |
4407 | return status; | 4407 | return status; |
4408 | } | 4408 | } |
4409 | 4409 | ||
4410 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4410 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4411 | struct nfs_fh *fh, const struct nfs_server *server) | 4411 | struct nfs_fh *fh, const struct nfs_server *server) |
4412 | { | 4412 | { |
4413 | __be32 *savep; | 4413 | __be32 *savep; |
4414 | uint32_t attrlen, | 4414 | uint32_t attrlen, |
4415 | bitmap[3] = {0}; | 4415 | bitmap[3] = {0}; |
4416 | int status; | 4416 | int status; |
4417 | 4417 | ||
4418 | status = decode_op_hdr(xdr, OP_GETATTR); | 4418 | status = decode_op_hdr(xdr, OP_GETATTR); |
4419 | if (status < 0) | 4419 | if (status < 0) |
4420 | goto xdr_error; | 4420 | goto xdr_error; |
4421 | 4421 | ||
4422 | status = decode_attr_bitmap(xdr, bitmap); | 4422 | status = decode_attr_bitmap(xdr, bitmap); |
4423 | if (status < 0) | 4423 | if (status < 0) |
4424 | goto xdr_error; | 4424 | goto xdr_error; |
4425 | 4425 | ||
4426 | status = decode_attr_length(xdr, &attrlen, &savep); | 4426 | status = decode_attr_length(xdr, &attrlen, &savep); |
4427 | if (status < 0) | 4427 | if (status < 0) |
4428 | goto xdr_error; | 4428 | goto xdr_error; |
4429 | 4429 | ||
4430 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server); | 4430 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server); |
4431 | if (status < 0) | 4431 | if (status < 0) |
4432 | goto xdr_error; | 4432 | goto xdr_error; |
4433 | 4433 | ||
4434 | status = verify_attr_len(xdr, savep, attrlen); | 4434 | status = verify_attr_len(xdr, savep, attrlen); |
4435 | xdr_error: | 4435 | xdr_error: |
4436 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4436 | dprintk("%s: xdr returned %d\n", __func__, -status); |
4437 | return status; | 4437 | return status; |
4438 | } | 4438 | } |
4439 | 4439 | ||
4440 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4440 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4441 | const struct nfs_server *server) | 4441 | const struct nfs_server *server) |
4442 | { | 4442 | { |
4443 | return decode_getfattr_generic(xdr, fattr, NULL, server); | 4443 | return decode_getfattr_generic(xdr, fattr, NULL, server); |
4444 | } | 4444 | } |
4445 | 4445 | ||
4446 | /* | 4446 | /* |
4447 | * Decode potentially multiple layout types. Currently we only support | 4447 | * Decode potentially multiple layout types. Currently we only support |
4448 | * one layout driver per file system. | 4448 | * one layout driver per file system. |
4449 | */ | 4449 | */ |
4450 | static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, | 4450 | static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, |
4451 | uint32_t *layouttype) | 4451 | uint32_t *layouttype) |
4452 | { | 4452 | { |
4453 | uint32_t *p; | 4453 | uint32_t *p; |
4454 | int num; | 4454 | int num; |
4455 | 4455 | ||
4456 | p = xdr_inline_decode(xdr, 4); | 4456 | p = xdr_inline_decode(xdr, 4); |
4457 | if (unlikely(!p)) | 4457 | if (unlikely(!p)) |
4458 | goto out_overflow; | 4458 | goto out_overflow; |
4459 | num = be32_to_cpup(p); | 4459 | num = be32_to_cpup(p); |
4460 | 4460 | ||
4461 | /* pNFS is not supported by the underlying file system */ | 4461 | /* pNFS is not supported by the underlying file system */ |
4462 | if (num == 0) { | 4462 | if (num == 0) { |
4463 | *layouttype = 0; | 4463 | *layouttype = 0; |
4464 | return 0; | 4464 | return 0; |
4465 | } | 4465 | } |
4466 | if (num > 1) | 4466 | if (num > 1) |
4467 | printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers " | 4467 | printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers " |
4468 | "per filesystem not supported\n", __func__); | 4468 | "per filesystem not supported\n", __func__); |
4469 | 4469 | ||
4470 | /* Decode and set first layout type, move xdr->p past unused types */ | 4470 | /* Decode and set first layout type, move xdr->p past unused types */ |
4471 | p = xdr_inline_decode(xdr, num * 4); | 4471 | p = xdr_inline_decode(xdr, num * 4); |
4472 | if (unlikely(!p)) | 4472 | if (unlikely(!p)) |
4473 | goto out_overflow; | 4473 | goto out_overflow; |
4474 | *layouttype = be32_to_cpup(p); | 4474 | *layouttype = be32_to_cpup(p); |
4475 | return 0; | 4475 | return 0; |
4476 | out_overflow: | 4476 | out_overflow: |
4477 | print_overflow_msg(__func__, xdr); | 4477 | print_overflow_msg(__func__, xdr); |
4478 | return -EIO; | 4478 | return -EIO; |
4479 | } | 4479 | } |
4480 | 4480 | ||
4481 | /* | 4481 | /* |
4482 | * The type of file system exported. | 4482 | * The type of file system exported. |
4483 | * Note we must ensure that layouttype is set in any non-error case. | 4483 | * Note we must ensure that layouttype is set in any non-error case. |
4484 | */ | 4484 | */ |
4485 | static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, | 4485 | static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, |
4486 | uint32_t *layouttype) | 4486 | uint32_t *layouttype) |
4487 | { | 4487 | { |
4488 | int status = 0; | 4488 | int status = 0; |
4489 | 4489 | ||
4490 | dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); | 4490 | dprintk("%s: bitmap is %x\n", __func__, bitmap[1]); |
4491 | if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) | 4491 | if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U))) |
4492 | return -EIO; | 4492 | return -EIO; |
4493 | if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { | 4493 | if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) { |
4494 | status = decode_first_pnfs_layout_type(xdr, layouttype); | 4494 | status = decode_first_pnfs_layout_type(xdr, layouttype); |
4495 | bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; | 4495 | bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES; |
4496 | } else | 4496 | } else |
4497 | *layouttype = 0; | 4497 | *layouttype = 0; |
4498 | return status; | 4498 | return status; |
4499 | } | 4499 | } |
4500 | 4500 | ||
4501 | /* | 4501 | /* |
4502 | * The prefered block size for layout directed io | 4502 | * The prefered block size for layout directed io |
4503 | */ | 4503 | */ |
4504 | static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, | 4504 | static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, |
4505 | uint32_t *res) | 4505 | uint32_t *res) |
4506 | { | 4506 | { |
4507 | __be32 *p; | 4507 | __be32 *p; |
4508 | 4508 | ||
4509 | dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); | 4509 | dprintk("%s: bitmap is %x\n", __func__, bitmap[2]); |
4510 | *res = 0; | 4510 | *res = 0; |
4511 | if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) { | 4511 | if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) { |
4512 | p = xdr_inline_decode(xdr, 4); | 4512 | p = xdr_inline_decode(xdr, 4); |
4513 | if (unlikely(!p)) { | 4513 | if (unlikely(!p)) { |
4514 | print_overflow_msg(__func__, xdr); | 4514 | print_overflow_msg(__func__, xdr); |
4515 | return -EIO; | 4515 | return -EIO; |
4516 | } | 4516 | } |
4517 | *res = be32_to_cpup(p); | 4517 | *res = be32_to_cpup(p); |
4518 | bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE; | 4518 | bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE; |
4519 | } | 4519 | } |
4520 | return 0; | 4520 | return 0; |
4521 | } | 4521 | } |
4522 | 4522 | ||
4523 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | 4523 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) |
4524 | { | 4524 | { |
4525 | __be32 *savep; | 4525 | __be32 *savep; |
4526 | uint32_t attrlen, bitmap[3]; | 4526 | uint32_t attrlen, bitmap[3]; |
4527 | int status; | 4527 | int status; |
4528 | 4528 | ||
4529 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4529 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
4530 | goto xdr_error; | 4530 | goto xdr_error; |
4531 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 4531 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
4532 | goto xdr_error; | 4532 | goto xdr_error; |
4533 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 4533 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
4534 | goto xdr_error; | 4534 | goto xdr_error; |
4535 | 4535 | ||
4536 | fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */ | 4536 | fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */ |
4537 | 4537 | ||
4538 | if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0) | 4538 | if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0) |
4539 | goto xdr_error; | 4539 | goto xdr_error; |
4540 | if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0) | 4540 | if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0) |
4541 | goto xdr_error; | 4541 | goto xdr_error; |
4542 | if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0) | 4542 | if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0) |
4543 | goto xdr_error; | 4543 | goto xdr_error; |
4544 | fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax; | 4544 | fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax; |
4545 | if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0) | 4545 | if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0) |
4546 | goto xdr_error; | 4546 | goto xdr_error; |
4547 | fsinfo->wtpref = fsinfo->wtmax; | 4547 | fsinfo->wtpref = fsinfo->wtmax; |
4548 | status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); | 4548 | status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta); |
4549 | if (status != 0) | 4549 | if (status != 0) |
4550 | goto xdr_error; | 4550 | goto xdr_error; |
4551 | status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); | 4551 | status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype); |
4552 | if (status != 0) | 4552 | if (status != 0) |
4553 | goto xdr_error; | 4553 | goto xdr_error; |
4554 | status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize); | 4554 | status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize); |
4555 | if (status) | 4555 | if (status) |
4556 | goto xdr_error; | 4556 | goto xdr_error; |
4557 | 4557 | ||
4558 | status = verify_attr_len(xdr, savep, attrlen); | 4558 | status = verify_attr_len(xdr, savep, attrlen); |
4559 | xdr_error: | 4559 | xdr_error: |
4560 | dprintk("%s: xdr returned %d!\n", __func__, -status); | 4560 | dprintk("%s: xdr returned %d!\n", __func__, -status); |
4561 | return status; | 4561 | return status; |
4562 | } | 4562 | } |
4563 | 4563 | ||
4564 | static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) | 4564 | static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) |
4565 | { | 4565 | { |
4566 | __be32 *p; | 4566 | __be32 *p; |
4567 | uint32_t len; | 4567 | uint32_t len; |
4568 | int status; | 4568 | int status; |
4569 | 4569 | ||
4570 | /* Zero handle first to allow comparisons */ | 4570 | /* Zero handle first to allow comparisons */ |
4571 | memset(fh, 0, sizeof(*fh)); | 4571 | memset(fh, 0, sizeof(*fh)); |
4572 | 4572 | ||
4573 | status = decode_op_hdr(xdr, OP_GETFH); | 4573 | status = decode_op_hdr(xdr, OP_GETFH); |
4574 | if (status) | 4574 | if (status) |
4575 | return status; | 4575 | return status; |
4576 | 4576 | ||
4577 | p = xdr_inline_decode(xdr, 4); | 4577 | p = xdr_inline_decode(xdr, 4); |
4578 | if (unlikely(!p)) | 4578 | if (unlikely(!p)) |
4579 | goto out_overflow; | 4579 | goto out_overflow; |
4580 | len = be32_to_cpup(p); | 4580 | len = be32_to_cpup(p); |
4581 | if (len > NFS4_FHSIZE) | 4581 | if (len > NFS4_FHSIZE) |
4582 | return -EIO; | 4582 | return -EIO; |
4583 | fh->size = len; | 4583 | fh->size = len; |
4584 | p = xdr_inline_decode(xdr, len); | 4584 | p = xdr_inline_decode(xdr, len); |
4585 | if (unlikely(!p)) | 4585 | if (unlikely(!p)) |
4586 | goto out_overflow; | 4586 | goto out_overflow; |
4587 | memcpy(fh->data, p, len); | 4587 | memcpy(fh->data, p, len); |
4588 | return 0; | 4588 | return 0; |
4589 | out_overflow: | 4589 | out_overflow: |
4590 | print_overflow_msg(__func__, xdr); | 4590 | print_overflow_msg(__func__, xdr); |
4591 | return -EIO; | 4591 | return -EIO; |
4592 | } | 4592 | } |
4593 | 4593 | ||
4594 | static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | 4594 | static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) |
4595 | { | 4595 | { |
4596 | int status; | 4596 | int status; |
4597 | 4597 | ||
4598 | status = decode_op_hdr(xdr, OP_LINK); | 4598 | status = decode_op_hdr(xdr, OP_LINK); |
4599 | if (status) | 4599 | if (status) |
4600 | return status; | 4600 | return status; |
4601 | return decode_change_info(xdr, cinfo); | 4601 | return decode_change_info(xdr, cinfo); |
4602 | } | 4602 | } |
4603 | 4603 | ||
4604 | /* | 4604 | /* |
4605 | * We create the owner, so we know a proper owner.id length is 4. | 4605 | * We create the owner, so we know a proper owner.id length is 4. |
4606 | */ | 4606 | */ |
4607 | static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) | 4607 | static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) |
4608 | { | 4608 | { |
4609 | uint64_t offset, length, clientid; | 4609 | uint64_t offset, length, clientid; |
4610 | __be32 *p; | 4610 | __be32 *p; |
4611 | uint32_t namelen, type; | 4611 | uint32_t namelen, type; |
4612 | 4612 | ||
4613 | p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ | 4613 | p = xdr_inline_decode(xdr, 32); /* read 32 bytes */ |
4614 | if (unlikely(!p)) | 4614 | if (unlikely(!p)) |
4615 | goto out_overflow; | 4615 | goto out_overflow; |
4616 | p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ | 4616 | p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */ |
4617 | p = xdr_decode_hyper(p, &length); | 4617 | p = xdr_decode_hyper(p, &length); |
4618 | type = be32_to_cpup(p++); /* 4 byte read */ | 4618 | type = be32_to_cpup(p++); /* 4 byte read */ |
4619 | if (fl != NULL) { /* manipulate file lock */ | 4619 | if (fl != NULL) { /* manipulate file lock */ |
4620 | fl->fl_start = (loff_t)offset; | 4620 | fl->fl_start = (loff_t)offset; |
4621 | fl->fl_end = fl->fl_start + (loff_t)length - 1; | 4621 | fl->fl_end = fl->fl_start + (loff_t)length - 1; |
4622 | if (length == ~(uint64_t)0) | 4622 | if (length == ~(uint64_t)0) |
4623 | fl->fl_end = OFFSET_MAX; | 4623 | fl->fl_end = OFFSET_MAX; |
4624 | fl->fl_type = F_WRLCK; | 4624 | fl->fl_type = F_WRLCK; |
4625 | if (type & 1) | 4625 | if (type & 1) |
4626 | fl->fl_type = F_RDLCK; | 4626 | fl->fl_type = F_RDLCK; |
4627 | fl->fl_pid = 0; | 4627 | fl->fl_pid = 0; |
4628 | } | 4628 | } |
4629 | p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ | 4629 | p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */ |
4630 | namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ | 4630 | namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */ |
4631 | p = xdr_inline_decode(xdr, namelen); /* variable size field */ | 4631 | p = xdr_inline_decode(xdr, namelen); /* variable size field */ |
4632 | if (likely(p)) | 4632 | if (likely(p)) |
4633 | return -NFS4ERR_DENIED; | 4633 | return -NFS4ERR_DENIED; |
4634 | out_overflow: | 4634 | out_overflow: |
4635 | print_overflow_msg(__func__, xdr); | 4635 | print_overflow_msg(__func__, xdr); |
4636 | return -EIO; | 4636 | return -EIO; |
4637 | } | 4637 | } |
4638 | 4638 | ||
4639 | static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) | 4639 | static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) |
4640 | { | 4640 | { |
4641 | int status; | 4641 | int status; |
4642 | 4642 | ||
4643 | status = decode_op_hdr(xdr, OP_LOCK); | 4643 | status = decode_op_hdr(xdr, OP_LOCK); |
4644 | if (status == -EIO) | 4644 | if (status == -EIO) |
4645 | goto out; | 4645 | goto out; |
4646 | if (status == 0) { | 4646 | if (status == 0) { |
4647 | status = decode_stateid(xdr, &res->stateid); | 4647 | status = decode_stateid(xdr, &res->stateid); |
4648 | if (unlikely(status)) | 4648 | if (unlikely(status)) |
4649 | goto out; | 4649 | goto out; |
4650 | } else if (status == -NFS4ERR_DENIED) | 4650 | } else if (status == -NFS4ERR_DENIED) |
4651 | status = decode_lock_denied(xdr, NULL); | 4651 | status = decode_lock_denied(xdr, NULL); |
4652 | if (res->open_seqid != NULL) | 4652 | if (res->open_seqid != NULL) |
4653 | nfs_increment_open_seqid(status, res->open_seqid); | 4653 | nfs_increment_open_seqid(status, res->open_seqid); |
4654 | nfs_increment_lock_seqid(status, res->lock_seqid); | 4654 | nfs_increment_lock_seqid(status, res->lock_seqid); |
4655 | out: | 4655 | out: |
4656 | return status; | 4656 | return status; |
4657 | } | 4657 | } |
4658 | 4658 | ||
4659 | static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) | 4659 | static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) |
4660 | { | 4660 | { |
4661 | int status; | 4661 | int status; |
4662 | status = decode_op_hdr(xdr, OP_LOCKT); | 4662 | status = decode_op_hdr(xdr, OP_LOCKT); |
4663 | if (status == -NFS4ERR_DENIED) | 4663 | if (status == -NFS4ERR_DENIED) |
4664 | return decode_lock_denied(xdr, res->denied); | 4664 | return decode_lock_denied(xdr, res->denied); |
4665 | return status; | 4665 | return status; |
4666 | } | 4666 | } |
4667 | 4667 | ||
4668 | static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) | 4668 | static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) |
4669 | { | 4669 | { |
4670 | int status; | 4670 | int status; |
4671 | 4671 | ||
4672 | status = decode_op_hdr(xdr, OP_LOCKU); | 4672 | status = decode_op_hdr(xdr, OP_LOCKU); |
4673 | if (status != -EIO) | 4673 | if (status != -EIO) |
4674 | nfs_increment_lock_seqid(status, res->seqid); | 4674 | nfs_increment_lock_seqid(status, res->seqid); |
4675 | if (status == 0) | 4675 | if (status == 0) |
4676 | status = decode_stateid(xdr, &res->stateid); | 4676 | status = decode_stateid(xdr, &res->stateid); |
4677 | return status; | 4677 | return status; |
4678 | } | 4678 | } |
4679 | 4679 | ||
4680 | static int decode_release_lockowner(struct xdr_stream *xdr) | 4680 | static int decode_release_lockowner(struct xdr_stream *xdr) |
4681 | { | 4681 | { |
4682 | return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); | 4682 | return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); |
4683 | } | 4683 | } |
4684 | 4684 | ||
4685 | static int decode_lookup(struct xdr_stream *xdr) | 4685 | static int decode_lookup(struct xdr_stream *xdr) |
4686 | { | 4686 | { |
4687 | return decode_op_hdr(xdr, OP_LOOKUP); | 4687 | return decode_op_hdr(xdr, OP_LOOKUP); |
4688 | } | 4688 | } |
4689 | 4689 | ||
4690 | /* This is too sick! */ | 4690 | /* This is too sick! */ |
4691 | static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize) | 4691 | static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize) |
4692 | { | 4692 | { |
4693 | __be32 *p; | 4693 | __be32 *p; |
4694 | uint32_t limit_type, nblocks, blocksize; | 4694 | uint32_t limit_type, nblocks, blocksize; |
4695 | 4695 | ||
4696 | p = xdr_inline_decode(xdr, 12); | 4696 | p = xdr_inline_decode(xdr, 12); |
4697 | if (unlikely(!p)) | 4697 | if (unlikely(!p)) |
4698 | goto out_overflow; | 4698 | goto out_overflow; |
4699 | limit_type = be32_to_cpup(p++); | 4699 | limit_type = be32_to_cpup(p++); |
4700 | switch (limit_type) { | 4700 | switch (limit_type) { |
4701 | case 1: | 4701 | case 1: |
4702 | xdr_decode_hyper(p, maxsize); | 4702 | xdr_decode_hyper(p, maxsize); |
4703 | break; | 4703 | break; |
4704 | case 2: | 4704 | case 2: |
4705 | nblocks = be32_to_cpup(p++); | 4705 | nblocks = be32_to_cpup(p++); |
4706 | blocksize = be32_to_cpup(p); | 4706 | blocksize = be32_to_cpup(p); |
4707 | *maxsize = (uint64_t)nblocks * (uint64_t)blocksize; | 4707 | *maxsize = (uint64_t)nblocks * (uint64_t)blocksize; |
4708 | } | 4708 | } |
4709 | return 0; | 4709 | return 0; |
4710 | out_overflow: | 4710 | out_overflow: |
4711 | print_overflow_msg(__func__, xdr); | 4711 | print_overflow_msg(__func__, xdr); |
4712 | return -EIO; | 4712 | return -EIO; |
4713 | } | 4713 | } |
4714 | 4714 | ||
4715 | static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) | 4715 | static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) |
4716 | { | 4716 | { |
4717 | __be32 *p; | 4717 | __be32 *p; |
4718 | uint32_t delegation_type; | 4718 | uint32_t delegation_type; |
4719 | int status; | 4719 | int status; |
4720 | 4720 | ||
4721 | p = xdr_inline_decode(xdr, 4); | 4721 | p = xdr_inline_decode(xdr, 4); |
4722 | if (unlikely(!p)) | 4722 | if (unlikely(!p)) |
4723 | goto out_overflow; | 4723 | goto out_overflow; |
4724 | delegation_type = be32_to_cpup(p); | 4724 | delegation_type = be32_to_cpup(p); |
4725 | if (delegation_type == NFS4_OPEN_DELEGATE_NONE) { | 4725 | if (delegation_type == NFS4_OPEN_DELEGATE_NONE) { |
4726 | res->delegation_type = 0; | 4726 | res->delegation_type = 0; |
4727 | return 0; | 4727 | return 0; |
4728 | } | 4728 | } |
4729 | status = decode_stateid(xdr, &res->delegation); | 4729 | status = decode_stateid(xdr, &res->delegation); |
4730 | if (unlikely(status)) | 4730 | if (unlikely(status)) |
4731 | return status; | 4731 | return status; |
4732 | p = xdr_inline_decode(xdr, 4); | 4732 | p = xdr_inline_decode(xdr, 4); |
4733 | if (unlikely(!p)) | 4733 | if (unlikely(!p)) |
4734 | goto out_overflow; | 4734 | goto out_overflow; |
4735 | res->do_recall = be32_to_cpup(p); | 4735 | res->do_recall = be32_to_cpup(p); |
4736 | 4736 | ||
4737 | switch (delegation_type) { | 4737 | switch (delegation_type) { |
4738 | case NFS4_OPEN_DELEGATE_READ: | 4738 | case NFS4_OPEN_DELEGATE_READ: |
4739 | res->delegation_type = FMODE_READ; | 4739 | res->delegation_type = FMODE_READ; |
4740 | break; | 4740 | break; |
4741 | case NFS4_OPEN_DELEGATE_WRITE: | 4741 | case NFS4_OPEN_DELEGATE_WRITE: |
4742 | res->delegation_type = FMODE_WRITE|FMODE_READ; | 4742 | res->delegation_type = FMODE_WRITE|FMODE_READ; |
4743 | if (decode_space_limit(xdr, &res->maxsize) < 0) | 4743 | if (decode_space_limit(xdr, &res->maxsize) < 0) |
4744 | return -EIO; | 4744 | return -EIO; |
4745 | } | 4745 | } |
4746 | return decode_ace(xdr, NULL, res->server->nfs_client); | 4746 | return decode_ace(xdr, NULL, res->server->nfs_client); |
4747 | out_overflow: | 4747 | out_overflow: |
4748 | print_overflow_msg(__func__, xdr); | 4748 | print_overflow_msg(__func__, xdr); |
4749 | return -EIO; | 4749 | return -EIO; |
4750 | } | 4750 | } |
4751 | 4751 | ||
4752 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | 4752 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) |
4753 | { | 4753 | { |
4754 | __be32 *p; | 4754 | __be32 *p; |
4755 | uint32_t savewords, bmlen, i; | 4755 | uint32_t savewords, bmlen, i; |
4756 | int status; | 4756 | int status; |
4757 | 4757 | ||
4758 | status = decode_op_hdr(xdr, OP_OPEN); | 4758 | status = decode_op_hdr(xdr, OP_OPEN); |
4759 | if (status != -EIO) | 4759 | if (status != -EIO) |
4760 | nfs_increment_open_seqid(status, res->seqid); | 4760 | nfs_increment_open_seqid(status, res->seqid); |
4761 | if (!status) | 4761 | if (!status) |
4762 | status = decode_stateid(xdr, &res->stateid); | 4762 | status = decode_stateid(xdr, &res->stateid); |
4763 | if (unlikely(status)) | 4763 | if (unlikely(status)) |
4764 | return status; | 4764 | return status; |
4765 | 4765 | ||
4766 | decode_change_info(xdr, &res->cinfo); | 4766 | decode_change_info(xdr, &res->cinfo); |
4767 | 4767 | ||
4768 | p = xdr_inline_decode(xdr, 8); | 4768 | p = xdr_inline_decode(xdr, 8); |
4769 | if (unlikely(!p)) | 4769 | if (unlikely(!p)) |
4770 | goto out_overflow; | 4770 | goto out_overflow; |
4771 | res->rflags = be32_to_cpup(p++); | 4771 | res->rflags = be32_to_cpup(p++); |
4772 | bmlen = be32_to_cpup(p); | 4772 | bmlen = be32_to_cpup(p); |
4773 | if (bmlen > 10) | 4773 | if (bmlen > 10) |
4774 | goto xdr_error; | 4774 | goto xdr_error; |
4775 | 4775 | ||
4776 | p = xdr_inline_decode(xdr, bmlen << 2); | 4776 | p = xdr_inline_decode(xdr, bmlen << 2); |
4777 | if (unlikely(!p)) | 4777 | if (unlikely(!p)) |
4778 | goto out_overflow; | 4778 | goto out_overflow; |
4779 | savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); | 4779 | savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE); |
4780 | for (i = 0; i < savewords; ++i) | 4780 | for (i = 0; i < savewords; ++i) |
4781 | res->attrset[i] = be32_to_cpup(p++); | 4781 | res->attrset[i] = be32_to_cpup(p++); |
4782 | for (; i < NFS4_BITMAP_SIZE; i++) | 4782 | for (; i < NFS4_BITMAP_SIZE; i++) |
4783 | res->attrset[i] = 0; | 4783 | res->attrset[i] = 0; |
4784 | 4784 | ||
4785 | return decode_delegation(xdr, res); | 4785 | return decode_delegation(xdr, res); |
4786 | xdr_error: | 4786 | xdr_error: |
4787 | dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); | 4787 | dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); |
4788 | return -EIO; | 4788 | return -EIO; |
4789 | out_overflow: | 4789 | out_overflow: |
4790 | print_overflow_msg(__func__, xdr); | 4790 | print_overflow_msg(__func__, xdr); |
4791 | return -EIO; | 4791 | return -EIO; |
4792 | } | 4792 | } |
4793 | 4793 | ||
4794 | static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) | 4794 | static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) |
4795 | { | 4795 | { |
4796 | int status; | 4796 | int status; |
4797 | 4797 | ||
4798 | status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); | 4798 | status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); |
4799 | if (status != -EIO) | 4799 | if (status != -EIO) |
4800 | nfs_increment_open_seqid(status, res->seqid); | 4800 | nfs_increment_open_seqid(status, res->seqid); |
4801 | if (!status) | 4801 | if (!status) |
4802 | status = decode_stateid(xdr, &res->stateid); | 4802 | status = decode_stateid(xdr, &res->stateid); |
4803 | return status; | 4803 | return status; |
4804 | } | 4804 | } |
4805 | 4805 | ||
4806 | static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res) | 4806 | static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res) |
4807 | { | 4807 | { |
4808 | int status; | 4808 | int status; |
4809 | 4809 | ||
4810 | status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); | 4810 | status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); |
4811 | if (status != -EIO) | 4811 | if (status != -EIO) |
4812 | nfs_increment_open_seqid(status, res->seqid); | 4812 | nfs_increment_open_seqid(status, res->seqid); |
4813 | if (!status) | 4813 | if (!status) |
4814 | status = decode_stateid(xdr, &res->stateid); | 4814 | status = decode_stateid(xdr, &res->stateid); |
4815 | return status; | 4815 | return status; |
4816 | } | 4816 | } |
4817 | 4817 | ||
4818 | static int decode_putfh(struct xdr_stream *xdr) | 4818 | static int decode_putfh(struct xdr_stream *xdr) |
4819 | { | 4819 | { |
4820 | return decode_op_hdr(xdr, OP_PUTFH); | 4820 | return decode_op_hdr(xdr, OP_PUTFH); |
4821 | } | 4821 | } |
4822 | 4822 | ||
4823 | static int decode_putrootfh(struct xdr_stream *xdr) | 4823 | static int decode_putrootfh(struct xdr_stream *xdr) |
4824 | { | 4824 | { |
4825 | return decode_op_hdr(xdr, OP_PUTROOTFH); | 4825 | return decode_op_hdr(xdr, OP_PUTROOTFH); |
4826 | } | 4826 | } |
4827 | 4827 | ||
4828 | static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) | 4828 | static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) |
4829 | { | 4829 | { |
4830 | struct kvec *iov = req->rq_rcv_buf.head; | 4830 | struct kvec *iov = req->rq_rcv_buf.head; |
4831 | __be32 *p; | 4831 | __be32 *p; |
4832 | uint32_t count, eof, recvd, hdrlen; | 4832 | uint32_t count, eof, recvd, hdrlen; |
4833 | int status; | 4833 | int status; |
4834 | 4834 | ||
4835 | status = decode_op_hdr(xdr, OP_READ); | 4835 | status = decode_op_hdr(xdr, OP_READ); |
4836 | if (status) | 4836 | if (status) |
4837 | return status; | 4837 | return status; |
4838 | p = xdr_inline_decode(xdr, 8); | 4838 | p = xdr_inline_decode(xdr, 8); |
4839 | if (unlikely(!p)) | 4839 | if (unlikely(!p)) |
4840 | goto out_overflow; | 4840 | goto out_overflow; |
4841 | eof = be32_to_cpup(p++); | 4841 | eof = be32_to_cpup(p++); |
4842 | count = be32_to_cpup(p); | 4842 | count = be32_to_cpup(p); |
4843 | hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; | 4843 | hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; |
4844 | recvd = req->rq_rcv_buf.len - hdrlen; | 4844 | recvd = req->rq_rcv_buf.len - hdrlen; |
4845 | if (count > recvd) { | 4845 | if (count > recvd) { |
4846 | dprintk("NFS: server cheating in read reply: " | 4846 | dprintk("NFS: server cheating in read reply: " |
4847 | "count %u > recvd %u\n", count, recvd); | 4847 | "count %u > recvd %u\n", count, recvd); |
4848 | count = recvd; | 4848 | count = recvd; |
4849 | eof = 0; | 4849 | eof = 0; |
4850 | } | 4850 | } |
4851 | xdr_read_pages(xdr, count); | 4851 | xdr_read_pages(xdr, count); |
4852 | res->eof = eof; | 4852 | res->eof = eof; |
4853 | res->count = count; | 4853 | res->count = count; |
4854 | return 0; | 4854 | return 0; |
4855 | out_overflow: | 4855 | out_overflow: |
4856 | print_overflow_msg(__func__, xdr); | 4856 | print_overflow_msg(__func__, xdr); |
4857 | return -EIO; | 4857 | return -EIO; |
4858 | } | 4858 | } |
4859 | 4859 | ||
4860 | static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) | 4860 | static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) |
4861 | { | 4861 | { |
4862 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 4862 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
4863 | struct kvec *iov = rcvbuf->head; | 4863 | struct kvec *iov = rcvbuf->head; |
4864 | size_t hdrlen; | 4864 | size_t hdrlen; |
4865 | u32 recvd, pglen = rcvbuf->page_len; | 4865 | u32 recvd, pglen = rcvbuf->page_len; |
4866 | int status; | 4866 | int status; |
4867 | 4867 | ||
4868 | status = decode_op_hdr(xdr, OP_READDIR); | 4868 | status = decode_op_hdr(xdr, OP_READDIR); |
4869 | if (!status) | 4869 | if (!status) |
4870 | status = decode_verifier(xdr, readdir->verifier.data); | 4870 | status = decode_verifier(xdr, readdir->verifier.data); |
4871 | if (unlikely(status)) | 4871 | if (unlikely(status)) |
4872 | return status; | 4872 | return status; |
4873 | dprintk("%s: verifier = %08x:%08x\n", | 4873 | dprintk("%s: verifier = %08x:%08x\n", |
4874 | __func__, | 4874 | __func__, |
4875 | ((u32 *)readdir->verifier.data)[0], | 4875 | ((u32 *)readdir->verifier.data)[0], |
4876 | ((u32 *)readdir->verifier.data)[1]); | 4876 | ((u32 *)readdir->verifier.data)[1]); |
4877 | 4877 | ||
4878 | 4878 | ||
4879 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; | 4879 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; |
4880 | recvd = rcvbuf->len - hdrlen; | 4880 | recvd = rcvbuf->len - hdrlen; |
4881 | if (pglen > recvd) | 4881 | if (pglen > recvd) |
4882 | pglen = recvd; | 4882 | pglen = recvd; |
4883 | xdr_read_pages(xdr, pglen); | 4883 | xdr_read_pages(xdr, pglen); |
4884 | 4884 | ||
4885 | 4885 | ||
4886 | return pglen; | 4886 | return pglen; |
4887 | } | 4887 | } |
4888 | 4888 | ||
4889 | static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) | 4889 | static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) |
4890 | { | 4890 | { |
4891 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 4891 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
4892 | struct kvec *iov = rcvbuf->head; | 4892 | struct kvec *iov = rcvbuf->head; |
4893 | size_t hdrlen; | 4893 | size_t hdrlen; |
4894 | u32 len, recvd; | 4894 | u32 len, recvd; |
4895 | __be32 *p; | 4895 | __be32 *p; |
4896 | int status; | 4896 | int status; |
4897 | 4897 | ||
4898 | status = decode_op_hdr(xdr, OP_READLINK); | 4898 | status = decode_op_hdr(xdr, OP_READLINK); |
4899 | if (status) | 4899 | if (status) |
4900 | return status; | 4900 | return status; |
4901 | 4901 | ||
4902 | /* Convert length of symlink */ | 4902 | /* Convert length of symlink */ |
4903 | p = xdr_inline_decode(xdr, 4); | 4903 | p = xdr_inline_decode(xdr, 4); |
4904 | if (unlikely(!p)) | 4904 | if (unlikely(!p)) |
4905 | goto out_overflow; | 4905 | goto out_overflow; |
4906 | len = be32_to_cpup(p); | 4906 | len = be32_to_cpup(p); |
4907 | if (len >= rcvbuf->page_len || len <= 0) { | 4907 | if (len >= rcvbuf->page_len || len <= 0) { |
4908 | dprintk("nfs: server returned giant symlink!\n"); | 4908 | dprintk("nfs: server returned giant symlink!\n"); |
4909 | return -ENAMETOOLONG; | 4909 | return -ENAMETOOLONG; |
4910 | } | 4910 | } |
4911 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; | 4911 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; |
4912 | recvd = req->rq_rcv_buf.len - hdrlen; | 4912 | recvd = req->rq_rcv_buf.len - hdrlen; |
4913 | if (recvd < len) { | 4913 | if (recvd < len) { |
4914 | dprintk("NFS: server cheating in readlink reply: " | 4914 | dprintk("NFS: server cheating in readlink reply: " |
4915 | "count %u > recvd %u\n", len, recvd); | 4915 | "count %u > recvd %u\n", len, recvd); |
4916 | return -EIO; | 4916 | return -EIO; |
4917 | } | 4917 | } |
4918 | xdr_read_pages(xdr, len); | 4918 | xdr_read_pages(xdr, len); |
4919 | /* | 4919 | /* |
4920 | * The XDR encode routine has set things up so that | 4920 | * The XDR encode routine has set things up so that |
4921 | * the link text will be copied directly into the | 4921 | * the link text will be copied directly into the |
4922 | * buffer. We just have to do overflow-checking, | 4922 | * buffer. We just have to do overflow-checking, |
4923 | * and and null-terminate the text (the VFS expects | 4923 | * and and null-terminate the text (the VFS expects |
4924 | * null-termination). | 4924 | * null-termination). |
4925 | */ | 4925 | */ |
4926 | xdr_terminate_string(rcvbuf, len); | 4926 | xdr_terminate_string(rcvbuf, len); |
4927 | return 0; | 4927 | return 0; |
4928 | out_overflow: | 4928 | out_overflow: |
4929 | print_overflow_msg(__func__, xdr); | 4929 | print_overflow_msg(__func__, xdr); |
4930 | return -EIO; | 4930 | return -EIO; |
4931 | } | 4931 | } |
4932 | 4932 | ||
4933 | static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | 4933 | static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) |
4934 | { | 4934 | { |
4935 | int status; | 4935 | int status; |
4936 | 4936 | ||
4937 | status = decode_op_hdr(xdr, OP_REMOVE); | 4937 | status = decode_op_hdr(xdr, OP_REMOVE); |
4938 | if (status) | 4938 | if (status) |
4939 | goto out; | 4939 | goto out; |
4940 | status = decode_change_info(xdr, cinfo); | 4940 | status = decode_change_info(xdr, cinfo); |
4941 | out: | 4941 | out: |
4942 | return status; | 4942 | return status; |
4943 | } | 4943 | } |
4944 | 4944 | ||
4945 | static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo, | 4945 | static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo, |
4946 | struct nfs4_change_info *new_cinfo) | 4946 | struct nfs4_change_info *new_cinfo) |
4947 | { | 4947 | { |
4948 | int status; | 4948 | int status; |
4949 | 4949 | ||
4950 | status = decode_op_hdr(xdr, OP_RENAME); | 4950 | status = decode_op_hdr(xdr, OP_RENAME); |
4951 | if (status) | 4951 | if (status) |
4952 | goto out; | 4952 | goto out; |
4953 | if ((status = decode_change_info(xdr, old_cinfo))) | 4953 | if ((status = decode_change_info(xdr, old_cinfo))) |
4954 | goto out; | 4954 | goto out; |
4955 | status = decode_change_info(xdr, new_cinfo); | 4955 | status = decode_change_info(xdr, new_cinfo); |
4956 | out: | 4956 | out: |
4957 | return status; | 4957 | return status; |
4958 | } | 4958 | } |
4959 | 4959 | ||
4960 | static int decode_renew(struct xdr_stream *xdr) | 4960 | static int decode_renew(struct xdr_stream *xdr) |
4961 | { | 4961 | { |
4962 | return decode_op_hdr(xdr, OP_RENEW); | 4962 | return decode_op_hdr(xdr, OP_RENEW); |
4963 | } | 4963 | } |
4964 | 4964 | ||
4965 | static int | 4965 | static int |
4966 | decode_restorefh(struct xdr_stream *xdr) | 4966 | decode_restorefh(struct xdr_stream *xdr) |
4967 | { | 4967 | { |
4968 | return decode_op_hdr(xdr, OP_RESTOREFH); | 4968 | return decode_op_hdr(xdr, OP_RESTOREFH); |
4969 | } | 4969 | } |
4970 | 4970 | ||
4971 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | 4971 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, |
4972 | struct nfs_getaclres *res) | 4972 | struct nfs_getaclres *res) |
4973 | { | 4973 | { |
4974 | __be32 *savep, *bm_p; | 4974 | __be32 *savep, *bm_p; |
4975 | uint32_t attrlen, | 4975 | uint32_t attrlen, |
4976 | bitmap[3] = {0}; | 4976 | bitmap[3] = {0}; |
4977 | struct kvec *iov = req->rq_rcv_buf.head; | 4977 | struct kvec *iov = req->rq_rcv_buf.head; |
4978 | int status; | 4978 | int status; |
4979 | 4979 | ||
4980 | res->acl_len = 0; | 4980 | res->acl_len = 0; |
4981 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 4981 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
4982 | goto out; | 4982 | goto out; |
4983 | bm_p = xdr->p; | 4983 | bm_p = xdr->p; |
4984 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 4984 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
4985 | goto out; | 4985 | goto out; |
4986 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | 4986 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
4987 | goto out; | 4987 | goto out; |
4988 | 4988 | ||
4989 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) | 4989 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) |
4990 | return -EIO; | 4990 | return -EIO; |
4991 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { | 4991 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { |
4992 | size_t hdrlen; | 4992 | size_t hdrlen; |
4993 | u32 recvd; | 4993 | u32 recvd; |
4994 | 4994 | ||
4995 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words | 4995 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words |
4996 | * are stored with the acl data to handle the problem of | 4996 | * are stored with the acl data to handle the problem of |
4997 | * variable length bitmaps.*/ | 4997 | * variable length bitmaps.*/ |
4998 | xdr->p = bm_p; | 4998 | xdr->p = bm_p; |
4999 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; | 4999 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; |
5000 | res->acl_data_offset <<= 2; | 5000 | res->acl_data_offset <<= 2; |
5001 | 5001 | ||
5002 | /* We ignore &savep and don't do consistency checks on | 5002 | /* We ignore &savep and don't do consistency checks on |
5003 | * the attr length. Let userspace figure it out.... */ | 5003 | * the attr length. Let userspace figure it out.... */ |
5004 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; | 5004 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; |
5005 | attrlen += res->acl_data_offset; | 5005 | attrlen += res->acl_data_offset; |
5006 | recvd = req->rq_rcv_buf.len - hdrlen; | 5006 | recvd = req->rq_rcv_buf.len - hdrlen; |
5007 | if (attrlen > recvd) { | 5007 | if (attrlen > recvd) { |
5008 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { | 5008 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { |
5009 | /* getxattr interface called with a NULL buf */ | 5009 | /* getxattr interface called with a NULL buf */ |
5010 | res->acl_len = attrlen; | 5010 | res->acl_len = attrlen; |
5011 | goto out; | 5011 | goto out; |
5012 | } | 5012 | } |
5013 | dprintk("NFS: acl reply: attrlen %u > recvd %u\n", | 5013 | dprintk("NFS: acl reply: attrlen %u > recvd %u\n", |
5014 | attrlen, recvd); | 5014 | attrlen, recvd); |
5015 | return -EINVAL; | 5015 | return -EINVAL; |
5016 | } | 5016 | } |
5017 | xdr_read_pages(xdr, attrlen); | 5017 | xdr_read_pages(xdr, attrlen); |
5018 | res->acl_len = attrlen; | 5018 | res->acl_len = attrlen; |
5019 | } else | 5019 | } else |
5020 | status = -EOPNOTSUPP; | 5020 | status = -EOPNOTSUPP; |
5021 | 5021 | ||
5022 | out: | 5022 | out: |
5023 | return status; | 5023 | return status; |
5024 | } | 5024 | } |
5025 | 5025 | ||
5026 | static int | 5026 | static int |
5027 | decode_savefh(struct xdr_stream *xdr) | 5027 | decode_savefh(struct xdr_stream *xdr) |
5028 | { | 5028 | { |
5029 | return decode_op_hdr(xdr, OP_SAVEFH); | 5029 | return decode_op_hdr(xdr, OP_SAVEFH); |
5030 | } | 5030 | } |
5031 | 5031 | ||
5032 | static int decode_setattr(struct xdr_stream *xdr) | 5032 | static int decode_setattr(struct xdr_stream *xdr) |
5033 | { | 5033 | { |
5034 | __be32 *p; | 5034 | __be32 *p; |
5035 | uint32_t bmlen; | 5035 | uint32_t bmlen; |
5036 | int status; | 5036 | int status; |
5037 | 5037 | ||
5038 | status = decode_op_hdr(xdr, OP_SETATTR); | 5038 | status = decode_op_hdr(xdr, OP_SETATTR); |
5039 | if (status) | 5039 | if (status) |
5040 | return status; | 5040 | return status; |
5041 | p = xdr_inline_decode(xdr, 4); | 5041 | p = xdr_inline_decode(xdr, 4); |
5042 | if (unlikely(!p)) | 5042 | if (unlikely(!p)) |
5043 | goto out_overflow; | 5043 | goto out_overflow; |
5044 | bmlen = be32_to_cpup(p); | 5044 | bmlen = be32_to_cpup(p); |
5045 | p = xdr_inline_decode(xdr, bmlen << 2); | 5045 | p = xdr_inline_decode(xdr, bmlen << 2); |
5046 | if (likely(p)) | 5046 | if (likely(p)) |
5047 | return 0; | 5047 | return 0; |
5048 | out_overflow: | 5048 | out_overflow: |
5049 | print_overflow_msg(__func__, xdr); | 5049 | print_overflow_msg(__func__, xdr); |
5050 | return -EIO; | 5050 | return -EIO; |
5051 | } | 5051 | } |
5052 | 5052 | ||
5053 | static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res) | 5053 | static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res) |
5054 | { | 5054 | { |
5055 | __be32 *p; | 5055 | __be32 *p; |
5056 | uint32_t opnum; | 5056 | uint32_t opnum; |
5057 | int32_t nfserr; | 5057 | int32_t nfserr; |
5058 | 5058 | ||
5059 | p = xdr_inline_decode(xdr, 8); | 5059 | p = xdr_inline_decode(xdr, 8); |
5060 | if (unlikely(!p)) | 5060 | if (unlikely(!p)) |
5061 | goto out_overflow; | 5061 | goto out_overflow; |
5062 | opnum = be32_to_cpup(p++); | 5062 | opnum = be32_to_cpup(p++); |
5063 | if (opnum != OP_SETCLIENTID) { | 5063 | if (opnum != OP_SETCLIENTID) { |
5064 | dprintk("nfs: decode_setclientid: Server returned operation" | 5064 | dprintk("nfs: decode_setclientid: Server returned operation" |
5065 | " %d\n", opnum); | 5065 | " %d\n", opnum); |
5066 | return -EIO; | 5066 | return -EIO; |
5067 | } | 5067 | } |
5068 | nfserr = be32_to_cpup(p); | 5068 | nfserr = be32_to_cpup(p); |
5069 | if (nfserr == NFS_OK) { | 5069 | if (nfserr == NFS_OK) { |
5070 | p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); | 5070 | p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE); |
5071 | if (unlikely(!p)) | 5071 | if (unlikely(!p)) |
5072 | goto out_overflow; | 5072 | goto out_overflow; |
5073 | p = xdr_decode_hyper(p, &res->clientid); | 5073 | p = xdr_decode_hyper(p, &res->clientid); |
5074 | memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); | 5074 | memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE); |
5075 | } else if (nfserr == NFSERR_CLID_INUSE) { | 5075 | } else if (nfserr == NFSERR_CLID_INUSE) { |
5076 | uint32_t len; | 5076 | uint32_t len; |
5077 | 5077 | ||
5078 | /* skip netid string */ | 5078 | /* skip netid string */ |
5079 | p = xdr_inline_decode(xdr, 4); | 5079 | p = xdr_inline_decode(xdr, 4); |
5080 | if (unlikely(!p)) | 5080 | if (unlikely(!p)) |
5081 | goto out_overflow; | 5081 | goto out_overflow; |
5082 | len = be32_to_cpup(p); | 5082 | len = be32_to_cpup(p); |
5083 | p = xdr_inline_decode(xdr, len); | 5083 | p = xdr_inline_decode(xdr, len); |
5084 | if (unlikely(!p)) | 5084 | if (unlikely(!p)) |
5085 | goto out_overflow; | 5085 | goto out_overflow; |
5086 | 5086 | ||
5087 | /* skip uaddr string */ | 5087 | /* skip uaddr string */ |
5088 | p = xdr_inline_decode(xdr, 4); | 5088 | p = xdr_inline_decode(xdr, 4); |
5089 | if (unlikely(!p)) | 5089 | if (unlikely(!p)) |
5090 | goto out_overflow; | 5090 | goto out_overflow; |
5091 | len = be32_to_cpup(p); | 5091 | len = be32_to_cpup(p); |
5092 | p = xdr_inline_decode(xdr, len); | 5092 | p = xdr_inline_decode(xdr, len); |
5093 | if (unlikely(!p)) | 5093 | if (unlikely(!p)) |
5094 | goto out_overflow; | 5094 | goto out_overflow; |
5095 | return -NFSERR_CLID_INUSE; | 5095 | return -NFSERR_CLID_INUSE; |
5096 | } else | 5096 | } else |
5097 | return nfs4_stat_to_errno(nfserr); | 5097 | return nfs4_stat_to_errno(nfserr); |
5098 | 5098 | ||
5099 | return 0; | 5099 | return 0; |
5100 | out_overflow: | 5100 | out_overflow: |
5101 | print_overflow_msg(__func__, xdr); | 5101 | print_overflow_msg(__func__, xdr); |
5102 | return -EIO; | 5102 | return -EIO; |
5103 | } | 5103 | } |
5104 | 5104 | ||
5105 | static int decode_setclientid_confirm(struct xdr_stream *xdr) | 5105 | static int decode_setclientid_confirm(struct xdr_stream *xdr) |
5106 | { | 5106 | { |
5107 | return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM); | 5107 | return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM); |
5108 | } | 5108 | } |
5109 | 5109 | ||
5110 | static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res) | 5110 | static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res) |
5111 | { | 5111 | { |
5112 | __be32 *p; | 5112 | __be32 *p; |
5113 | int status; | 5113 | int status; |
5114 | 5114 | ||
5115 | status = decode_op_hdr(xdr, OP_WRITE); | 5115 | status = decode_op_hdr(xdr, OP_WRITE); |
5116 | if (status) | 5116 | if (status) |
5117 | return status; | 5117 | return status; |
5118 | 5118 | ||
5119 | p = xdr_inline_decode(xdr, 16); | 5119 | p = xdr_inline_decode(xdr, 16); |
5120 | if (unlikely(!p)) | 5120 | if (unlikely(!p)) |
5121 | goto out_overflow; | 5121 | goto out_overflow; |
5122 | res->count = be32_to_cpup(p++); | 5122 | res->count = be32_to_cpup(p++); |
5123 | res->verf->committed = be32_to_cpup(p++); | 5123 | res->verf->committed = be32_to_cpup(p++); |
5124 | memcpy(res->verf->verifier, p, 8); | 5124 | memcpy(res->verf->verifier, p, 8); |
5125 | return 0; | 5125 | return 0; |
5126 | out_overflow: | 5126 | out_overflow: |
5127 | print_overflow_msg(__func__, xdr); | 5127 | print_overflow_msg(__func__, xdr); |
5128 | return -EIO; | 5128 | return -EIO; |
5129 | } | 5129 | } |
5130 | 5130 | ||
5131 | static int decode_delegreturn(struct xdr_stream *xdr) | 5131 | static int decode_delegreturn(struct xdr_stream *xdr) |
5132 | { | 5132 | { |
5133 | return decode_op_hdr(xdr, OP_DELEGRETURN); | 5133 | return decode_op_hdr(xdr, OP_DELEGRETURN); |
5134 | } | 5134 | } |
5135 | 5135 | ||
5136 | static int decode_secinfo_gss(struct xdr_stream *xdr, struct nfs4_secinfo_flavor *flavor) | 5136 | static int decode_secinfo_gss(struct xdr_stream *xdr, struct nfs4_secinfo_flavor *flavor) |
5137 | { | 5137 | { |
5138 | __be32 *p; | 5138 | __be32 *p; |
5139 | 5139 | ||
5140 | p = xdr_inline_decode(xdr, 4); | 5140 | p = xdr_inline_decode(xdr, 4); |
5141 | if (unlikely(!p)) | 5141 | if (unlikely(!p)) |
5142 | goto out_overflow; | 5142 | goto out_overflow; |
5143 | flavor->gss.sec_oid4.len = be32_to_cpup(p); | 5143 | flavor->gss.sec_oid4.len = be32_to_cpup(p); |
5144 | if (flavor->gss.sec_oid4.len > GSS_OID_MAX_LEN) | 5144 | if (flavor->gss.sec_oid4.len > GSS_OID_MAX_LEN) |
5145 | goto out_err; | 5145 | goto out_err; |
5146 | 5146 | ||
5147 | p = xdr_inline_decode(xdr, flavor->gss.sec_oid4.len); | 5147 | p = xdr_inline_decode(xdr, flavor->gss.sec_oid4.len); |
5148 | if (unlikely(!p)) | 5148 | if (unlikely(!p)) |
5149 | goto out_overflow; | 5149 | goto out_overflow; |
5150 | memcpy(flavor->gss.sec_oid4.data, p, flavor->gss.sec_oid4.len); | 5150 | memcpy(flavor->gss.sec_oid4.data, p, flavor->gss.sec_oid4.len); |
5151 | 5151 | ||
5152 | p = xdr_inline_decode(xdr, 8); | 5152 | p = xdr_inline_decode(xdr, 8); |
5153 | if (unlikely(!p)) | 5153 | if (unlikely(!p)) |
5154 | goto out_overflow; | 5154 | goto out_overflow; |
5155 | flavor->gss.qop4 = be32_to_cpup(p++); | 5155 | flavor->gss.qop4 = be32_to_cpup(p++); |
5156 | flavor->gss.service = be32_to_cpup(p); | 5156 | flavor->gss.service = be32_to_cpup(p); |
5157 | 5157 | ||
5158 | return 0; | 5158 | return 0; |
5159 | 5159 | ||
5160 | out_overflow: | 5160 | out_overflow: |
5161 | print_overflow_msg(__func__, xdr); | 5161 | print_overflow_msg(__func__, xdr); |
5162 | return -EIO; | 5162 | return -EIO; |
5163 | out_err: | 5163 | out_err: |
5164 | return -EINVAL; | 5164 | return -EINVAL; |
5165 | } | 5165 | } |
5166 | 5166 | ||
5167 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | 5167 | static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) |
5168 | { | 5168 | { |
5169 | struct nfs4_secinfo_flavor *sec_flavor; | 5169 | struct nfs4_secinfo_flavor *sec_flavor; |
5170 | int status; | 5170 | int status; |
5171 | __be32 *p; | 5171 | __be32 *p; |
5172 | int i, num_flavors; | 5172 | int i, num_flavors; |
5173 | 5173 | ||
5174 | status = decode_op_hdr(xdr, OP_SECINFO); | 5174 | status = decode_op_hdr(xdr, OP_SECINFO); |
5175 | if (status) | 5175 | if (status) |
5176 | goto out; | 5176 | goto out; |
5177 | p = xdr_inline_decode(xdr, 4); | 5177 | p = xdr_inline_decode(xdr, 4); |
5178 | if (unlikely(!p)) | 5178 | if (unlikely(!p)) |
5179 | goto out_overflow; | 5179 | goto out_overflow; |
5180 | 5180 | ||
5181 | res->flavors->num_flavors = 0; | 5181 | res->flavors->num_flavors = 0; |
5182 | num_flavors = be32_to_cpup(p); | 5182 | num_flavors = be32_to_cpup(p); |
5183 | 5183 | ||
5184 | for (i = 0; i < num_flavors; i++) { | 5184 | for (i = 0; i < num_flavors; i++) { |
5185 | sec_flavor = &res->flavors->flavors[i]; | 5185 | sec_flavor = &res->flavors->flavors[i]; |
5186 | if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE) | 5186 | if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE) |
5187 | break; | 5187 | break; |
5188 | 5188 | ||
5189 | p = xdr_inline_decode(xdr, 4); | 5189 | p = xdr_inline_decode(xdr, 4); |
5190 | if (unlikely(!p)) | 5190 | if (unlikely(!p)) |
5191 | goto out_overflow; | 5191 | goto out_overflow; |
5192 | sec_flavor->flavor = be32_to_cpup(p); | 5192 | sec_flavor->flavor = be32_to_cpup(p); |
5193 | 5193 | ||
5194 | if (sec_flavor->flavor == RPC_AUTH_GSS) { | 5194 | if (sec_flavor->flavor == RPC_AUTH_GSS) { |
5195 | status = decode_secinfo_gss(xdr, sec_flavor); | 5195 | status = decode_secinfo_gss(xdr, sec_flavor); |
5196 | if (status) | 5196 | if (status) |
5197 | goto out; | 5197 | goto out; |
5198 | } | 5198 | } |
5199 | res->flavors->num_flavors++; | 5199 | res->flavors->num_flavors++; |
5200 | } | 5200 | } |
5201 | 5201 | ||
5202 | out: | 5202 | out: |
5203 | return status; | 5203 | return status; |
5204 | out_overflow: | 5204 | out_overflow: |
5205 | print_overflow_msg(__func__, xdr); | 5205 | print_overflow_msg(__func__, xdr); |
5206 | return -EIO; | 5206 | return -EIO; |
5207 | } | 5207 | } |
5208 | 5208 | ||
5209 | #if defined(CONFIG_NFS_V4_1) | 5209 | #if defined(CONFIG_NFS_V4_1) |
5210 | static int decode_exchange_id(struct xdr_stream *xdr, | 5210 | static int decode_exchange_id(struct xdr_stream *xdr, |
5211 | struct nfs41_exchange_id_res *res) | 5211 | struct nfs41_exchange_id_res *res) |
5212 | { | 5212 | { |
5213 | __be32 *p; | 5213 | __be32 *p; |
5214 | uint32_t dummy; | 5214 | uint32_t dummy; |
5215 | char *dummy_str; | 5215 | char *dummy_str; |
5216 | int status; | 5216 | int status; |
5217 | struct nfs_client *clp = res->client; | 5217 | struct nfs_client *clp = res->client; |
5218 | 5218 | ||
5219 | status = decode_op_hdr(xdr, OP_EXCHANGE_ID); | 5219 | status = decode_op_hdr(xdr, OP_EXCHANGE_ID); |
5220 | if (status) | 5220 | if (status) |
5221 | return status; | 5221 | return status; |
5222 | 5222 | ||
5223 | p = xdr_inline_decode(xdr, 8); | 5223 | p = xdr_inline_decode(xdr, 8); |
5224 | if (unlikely(!p)) | 5224 | if (unlikely(!p)) |
5225 | goto out_overflow; | 5225 | goto out_overflow; |
5226 | xdr_decode_hyper(p, &clp->cl_clientid); | 5226 | xdr_decode_hyper(p, &clp->cl_clientid); |
5227 | p = xdr_inline_decode(xdr, 12); | 5227 | p = xdr_inline_decode(xdr, 12); |
5228 | if (unlikely(!p)) | 5228 | if (unlikely(!p)) |
5229 | goto out_overflow; | 5229 | goto out_overflow; |
5230 | clp->cl_seqid = be32_to_cpup(p++); | 5230 | clp->cl_seqid = be32_to_cpup(p++); |
5231 | clp->cl_exchange_flags = be32_to_cpup(p++); | 5231 | clp->cl_exchange_flags = be32_to_cpup(p++); |
5232 | 5232 | ||
5233 | /* We ask for SP4_NONE */ | 5233 | /* We ask for SP4_NONE */ |
5234 | dummy = be32_to_cpup(p); | 5234 | dummy = be32_to_cpup(p); |
5235 | if (dummy != SP4_NONE) | 5235 | if (dummy != SP4_NONE) |
5236 | return -EIO; | 5236 | return -EIO; |
5237 | 5237 | ||
5238 | /* Throw away minor_id */ | 5238 | /* Throw away minor_id */ |
5239 | p = xdr_inline_decode(xdr, 8); | 5239 | p = xdr_inline_decode(xdr, 8); |
5240 | if (unlikely(!p)) | 5240 | if (unlikely(!p)) |
5241 | goto out_overflow; | 5241 | goto out_overflow; |
5242 | 5242 | ||
5243 | /* Throw away Major id */ | 5243 | /* Throw away Major id */ |
5244 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5244 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5245 | if (unlikely(status)) | 5245 | if (unlikely(status)) |
5246 | return status; | 5246 | return status; |
5247 | 5247 | ||
5248 | /* Save server_scope */ | 5248 | /* Save server_scope */ |
5249 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5249 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5250 | if (unlikely(status)) | 5250 | if (unlikely(status)) |
5251 | return status; | 5251 | return status; |
5252 | 5252 | ||
5253 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | 5253 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) |
5254 | return -EIO; | 5254 | return -EIO; |
5255 | 5255 | ||
5256 | memcpy(res->server_scope->server_scope, dummy_str, dummy); | 5256 | memcpy(res->server_scope->server_scope, dummy_str, dummy); |
5257 | res->server_scope->server_scope_sz = dummy; | 5257 | res->server_scope->server_scope_sz = dummy; |
5258 | 5258 | ||
5259 | /* Throw away Implementation id array */ | 5259 | /* Throw away Implementation id array */ |
5260 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5260 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5261 | if (unlikely(status)) | 5261 | if (unlikely(status)) |
5262 | return status; | 5262 | return status; |
5263 | 5263 | ||
5264 | return 0; | 5264 | return 0; |
5265 | out_overflow: | 5265 | out_overflow: |
5266 | print_overflow_msg(__func__, xdr); | 5266 | print_overflow_msg(__func__, xdr); |
5267 | return -EIO; | 5267 | return -EIO; |
5268 | } | 5268 | } |
5269 | 5269 | ||
5270 | static int decode_chan_attrs(struct xdr_stream *xdr, | 5270 | static int decode_chan_attrs(struct xdr_stream *xdr, |
5271 | struct nfs4_channel_attrs *attrs) | 5271 | struct nfs4_channel_attrs *attrs) |
5272 | { | 5272 | { |
5273 | __be32 *p; | 5273 | __be32 *p; |
5274 | u32 nr_attrs, val; | 5274 | u32 nr_attrs, val; |
5275 | 5275 | ||
5276 | p = xdr_inline_decode(xdr, 28); | 5276 | p = xdr_inline_decode(xdr, 28); |
5277 | if (unlikely(!p)) | 5277 | if (unlikely(!p)) |
5278 | goto out_overflow; | 5278 | goto out_overflow; |
5279 | val = be32_to_cpup(p++); /* headerpadsz */ | 5279 | val = be32_to_cpup(p++); /* headerpadsz */ |
5280 | if (val) | 5280 | if (val) |
5281 | return -EINVAL; /* no support for header padding yet */ | 5281 | return -EINVAL; /* no support for header padding yet */ |
5282 | attrs->max_rqst_sz = be32_to_cpup(p++); | 5282 | attrs->max_rqst_sz = be32_to_cpup(p++); |
5283 | attrs->max_resp_sz = be32_to_cpup(p++); | 5283 | attrs->max_resp_sz = be32_to_cpup(p++); |
5284 | attrs->max_resp_sz_cached = be32_to_cpup(p++); | 5284 | attrs->max_resp_sz_cached = be32_to_cpup(p++); |
5285 | attrs->max_ops = be32_to_cpup(p++); | 5285 | attrs->max_ops = be32_to_cpup(p++); |
5286 | attrs->max_reqs = be32_to_cpup(p++); | 5286 | attrs->max_reqs = be32_to_cpup(p++); |
5287 | nr_attrs = be32_to_cpup(p); | 5287 | nr_attrs = be32_to_cpup(p); |
5288 | if (unlikely(nr_attrs > 1)) { | 5288 | if (unlikely(nr_attrs > 1)) { |
5289 | printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n", | 5289 | printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n", |
5290 | __func__, nr_attrs); | 5290 | __func__, nr_attrs); |
5291 | return -EINVAL; | 5291 | return -EINVAL; |
5292 | } | 5292 | } |
5293 | if (nr_attrs == 1) { | 5293 | if (nr_attrs == 1) { |
5294 | p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ | 5294 | p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */ |
5295 | if (unlikely(!p)) | 5295 | if (unlikely(!p)) |
5296 | goto out_overflow; | 5296 | goto out_overflow; |
5297 | } | 5297 | } |
5298 | return 0; | 5298 | return 0; |
5299 | out_overflow: | 5299 | out_overflow: |
5300 | print_overflow_msg(__func__, xdr); | 5300 | print_overflow_msg(__func__, xdr); |
5301 | return -EIO; | 5301 | return -EIO; |
5302 | } | 5302 | } |
5303 | 5303 | ||
5304 | static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) | 5304 | static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) |
5305 | { | 5305 | { |
5306 | return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); | 5306 | return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); |
5307 | } | 5307 | } |
5308 | 5308 | ||
5309 | static int decode_create_session(struct xdr_stream *xdr, | 5309 | static int decode_create_session(struct xdr_stream *xdr, |
5310 | struct nfs41_create_session_res *res) | 5310 | struct nfs41_create_session_res *res) |
5311 | { | 5311 | { |
5312 | __be32 *p; | 5312 | __be32 *p; |
5313 | int status; | 5313 | int status; |
5314 | struct nfs_client *clp = res->client; | 5314 | struct nfs_client *clp = res->client; |
5315 | struct nfs4_session *session = clp->cl_session; | 5315 | struct nfs4_session *session = clp->cl_session; |
5316 | 5316 | ||
5317 | status = decode_op_hdr(xdr, OP_CREATE_SESSION); | 5317 | status = decode_op_hdr(xdr, OP_CREATE_SESSION); |
5318 | if (!status) | 5318 | if (!status) |
5319 | status = decode_sessionid(xdr, &session->sess_id); | 5319 | status = decode_sessionid(xdr, &session->sess_id); |
5320 | if (unlikely(status)) | 5320 | if (unlikely(status)) |
5321 | return status; | 5321 | return status; |
5322 | 5322 | ||
5323 | /* seqid, flags */ | 5323 | /* seqid, flags */ |
5324 | p = xdr_inline_decode(xdr, 8); | 5324 | p = xdr_inline_decode(xdr, 8); |
5325 | if (unlikely(!p)) | 5325 | if (unlikely(!p)) |
5326 | goto out_overflow; | 5326 | goto out_overflow; |
5327 | clp->cl_seqid = be32_to_cpup(p++); | 5327 | clp->cl_seqid = be32_to_cpup(p++); |
5328 | session->flags = be32_to_cpup(p); | 5328 | session->flags = be32_to_cpup(p); |
5329 | 5329 | ||
5330 | /* Channel attributes */ | 5330 | /* Channel attributes */ |
5331 | status = decode_chan_attrs(xdr, &session->fc_attrs); | 5331 | status = decode_chan_attrs(xdr, &session->fc_attrs); |
5332 | if (!status) | 5332 | if (!status) |
5333 | status = decode_chan_attrs(xdr, &session->bc_attrs); | 5333 | status = decode_chan_attrs(xdr, &session->bc_attrs); |
5334 | return status; | 5334 | return status; |
5335 | out_overflow: | 5335 | out_overflow: |
5336 | print_overflow_msg(__func__, xdr); | 5336 | print_overflow_msg(__func__, xdr); |
5337 | return -EIO; | 5337 | return -EIO; |
5338 | } | 5338 | } |
5339 | 5339 | ||
5340 | static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) | 5340 | static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) |
5341 | { | 5341 | { |
5342 | return decode_op_hdr(xdr, OP_DESTROY_SESSION); | 5342 | return decode_op_hdr(xdr, OP_DESTROY_SESSION); |
5343 | } | 5343 | } |
5344 | 5344 | ||
5345 | static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) | 5345 | static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) |
5346 | { | 5346 | { |
5347 | return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); | 5347 | return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); |
5348 | } | 5348 | } |
5349 | #endif /* CONFIG_NFS_V4_1 */ | 5349 | #endif /* CONFIG_NFS_V4_1 */ |
5350 | 5350 | ||
5351 | static int decode_sequence(struct xdr_stream *xdr, | 5351 | static int decode_sequence(struct xdr_stream *xdr, |
5352 | struct nfs4_sequence_res *res, | 5352 | struct nfs4_sequence_res *res, |
5353 | struct rpc_rqst *rqstp) | 5353 | struct rpc_rqst *rqstp) |
5354 | { | 5354 | { |
5355 | #if defined(CONFIG_NFS_V4_1) | 5355 | #if defined(CONFIG_NFS_V4_1) |
5356 | struct nfs4_sessionid id; | 5356 | struct nfs4_sessionid id; |
5357 | u32 dummy; | 5357 | u32 dummy; |
5358 | int status; | 5358 | int status; |
5359 | __be32 *p; | 5359 | __be32 *p; |
5360 | 5360 | ||
5361 | if (!res->sr_session) | 5361 | if (!res->sr_session) |
5362 | return 0; | 5362 | return 0; |
5363 | 5363 | ||
5364 | status = decode_op_hdr(xdr, OP_SEQUENCE); | 5364 | status = decode_op_hdr(xdr, OP_SEQUENCE); |
5365 | if (!status) | 5365 | if (!status) |
5366 | status = decode_sessionid(xdr, &id); | 5366 | status = decode_sessionid(xdr, &id); |
5367 | if (unlikely(status)) | 5367 | if (unlikely(status)) |
5368 | goto out_err; | 5368 | goto out_err; |
5369 | 5369 | ||
5370 | /* | 5370 | /* |
5371 | * If the server returns different values for sessionID, slotID or | 5371 | * If the server returns different values for sessionID, slotID or |
5372 | * sequence number, the server is looney tunes. | 5372 | * sequence number, the server is looney tunes. |
5373 | */ | 5373 | */ |
5374 | status = -EREMOTEIO; | 5374 | status = -EREMOTEIO; |
5375 | 5375 | ||
5376 | if (memcmp(id.data, res->sr_session->sess_id.data, | 5376 | if (memcmp(id.data, res->sr_session->sess_id.data, |
5377 | NFS4_MAX_SESSIONID_LEN)) { | 5377 | NFS4_MAX_SESSIONID_LEN)) { |
5378 | dprintk("%s Invalid session id\n", __func__); | 5378 | dprintk("%s Invalid session id\n", __func__); |
5379 | goto out_err; | 5379 | goto out_err; |
5380 | } | 5380 | } |
5381 | 5381 | ||
5382 | p = xdr_inline_decode(xdr, 20); | 5382 | p = xdr_inline_decode(xdr, 20); |
5383 | if (unlikely(!p)) | 5383 | if (unlikely(!p)) |
5384 | goto out_overflow; | 5384 | goto out_overflow; |
5385 | 5385 | ||
5386 | /* seqid */ | 5386 | /* seqid */ |
5387 | dummy = be32_to_cpup(p++); | 5387 | dummy = be32_to_cpup(p++); |
5388 | if (dummy != res->sr_slot->seq_nr) { | 5388 | if (dummy != res->sr_slot->seq_nr) { |
5389 | dprintk("%s Invalid sequence number\n", __func__); | 5389 | dprintk("%s Invalid sequence number\n", __func__); |
5390 | goto out_err; | 5390 | goto out_err; |
5391 | } | 5391 | } |
5392 | /* slot id */ | 5392 | /* slot id */ |
5393 | dummy = be32_to_cpup(p++); | 5393 | dummy = be32_to_cpup(p++); |
5394 | if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) { | 5394 | if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) { |
5395 | dprintk("%s Invalid slot id\n", __func__); | 5395 | dprintk("%s Invalid slot id\n", __func__); |
5396 | goto out_err; | 5396 | goto out_err; |
5397 | } | 5397 | } |
5398 | /* highest slot id - currently not processed */ | 5398 | /* highest slot id - currently not processed */ |
5399 | dummy = be32_to_cpup(p++); | 5399 | dummy = be32_to_cpup(p++); |
5400 | /* target highest slot id - currently not processed */ | 5400 | /* target highest slot id - currently not processed */ |
5401 | dummy = be32_to_cpup(p++); | 5401 | dummy = be32_to_cpup(p++); |
5402 | /* result flags */ | 5402 | /* result flags */ |
5403 | res->sr_status_flags = be32_to_cpup(p); | 5403 | res->sr_status_flags = be32_to_cpup(p); |
5404 | status = 0; | 5404 | status = 0; |
5405 | out_err: | 5405 | out_err: |
5406 | res->sr_status = status; | 5406 | res->sr_status = status; |
5407 | return status; | 5407 | return status; |
5408 | out_overflow: | 5408 | out_overflow: |
5409 | print_overflow_msg(__func__, xdr); | 5409 | print_overflow_msg(__func__, xdr); |
5410 | status = -EIO; | 5410 | status = -EIO; |
5411 | goto out_err; | 5411 | goto out_err; |
5412 | #else /* CONFIG_NFS_V4_1 */ | 5412 | #else /* CONFIG_NFS_V4_1 */ |
5413 | return 0; | 5413 | return 0; |
5414 | #endif /* CONFIG_NFS_V4_1 */ | 5414 | #endif /* CONFIG_NFS_V4_1 */ |
5415 | } | 5415 | } |
5416 | 5416 | ||
5417 | #if defined(CONFIG_NFS_V4_1) | 5417 | #if defined(CONFIG_NFS_V4_1) |
5418 | /* | 5418 | /* |
5419 | * TODO: Need to handle case when EOF != true; | 5419 | * TODO: Need to handle case when EOF != true; |
5420 | */ | 5420 | */ |
5421 | static int decode_getdevicelist(struct xdr_stream *xdr, | 5421 | static int decode_getdevicelist(struct xdr_stream *xdr, |
5422 | struct pnfs_devicelist *res) | 5422 | struct pnfs_devicelist *res) |
5423 | { | 5423 | { |
5424 | __be32 *p; | 5424 | __be32 *p; |
5425 | int status, i; | 5425 | int status, i; |
5426 | struct nfs_writeverf verftemp; | 5426 | struct nfs_writeverf verftemp; |
5427 | 5427 | ||
5428 | status = decode_op_hdr(xdr, OP_GETDEVICELIST); | 5428 | status = decode_op_hdr(xdr, OP_GETDEVICELIST); |
5429 | if (status) | 5429 | if (status) |
5430 | return status; | 5430 | return status; |
5431 | 5431 | ||
5432 | p = xdr_inline_decode(xdr, 8 + 8 + 4); | 5432 | p = xdr_inline_decode(xdr, 8 + 8 + 4); |
5433 | if (unlikely(!p)) | 5433 | if (unlikely(!p)) |
5434 | goto out_overflow; | 5434 | goto out_overflow; |
5435 | 5435 | ||
5436 | /* TODO: Skip cookie for now */ | 5436 | /* TODO: Skip cookie for now */ |
5437 | p += 2; | 5437 | p += 2; |
5438 | 5438 | ||
5439 | /* Read verifier */ | 5439 | /* Read verifier */ |
5440 | p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8); | 5440 | p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8); |
5441 | 5441 | ||
5442 | res->num_devs = be32_to_cpup(p); | 5442 | res->num_devs = be32_to_cpup(p); |
5443 | 5443 | ||
5444 | dprintk("%s: num_dev %d\n", __func__, res->num_devs); | 5444 | dprintk("%s: num_dev %d\n", __func__, res->num_devs); |
5445 | 5445 | ||
5446 | if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) { | 5446 | if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) { |
5447 | printk(KERN_ERR "%s too many result dev_num %u\n", | 5447 | printk(KERN_ERR "%s too many result dev_num %u\n", |
5448 | __func__, res->num_devs); | 5448 | __func__, res->num_devs); |
5449 | return -EIO; | 5449 | return -EIO; |
5450 | } | 5450 | } |
5451 | 5451 | ||
5452 | p = xdr_inline_decode(xdr, | 5452 | p = xdr_inline_decode(xdr, |
5453 | res->num_devs * NFS4_DEVICEID4_SIZE + 4); | 5453 | res->num_devs * NFS4_DEVICEID4_SIZE + 4); |
5454 | if (unlikely(!p)) | 5454 | if (unlikely(!p)) |
5455 | goto out_overflow; | 5455 | goto out_overflow; |
5456 | for (i = 0; i < res->num_devs; i++) | 5456 | for (i = 0; i < res->num_devs; i++) |
5457 | p = xdr_decode_opaque_fixed(p, res->dev_id[i].data, | 5457 | p = xdr_decode_opaque_fixed(p, res->dev_id[i].data, |
5458 | NFS4_DEVICEID4_SIZE); | 5458 | NFS4_DEVICEID4_SIZE); |
5459 | res->eof = be32_to_cpup(p); | 5459 | res->eof = be32_to_cpup(p); |
5460 | return 0; | 5460 | return 0; |
5461 | out_overflow: | 5461 | out_overflow: |
5462 | print_overflow_msg(__func__, xdr); | 5462 | print_overflow_msg(__func__, xdr); |
5463 | return -EIO; | 5463 | return -EIO; |
5464 | } | 5464 | } |
5465 | 5465 | ||
5466 | static int decode_getdeviceinfo(struct xdr_stream *xdr, | 5466 | static int decode_getdeviceinfo(struct xdr_stream *xdr, |
5467 | struct pnfs_device *pdev) | 5467 | struct pnfs_device *pdev) |
5468 | { | 5468 | { |
5469 | __be32 *p; | 5469 | __be32 *p; |
5470 | uint32_t len, type; | 5470 | uint32_t len, type; |
5471 | int status; | 5471 | int status; |
5472 | 5472 | ||
5473 | status = decode_op_hdr(xdr, OP_GETDEVICEINFO); | 5473 | status = decode_op_hdr(xdr, OP_GETDEVICEINFO); |
5474 | if (status) { | 5474 | if (status) { |
5475 | if (status == -ETOOSMALL) { | 5475 | if (status == -ETOOSMALL) { |
5476 | p = xdr_inline_decode(xdr, 4); | 5476 | p = xdr_inline_decode(xdr, 4); |
5477 | if (unlikely(!p)) | 5477 | if (unlikely(!p)) |
5478 | goto out_overflow; | 5478 | goto out_overflow; |
5479 | pdev->mincount = be32_to_cpup(p); | 5479 | pdev->mincount = be32_to_cpup(p); |
5480 | dprintk("%s: Min count too small. mincnt = %u\n", | 5480 | dprintk("%s: Min count too small. mincnt = %u\n", |
5481 | __func__, pdev->mincount); | 5481 | __func__, pdev->mincount); |
5482 | } | 5482 | } |
5483 | return status; | 5483 | return status; |
5484 | } | 5484 | } |
5485 | 5485 | ||
5486 | p = xdr_inline_decode(xdr, 8); | 5486 | p = xdr_inline_decode(xdr, 8); |
5487 | if (unlikely(!p)) | 5487 | if (unlikely(!p)) |
5488 | goto out_overflow; | 5488 | goto out_overflow; |
5489 | type = be32_to_cpup(p++); | 5489 | type = be32_to_cpup(p++); |
5490 | if (type != pdev->layout_type) { | 5490 | if (type != pdev->layout_type) { |
5491 | dprintk("%s: layout mismatch req: %u pdev: %u\n", | 5491 | dprintk("%s: layout mismatch req: %u pdev: %u\n", |
5492 | __func__, pdev->layout_type, type); | 5492 | __func__, pdev->layout_type, type); |
5493 | return -EINVAL; | 5493 | return -EINVAL; |
5494 | } | 5494 | } |
5495 | /* | 5495 | /* |
5496 | * Get the length of the opaque device_addr4. xdr_read_pages places | 5496 | * Get the length of the opaque device_addr4. xdr_read_pages places |
5497 | * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages) | 5497 | * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages) |
5498 | * and places the remaining xdr data in xdr_buf->tail | 5498 | * and places the remaining xdr data in xdr_buf->tail |
5499 | */ | 5499 | */ |
5500 | pdev->mincount = be32_to_cpup(p); | 5500 | pdev->mincount = be32_to_cpup(p); |
5501 | xdr_read_pages(xdr, pdev->mincount); /* include space for the length */ | 5501 | xdr_read_pages(xdr, pdev->mincount); /* include space for the length */ |
5502 | 5502 | ||
5503 | /* Parse notification bitmap, verifying that it is zero. */ | 5503 | /* Parse notification bitmap, verifying that it is zero. */ |
5504 | p = xdr_inline_decode(xdr, 4); | 5504 | p = xdr_inline_decode(xdr, 4); |
5505 | if (unlikely(!p)) | 5505 | if (unlikely(!p)) |
5506 | goto out_overflow; | 5506 | goto out_overflow; |
5507 | len = be32_to_cpup(p); | 5507 | len = be32_to_cpup(p); |
5508 | if (len) { | 5508 | if (len) { |
5509 | uint32_t i; | 5509 | uint32_t i; |
5510 | 5510 | ||
5511 | p = xdr_inline_decode(xdr, 4 * len); | 5511 | p = xdr_inline_decode(xdr, 4 * len); |
5512 | if (unlikely(!p)) | 5512 | if (unlikely(!p)) |
5513 | goto out_overflow; | 5513 | goto out_overflow; |
5514 | for (i = 0; i < len; i++, p++) { | 5514 | for (i = 0; i < len; i++, p++) { |
5515 | if (be32_to_cpup(p)) { | 5515 | if (be32_to_cpup(p)) { |
5516 | dprintk("%s: notifications not supported\n", | 5516 | dprintk("%s: notifications not supported\n", |
5517 | __func__); | 5517 | __func__); |
5518 | return -EIO; | 5518 | return -EIO; |
5519 | } | 5519 | } |
5520 | } | 5520 | } |
5521 | } | 5521 | } |
5522 | return 0; | 5522 | return 0; |
5523 | out_overflow: | 5523 | out_overflow: |
5524 | print_overflow_msg(__func__, xdr); | 5524 | print_overflow_msg(__func__, xdr); |
5525 | return -EIO; | 5525 | return -EIO; |
5526 | } | 5526 | } |
5527 | 5527 | ||
5528 | static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | 5528 | static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, |
5529 | struct nfs4_layoutget_res *res) | 5529 | struct nfs4_layoutget_res *res) |
5530 | { | 5530 | { |
5531 | __be32 *p; | 5531 | __be32 *p; |
5532 | int status; | 5532 | int status; |
5533 | u32 layout_count; | 5533 | u32 layout_count; |
5534 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 5534 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
5535 | struct kvec *iov = rcvbuf->head; | 5535 | struct kvec *iov = rcvbuf->head; |
5536 | u32 hdrlen, recvd; | 5536 | u32 hdrlen, recvd; |
5537 | 5537 | ||
5538 | status = decode_op_hdr(xdr, OP_LAYOUTGET); | 5538 | status = decode_op_hdr(xdr, OP_LAYOUTGET); |
5539 | if (status) | 5539 | if (status) |
5540 | return status; | 5540 | return status; |
5541 | p = xdr_inline_decode(xdr, 8 + NFS4_STATEID_SIZE); | 5541 | p = xdr_inline_decode(xdr, 8 + NFS4_STATEID_SIZE); |
5542 | if (unlikely(!p)) | 5542 | if (unlikely(!p)) |
5543 | goto out_overflow; | 5543 | goto out_overflow; |
5544 | res->return_on_close = be32_to_cpup(p++); | 5544 | res->return_on_close = be32_to_cpup(p++); |
5545 | p = xdr_decode_opaque_fixed(p, res->stateid.data, NFS4_STATEID_SIZE); | 5545 | p = xdr_decode_opaque_fixed(p, res->stateid.data, NFS4_STATEID_SIZE); |
5546 | layout_count = be32_to_cpup(p); | 5546 | layout_count = be32_to_cpup(p); |
5547 | if (!layout_count) { | 5547 | if (!layout_count) { |
5548 | dprintk("%s: server responded with empty layout array\n", | 5548 | dprintk("%s: server responded with empty layout array\n", |
5549 | __func__); | 5549 | __func__); |
5550 | return -EINVAL; | 5550 | return -EINVAL; |
5551 | } | 5551 | } |
5552 | 5552 | ||
5553 | p = xdr_inline_decode(xdr, 28); | 5553 | p = xdr_inline_decode(xdr, 28); |
5554 | if (unlikely(!p)) | 5554 | if (unlikely(!p)) |
5555 | goto out_overflow; | 5555 | goto out_overflow; |
5556 | p = xdr_decode_hyper(p, &res->range.offset); | 5556 | p = xdr_decode_hyper(p, &res->range.offset); |
5557 | p = xdr_decode_hyper(p, &res->range.length); | 5557 | p = xdr_decode_hyper(p, &res->range.length); |
5558 | res->range.iomode = be32_to_cpup(p++); | 5558 | res->range.iomode = be32_to_cpup(p++); |
5559 | res->type = be32_to_cpup(p++); | 5559 | res->type = be32_to_cpup(p++); |
5560 | res->layoutp->len = be32_to_cpup(p); | 5560 | res->layoutp->len = be32_to_cpup(p); |
5561 | 5561 | ||
5562 | dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", | 5562 | dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", |
5563 | __func__, | 5563 | __func__, |
5564 | (unsigned long)res->range.offset, | 5564 | (unsigned long)res->range.offset, |
5565 | (unsigned long)res->range.length, | 5565 | (unsigned long)res->range.length, |
5566 | res->range.iomode, | 5566 | res->range.iomode, |
5567 | res->type, | 5567 | res->type, |
5568 | res->layoutp->len); | 5568 | res->layoutp->len); |
5569 | 5569 | ||
5570 | hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; | 5570 | hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; |
5571 | recvd = req->rq_rcv_buf.len - hdrlen; | 5571 | recvd = req->rq_rcv_buf.len - hdrlen; |
5572 | if (res->layoutp->len > recvd) { | 5572 | if (res->layoutp->len > recvd) { |
5573 | dprintk("NFS: server cheating in layoutget reply: " | 5573 | dprintk("NFS: server cheating in layoutget reply: " |
5574 | "layout len %u > recvd %u\n", | 5574 | "layout len %u > recvd %u\n", |
5575 | res->layoutp->len, recvd); | 5575 | res->layoutp->len, recvd); |
5576 | return -EINVAL; | 5576 | return -EINVAL; |
5577 | } | 5577 | } |
5578 | 5578 | ||
5579 | xdr_read_pages(xdr, res->layoutp->len); | 5579 | xdr_read_pages(xdr, res->layoutp->len); |
5580 | 5580 | ||
5581 | if (layout_count > 1) { | 5581 | if (layout_count > 1) { |
5582 | /* We only handle a length one array at the moment. Any | 5582 | /* We only handle a length one array at the moment. Any |
5583 | * further entries are just ignored. Note that this means | 5583 | * further entries are just ignored. Note that this means |
5584 | * the client may see a response that is less than the | 5584 | * the client may see a response that is less than the |
5585 | * minimum it requested. | 5585 | * minimum it requested. |
5586 | */ | 5586 | */ |
5587 | dprintk("%s: server responded with %d layouts, dropping tail\n", | 5587 | dprintk("%s: server responded with %d layouts, dropping tail\n", |
5588 | __func__, layout_count); | 5588 | __func__, layout_count); |
5589 | } | 5589 | } |
5590 | 5590 | ||
5591 | return 0; | 5591 | return 0; |
5592 | out_overflow: | 5592 | out_overflow: |
5593 | print_overflow_msg(__func__, xdr); | 5593 | print_overflow_msg(__func__, xdr); |
5594 | return -EIO; | 5594 | return -EIO; |
5595 | } | 5595 | } |
5596 | 5596 | ||
5597 | static int decode_layoutreturn(struct xdr_stream *xdr, | 5597 | static int decode_layoutreturn(struct xdr_stream *xdr, |
5598 | struct nfs4_layoutreturn_res *res) | 5598 | struct nfs4_layoutreturn_res *res) |
5599 | { | 5599 | { |
5600 | __be32 *p; | 5600 | __be32 *p; |
5601 | int status; | 5601 | int status; |
5602 | 5602 | ||
5603 | status = decode_op_hdr(xdr, OP_LAYOUTRETURN); | 5603 | status = decode_op_hdr(xdr, OP_LAYOUTRETURN); |
5604 | if (status) | 5604 | if (status) |
5605 | return status; | 5605 | return status; |
5606 | p = xdr_inline_decode(xdr, 4); | 5606 | p = xdr_inline_decode(xdr, 4); |
5607 | if (unlikely(!p)) | 5607 | if (unlikely(!p)) |
5608 | goto out_overflow; | 5608 | goto out_overflow; |
5609 | res->lrs_present = be32_to_cpup(p); | 5609 | res->lrs_present = be32_to_cpup(p); |
5610 | if (res->lrs_present) | 5610 | if (res->lrs_present) |
5611 | status = decode_stateid(xdr, &res->stateid); | 5611 | status = decode_stateid(xdr, &res->stateid); |
5612 | return status; | 5612 | return status; |
5613 | out_overflow: | 5613 | out_overflow: |
5614 | print_overflow_msg(__func__, xdr); | 5614 | print_overflow_msg(__func__, xdr); |
5615 | return -EIO; | 5615 | return -EIO; |
5616 | } | 5616 | } |
5617 | 5617 | ||
5618 | static int decode_layoutcommit(struct xdr_stream *xdr, | 5618 | static int decode_layoutcommit(struct xdr_stream *xdr, |
5619 | struct rpc_rqst *req, | 5619 | struct rpc_rqst *req, |
5620 | struct nfs4_layoutcommit_res *res) | 5620 | struct nfs4_layoutcommit_res *res) |
5621 | { | 5621 | { |
5622 | __be32 *p; | 5622 | __be32 *p; |
5623 | __u32 sizechanged; | 5623 | __u32 sizechanged; |
5624 | int status; | 5624 | int status; |
5625 | 5625 | ||
5626 | status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); | 5626 | status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); |
5627 | res->status = status; | 5627 | res->status = status; |
5628 | if (status) | 5628 | if (status) |
5629 | return status; | 5629 | return status; |
5630 | 5630 | ||
5631 | p = xdr_inline_decode(xdr, 4); | 5631 | p = xdr_inline_decode(xdr, 4); |
5632 | if (unlikely(!p)) | 5632 | if (unlikely(!p)) |
5633 | goto out_overflow; | 5633 | goto out_overflow; |
5634 | sizechanged = be32_to_cpup(p); | 5634 | sizechanged = be32_to_cpup(p); |
5635 | 5635 | ||
5636 | if (sizechanged) { | 5636 | if (sizechanged) { |
5637 | /* throw away new size */ | 5637 | /* throw away new size */ |
5638 | p = xdr_inline_decode(xdr, 8); | 5638 | p = xdr_inline_decode(xdr, 8); |
5639 | if (unlikely(!p)) | 5639 | if (unlikely(!p)) |
5640 | goto out_overflow; | 5640 | goto out_overflow; |
5641 | } | 5641 | } |
5642 | return 0; | 5642 | return 0; |
5643 | out_overflow: | 5643 | out_overflow: |
5644 | print_overflow_msg(__func__, xdr); | 5644 | print_overflow_msg(__func__, xdr); |
5645 | return -EIO; | 5645 | return -EIO; |
5646 | } | 5646 | } |
5647 | 5647 | ||
5648 | static int decode_test_stateid(struct xdr_stream *xdr, | 5648 | static int decode_test_stateid(struct xdr_stream *xdr, |
5649 | struct nfs41_test_stateid_res *res) | 5649 | struct nfs41_test_stateid_res *res) |
5650 | { | 5650 | { |
5651 | __be32 *p; | 5651 | __be32 *p; |
5652 | int status; | 5652 | int status; |
5653 | int num_res; | 5653 | int num_res; |
5654 | 5654 | ||
5655 | status = decode_op_hdr(xdr, OP_TEST_STATEID); | 5655 | status = decode_op_hdr(xdr, OP_TEST_STATEID); |
5656 | if (status) | 5656 | if (status) |
5657 | return status; | 5657 | return status; |
5658 | 5658 | ||
5659 | p = xdr_inline_decode(xdr, 4); | 5659 | p = xdr_inline_decode(xdr, 4); |
5660 | if (unlikely(!p)) | 5660 | if (unlikely(!p)) |
5661 | goto out_overflow; | 5661 | goto out_overflow; |
5662 | num_res = be32_to_cpup(p++); | 5662 | num_res = be32_to_cpup(p++); |
5663 | if (num_res != 1) | 5663 | if (num_res != 1) |
5664 | goto out; | 5664 | goto out; |
5665 | 5665 | ||
5666 | p = xdr_inline_decode(xdr, 4); | 5666 | p = xdr_inline_decode(xdr, 4); |
5667 | if (unlikely(!p)) | 5667 | if (unlikely(!p)) |
5668 | goto out_overflow; | 5668 | goto out_overflow; |
5669 | res->status = be32_to_cpup(p++); | 5669 | res->status = be32_to_cpup(p++); |
5670 | return res->status; | 5670 | return res->status; |
5671 | out_overflow: | 5671 | out_overflow: |
5672 | print_overflow_msg(__func__, xdr); | 5672 | print_overflow_msg(__func__, xdr); |
5673 | out: | 5673 | out: |
5674 | return -EIO; | 5674 | return -EIO; |
5675 | } | 5675 | } |
5676 | 5676 | ||
5677 | static int decode_free_stateid(struct xdr_stream *xdr, | 5677 | static int decode_free_stateid(struct xdr_stream *xdr, |
5678 | struct nfs41_free_stateid_res *res) | 5678 | struct nfs41_free_stateid_res *res) |
5679 | { | 5679 | { |
5680 | __be32 *p; | 5680 | __be32 *p; |
5681 | int status; | 5681 | int status; |
5682 | 5682 | ||
5683 | status = decode_op_hdr(xdr, OP_FREE_STATEID); | 5683 | status = decode_op_hdr(xdr, OP_FREE_STATEID); |
5684 | if (status) | 5684 | if (status) |
5685 | return status; | 5685 | return status; |
5686 | 5686 | ||
5687 | p = xdr_inline_decode(xdr, 4); | 5687 | p = xdr_inline_decode(xdr, 4); |
5688 | if (unlikely(!p)) | 5688 | if (unlikely(!p)) |
5689 | goto out_overflow; | 5689 | goto out_overflow; |
5690 | res->status = be32_to_cpup(p++); | 5690 | res->status = be32_to_cpup(p++); |
5691 | return res->status; | 5691 | return res->status; |
5692 | out_overflow: | 5692 | out_overflow: |
5693 | print_overflow_msg(__func__, xdr); | 5693 | print_overflow_msg(__func__, xdr); |
5694 | return -EIO; | 5694 | return -EIO; |
5695 | } | 5695 | } |
5696 | #endif /* CONFIG_NFS_V4_1 */ | 5696 | #endif /* CONFIG_NFS_V4_1 */ |
5697 | 5697 | ||
5698 | /* | 5698 | /* |
5699 | * END OF "GENERIC" DECODE ROUTINES. | 5699 | * END OF "GENERIC" DECODE ROUTINES. |
5700 | */ | 5700 | */ |
5701 | 5701 | ||
5702 | /* | 5702 | /* |
5703 | * Decode OPEN_DOWNGRADE response | 5703 | * Decode OPEN_DOWNGRADE response |
5704 | */ | 5704 | */ |
5705 | static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, | 5705 | static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, |
5706 | struct xdr_stream *xdr, | 5706 | struct xdr_stream *xdr, |
5707 | struct nfs_closeres *res) | 5707 | struct nfs_closeres *res) |
5708 | { | 5708 | { |
5709 | struct compound_hdr hdr; | 5709 | struct compound_hdr hdr; |
5710 | int status; | 5710 | int status; |
5711 | 5711 | ||
5712 | status = decode_compound_hdr(xdr, &hdr); | 5712 | status = decode_compound_hdr(xdr, &hdr); |
5713 | if (status) | 5713 | if (status) |
5714 | goto out; | 5714 | goto out; |
5715 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5715 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5716 | if (status) | 5716 | if (status) |
5717 | goto out; | 5717 | goto out; |
5718 | status = decode_putfh(xdr); | 5718 | status = decode_putfh(xdr); |
5719 | if (status) | 5719 | if (status) |
5720 | goto out; | 5720 | goto out; |
5721 | status = decode_open_downgrade(xdr, res); | 5721 | status = decode_open_downgrade(xdr, res); |
5722 | if (status != 0) | 5722 | if (status != 0) |
5723 | goto out; | 5723 | goto out; |
5724 | decode_getfattr(xdr, res->fattr, res->server); | 5724 | decode_getfattr(xdr, res->fattr, res->server); |
5725 | out: | 5725 | out: |
5726 | return status; | 5726 | return status; |
5727 | } | 5727 | } |
5728 | 5728 | ||
5729 | /* | 5729 | /* |
5730 | * Decode ACCESS response | 5730 | * Decode ACCESS response |
5731 | */ | 5731 | */ |
5732 | static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5732 | static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5733 | struct nfs4_accessres *res) | 5733 | struct nfs4_accessres *res) |
5734 | { | 5734 | { |
5735 | struct compound_hdr hdr; | 5735 | struct compound_hdr hdr; |
5736 | int status; | 5736 | int status; |
5737 | 5737 | ||
5738 | status = decode_compound_hdr(xdr, &hdr); | 5738 | status = decode_compound_hdr(xdr, &hdr); |
5739 | if (status) | 5739 | if (status) |
5740 | goto out; | 5740 | goto out; |
5741 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5741 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5742 | if (status) | 5742 | if (status) |
5743 | goto out; | 5743 | goto out; |
5744 | status = decode_putfh(xdr); | 5744 | status = decode_putfh(xdr); |
5745 | if (status != 0) | 5745 | if (status != 0) |
5746 | goto out; | 5746 | goto out; |
5747 | status = decode_access(xdr, res); | 5747 | status = decode_access(xdr, res); |
5748 | if (status != 0) | 5748 | if (status != 0) |
5749 | goto out; | 5749 | goto out; |
5750 | decode_getfattr(xdr, res->fattr, res->server); | 5750 | decode_getfattr(xdr, res->fattr, res->server); |
5751 | out: | 5751 | out: |
5752 | return status; | 5752 | return status; |
5753 | } | 5753 | } |
5754 | 5754 | ||
5755 | /* | 5755 | /* |
5756 | * Decode LOOKUP response | 5756 | * Decode LOOKUP response |
5757 | */ | 5757 | */ |
5758 | static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5758 | static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5759 | struct nfs4_lookup_res *res) | 5759 | struct nfs4_lookup_res *res) |
5760 | { | 5760 | { |
5761 | struct compound_hdr hdr; | 5761 | struct compound_hdr hdr; |
5762 | int status; | 5762 | int status; |
5763 | 5763 | ||
5764 | status = decode_compound_hdr(xdr, &hdr); | 5764 | status = decode_compound_hdr(xdr, &hdr); |
5765 | if (status) | 5765 | if (status) |
5766 | goto out; | 5766 | goto out; |
5767 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5767 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5768 | if (status) | 5768 | if (status) |
5769 | goto out; | 5769 | goto out; |
5770 | status = decode_putfh(xdr); | 5770 | status = decode_putfh(xdr); |
5771 | if (status) | 5771 | if (status) |
5772 | goto out; | 5772 | goto out; |
5773 | status = decode_lookup(xdr); | 5773 | status = decode_lookup(xdr); |
5774 | if (status) | 5774 | if (status) |
5775 | goto out; | 5775 | goto out; |
5776 | status = decode_getfh(xdr, res->fh); | 5776 | status = decode_getfh(xdr, res->fh); |
5777 | if (status) | 5777 | if (status) |
5778 | goto out; | 5778 | goto out; |
5779 | status = decode_getfattr(xdr, res->fattr, res->server); | 5779 | status = decode_getfattr(xdr, res->fattr, res->server); |
5780 | out: | 5780 | out: |
5781 | return status; | 5781 | return status; |
5782 | } | 5782 | } |
5783 | 5783 | ||
5784 | /* | 5784 | /* |
5785 | * Decode LOOKUP_ROOT response | 5785 | * Decode LOOKUP_ROOT response |
5786 | */ | 5786 | */ |
5787 | static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, | 5787 | static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, |
5788 | struct xdr_stream *xdr, | 5788 | struct xdr_stream *xdr, |
5789 | struct nfs4_lookup_res *res) | 5789 | struct nfs4_lookup_res *res) |
5790 | { | 5790 | { |
5791 | struct compound_hdr hdr; | 5791 | struct compound_hdr hdr; |
5792 | int status; | 5792 | int status; |
5793 | 5793 | ||
5794 | status = decode_compound_hdr(xdr, &hdr); | 5794 | status = decode_compound_hdr(xdr, &hdr); |
5795 | if (status) | 5795 | if (status) |
5796 | goto out; | 5796 | goto out; |
5797 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5797 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5798 | if (status) | 5798 | if (status) |
5799 | goto out; | 5799 | goto out; |
5800 | status = decode_putrootfh(xdr); | 5800 | status = decode_putrootfh(xdr); |
5801 | if (status) | 5801 | if (status) |
5802 | goto out; | 5802 | goto out; |
5803 | status = decode_getfh(xdr, res->fh); | 5803 | status = decode_getfh(xdr, res->fh); |
5804 | if (status == 0) | 5804 | if (status == 0) |
5805 | status = decode_getfattr(xdr, res->fattr, res->server); | 5805 | status = decode_getfattr(xdr, res->fattr, res->server); |
5806 | out: | 5806 | out: |
5807 | return status; | 5807 | return status; |
5808 | } | 5808 | } |
5809 | 5809 | ||
5810 | /* | 5810 | /* |
5811 | * Decode REMOVE response | 5811 | * Decode REMOVE response |
5812 | */ | 5812 | */ |
5813 | static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5813 | static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5814 | struct nfs_removeres *res) | 5814 | struct nfs_removeres *res) |
5815 | { | 5815 | { |
5816 | struct compound_hdr hdr; | 5816 | struct compound_hdr hdr; |
5817 | int status; | 5817 | int status; |
5818 | 5818 | ||
5819 | status = decode_compound_hdr(xdr, &hdr); | 5819 | status = decode_compound_hdr(xdr, &hdr); |
5820 | if (status) | 5820 | if (status) |
5821 | goto out; | 5821 | goto out; |
5822 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5822 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5823 | if (status) | 5823 | if (status) |
5824 | goto out; | 5824 | goto out; |
5825 | status = decode_putfh(xdr); | 5825 | status = decode_putfh(xdr); |
5826 | if (status) | 5826 | if (status) |
5827 | goto out; | 5827 | goto out; |
5828 | status = decode_remove(xdr, &res->cinfo); | 5828 | status = decode_remove(xdr, &res->cinfo); |
5829 | if (status) | 5829 | if (status) |
5830 | goto out; | 5830 | goto out; |
5831 | decode_getfattr(xdr, res->dir_attr, res->server); | 5831 | decode_getfattr(xdr, res->dir_attr, res->server); |
5832 | out: | 5832 | out: |
5833 | return status; | 5833 | return status; |
5834 | } | 5834 | } |
5835 | 5835 | ||
5836 | /* | 5836 | /* |
5837 | * Decode RENAME response | 5837 | * Decode RENAME response |
5838 | */ | 5838 | */ |
5839 | static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5839 | static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5840 | struct nfs_renameres *res) | 5840 | struct nfs_renameres *res) |
5841 | { | 5841 | { |
5842 | struct compound_hdr hdr; | 5842 | struct compound_hdr hdr; |
5843 | int status; | 5843 | int status; |
5844 | 5844 | ||
5845 | status = decode_compound_hdr(xdr, &hdr); | 5845 | status = decode_compound_hdr(xdr, &hdr); |
5846 | if (status) | 5846 | if (status) |
5847 | goto out; | 5847 | goto out; |
5848 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5848 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5849 | if (status) | 5849 | if (status) |
5850 | goto out; | 5850 | goto out; |
5851 | status = decode_putfh(xdr); | 5851 | status = decode_putfh(xdr); |
5852 | if (status) | 5852 | if (status) |
5853 | goto out; | 5853 | goto out; |
5854 | status = decode_savefh(xdr); | 5854 | status = decode_savefh(xdr); |
5855 | if (status) | 5855 | if (status) |
5856 | goto out; | 5856 | goto out; |
5857 | status = decode_putfh(xdr); | 5857 | status = decode_putfh(xdr); |
5858 | if (status) | 5858 | if (status) |
5859 | goto out; | 5859 | goto out; |
5860 | status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); | 5860 | status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo); |
5861 | if (status) | 5861 | if (status) |
5862 | goto out; | 5862 | goto out; |
5863 | /* Current FH is target directory */ | 5863 | /* Current FH is target directory */ |
5864 | if (decode_getfattr(xdr, res->new_fattr, res->server)) | 5864 | if (decode_getfattr(xdr, res->new_fattr, res->server)) |
5865 | goto out; | 5865 | goto out; |
5866 | status = decode_restorefh(xdr); | 5866 | status = decode_restorefh(xdr); |
5867 | if (status) | 5867 | if (status) |
5868 | goto out; | 5868 | goto out; |
5869 | decode_getfattr(xdr, res->old_fattr, res->server); | 5869 | decode_getfattr(xdr, res->old_fattr, res->server); |
5870 | out: | 5870 | out: |
5871 | return status; | 5871 | return status; |
5872 | } | 5872 | } |
5873 | 5873 | ||
5874 | /* | 5874 | /* |
5875 | * Decode LINK response | 5875 | * Decode LINK response |
5876 | */ | 5876 | */ |
5877 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5877 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5878 | struct nfs4_link_res *res) | 5878 | struct nfs4_link_res *res) |
5879 | { | 5879 | { |
5880 | struct compound_hdr hdr; | 5880 | struct compound_hdr hdr; |
5881 | int status; | 5881 | int status; |
5882 | 5882 | ||
5883 | status = decode_compound_hdr(xdr, &hdr); | 5883 | status = decode_compound_hdr(xdr, &hdr); |
5884 | if (status) | 5884 | if (status) |
5885 | goto out; | 5885 | goto out; |
5886 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5886 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5887 | if (status) | 5887 | if (status) |
5888 | goto out; | 5888 | goto out; |
5889 | status = decode_putfh(xdr); | 5889 | status = decode_putfh(xdr); |
5890 | if (status) | 5890 | if (status) |
5891 | goto out; | 5891 | goto out; |
5892 | status = decode_savefh(xdr); | 5892 | status = decode_savefh(xdr); |
5893 | if (status) | 5893 | if (status) |
5894 | goto out; | 5894 | goto out; |
5895 | status = decode_putfh(xdr); | 5895 | status = decode_putfh(xdr); |
5896 | if (status) | 5896 | if (status) |
5897 | goto out; | 5897 | goto out; |
5898 | status = decode_link(xdr, &res->cinfo); | 5898 | status = decode_link(xdr, &res->cinfo); |
5899 | if (status) | 5899 | if (status) |
5900 | goto out; | 5900 | goto out; |
5901 | /* | 5901 | /* |
5902 | * Note order: OP_LINK leaves the directory as the current | 5902 | * Note order: OP_LINK leaves the directory as the current |
5903 | * filehandle. | 5903 | * filehandle. |
5904 | */ | 5904 | */ |
5905 | if (decode_getfattr(xdr, res->dir_attr, res->server)) | 5905 | if (decode_getfattr(xdr, res->dir_attr, res->server)) |
5906 | goto out; | 5906 | goto out; |
5907 | status = decode_restorefh(xdr); | 5907 | status = decode_restorefh(xdr); |
5908 | if (status) | 5908 | if (status) |
5909 | goto out; | 5909 | goto out; |
5910 | decode_getfattr(xdr, res->fattr, res->server); | 5910 | decode_getfattr(xdr, res->fattr, res->server); |
5911 | out: | 5911 | out: |
5912 | return status; | 5912 | return status; |
5913 | } | 5913 | } |
5914 | 5914 | ||
5915 | /* | 5915 | /* |
5916 | * Decode CREATE response | 5916 | * Decode CREATE response |
5917 | */ | 5917 | */ |
5918 | static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5918 | static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5919 | struct nfs4_create_res *res) | 5919 | struct nfs4_create_res *res) |
5920 | { | 5920 | { |
5921 | struct compound_hdr hdr; | 5921 | struct compound_hdr hdr; |
5922 | int status; | 5922 | int status; |
5923 | 5923 | ||
5924 | status = decode_compound_hdr(xdr, &hdr); | 5924 | status = decode_compound_hdr(xdr, &hdr); |
5925 | if (status) | 5925 | if (status) |
5926 | goto out; | 5926 | goto out; |
5927 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5927 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5928 | if (status) | 5928 | if (status) |
5929 | goto out; | 5929 | goto out; |
5930 | status = decode_putfh(xdr); | 5930 | status = decode_putfh(xdr); |
5931 | if (status) | 5931 | if (status) |
5932 | goto out; | 5932 | goto out; |
5933 | status = decode_savefh(xdr); | 5933 | status = decode_savefh(xdr); |
5934 | if (status) | 5934 | if (status) |
5935 | goto out; | 5935 | goto out; |
5936 | status = decode_create(xdr, &res->dir_cinfo); | 5936 | status = decode_create(xdr, &res->dir_cinfo); |
5937 | if (status) | 5937 | if (status) |
5938 | goto out; | 5938 | goto out; |
5939 | status = decode_getfh(xdr, res->fh); | 5939 | status = decode_getfh(xdr, res->fh); |
5940 | if (status) | 5940 | if (status) |
5941 | goto out; | 5941 | goto out; |
5942 | if (decode_getfattr(xdr, res->fattr, res->server)) | 5942 | if (decode_getfattr(xdr, res->fattr, res->server)) |
5943 | goto out; | 5943 | goto out; |
5944 | status = decode_restorefh(xdr); | 5944 | status = decode_restorefh(xdr); |
5945 | if (status) | 5945 | if (status) |
5946 | goto out; | 5946 | goto out; |
5947 | decode_getfattr(xdr, res->dir_fattr, res->server); | 5947 | decode_getfattr(xdr, res->dir_fattr, res->server); |
5948 | out: | 5948 | out: |
5949 | return status; | 5949 | return status; |
5950 | } | 5950 | } |
5951 | 5951 | ||
5952 | /* | 5952 | /* |
5953 | * Decode SYMLINK response | 5953 | * Decode SYMLINK response |
5954 | */ | 5954 | */ |
5955 | static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5955 | static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5956 | struct nfs4_create_res *res) | 5956 | struct nfs4_create_res *res) |
5957 | { | 5957 | { |
5958 | return nfs4_xdr_dec_create(rqstp, xdr, res); | 5958 | return nfs4_xdr_dec_create(rqstp, xdr, res); |
5959 | } | 5959 | } |
5960 | 5960 | ||
5961 | /* | 5961 | /* |
5962 | * Decode GETATTR response | 5962 | * Decode GETATTR response |
5963 | */ | 5963 | */ |
5964 | static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 5964 | static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
5965 | struct nfs4_getattr_res *res) | 5965 | struct nfs4_getattr_res *res) |
5966 | { | 5966 | { |
5967 | struct compound_hdr hdr; | 5967 | struct compound_hdr hdr; |
5968 | int status; | 5968 | int status; |
5969 | 5969 | ||
5970 | status = decode_compound_hdr(xdr, &hdr); | 5970 | status = decode_compound_hdr(xdr, &hdr); |
5971 | if (status) | 5971 | if (status) |
5972 | goto out; | 5972 | goto out; |
5973 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 5973 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
5974 | if (status) | 5974 | if (status) |
5975 | goto out; | 5975 | goto out; |
5976 | status = decode_putfh(xdr); | 5976 | status = decode_putfh(xdr); |
5977 | if (status) | 5977 | if (status) |
5978 | goto out; | 5978 | goto out; |
5979 | status = decode_getfattr(xdr, res->fattr, res->server); | 5979 | status = decode_getfattr(xdr, res->fattr, res->server); |
5980 | out: | 5980 | out: |
5981 | return status; | 5981 | return status; |
5982 | } | 5982 | } |
5983 | 5983 | ||
5984 | /* | 5984 | /* |
5985 | * Encode an SETACL request | 5985 | * Encode an SETACL request |
5986 | */ | 5986 | */ |
5987 | static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr, | 5987 | static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr, |
5988 | struct nfs_setaclargs *args) | 5988 | struct nfs_setaclargs *args) |
5989 | { | 5989 | { |
5990 | struct compound_hdr hdr = { | 5990 | struct compound_hdr hdr = { |
5991 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | 5991 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), |
5992 | }; | 5992 | }; |
5993 | 5993 | ||
5994 | encode_compound_hdr(xdr, req, &hdr); | 5994 | encode_compound_hdr(xdr, req, &hdr); |
5995 | encode_sequence(xdr, &args->seq_args, &hdr); | 5995 | encode_sequence(xdr, &args->seq_args, &hdr); |
5996 | encode_putfh(xdr, args->fh, &hdr); | 5996 | encode_putfh(xdr, args->fh, &hdr); |
5997 | encode_setacl(xdr, args, &hdr); | 5997 | encode_setacl(xdr, args, &hdr); |
5998 | encode_nops(&hdr); | 5998 | encode_nops(&hdr); |
5999 | } | 5999 | } |
6000 | 6000 | ||
6001 | /* | 6001 | /* |
6002 | * Decode SETACL response | 6002 | * Decode SETACL response |
6003 | */ | 6003 | */ |
6004 | static int | 6004 | static int |
6005 | nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6005 | nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6006 | struct nfs_setaclres *res) | 6006 | struct nfs_setaclres *res) |
6007 | { | 6007 | { |
6008 | struct compound_hdr hdr; | 6008 | struct compound_hdr hdr; |
6009 | int status; | 6009 | int status; |
6010 | 6010 | ||
6011 | status = decode_compound_hdr(xdr, &hdr); | 6011 | status = decode_compound_hdr(xdr, &hdr); |
6012 | if (status) | 6012 | if (status) |
6013 | goto out; | 6013 | goto out; |
6014 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6014 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6015 | if (status) | 6015 | if (status) |
6016 | goto out; | 6016 | goto out; |
6017 | status = decode_putfh(xdr); | 6017 | status = decode_putfh(xdr); |
6018 | if (status) | 6018 | if (status) |
6019 | goto out; | 6019 | goto out; |
6020 | status = decode_setattr(xdr); | 6020 | status = decode_setattr(xdr); |
6021 | out: | 6021 | out: |
6022 | return status; | 6022 | return status; |
6023 | } | 6023 | } |
6024 | 6024 | ||
6025 | /* | 6025 | /* |
6026 | * Decode GETACL response | 6026 | * Decode GETACL response |
6027 | */ | 6027 | */ |
6028 | static int | 6028 | static int |
6029 | nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6029 | nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6030 | struct nfs_getaclres *res) | 6030 | struct nfs_getaclres *res) |
6031 | { | 6031 | { |
6032 | struct compound_hdr hdr; | 6032 | struct compound_hdr hdr; |
6033 | int status; | 6033 | int status; |
6034 | 6034 | ||
6035 | status = decode_compound_hdr(xdr, &hdr); | 6035 | status = decode_compound_hdr(xdr, &hdr); |
6036 | if (status) | 6036 | if (status) |
6037 | goto out; | 6037 | goto out; |
6038 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6038 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6039 | if (status) | 6039 | if (status) |
6040 | goto out; | 6040 | goto out; |
6041 | status = decode_putfh(xdr); | 6041 | status = decode_putfh(xdr); |
6042 | if (status) | 6042 | if (status) |
6043 | goto out; | 6043 | goto out; |
6044 | status = decode_getacl(xdr, rqstp, res); | 6044 | status = decode_getacl(xdr, rqstp, res); |
6045 | 6045 | ||
6046 | out: | 6046 | out: |
6047 | return status; | 6047 | return status; |
6048 | } | 6048 | } |
6049 | 6049 | ||
6050 | /* | 6050 | /* |
6051 | * Decode CLOSE response | 6051 | * Decode CLOSE response |
6052 | */ | 6052 | */ |
6053 | static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6053 | static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6054 | struct nfs_closeres *res) | 6054 | struct nfs_closeres *res) |
6055 | { | 6055 | { |
6056 | struct compound_hdr hdr; | 6056 | struct compound_hdr hdr; |
6057 | int status; | 6057 | int status; |
6058 | 6058 | ||
6059 | status = decode_compound_hdr(xdr, &hdr); | 6059 | status = decode_compound_hdr(xdr, &hdr); |
6060 | if (status) | 6060 | if (status) |
6061 | goto out; | 6061 | goto out; |
6062 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6062 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6063 | if (status) | 6063 | if (status) |
6064 | goto out; | 6064 | goto out; |
6065 | status = decode_putfh(xdr); | 6065 | status = decode_putfh(xdr); |
6066 | if (status) | 6066 | if (status) |
6067 | goto out; | 6067 | goto out; |
6068 | status = decode_close(xdr, res); | 6068 | status = decode_close(xdr, res); |
6069 | if (status != 0) | 6069 | if (status != 0) |
6070 | goto out; | 6070 | goto out; |
6071 | /* | 6071 | /* |
6072 | * Note: Server may do delete on close for this file | 6072 | * Note: Server may do delete on close for this file |
6073 | * in which case the getattr call will fail with | 6073 | * in which case the getattr call will fail with |
6074 | * an ESTALE error. Shouldn't be a problem, | 6074 | * an ESTALE error. Shouldn't be a problem, |
6075 | * though, since fattr->valid will remain unset. | 6075 | * though, since fattr->valid will remain unset. |
6076 | */ | 6076 | */ |
6077 | decode_getfattr(xdr, res->fattr, res->server); | 6077 | decode_getfattr(xdr, res->fattr, res->server); |
6078 | out: | 6078 | out: |
6079 | return status; | 6079 | return status; |
6080 | } | 6080 | } |
6081 | 6081 | ||
6082 | /* | 6082 | /* |
6083 | * Decode OPEN response | 6083 | * Decode OPEN response |
6084 | */ | 6084 | */ |
6085 | static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6085 | static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6086 | struct nfs_openres *res) | 6086 | struct nfs_openres *res) |
6087 | { | 6087 | { |
6088 | struct compound_hdr hdr; | 6088 | struct compound_hdr hdr; |
6089 | int status; | 6089 | int status; |
6090 | 6090 | ||
6091 | status = decode_compound_hdr(xdr, &hdr); | 6091 | status = decode_compound_hdr(xdr, &hdr); |
6092 | if (status) | 6092 | if (status) |
6093 | goto out; | 6093 | goto out; |
6094 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6094 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6095 | if (status) | 6095 | if (status) |
6096 | goto out; | 6096 | goto out; |
6097 | status = decode_putfh(xdr); | 6097 | status = decode_putfh(xdr); |
6098 | if (status) | 6098 | if (status) |
6099 | goto out; | 6099 | goto out; |
6100 | status = decode_savefh(xdr); | 6100 | status = decode_savefh(xdr); |
6101 | if (status) | 6101 | if (status) |
6102 | goto out; | 6102 | goto out; |
6103 | status = decode_open(xdr, res); | 6103 | status = decode_open(xdr, res); |
6104 | if (status) | 6104 | if (status) |
6105 | goto out; | 6105 | goto out; |
6106 | if (decode_getfh(xdr, &res->fh) != 0) | 6106 | if (decode_getfh(xdr, &res->fh) != 0) |
6107 | goto out; | 6107 | goto out; |
6108 | if (decode_getfattr(xdr, res->f_attr, res->server) != 0) | 6108 | if (decode_getfattr(xdr, res->f_attr, res->server) != 0) |
6109 | goto out; | 6109 | goto out; |
6110 | if (decode_restorefh(xdr) != 0) | 6110 | if (decode_restorefh(xdr) != 0) |
6111 | goto out; | 6111 | goto out; |
6112 | decode_getfattr(xdr, res->dir_attr, res->server); | 6112 | decode_getfattr(xdr, res->dir_attr, res->server); |
6113 | out: | 6113 | out: |
6114 | return status; | 6114 | return status; |
6115 | } | 6115 | } |
6116 | 6116 | ||
6117 | /* | 6117 | /* |
6118 | * Decode OPEN_CONFIRM response | 6118 | * Decode OPEN_CONFIRM response |
6119 | */ | 6119 | */ |
6120 | static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, | 6120 | static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, |
6121 | struct xdr_stream *xdr, | 6121 | struct xdr_stream *xdr, |
6122 | struct nfs_open_confirmres *res) | 6122 | struct nfs_open_confirmres *res) |
6123 | { | 6123 | { |
6124 | struct compound_hdr hdr; | 6124 | struct compound_hdr hdr; |
6125 | int status; | 6125 | int status; |
6126 | 6126 | ||
6127 | status = decode_compound_hdr(xdr, &hdr); | 6127 | status = decode_compound_hdr(xdr, &hdr); |
6128 | if (status) | 6128 | if (status) |
6129 | goto out; | 6129 | goto out; |
6130 | status = decode_putfh(xdr); | 6130 | status = decode_putfh(xdr); |
6131 | if (status) | 6131 | if (status) |
6132 | goto out; | 6132 | goto out; |
6133 | status = decode_open_confirm(xdr, res); | 6133 | status = decode_open_confirm(xdr, res); |
6134 | out: | 6134 | out: |
6135 | return status; | 6135 | return status; |
6136 | } | 6136 | } |
6137 | 6137 | ||
6138 | /* | 6138 | /* |
6139 | * Decode OPEN response | 6139 | * Decode OPEN response |
6140 | */ | 6140 | */ |
6141 | static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, | 6141 | static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, |
6142 | struct xdr_stream *xdr, | 6142 | struct xdr_stream *xdr, |
6143 | struct nfs_openres *res) | 6143 | struct nfs_openres *res) |
6144 | { | 6144 | { |
6145 | struct compound_hdr hdr; | 6145 | struct compound_hdr hdr; |
6146 | int status; | 6146 | int status; |
6147 | 6147 | ||
6148 | status = decode_compound_hdr(xdr, &hdr); | 6148 | status = decode_compound_hdr(xdr, &hdr); |
6149 | if (status) | 6149 | if (status) |
6150 | goto out; | 6150 | goto out; |
6151 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6151 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6152 | if (status) | 6152 | if (status) |
6153 | goto out; | 6153 | goto out; |
6154 | status = decode_putfh(xdr); | 6154 | status = decode_putfh(xdr); |
6155 | if (status) | 6155 | if (status) |
6156 | goto out; | 6156 | goto out; |
6157 | status = decode_open(xdr, res); | 6157 | status = decode_open(xdr, res); |
6158 | if (status) | 6158 | if (status) |
6159 | goto out; | 6159 | goto out; |
6160 | decode_getfattr(xdr, res->f_attr, res->server); | 6160 | decode_getfattr(xdr, res->f_attr, res->server); |
6161 | out: | 6161 | out: |
6162 | return status; | 6162 | return status; |
6163 | } | 6163 | } |
6164 | 6164 | ||
6165 | /* | 6165 | /* |
6166 | * Decode SETATTR response | 6166 | * Decode SETATTR response |
6167 | */ | 6167 | */ |
6168 | static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, | 6168 | static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, |
6169 | struct xdr_stream *xdr, | 6169 | struct xdr_stream *xdr, |
6170 | struct nfs_setattrres *res) | 6170 | struct nfs_setattrres *res) |
6171 | { | 6171 | { |
6172 | struct compound_hdr hdr; | 6172 | struct compound_hdr hdr; |
6173 | int status; | 6173 | int status; |
6174 | 6174 | ||
6175 | status = decode_compound_hdr(xdr, &hdr); | 6175 | status = decode_compound_hdr(xdr, &hdr); |
6176 | if (status) | 6176 | if (status) |
6177 | goto out; | 6177 | goto out; |
6178 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6178 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6179 | if (status) | 6179 | if (status) |
6180 | goto out; | 6180 | goto out; |
6181 | status = decode_putfh(xdr); | 6181 | status = decode_putfh(xdr); |
6182 | if (status) | 6182 | if (status) |
6183 | goto out; | 6183 | goto out; |
6184 | status = decode_setattr(xdr); | 6184 | status = decode_setattr(xdr); |
6185 | if (status) | 6185 | if (status) |
6186 | goto out; | 6186 | goto out; |
6187 | decode_getfattr(xdr, res->fattr, res->server); | 6187 | decode_getfattr(xdr, res->fattr, res->server); |
6188 | out: | 6188 | out: |
6189 | return status; | 6189 | return status; |
6190 | } | 6190 | } |
6191 | 6191 | ||
6192 | /* | 6192 | /* |
6193 | * Decode LOCK response | 6193 | * Decode LOCK response |
6194 | */ | 6194 | */ |
6195 | static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6195 | static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6196 | struct nfs_lock_res *res) | 6196 | struct nfs_lock_res *res) |
6197 | { | 6197 | { |
6198 | struct compound_hdr hdr; | 6198 | struct compound_hdr hdr; |
6199 | int status; | 6199 | int status; |
6200 | 6200 | ||
6201 | status = decode_compound_hdr(xdr, &hdr); | 6201 | status = decode_compound_hdr(xdr, &hdr); |
6202 | if (status) | 6202 | if (status) |
6203 | goto out; | 6203 | goto out; |
6204 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6204 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6205 | if (status) | 6205 | if (status) |
6206 | goto out; | 6206 | goto out; |
6207 | status = decode_putfh(xdr); | 6207 | status = decode_putfh(xdr); |
6208 | if (status) | 6208 | if (status) |
6209 | goto out; | 6209 | goto out; |
6210 | status = decode_lock(xdr, res); | 6210 | status = decode_lock(xdr, res); |
6211 | out: | 6211 | out: |
6212 | return status; | 6212 | return status; |
6213 | } | 6213 | } |
6214 | 6214 | ||
6215 | /* | 6215 | /* |
6216 | * Decode LOCKT response | 6216 | * Decode LOCKT response |
6217 | */ | 6217 | */ |
6218 | static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6218 | static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6219 | struct nfs_lockt_res *res) | 6219 | struct nfs_lockt_res *res) |
6220 | { | 6220 | { |
6221 | struct compound_hdr hdr; | 6221 | struct compound_hdr hdr; |
6222 | int status; | 6222 | int status; |
6223 | 6223 | ||
6224 | status = decode_compound_hdr(xdr, &hdr); | 6224 | status = decode_compound_hdr(xdr, &hdr); |
6225 | if (status) | 6225 | if (status) |
6226 | goto out; | 6226 | goto out; |
6227 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6227 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6228 | if (status) | 6228 | if (status) |
6229 | goto out; | 6229 | goto out; |
6230 | status = decode_putfh(xdr); | 6230 | status = decode_putfh(xdr); |
6231 | if (status) | 6231 | if (status) |
6232 | goto out; | 6232 | goto out; |
6233 | status = decode_lockt(xdr, res); | 6233 | status = decode_lockt(xdr, res); |
6234 | out: | 6234 | out: |
6235 | return status; | 6235 | return status; |
6236 | } | 6236 | } |
6237 | 6237 | ||
6238 | /* | 6238 | /* |
6239 | * Decode LOCKU response | 6239 | * Decode LOCKU response |
6240 | */ | 6240 | */ |
6241 | static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6241 | static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6242 | struct nfs_locku_res *res) | 6242 | struct nfs_locku_res *res) |
6243 | { | 6243 | { |
6244 | struct compound_hdr hdr; | 6244 | struct compound_hdr hdr; |
6245 | int status; | 6245 | int status; |
6246 | 6246 | ||
6247 | status = decode_compound_hdr(xdr, &hdr); | 6247 | status = decode_compound_hdr(xdr, &hdr); |
6248 | if (status) | 6248 | if (status) |
6249 | goto out; | 6249 | goto out; |
6250 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6250 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6251 | if (status) | 6251 | if (status) |
6252 | goto out; | 6252 | goto out; |
6253 | status = decode_putfh(xdr); | 6253 | status = decode_putfh(xdr); |
6254 | if (status) | 6254 | if (status) |
6255 | goto out; | 6255 | goto out; |
6256 | status = decode_locku(xdr, res); | 6256 | status = decode_locku(xdr, res); |
6257 | out: | 6257 | out: |
6258 | return status; | 6258 | return status; |
6259 | } | 6259 | } |
6260 | 6260 | ||
6261 | static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, | 6261 | static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, |
6262 | struct xdr_stream *xdr, void *dummy) | 6262 | struct xdr_stream *xdr, void *dummy) |
6263 | { | 6263 | { |
6264 | struct compound_hdr hdr; | 6264 | struct compound_hdr hdr; |
6265 | int status; | 6265 | int status; |
6266 | 6266 | ||
6267 | status = decode_compound_hdr(xdr, &hdr); | 6267 | status = decode_compound_hdr(xdr, &hdr); |
6268 | if (!status) | 6268 | if (!status) |
6269 | status = decode_release_lockowner(xdr); | 6269 | status = decode_release_lockowner(xdr); |
6270 | return status; | 6270 | return status; |
6271 | } | 6271 | } |
6272 | 6272 | ||
6273 | /* | 6273 | /* |
6274 | * Decode READLINK response | 6274 | * Decode READLINK response |
6275 | */ | 6275 | */ |
6276 | static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, | 6276 | static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, |
6277 | struct xdr_stream *xdr, | 6277 | struct xdr_stream *xdr, |
6278 | struct nfs4_readlink_res *res) | 6278 | struct nfs4_readlink_res *res) |
6279 | { | 6279 | { |
6280 | struct compound_hdr hdr; | 6280 | struct compound_hdr hdr; |
6281 | int status; | 6281 | int status; |
6282 | 6282 | ||
6283 | status = decode_compound_hdr(xdr, &hdr); | 6283 | status = decode_compound_hdr(xdr, &hdr); |
6284 | if (status) | 6284 | if (status) |
6285 | goto out; | 6285 | goto out; |
6286 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6286 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6287 | if (status) | 6287 | if (status) |
6288 | goto out; | 6288 | goto out; |
6289 | status = decode_putfh(xdr); | 6289 | status = decode_putfh(xdr); |
6290 | if (status) | 6290 | if (status) |
6291 | goto out; | 6291 | goto out; |
6292 | status = decode_readlink(xdr, rqstp); | 6292 | status = decode_readlink(xdr, rqstp); |
6293 | out: | 6293 | out: |
6294 | return status; | 6294 | return status; |
6295 | } | 6295 | } |
6296 | 6296 | ||
6297 | /* | 6297 | /* |
6298 | * Decode READDIR response | 6298 | * Decode READDIR response |
6299 | */ | 6299 | */ |
6300 | static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6300 | static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6301 | struct nfs4_readdir_res *res) | 6301 | struct nfs4_readdir_res *res) |
6302 | { | 6302 | { |
6303 | struct compound_hdr hdr; | 6303 | struct compound_hdr hdr; |
6304 | int status; | 6304 | int status; |
6305 | 6305 | ||
6306 | status = decode_compound_hdr(xdr, &hdr); | 6306 | status = decode_compound_hdr(xdr, &hdr); |
6307 | if (status) | 6307 | if (status) |
6308 | goto out; | 6308 | goto out; |
6309 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6309 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6310 | if (status) | 6310 | if (status) |
6311 | goto out; | 6311 | goto out; |
6312 | status = decode_putfh(xdr); | 6312 | status = decode_putfh(xdr); |
6313 | if (status) | 6313 | if (status) |
6314 | goto out; | 6314 | goto out; |
6315 | status = decode_readdir(xdr, rqstp, res); | 6315 | status = decode_readdir(xdr, rqstp, res); |
6316 | out: | 6316 | out: |
6317 | return status; | 6317 | return status; |
6318 | } | 6318 | } |
6319 | 6319 | ||
6320 | /* | 6320 | /* |
6321 | * Decode Read response | 6321 | * Decode Read response |
6322 | */ | 6322 | */ |
6323 | static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6323 | static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6324 | struct nfs_readres *res) | 6324 | struct nfs_readres *res) |
6325 | { | 6325 | { |
6326 | struct compound_hdr hdr; | 6326 | struct compound_hdr hdr; |
6327 | int status; | 6327 | int status; |
6328 | 6328 | ||
6329 | status = decode_compound_hdr(xdr, &hdr); | 6329 | status = decode_compound_hdr(xdr, &hdr); |
6330 | if (status) | 6330 | if (status) |
6331 | goto out; | 6331 | goto out; |
6332 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6332 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6333 | if (status) | 6333 | if (status) |
6334 | goto out; | 6334 | goto out; |
6335 | status = decode_putfh(xdr); | 6335 | status = decode_putfh(xdr); |
6336 | if (status) | 6336 | if (status) |
6337 | goto out; | 6337 | goto out; |
6338 | status = decode_read(xdr, rqstp, res); | 6338 | status = decode_read(xdr, rqstp, res); |
6339 | if (!status) | 6339 | if (!status) |
6340 | status = res->count; | 6340 | status = res->count; |
6341 | out: | 6341 | out: |
6342 | return status; | 6342 | return status; |
6343 | } | 6343 | } |
6344 | 6344 | ||
6345 | /* | 6345 | /* |
6346 | * Decode WRITE response | 6346 | * Decode WRITE response |
6347 | */ | 6347 | */ |
6348 | static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6348 | static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6349 | struct nfs_writeres *res) | 6349 | struct nfs_writeres *res) |
6350 | { | 6350 | { |
6351 | struct compound_hdr hdr; | 6351 | struct compound_hdr hdr; |
6352 | int status; | 6352 | int status; |
6353 | 6353 | ||
6354 | status = decode_compound_hdr(xdr, &hdr); | 6354 | status = decode_compound_hdr(xdr, &hdr); |
6355 | if (status) | 6355 | if (status) |
6356 | goto out; | 6356 | goto out; |
6357 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6357 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6358 | if (status) | 6358 | if (status) |
6359 | goto out; | 6359 | goto out; |
6360 | status = decode_putfh(xdr); | 6360 | status = decode_putfh(xdr); |
6361 | if (status) | 6361 | if (status) |
6362 | goto out; | 6362 | goto out; |
6363 | status = decode_write(xdr, res); | 6363 | status = decode_write(xdr, res); |
6364 | if (status) | 6364 | if (status) |
6365 | goto out; | 6365 | goto out; |
6366 | if (res->fattr) | 6366 | if (res->fattr) |
6367 | decode_getfattr(xdr, res->fattr, res->server); | 6367 | decode_getfattr(xdr, res->fattr, res->server); |
6368 | if (!status) | 6368 | if (!status) |
6369 | status = res->count; | 6369 | status = res->count; |
6370 | out: | 6370 | out: |
6371 | return status; | 6371 | return status; |
6372 | } | 6372 | } |
6373 | 6373 | ||
6374 | /* | 6374 | /* |
6375 | * Decode COMMIT response | 6375 | * Decode COMMIT response |
6376 | */ | 6376 | */ |
6377 | static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6377 | static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6378 | struct nfs_writeres *res) | 6378 | struct nfs_writeres *res) |
6379 | { | 6379 | { |
6380 | struct compound_hdr hdr; | 6380 | struct compound_hdr hdr; |
6381 | int status; | 6381 | int status; |
6382 | 6382 | ||
6383 | status = decode_compound_hdr(xdr, &hdr); | 6383 | status = decode_compound_hdr(xdr, &hdr); |
6384 | if (status) | 6384 | if (status) |
6385 | goto out; | 6385 | goto out; |
6386 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6386 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6387 | if (status) | 6387 | if (status) |
6388 | goto out; | 6388 | goto out; |
6389 | status = decode_putfh(xdr); | 6389 | status = decode_putfh(xdr); |
6390 | if (status) | 6390 | if (status) |
6391 | goto out; | 6391 | goto out; |
6392 | status = decode_commit(xdr, res); | 6392 | status = decode_commit(xdr, res); |
6393 | if (status) | 6393 | if (status) |
6394 | goto out; | 6394 | goto out; |
6395 | if (res->fattr) | 6395 | if (res->fattr) |
6396 | decode_getfattr(xdr, res->fattr, res->server); | 6396 | decode_getfattr(xdr, res->fattr, res->server); |
6397 | out: | 6397 | out: |
6398 | return status; | 6398 | return status; |
6399 | } | 6399 | } |
6400 | 6400 | ||
6401 | /* | 6401 | /* |
6402 | * Decode FSINFO response | 6402 | * Decode FSINFO response |
6403 | */ | 6403 | */ |
6404 | static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, | 6404 | static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr, |
6405 | struct nfs4_fsinfo_res *res) | 6405 | struct nfs4_fsinfo_res *res) |
6406 | { | 6406 | { |
6407 | struct compound_hdr hdr; | 6407 | struct compound_hdr hdr; |
6408 | int status; | 6408 | int status; |
6409 | 6409 | ||
6410 | status = decode_compound_hdr(xdr, &hdr); | 6410 | status = decode_compound_hdr(xdr, &hdr); |
6411 | if (!status) | 6411 | if (!status) |
6412 | status = decode_sequence(xdr, &res->seq_res, req); | 6412 | status = decode_sequence(xdr, &res->seq_res, req); |
6413 | if (!status) | 6413 | if (!status) |
6414 | status = decode_putfh(xdr); | 6414 | status = decode_putfh(xdr); |
6415 | if (!status) | 6415 | if (!status) |
6416 | status = decode_fsinfo(xdr, res->fsinfo); | 6416 | status = decode_fsinfo(xdr, res->fsinfo); |
6417 | return status; | 6417 | return status; |
6418 | } | 6418 | } |
6419 | 6419 | ||
6420 | /* | 6420 | /* |
6421 | * Decode PATHCONF response | 6421 | * Decode PATHCONF response |
6422 | */ | 6422 | */ |
6423 | static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, | 6423 | static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr, |
6424 | struct nfs4_pathconf_res *res) | 6424 | struct nfs4_pathconf_res *res) |
6425 | { | 6425 | { |
6426 | struct compound_hdr hdr; | 6426 | struct compound_hdr hdr; |
6427 | int status; | 6427 | int status; |
6428 | 6428 | ||
6429 | status = decode_compound_hdr(xdr, &hdr); | 6429 | status = decode_compound_hdr(xdr, &hdr); |
6430 | if (!status) | 6430 | if (!status) |
6431 | status = decode_sequence(xdr, &res->seq_res, req); | 6431 | status = decode_sequence(xdr, &res->seq_res, req); |
6432 | if (!status) | 6432 | if (!status) |
6433 | status = decode_putfh(xdr); | 6433 | status = decode_putfh(xdr); |
6434 | if (!status) | 6434 | if (!status) |
6435 | status = decode_pathconf(xdr, res->pathconf); | 6435 | status = decode_pathconf(xdr, res->pathconf); |
6436 | return status; | 6436 | return status; |
6437 | } | 6437 | } |
6438 | 6438 | ||
6439 | /* | 6439 | /* |
6440 | * Decode STATFS response | 6440 | * Decode STATFS response |
6441 | */ | 6441 | */ |
6442 | static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, | 6442 | static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr, |
6443 | struct nfs4_statfs_res *res) | 6443 | struct nfs4_statfs_res *res) |
6444 | { | 6444 | { |
6445 | struct compound_hdr hdr; | 6445 | struct compound_hdr hdr; |
6446 | int status; | 6446 | int status; |
6447 | 6447 | ||
6448 | status = decode_compound_hdr(xdr, &hdr); | 6448 | status = decode_compound_hdr(xdr, &hdr); |
6449 | if (!status) | 6449 | if (!status) |
6450 | status = decode_sequence(xdr, &res->seq_res, req); | 6450 | status = decode_sequence(xdr, &res->seq_res, req); |
6451 | if (!status) | 6451 | if (!status) |
6452 | status = decode_putfh(xdr); | 6452 | status = decode_putfh(xdr); |
6453 | if (!status) | 6453 | if (!status) |
6454 | status = decode_statfs(xdr, res->fsstat); | 6454 | status = decode_statfs(xdr, res->fsstat); |
6455 | return status; | 6455 | return status; |
6456 | } | 6456 | } |
6457 | 6457 | ||
6458 | /* | 6458 | /* |
6459 | * Decode GETATTR_BITMAP response | 6459 | * Decode GETATTR_BITMAP response |
6460 | */ | 6460 | */ |
6461 | static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, | 6461 | static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, |
6462 | struct xdr_stream *xdr, | 6462 | struct xdr_stream *xdr, |
6463 | struct nfs4_server_caps_res *res) | 6463 | struct nfs4_server_caps_res *res) |
6464 | { | 6464 | { |
6465 | struct compound_hdr hdr; | 6465 | struct compound_hdr hdr; |
6466 | int status; | 6466 | int status; |
6467 | 6467 | ||
6468 | status = decode_compound_hdr(xdr, &hdr); | 6468 | status = decode_compound_hdr(xdr, &hdr); |
6469 | if (status) | 6469 | if (status) |
6470 | goto out; | 6470 | goto out; |
6471 | status = decode_sequence(xdr, &res->seq_res, req); | 6471 | status = decode_sequence(xdr, &res->seq_res, req); |
6472 | if (status) | 6472 | if (status) |
6473 | goto out; | 6473 | goto out; |
6474 | status = decode_putfh(xdr); | 6474 | status = decode_putfh(xdr); |
6475 | if (status) | 6475 | if (status) |
6476 | goto out; | 6476 | goto out; |
6477 | status = decode_server_caps(xdr, res); | 6477 | status = decode_server_caps(xdr, res); |
6478 | out: | 6478 | out: |
6479 | return status; | 6479 | return status; |
6480 | } | 6480 | } |
6481 | 6481 | ||
6482 | /* | 6482 | /* |
6483 | * Decode RENEW response | 6483 | * Decode RENEW response |
6484 | */ | 6484 | */ |
6485 | static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | 6485 | static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, |
6486 | void *__unused) | 6486 | void *__unused) |
6487 | { | 6487 | { |
6488 | struct compound_hdr hdr; | 6488 | struct compound_hdr hdr; |
6489 | int status; | 6489 | int status; |
6490 | 6490 | ||
6491 | status = decode_compound_hdr(xdr, &hdr); | 6491 | status = decode_compound_hdr(xdr, &hdr); |
6492 | if (!status) | 6492 | if (!status) |
6493 | status = decode_renew(xdr); | 6493 | status = decode_renew(xdr); |
6494 | return status; | 6494 | return status; |
6495 | } | 6495 | } |
6496 | 6496 | ||
6497 | /* | 6497 | /* |
6498 | * Decode SETCLIENTID response | 6498 | * Decode SETCLIENTID response |
6499 | */ | 6499 | */ |
6500 | static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, | 6500 | static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, |
6501 | struct xdr_stream *xdr, | 6501 | struct xdr_stream *xdr, |
6502 | struct nfs4_setclientid_res *res) | 6502 | struct nfs4_setclientid_res *res) |
6503 | { | 6503 | { |
6504 | struct compound_hdr hdr; | 6504 | struct compound_hdr hdr; |
6505 | int status; | 6505 | int status; |
6506 | 6506 | ||
6507 | status = decode_compound_hdr(xdr, &hdr); | 6507 | status = decode_compound_hdr(xdr, &hdr); |
6508 | if (!status) | 6508 | if (!status) |
6509 | status = decode_setclientid(xdr, res); | 6509 | status = decode_setclientid(xdr, res); |
6510 | return status; | 6510 | return status; |
6511 | } | 6511 | } |
6512 | 6512 | ||
6513 | /* | 6513 | /* |
6514 | * Decode SETCLIENTID_CONFIRM response | 6514 | * Decode SETCLIENTID_CONFIRM response |
6515 | */ | 6515 | */ |
6516 | static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, | 6516 | static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, |
6517 | struct xdr_stream *xdr, | 6517 | struct xdr_stream *xdr, |
6518 | struct nfs_fsinfo *fsinfo) | 6518 | struct nfs_fsinfo *fsinfo) |
6519 | { | 6519 | { |
6520 | struct compound_hdr hdr; | 6520 | struct compound_hdr hdr; |
6521 | int status; | 6521 | int status; |
6522 | 6522 | ||
6523 | status = decode_compound_hdr(xdr, &hdr); | 6523 | status = decode_compound_hdr(xdr, &hdr); |
6524 | if (!status) | 6524 | if (!status) |
6525 | status = decode_setclientid_confirm(xdr); | 6525 | status = decode_setclientid_confirm(xdr); |
6526 | if (!status) | 6526 | if (!status) |
6527 | status = decode_putrootfh(xdr); | 6527 | status = decode_putrootfh(xdr); |
6528 | if (!status) | 6528 | if (!status) |
6529 | status = decode_fsinfo(xdr, fsinfo); | 6529 | status = decode_fsinfo(xdr, fsinfo); |
6530 | return status; | 6530 | return status; |
6531 | } | 6531 | } |
6532 | 6532 | ||
6533 | /* | 6533 | /* |
6534 | * Decode DELEGRETURN response | 6534 | * Decode DELEGRETURN response |
6535 | */ | 6535 | */ |
6536 | static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, | 6536 | static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, |
6537 | struct xdr_stream *xdr, | 6537 | struct xdr_stream *xdr, |
6538 | struct nfs4_delegreturnres *res) | 6538 | struct nfs4_delegreturnres *res) |
6539 | { | 6539 | { |
6540 | struct compound_hdr hdr; | 6540 | struct compound_hdr hdr; |
6541 | int status; | 6541 | int status; |
6542 | 6542 | ||
6543 | status = decode_compound_hdr(xdr, &hdr); | 6543 | status = decode_compound_hdr(xdr, &hdr); |
6544 | if (status) | 6544 | if (status) |
6545 | goto out; | 6545 | goto out; |
6546 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6546 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6547 | if (status) | 6547 | if (status) |
6548 | goto out; | 6548 | goto out; |
6549 | status = decode_putfh(xdr); | 6549 | status = decode_putfh(xdr); |
6550 | if (status != 0) | 6550 | if (status != 0) |
6551 | goto out; | 6551 | goto out; |
6552 | status = decode_delegreturn(xdr); | 6552 | status = decode_delegreturn(xdr); |
6553 | if (status != 0) | 6553 | if (status != 0) |
6554 | goto out; | 6554 | goto out; |
6555 | decode_getfattr(xdr, res->fattr, res->server); | 6555 | decode_getfattr(xdr, res->fattr, res->server); |
6556 | out: | 6556 | out: |
6557 | return status; | 6557 | return status; |
6558 | } | 6558 | } |
6559 | 6559 | ||
6560 | /* | 6560 | /* |
6561 | * Decode FS_LOCATIONS response | 6561 | * Decode FS_LOCATIONS response |
6562 | */ | 6562 | */ |
6563 | static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, | 6563 | static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, |
6564 | struct xdr_stream *xdr, | 6564 | struct xdr_stream *xdr, |
6565 | struct nfs4_fs_locations_res *res) | 6565 | struct nfs4_fs_locations_res *res) |
6566 | { | 6566 | { |
6567 | struct compound_hdr hdr; | 6567 | struct compound_hdr hdr; |
6568 | int status; | 6568 | int status; |
6569 | 6569 | ||
6570 | status = decode_compound_hdr(xdr, &hdr); | 6570 | status = decode_compound_hdr(xdr, &hdr); |
6571 | if (status) | 6571 | if (status) |
6572 | goto out; | 6572 | goto out; |
6573 | status = decode_sequence(xdr, &res->seq_res, req); | 6573 | status = decode_sequence(xdr, &res->seq_res, req); |
6574 | if (status) | 6574 | if (status) |
6575 | goto out; | 6575 | goto out; |
6576 | status = decode_putfh(xdr); | 6576 | status = decode_putfh(xdr); |
6577 | if (status) | 6577 | if (status) |
6578 | goto out; | 6578 | goto out; |
6579 | status = decode_lookup(xdr); | 6579 | status = decode_lookup(xdr); |
6580 | if (status) | 6580 | if (status) |
6581 | goto out; | 6581 | goto out; |
6582 | xdr_enter_page(xdr, PAGE_SIZE); | 6582 | xdr_enter_page(xdr, PAGE_SIZE); |
6583 | status = decode_getfattr(xdr, &res->fs_locations->fattr, | 6583 | status = decode_getfattr(xdr, &res->fs_locations->fattr, |
6584 | res->fs_locations->server); | 6584 | res->fs_locations->server); |
6585 | out: | 6585 | out: |
6586 | return status; | 6586 | return status; |
6587 | } | 6587 | } |
6588 | 6588 | ||
6589 | /* | 6589 | /* |
6590 | * Decode SECINFO response | 6590 | * Decode SECINFO response |
6591 | */ | 6591 | */ |
6592 | static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, | 6592 | static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, |
6593 | struct xdr_stream *xdr, | 6593 | struct xdr_stream *xdr, |
6594 | struct nfs4_secinfo_res *res) | 6594 | struct nfs4_secinfo_res *res) |
6595 | { | 6595 | { |
6596 | struct compound_hdr hdr; | 6596 | struct compound_hdr hdr; |
6597 | int status; | 6597 | int status; |
6598 | 6598 | ||
6599 | status = decode_compound_hdr(xdr, &hdr); | 6599 | status = decode_compound_hdr(xdr, &hdr); |
6600 | if (status) | 6600 | if (status) |
6601 | goto out; | 6601 | goto out; |
6602 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6602 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6603 | if (status) | 6603 | if (status) |
6604 | goto out; | 6604 | goto out; |
6605 | status = decode_putfh(xdr); | 6605 | status = decode_putfh(xdr); |
6606 | if (status) | 6606 | if (status) |
6607 | goto out; | 6607 | goto out; |
6608 | status = decode_secinfo(xdr, res); | 6608 | status = decode_secinfo(xdr, res); |
6609 | out: | 6609 | out: |
6610 | return status; | 6610 | return status; |
6611 | } | 6611 | } |
6612 | 6612 | ||
6613 | #if defined(CONFIG_NFS_V4_1) | 6613 | #if defined(CONFIG_NFS_V4_1) |
6614 | /* | 6614 | /* |
6615 | * Decode EXCHANGE_ID response | 6615 | * Decode EXCHANGE_ID response |
6616 | */ | 6616 | */ |
6617 | static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, | 6617 | static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, |
6618 | struct xdr_stream *xdr, | 6618 | struct xdr_stream *xdr, |
6619 | void *res) | 6619 | void *res) |
6620 | { | 6620 | { |
6621 | struct compound_hdr hdr; | 6621 | struct compound_hdr hdr; |
6622 | int status; | 6622 | int status; |
6623 | 6623 | ||
6624 | status = decode_compound_hdr(xdr, &hdr); | 6624 | status = decode_compound_hdr(xdr, &hdr); |
6625 | if (!status) | 6625 | if (!status) |
6626 | status = decode_exchange_id(xdr, res); | 6626 | status = decode_exchange_id(xdr, res); |
6627 | return status; | 6627 | return status; |
6628 | } | 6628 | } |
6629 | 6629 | ||
6630 | /* | 6630 | /* |
6631 | * Decode CREATE_SESSION response | 6631 | * Decode CREATE_SESSION response |
6632 | */ | 6632 | */ |
6633 | static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, | 6633 | static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, |
6634 | struct xdr_stream *xdr, | 6634 | struct xdr_stream *xdr, |
6635 | struct nfs41_create_session_res *res) | 6635 | struct nfs41_create_session_res *res) |
6636 | { | 6636 | { |
6637 | struct compound_hdr hdr; | 6637 | struct compound_hdr hdr; |
6638 | int status; | 6638 | int status; |
6639 | 6639 | ||
6640 | status = decode_compound_hdr(xdr, &hdr); | 6640 | status = decode_compound_hdr(xdr, &hdr); |
6641 | if (!status) | 6641 | if (!status) |
6642 | status = decode_create_session(xdr, res); | 6642 | status = decode_create_session(xdr, res); |
6643 | return status; | 6643 | return status; |
6644 | } | 6644 | } |
6645 | 6645 | ||
6646 | /* | 6646 | /* |
6647 | * Decode DESTROY_SESSION response | 6647 | * Decode DESTROY_SESSION response |
6648 | */ | 6648 | */ |
6649 | static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, | 6649 | static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, |
6650 | struct xdr_stream *xdr, | 6650 | struct xdr_stream *xdr, |
6651 | void *res) | 6651 | void *res) |
6652 | { | 6652 | { |
6653 | struct compound_hdr hdr; | 6653 | struct compound_hdr hdr; |
6654 | int status; | 6654 | int status; |
6655 | 6655 | ||
6656 | status = decode_compound_hdr(xdr, &hdr); | 6656 | status = decode_compound_hdr(xdr, &hdr); |
6657 | if (!status) | 6657 | if (!status) |
6658 | status = decode_destroy_session(xdr, res); | 6658 | status = decode_destroy_session(xdr, res); |
6659 | return status; | 6659 | return status; |
6660 | } | 6660 | } |
6661 | 6661 | ||
6662 | /* | 6662 | /* |
6663 | * Decode SEQUENCE response | 6663 | * Decode SEQUENCE response |
6664 | */ | 6664 | */ |
6665 | static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, | 6665 | static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, |
6666 | struct xdr_stream *xdr, | 6666 | struct xdr_stream *xdr, |
6667 | struct nfs4_sequence_res *res) | 6667 | struct nfs4_sequence_res *res) |
6668 | { | 6668 | { |
6669 | struct compound_hdr hdr; | 6669 | struct compound_hdr hdr; |
6670 | int status; | 6670 | int status; |
6671 | 6671 | ||
6672 | status = decode_compound_hdr(xdr, &hdr); | 6672 | status = decode_compound_hdr(xdr, &hdr); |
6673 | if (!status) | 6673 | if (!status) |
6674 | status = decode_sequence(xdr, res, rqstp); | 6674 | status = decode_sequence(xdr, res, rqstp); |
6675 | return status; | 6675 | return status; |
6676 | } | 6676 | } |
6677 | 6677 | ||
6678 | /* | 6678 | /* |
6679 | * Decode GET_LEASE_TIME response | 6679 | * Decode GET_LEASE_TIME response |
6680 | */ | 6680 | */ |
6681 | static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, | 6681 | static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, |
6682 | struct xdr_stream *xdr, | 6682 | struct xdr_stream *xdr, |
6683 | struct nfs4_get_lease_time_res *res) | 6683 | struct nfs4_get_lease_time_res *res) |
6684 | { | 6684 | { |
6685 | struct compound_hdr hdr; | 6685 | struct compound_hdr hdr; |
6686 | int status; | 6686 | int status; |
6687 | 6687 | ||
6688 | status = decode_compound_hdr(xdr, &hdr); | 6688 | status = decode_compound_hdr(xdr, &hdr); |
6689 | if (!status) | 6689 | if (!status) |
6690 | status = decode_sequence(xdr, &res->lr_seq_res, rqstp); | 6690 | status = decode_sequence(xdr, &res->lr_seq_res, rqstp); |
6691 | if (!status) | 6691 | if (!status) |
6692 | status = decode_putrootfh(xdr); | 6692 | status = decode_putrootfh(xdr); |
6693 | if (!status) | 6693 | if (!status) |
6694 | status = decode_fsinfo(xdr, res->lr_fsinfo); | 6694 | status = decode_fsinfo(xdr, res->lr_fsinfo); |
6695 | return status; | 6695 | return status; |
6696 | } | 6696 | } |
6697 | 6697 | ||
6698 | /* | 6698 | /* |
6699 | * Decode RECLAIM_COMPLETE response | 6699 | * Decode RECLAIM_COMPLETE response |
6700 | */ | 6700 | */ |
6701 | static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, | 6701 | static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, |
6702 | struct xdr_stream *xdr, | 6702 | struct xdr_stream *xdr, |
6703 | struct nfs41_reclaim_complete_res *res) | 6703 | struct nfs41_reclaim_complete_res *res) |
6704 | { | 6704 | { |
6705 | struct compound_hdr hdr; | 6705 | struct compound_hdr hdr; |
6706 | int status; | 6706 | int status; |
6707 | 6707 | ||
6708 | status = decode_compound_hdr(xdr, &hdr); | 6708 | status = decode_compound_hdr(xdr, &hdr); |
6709 | if (!status) | 6709 | if (!status) |
6710 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6710 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6711 | if (!status) | 6711 | if (!status) |
6712 | status = decode_reclaim_complete(xdr, (void *)NULL); | 6712 | status = decode_reclaim_complete(xdr, (void *)NULL); |
6713 | return status; | 6713 | return status; |
6714 | } | 6714 | } |
6715 | 6715 | ||
6716 | /* | 6716 | /* |
6717 | * Decode GETDEVICELIST response | 6717 | * Decode GETDEVICELIST response |
6718 | */ | 6718 | */ |
6719 | static int nfs4_xdr_dec_getdevicelist(struct rpc_rqst *rqstp, | 6719 | static int nfs4_xdr_dec_getdevicelist(struct rpc_rqst *rqstp, |
6720 | struct xdr_stream *xdr, | 6720 | struct xdr_stream *xdr, |
6721 | struct nfs4_getdevicelist_res *res) | 6721 | struct nfs4_getdevicelist_res *res) |
6722 | { | 6722 | { |
6723 | struct compound_hdr hdr; | 6723 | struct compound_hdr hdr; |
6724 | int status; | 6724 | int status; |
6725 | 6725 | ||
6726 | dprintk("encoding getdevicelist!\n"); | 6726 | dprintk("encoding getdevicelist!\n"); |
6727 | 6727 | ||
6728 | status = decode_compound_hdr(xdr, &hdr); | 6728 | status = decode_compound_hdr(xdr, &hdr); |
6729 | if (status != 0) | 6729 | if (status != 0) |
6730 | goto out; | 6730 | goto out; |
6731 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6731 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6732 | if (status != 0) | 6732 | if (status != 0) |
6733 | goto out; | 6733 | goto out; |
6734 | status = decode_putfh(xdr); | 6734 | status = decode_putfh(xdr); |
6735 | if (status != 0) | 6735 | if (status != 0) |
6736 | goto out; | 6736 | goto out; |
6737 | status = decode_getdevicelist(xdr, res->devlist); | 6737 | status = decode_getdevicelist(xdr, res->devlist); |
6738 | out: | 6738 | out: |
6739 | return status; | 6739 | return status; |
6740 | } | 6740 | } |
6741 | 6741 | ||
6742 | /* | 6742 | /* |
6743 | * Decode GETDEVINFO response | 6743 | * Decode GETDEVINFO response |
6744 | */ | 6744 | */ |
6745 | static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, | 6745 | static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, |
6746 | struct xdr_stream *xdr, | 6746 | struct xdr_stream *xdr, |
6747 | struct nfs4_getdeviceinfo_res *res) | 6747 | struct nfs4_getdeviceinfo_res *res) |
6748 | { | 6748 | { |
6749 | struct compound_hdr hdr; | 6749 | struct compound_hdr hdr; |
6750 | int status; | 6750 | int status; |
6751 | 6751 | ||
6752 | status = decode_compound_hdr(xdr, &hdr); | 6752 | status = decode_compound_hdr(xdr, &hdr); |
6753 | if (status != 0) | 6753 | if (status != 0) |
6754 | goto out; | 6754 | goto out; |
6755 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6755 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6756 | if (status != 0) | 6756 | if (status != 0) |
6757 | goto out; | 6757 | goto out; |
6758 | status = decode_getdeviceinfo(xdr, res->pdev); | 6758 | status = decode_getdeviceinfo(xdr, res->pdev); |
6759 | out: | 6759 | out: |
6760 | return status; | 6760 | return status; |
6761 | } | 6761 | } |
6762 | 6762 | ||
6763 | /* | 6763 | /* |
6764 | * Decode LAYOUTGET response | 6764 | * Decode LAYOUTGET response |
6765 | */ | 6765 | */ |
6766 | static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, | 6766 | static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, |
6767 | struct xdr_stream *xdr, | 6767 | struct xdr_stream *xdr, |
6768 | struct nfs4_layoutget_res *res) | 6768 | struct nfs4_layoutget_res *res) |
6769 | { | 6769 | { |
6770 | struct compound_hdr hdr; | 6770 | struct compound_hdr hdr; |
6771 | int status; | 6771 | int status; |
6772 | 6772 | ||
6773 | status = decode_compound_hdr(xdr, &hdr); | 6773 | status = decode_compound_hdr(xdr, &hdr); |
6774 | if (status) | 6774 | if (status) |
6775 | goto out; | 6775 | goto out; |
6776 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6776 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6777 | if (status) | 6777 | if (status) |
6778 | goto out; | 6778 | goto out; |
6779 | status = decode_putfh(xdr); | 6779 | status = decode_putfh(xdr); |
6780 | if (status) | 6780 | if (status) |
6781 | goto out; | 6781 | goto out; |
6782 | status = decode_layoutget(xdr, rqstp, res); | 6782 | status = decode_layoutget(xdr, rqstp, res); |
6783 | out: | 6783 | out: |
6784 | return status; | 6784 | return status; |
6785 | } | 6785 | } |
6786 | 6786 | ||
6787 | /* | 6787 | /* |
6788 | * Decode LAYOUTRETURN response | 6788 | * Decode LAYOUTRETURN response |
6789 | */ | 6789 | */ |
6790 | static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp, | 6790 | static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp, |
6791 | struct xdr_stream *xdr, | 6791 | struct xdr_stream *xdr, |
6792 | struct nfs4_layoutreturn_res *res) | 6792 | struct nfs4_layoutreturn_res *res) |
6793 | { | 6793 | { |
6794 | struct compound_hdr hdr; | 6794 | struct compound_hdr hdr; |
6795 | int status; | 6795 | int status; |
6796 | 6796 | ||
6797 | status = decode_compound_hdr(xdr, &hdr); | 6797 | status = decode_compound_hdr(xdr, &hdr); |
6798 | if (status) | 6798 | if (status) |
6799 | goto out; | 6799 | goto out; |
6800 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6800 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6801 | if (status) | 6801 | if (status) |
6802 | goto out; | 6802 | goto out; |
6803 | status = decode_putfh(xdr); | 6803 | status = decode_putfh(xdr); |
6804 | if (status) | 6804 | if (status) |
6805 | goto out; | 6805 | goto out; |
6806 | status = decode_layoutreturn(xdr, res); | 6806 | status = decode_layoutreturn(xdr, res); |
6807 | out: | 6807 | out: |
6808 | return status; | 6808 | return status; |
6809 | } | 6809 | } |
6810 | 6810 | ||
6811 | /* | 6811 | /* |
6812 | * Decode LAYOUTCOMMIT response | 6812 | * Decode LAYOUTCOMMIT response |
6813 | */ | 6813 | */ |
6814 | static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, | 6814 | static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, |
6815 | struct xdr_stream *xdr, | 6815 | struct xdr_stream *xdr, |
6816 | struct nfs4_layoutcommit_res *res) | 6816 | struct nfs4_layoutcommit_res *res) |
6817 | { | 6817 | { |
6818 | struct compound_hdr hdr; | 6818 | struct compound_hdr hdr; |
6819 | int status; | 6819 | int status; |
6820 | 6820 | ||
6821 | status = decode_compound_hdr(xdr, &hdr); | 6821 | status = decode_compound_hdr(xdr, &hdr); |
6822 | if (status) | 6822 | if (status) |
6823 | goto out; | 6823 | goto out; |
6824 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6824 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6825 | if (status) | 6825 | if (status) |
6826 | goto out; | 6826 | goto out; |
6827 | status = decode_putfh(xdr); | 6827 | status = decode_putfh(xdr); |
6828 | if (status) | 6828 | if (status) |
6829 | goto out; | 6829 | goto out; |
6830 | status = decode_layoutcommit(xdr, rqstp, res); | 6830 | status = decode_layoutcommit(xdr, rqstp, res); |
6831 | if (status) | 6831 | if (status) |
6832 | goto out; | 6832 | goto out; |
6833 | decode_getfattr(xdr, res->fattr, res->server); | 6833 | decode_getfattr(xdr, res->fattr, res->server); |
6834 | out: | 6834 | out: |
6835 | return status; | 6835 | return status; |
6836 | } | 6836 | } |
6837 | 6837 | ||
6838 | /* | 6838 | /* |
6839 | * Decode SECINFO_NO_NAME response | 6839 | * Decode SECINFO_NO_NAME response |
6840 | */ | 6840 | */ |
6841 | static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp, | 6841 | static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp, |
6842 | struct xdr_stream *xdr, | 6842 | struct xdr_stream *xdr, |
6843 | struct nfs4_secinfo_res *res) | 6843 | struct nfs4_secinfo_res *res) |
6844 | { | 6844 | { |
6845 | struct compound_hdr hdr; | 6845 | struct compound_hdr hdr; |
6846 | int status; | 6846 | int status; |
6847 | 6847 | ||
6848 | status = decode_compound_hdr(xdr, &hdr); | 6848 | status = decode_compound_hdr(xdr, &hdr); |
6849 | if (status) | 6849 | if (status) |
6850 | goto out; | 6850 | goto out; |
6851 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6851 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6852 | if (status) | 6852 | if (status) |
6853 | goto out; | 6853 | goto out; |
6854 | status = decode_putrootfh(xdr); | 6854 | status = decode_putrootfh(xdr); |
6855 | if (status) | 6855 | if (status) |
6856 | goto out; | 6856 | goto out; |
6857 | status = decode_secinfo(xdr, res); | 6857 | status = decode_secinfo(xdr, res); |
6858 | out: | 6858 | out: |
6859 | return status; | 6859 | return status; |
6860 | } | 6860 | } |
6861 | 6861 | ||
6862 | /* | 6862 | /* |
6863 | * Decode TEST_STATEID response | 6863 | * Decode TEST_STATEID response |
6864 | */ | 6864 | */ |
6865 | static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp, | 6865 | static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp, |
6866 | struct xdr_stream *xdr, | 6866 | struct xdr_stream *xdr, |
6867 | struct nfs41_test_stateid_res *res) | 6867 | struct nfs41_test_stateid_res *res) |
6868 | { | 6868 | { |
6869 | struct compound_hdr hdr; | 6869 | struct compound_hdr hdr; |
6870 | int status; | 6870 | int status; |
6871 | 6871 | ||
6872 | status = decode_compound_hdr(xdr, &hdr); | 6872 | status = decode_compound_hdr(xdr, &hdr); |
6873 | if (status) | 6873 | if (status) |
6874 | goto out; | 6874 | goto out; |
6875 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6875 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6876 | if (status) | 6876 | if (status) |
6877 | goto out; | 6877 | goto out; |
6878 | status = decode_test_stateid(xdr, res); | 6878 | status = decode_test_stateid(xdr, res); |
6879 | out: | 6879 | out: |
6880 | return status; | 6880 | return status; |
6881 | } | 6881 | } |
6882 | 6882 | ||
6883 | /* | 6883 | /* |
6884 | * Decode FREE_STATEID response | 6884 | * Decode FREE_STATEID response |
6885 | */ | 6885 | */ |
6886 | static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp, | 6886 | static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp, |
6887 | struct xdr_stream *xdr, | 6887 | struct xdr_stream *xdr, |
6888 | struct nfs41_free_stateid_res *res) | 6888 | struct nfs41_free_stateid_res *res) |
6889 | { | 6889 | { |
6890 | struct compound_hdr hdr; | 6890 | struct compound_hdr hdr; |
6891 | int status; | 6891 | int status; |
6892 | 6892 | ||
6893 | status = decode_compound_hdr(xdr, &hdr); | 6893 | status = decode_compound_hdr(xdr, &hdr); |
6894 | if (status) | 6894 | if (status) |
6895 | goto out; | 6895 | goto out; |
6896 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 6896 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
6897 | if (status) | 6897 | if (status) |
6898 | goto out; | 6898 | goto out; |
6899 | status = decode_free_stateid(xdr, res); | 6899 | status = decode_free_stateid(xdr, res); |
6900 | out: | 6900 | out: |
6901 | return status; | 6901 | return status; |
6902 | } | 6902 | } |
6903 | #endif /* CONFIG_NFS_V4_1 */ | 6903 | #endif /* CONFIG_NFS_V4_1 */ |
6904 | 6904 | ||
6905 | /** | 6905 | /** |
6906 | * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in | 6906 | * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in |
6907 | * the local page cache. | 6907 | * the local page cache. |
6908 | * @xdr: XDR stream where entry resides | 6908 | * @xdr: XDR stream where entry resides |
6909 | * @entry: buffer to fill in with entry data | 6909 | * @entry: buffer to fill in with entry data |
6910 | * @plus: boolean indicating whether this should be a readdirplus entry | 6910 | * @plus: boolean indicating whether this should be a readdirplus entry |
6911 | * | 6911 | * |
6912 | * Returns zero if successful, otherwise a negative errno value is | 6912 | * Returns zero if successful, otherwise a negative errno value is |
6913 | * returned. | 6913 | * returned. |
6914 | * | 6914 | * |
6915 | * This function is not invoked during READDIR reply decoding, but | 6915 | * This function is not invoked during READDIR reply decoding, but |
6916 | * rather whenever an application invokes the getdents(2) system call | 6916 | * rather whenever an application invokes the getdents(2) system call |
6917 | * on a directory already in our cache. | 6917 | * on a directory already in our cache. |
6918 | */ | 6918 | */ |
6919 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 6919 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
6920 | int plus) | 6920 | int plus) |
6921 | { | 6921 | { |
6922 | uint32_t bitmap[3] = {0}; | 6922 | uint32_t bitmap[3] = {0}; |
6923 | uint32_t len; | 6923 | uint32_t len; |
6924 | __be32 *p = xdr_inline_decode(xdr, 4); | 6924 | __be32 *p = xdr_inline_decode(xdr, 4); |
6925 | if (unlikely(!p)) | 6925 | if (unlikely(!p)) |
6926 | goto out_overflow; | 6926 | goto out_overflow; |
6927 | if (*p == xdr_zero) { | 6927 | if (*p == xdr_zero) { |
6928 | p = xdr_inline_decode(xdr, 4); | 6928 | p = xdr_inline_decode(xdr, 4); |
6929 | if (unlikely(!p)) | 6929 | if (unlikely(!p)) |
6930 | goto out_overflow; | 6930 | goto out_overflow; |
6931 | if (*p == xdr_zero) | 6931 | if (*p == xdr_zero) |
6932 | return -EAGAIN; | 6932 | return -EAGAIN; |
6933 | entry->eof = 1; | 6933 | entry->eof = 1; |
6934 | return -EBADCOOKIE; | 6934 | return -EBADCOOKIE; |
6935 | } | 6935 | } |
6936 | 6936 | ||
6937 | p = xdr_inline_decode(xdr, 12); | 6937 | p = xdr_inline_decode(xdr, 12); |
6938 | if (unlikely(!p)) | 6938 | if (unlikely(!p)) |
6939 | goto out_overflow; | 6939 | goto out_overflow; |
6940 | entry->prev_cookie = entry->cookie; | 6940 | entry->prev_cookie = entry->cookie; |
6941 | p = xdr_decode_hyper(p, &entry->cookie); | 6941 | p = xdr_decode_hyper(p, &entry->cookie); |
6942 | entry->len = be32_to_cpup(p); | 6942 | entry->len = be32_to_cpup(p); |
6943 | 6943 | ||
6944 | p = xdr_inline_decode(xdr, entry->len); | 6944 | p = xdr_inline_decode(xdr, entry->len); |
6945 | if (unlikely(!p)) | 6945 | if (unlikely(!p)) |
6946 | goto out_overflow; | 6946 | goto out_overflow; |
6947 | entry->name = (const char *) p; | 6947 | entry->name = (const char *) p; |
6948 | 6948 | ||
6949 | /* | 6949 | /* |
6950 | * In case the server doesn't return an inode number, | 6950 | * In case the server doesn't return an inode number, |
6951 | * we fake one here. (We don't use inode number 0, | 6951 | * we fake one here. (We don't use inode number 0, |
6952 | * since glibc seems to choke on it...) | 6952 | * since glibc seems to choke on it...) |
6953 | */ | 6953 | */ |
6954 | entry->ino = 1; | 6954 | entry->ino = 1; |
6955 | entry->fattr->valid = 0; | 6955 | entry->fattr->valid = 0; |
6956 | 6956 | ||
6957 | if (decode_attr_bitmap(xdr, bitmap) < 0) | 6957 | if (decode_attr_bitmap(xdr, bitmap) < 0) |
6958 | goto out_overflow; | 6958 | goto out_overflow; |
6959 | 6959 | ||
6960 | if (decode_attr_length(xdr, &len, &p) < 0) | 6960 | if (decode_attr_length(xdr, &len, &p) < 0) |
6961 | goto out_overflow; | 6961 | goto out_overflow; |
6962 | 6962 | ||
6963 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 6963 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
6964 | entry->server) < 0) | 6964 | entry->server) < 0) |
6965 | goto out_overflow; | 6965 | goto out_overflow; |
6966 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | 6966 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
6967 | entry->ino = entry->fattr->mounted_on_fileid; | 6967 | entry->ino = entry->fattr->mounted_on_fileid; |
6968 | else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) | 6968 | else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) |
6969 | entry->ino = entry->fattr->fileid; | 6969 | entry->ino = entry->fattr->fileid; |
6970 | 6970 | ||
6971 | entry->d_type = DT_UNKNOWN; | 6971 | entry->d_type = DT_UNKNOWN; |
6972 | if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) | 6972 | if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) |
6973 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); | 6973 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); |
6974 | 6974 | ||
6975 | return 0; | 6975 | return 0; |
6976 | 6976 | ||
6977 | out_overflow: | 6977 | out_overflow: |
6978 | print_overflow_msg(__func__, xdr); | 6978 | print_overflow_msg(__func__, xdr); |
6979 | return -EAGAIN; | 6979 | return -EAGAIN; |
6980 | } | 6980 | } |
6981 | 6981 | ||
6982 | /* | 6982 | /* |
6983 | * We need to translate between nfs status return values and | 6983 | * We need to translate between nfs status return values and |
6984 | * the local errno values which may not be the same. | 6984 | * the local errno values which may not be the same. |
6985 | */ | 6985 | */ |
6986 | static struct { | 6986 | static struct { |
6987 | int stat; | 6987 | int stat; |
6988 | int errno; | 6988 | int errno; |
6989 | } nfs_errtbl[] = { | 6989 | } nfs_errtbl[] = { |
6990 | { NFS4_OK, 0 }, | 6990 | { NFS4_OK, 0 }, |
6991 | { NFS4ERR_PERM, -EPERM }, | 6991 | { NFS4ERR_PERM, -EPERM }, |
6992 | { NFS4ERR_NOENT, -ENOENT }, | 6992 | { NFS4ERR_NOENT, -ENOENT }, |
6993 | { NFS4ERR_IO, -errno_NFSERR_IO}, | 6993 | { NFS4ERR_IO, -errno_NFSERR_IO}, |
6994 | { NFS4ERR_NXIO, -ENXIO }, | 6994 | { NFS4ERR_NXIO, -ENXIO }, |
6995 | { NFS4ERR_ACCESS, -EACCES }, | 6995 | { NFS4ERR_ACCESS, -EACCES }, |
6996 | { NFS4ERR_EXIST, -EEXIST }, | 6996 | { NFS4ERR_EXIST, -EEXIST }, |
6997 | { NFS4ERR_XDEV, -EXDEV }, | 6997 | { NFS4ERR_XDEV, -EXDEV }, |
6998 | { NFS4ERR_NOTDIR, -ENOTDIR }, | 6998 | { NFS4ERR_NOTDIR, -ENOTDIR }, |
6999 | { NFS4ERR_ISDIR, -EISDIR }, | 6999 | { NFS4ERR_ISDIR, -EISDIR }, |
7000 | { NFS4ERR_INVAL, -EINVAL }, | 7000 | { NFS4ERR_INVAL, -EINVAL }, |
7001 | { NFS4ERR_FBIG, -EFBIG }, | 7001 | { NFS4ERR_FBIG, -EFBIG }, |
7002 | { NFS4ERR_NOSPC, -ENOSPC }, | 7002 | { NFS4ERR_NOSPC, -ENOSPC }, |
7003 | { NFS4ERR_ROFS, -EROFS }, | 7003 | { NFS4ERR_ROFS, -EROFS }, |
7004 | { NFS4ERR_MLINK, -EMLINK }, | 7004 | { NFS4ERR_MLINK, -EMLINK }, |
7005 | { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, | 7005 | { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, |
7006 | { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, | 7006 | { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, |
7007 | { NFS4ERR_DQUOT, -EDQUOT }, | 7007 | { NFS4ERR_DQUOT, -EDQUOT }, |
7008 | { NFS4ERR_STALE, -ESTALE }, | 7008 | { NFS4ERR_STALE, -ESTALE }, |
7009 | { NFS4ERR_BADHANDLE, -EBADHANDLE }, | 7009 | { NFS4ERR_BADHANDLE, -EBADHANDLE }, |
7010 | { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, | 7010 | { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, |
7011 | { NFS4ERR_NOTSUPP, -ENOTSUPP }, | 7011 | { NFS4ERR_NOTSUPP, -ENOTSUPP }, |
7012 | { NFS4ERR_TOOSMALL, -ETOOSMALL }, | 7012 | { NFS4ERR_TOOSMALL, -ETOOSMALL }, |
7013 | { NFS4ERR_SERVERFAULT, -EREMOTEIO }, | 7013 | { NFS4ERR_SERVERFAULT, -EREMOTEIO }, |
7014 | { NFS4ERR_BADTYPE, -EBADTYPE }, | 7014 | { NFS4ERR_BADTYPE, -EBADTYPE }, |
7015 | { NFS4ERR_LOCKED, -EAGAIN }, | 7015 | { NFS4ERR_LOCKED, -EAGAIN }, |
7016 | { NFS4ERR_SYMLINK, -ELOOP }, | 7016 | { NFS4ERR_SYMLINK, -ELOOP }, |
7017 | { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, | 7017 | { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, |
7018 | { NFS4ERR_DEADLOCK, -EDEADLK }, | 7018 | { NFS4ERR_DEADLOCK, -EDEADLK }, |
7019 | { -1, -EIO } | 7019 | { -1, -EIO } |
7020 | }; | 7020 | }; |
7021 | 7021 | ||
7022 | /* | 7022 | /* |
7023 | * Convert an NFS error code to a local one. | 7023 | * Convert an NFS error code to a local one. |
7024 | * This one is used jointly by NFSv2 and NFSv3. | 7024 | * This one is used jointly by NFSv2 and NFSv3. |
7025 | */ | 7025 | */ |
7026 | static int | 7026 | static int |
7027 | nfs4_stat_to_errno(int stat) | 7027 | nfs4_stat_to_errno(int stat) |
7028 | { | 7028 | { |
7029 | int i; | 7029 | int i; |
7030 | for (i = 0; nfs_errtbl[i].stat != -1; i++) { | 7030 | for (i = 0; nfs_errtbl[i].stat != -1; i++) { |
7031 | if (nfs_errtbl[i].stat == stat) | 7031 | if (nfs_errtbl[i].stat == stat) |
7032 | return nfs_errtbl[i].errno; | 7032 | return nfs_errtbl[i].errno; |
7033 | } | 7033 | } |
7034 | if (stat <= 10000 || stat > 10100) { | 7034 | if (stat <= 10000 || stat > 10100) { |
7035 | /* The server is looney tunes. */ | 7035 | /* The server is looney tunes. */ |
7036 | return -EREMOTEIO; | 7036 | return -EREMOTEIO; |
7037 | } | 7037 | } |
7038 | /* If we cannot translate the error, the recovery routines should | 7038 | /* If we cannot translate the error, the recovery routines should |
7039 | * handle it. | 7039 | * handle it. |
7040 | * Note: remaining NFSv4 error codes have values > 10000, so should | 7040 | * Note: remaining NFSv4 error codes have values > 10000, so should |
7041 | * not conflict with native Linux error codes. | 7041 | * not conflict with native Linux error codes. |
7042 | */ | 7042 | */ |
7043 | return -stat; | 7043 | return -stat; |
7044 | } | 7044 | } |
7045 | 7045 | ||
7046 | #define PROC(proc, argtype, restype) \ | 7046 | #define PROC(proc, argtype, restype) \ |
7047 | [NFSPROC4_CLNT_##proc] = { \ | 7047 | [NFSPROC4_CLNT_##proc] = { \ |
7048 | .p_proc = NFSPROC4_COMPOUND, \ | 7048 | .p_proc = NFSPROC4_COMPOUND, \ |
7049 | .p_encode = (kxdreproc_t)nfs4_xdr_##argtype, \ | 7049 | .p_encode = (kxdreproc_t)nfs4_xdr_##argtype, \ |
7050 | .p_decode = (kxdrdproc_t)nfs4_xdr_##restype, \ | 7050 | .p_decode = (kxdrdproc_t)nfs4_xdr_##restype, \ |
7051 | .p_arglen = NFS4_##argtype##_sz, \ | 7051 | .p_arglen = NFS4_##argtype##_sz, \ |
7052 | .p_replen = NFS4_##restype##_sz, \ | 7052 | .p_replen = NFS4_##restype##_sz, \ |
7053 | .p_statidx = NFSPROC4_CLNT_##proc, \ | 7053 | .p_statidx = NFSPROC4_CLNT_##proc, \ |
7054 | .p_name = #proc, \ | 7054 | .p_name = #proc, \ |
7055 | } | 7055 | } |
7056 | 7056 | ||
7057 | struct rpc_procinfo nfs4_procedures[] = { | 7057 | struct rpc_procinfo nfs4_procedures[] = { |
7058 | PROC(READ, enc_read, dec_read), | 7058 | PROC(READ, enc_read, dec_read), |
7059 | PROC(WRITE, enc_write, dec_write), | 7059 | PROC(WRITE, enc_write, dec_write), |
7060 | PROC(COMMIT, enc_commit, dec_commit), | 7060 | PROC(COMMIT, enc_commit, dec_commit), |
7061 | PROC(OPEN, enc_open, dec_open), | 7061 | PROC(OPEN, enc_open, dec_open), |
7062 | PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), | 7062 | PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), |
7063 | PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr), | 7063 | PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr), |
7064 | PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade), | 7064 | PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade), |
7065 | PROC(CLOSE, enc_close, dec_close), | 7065 | PROC(CLOSE, enc_close, dec_close), |
7066 | PROC(SETATTR, enc_setattr, dec_setattr), | 7066 | PROC(SETATTR, enc_setattr, dec_setattr), |
7067 | PROC(FSINFO, enc_fsinfo, dec_fsinfo), | 7067 | PROC(FSINFO, enc_fsinfo, dec_fsinfo), |
7068 | PROC(RENEW, enc_renew, dec_renew), | 7068 | PROC(RENEW, enc_renew, dec_renew), |
7069 | PROC(SETCLIENTID, enc_setclientid, dec_setclientid), | 7069 | PROC(SETCLIENTID, enc_setclientid, dec_setclientid), |
7070 | PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), | 7070 | PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), |
7071 | PROC(LOCK, enc_lock, dec_lock), | 7071 | PROC(LOCK, enc_lock, dec_lock), |
7072 | PROC(LOCKT, enc_lockt, dec_lockt), | 7072 | PROC(LOCKT, enc_lockt, dec_lockt), |
7073 | PROC(LOCKU, enc_locku, dec_locku), | 7073 | PROC(LOCKU, enc_locku, dec_locku), |
7074 | PROC(ACCESS, enc_access, dec_access), | 7074 | PROC(ACCESS, enc_access, dec_access), |
7075 | PROC(GETATTR, enc_getattr, dec_getattr), | 7075 | PROC(GETATTR, enc_getattr, dec_getattr), |
7076 | PROC(LOOKUP, enc_lookup, dec_lookup), | 7076 | PROC(LOOKUP, enc_lookup, dec_lookup), |
7077 | PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), | 7077 | PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), |
7078 | PROC(REMOVE, enc_remove, dec_remove), | 7078 | PROC(REMOVE, enc_remove, dec_remove), |
7079 | PROC(RENAME, enc_rename, dec_rename), | 7079 | PROC(RENAME, enc_rename, dec_rename), |
7080 | PROC(LINK, enc_link, dec_link), | 7080 | PROC(LINK, enc_link, dec_link), |
7081 | PROC(SYMLINK, enc_symlink, dec_symlink), | 7081 | PROC(SYMLINK, enc_symlink, dec_symlink), |
7082 | PROC(CREATE, enc_create, dec_create), | 7082 | PROC(CREATE, enc_create, dec_create), |
7083 | PROC(PATHCONF, enc_pathconf, dec_pathconf), | 7083 | PROC(PATHCONF, enc_pathconf, dec_pathconf), |
7084 | PROC(STATFS, enc_statfs, dec_statfs), | 7084 | PROC(STATFS, enc_statfs, dec_statfs), |
7085 | PROC(READLINK, enc_readlink, dec_readlink), | 7085 | PROC(READLINK, enc_readlink, dec_readlink), |
7086 | PROC(READDIR, enc_readdir, dec_readdir), | 7086 | PROC(READDIR, enc_readdir, dec_readdir), |
7087 | PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), | 7087 | PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), |
7088 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), | 7088 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), |
7089 | PROC(GETACL, enc_getacl, dec_getacl), | 7089 | PROC(GETACL, enc_getacl, dec_getacl), |
7090 | PROC(SETACL, enc_setacl, dec_setacl), | 7090 | PROC(SETACL, enc_setacl, dec_setacl), |
7091 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), | 7091 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), |
7092 | PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), | 7092 | PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), |
7093 | PROC(SECINFO, enc_secinfo, dec_secinfo), | 7093 | PROC(SECINFO, enc_secinfo, dec_secinfo), |
7094 | #if defined(CONFIG_NFS_V4_1) | 7094 | #if defined(CONFIG_NFS_V4_1) |
7095 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), | 7095 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), |
7096 | PROC(CREATE_SESSION, enc_create_session, dec_create_session), | 7096 | PROC(CREATE_SESSION, enc_create_session, dec_create_session), |
7097 | PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), | 7097 | PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), |
7098 | PROC(SEQUENCE, enc_sequence, dec_sequence), | 7098 | PROC(SEQUENCE, enc_sequence, dec_sequence), |
7099 | PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), | 7099 | PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), |
7100 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), | 7100 | PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), |
7101 | PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), | 7101 | PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), |
7102 | PROC(LAYOUTGET, enc_layoutget, dec_layoutget), | 7102 | PROC(LAYOUTGET, enc_layoutget, dec_layoutget), |
7103 | PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), | 7103 | PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), |
7104 | PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), | 7104 | PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), |
7105 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), | 7105 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), |
7106 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), | 7106 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), |
7107 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), | 7107 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), |
7108 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), | 7108 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), |
7109 | #endif /* CONFIG_NFS_V4_1 */ | 7109 | #endif /* CONFIG_NFS_V4_1 */ |
7110 | }; | 7110 | }; |
7111 | 7111 | ||
7112 | struct rpc_version nfs_version4 = { | 7112 | const struct rpc_version nfs_version4 = { |
7113 | .number = 4, | 7113 | .number = 4, |
7114 | .nrprocs = ARRAY_SIZE(nfs4_procedures), | 7114 | .nrprocs = ARRAY_SIZE(nfs4_procedures), |
7115 | .procs = nfs4_procedures | 7115 | .procs = nfs4_procedures |
7116 | }; | 7116 | }; |
7117 | 7117 | ||
7118 | /* | 7118 | /* |
7119 | * Local variables: | 7119 | * Local variables: |
7120 | * c-basic-offset: 8 | 7120 | * c-basic-offset: 8 |
7121 | * End: | 7121 | * End: |
7122 | */ | 7122 | */ |
7123 | 7123 |
fs/nfsd/nfs4callback.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2001 The Regents of the University of Michigan. | 2 | * Copyright (c) 2001 The Regents of the University of Michigan. |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * Kendrick Smith <kmsmith@umich.edu> | 5 | * Kendrick Smith <kmsmith@umich.edu> |
6 | * Andy Adamson <andros@umich.edu> | 6 | * Andy Adamson <andros@umich.edu> |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | 10 | * are met: |
11 | * | 11 | * |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. Neither the name of the University nor the names of its | 17 | * 3. Neither the name of the University nor the names of its |
18 | * contributors may be used to endorse or promote products derived | 18 | * contributors may be used to endorse or promote products derived |
19 | * from this software without specific prior written permission. | 19 | * from this software without specific prior written permission. |
20 | * | 20 | * |
21 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | 21 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
22 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 22 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
23 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 23 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
24 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 24 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
29 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 29 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/sunrpc/clnt.h> | 34 | #include <linux/sunrpc/clnt.h> |
35 | #include <linux/sunrpc/svc_xprt.h> | 35 | #include <linux/sunrpc/svc_xprt.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include "nfsd.h" | 37 | #include "nfsd.h" |
38 | #include "state.h" | 38 | #include "state.h" |
39 | 39 | ||
40 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 40 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
41 | 41 | ||
42 | static void nfsd4_mark_cb_fault(struct nfs4_client *, int reason); | 42 | static void nfsd4_mark_cb_fault(struct nfs4_client *, int reason); |
43 | 43 | ||
44 | #define NFSPROC4_CB_NULL 0 | 44 | #define NFSPROC4_CB_NULL 0 |
45 | #define NFSPROC4_CB_COMPOUND 1 | 45 | #define NFSPROC4_CB_COMPOUND 1 |
46 | 46 | ||
47 | /* Index of predefined Linux callback client operations */ | 47 | /* Index of predefined Linux callback client operations */ |
48 | 48 | ||
49 | enum { | 49 | enum { |
50 | NFSPROC4_CLNT_CB_NULL = 0, | 50 | NFSPROC4_CLNT_CB_NULL = 0, |
51 | NFSPROC4_CLNT_CB_RECALL, | 51 | NFSPROC4_CLNT_CB_RECALL, |
52 | NFSPROC4_CLNT_CB_SEQUENCE, | 52 | NFSPROC4_CLNT_CB_SEQUENCE, |
53 | }; | 53 | }; |
54 | 54 | ||
55 | #define NFS4_MAXTAGLEN 20 | 55 | #define NFS4_MAXTAGLEN 20 |
56 | 56 | ||
57 | #define NFS4_enc_cb_null_sz 0 | 57 | #define NFS4_enc_cb_null_sz 0 |
58 | #define NFS4_dec_cb_null_sz 0 | 58 | #define NFS4_dec_cb_null_sz 0 |
59 | #define cb_compound_enc_hdr_sz 4 | 59 | #define cb_compound_enc_hdr_sz 4 |
60 | #define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2)) | 60 | #define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2)) |
61 | #define sessionid_sz (NFS4_MAX_SESSIONID_LEN >> 2) | 61 | #define sessionid_sz (NFS4_MAX_SESSIONID_LEN >> 2) |
62 | #define cb_sequence_enc_sz (sessionid_sz + 4 + \ | 62 | #define cb_sequence_enc_sz (sessionid_sz + 4 + \ |
63 | 1 /* no referring calls list yet */) | 63 | 1 /* no referring calls list yet */) |
64 | #define cb_sequence_dec_sz (op_dec_sz + sessionid_sz + 4) | 64 | #define cb_sequence_dec_sz (op_dec_sz + sessionid_sz + 4) |
65 | 65 | ||
66 | #define op_enc_sz 1 | 66 | #define op_enc_sz 1 |
67 | #define op_dec_sz 2 | 67 | #define op_dec_sz 2 |
68 | #define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2)) | 68 | #define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2)) |
69 | #define enc_stateid_sz (NFS4_STATEID_SIZE >> 2) | 69 | #define enc_stateid_sz (NFS4_STATEID_SIZE >> 2) |
70 | #define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \ | 70 | #define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \ |
71 | cb_sequence_enc_sz + \ | 71 | cb_sequence_enc_sz + \ |
72 | 1 + enc_stateid_sz + \ | 72 | 1 + enc_stateid_sz + \ |
73 | enc_nfs4_fh_sz) | 73 | enc_nfs4_fh_sz) |
74 | 74 | ||
75 | #define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \ | 75 | #define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \ |
76 | cb_sequence_dec_sz + \ | 76 | cb_sequence_dec_sz + \ |
77 | op_dec_sz) | 77 | op_dec_sz) |
78 | 78 | ||
79 | struct nfs4_cb_compound_hdr { | 79 | struct nfs4_cb_compound_hdr { |
80 | /* args */ | 80 | /* args */ |
81 | u32 ident; /* minorversion 0 only */ | 81 | u32 ident; /* minorversion 0 only */ |
82 | u32 nops; | 82 | u32 nops; |
83 | __be32 *nops_p; | 83 | __be32 *nops_p; |
84 | u32 minorversion; | 84 | u32 minorversion; |
85 | /* res */ | 85 | /* res */ |
86 | int status; | 86 | int status; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * Handle decode buffer overflows out-of-line. | 90 | * Handle decode buffer overflows out-of-line. |
91 | */ | 91 | */ |
92 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | 92 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) |
93 | { | 93 | { |
94 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " | 94 | dprintk("NFS: %s prematurely hit the end of our receive buffer. " |
95 | "Remaining buffer length is %tu words.\n", | 95 | "Remaining buffer length is %tu words.\n", |
96 | func, xdr->end - xdr->p); | 96 | func, xdr->end - xdr->p); |
97 | } | 97 | } |
98 | 98 | ||
99 | static __be32 *xdr_encode_empty_array(__be32 *p) | 99 | static __be32 *xdr_encode_empty_array(__be32 *p) |
100 | { | 100 | { |
101 | *p++ = xdr_zero; | 101 | *p++ = xdr_zero; |
102 | return p; | 102 | return p; |
103 | } | 103 | } |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * Encode/decode NFSv4 CB basic data types | 106 | * Encode/decode NFSv4 CB basic data types |
107 | * | 107 | * |
108 | * Basic NFSv4 callback data types are defined in section 15 of RFC | 108 | * Basic NFSv4 callback data types are defined in section 15 of RFC |
109 | * 3530: "Network File System (NFS) version 4 Protocol" and section | 109 | * 3530: "Network File System (NFS) version 4 Protocol" and section |
110 | * 20 of RFC 5661: "Network File System (NFS) Version 4 Minor Version | 110 | * 20 of RFC 5661: "Network File System (NFS) Version 4 Minor Version |
111 | * 1 Protocol" | 111 | * 1 Protocol" |
112 | */ | 112 | */ |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * nfs_cb_opnum4 | 115 | * nfs_cb_opnum4 |
116 | * | 116 | * |
117 | * enum nfs_cb_opnum4 { | 117 | * enum nfs_cb_opnum4 { |
118 | * OP_CB_GETATTR = 3, | 118 | * OP_CB_GETATTR = 3, |
119 | * ... | 119 | * ... |
120 | * }; | 120 | * }; |
121 | */ | 121 | */ |
122 | enum nfs_cb_opnum4 { | 122 | enum nfs_cb_opnum4 { |
123 | OP_CB_GETATTR = 3, | 123 | OP_CB_GETATTR = 3, |
124 | OP_CB_RECALL = 4, | 124 | OP_CB_RECALL = 4, |
125 | OP_CB_LAYOUTRECALL = 5, | 125 | OP_CB_LAYOUTRECALL = 5, |
126 | OP_CB_NOTIFY = 6, | 126 | OP_CB_NOTIFY = 6, |
127 | OP_CB_PUSH_DELEG = 7, | 127 | OP_CB_PUSH_DELEG = 7, |
128 | OP_CB_RECALL_ANY = 8, | 128 | OP_CB_RECALL_ANY = 8, |
129 | OP_CB_RECALLABLE_OBJ_AVAIL = 9, | 129 | OP_CB_RECALLABLE_OBJ_AVAIL = 9, |
130 | OP_CB_RECALL_SLOT = 10, | 130 | OP_CB_RECALL_SLOT = 10, |
131 | OP_CB_SEQUENCE = 11, | 131 | OP_CB_SEQUENCE = 11, |
132 | OP_CB_WANTS_CANCELLED = 12, | 132 | OP_CB_WANTS_CANCELLED = 12, |
133 | OP_CB_NOTIFY_LOCK = 13, | 133 | OP_CB_NOTIFY_LOCK = 13, |
134 | OP_CB_NOTIFY_DEVICEID = 14, | 134 | OP_CB_NOTIFY_DEVICEID = 14, |
135 | OP_CB_ILLEGAL = 10044 | 135 | OP_CB_ILLEGAL = 10044 |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static void encode_nfs_cb_opnum4(struct xdr_stream *xdr, enum nfs_cb_opnum4 op) | 138 | static void encode_nfs_cb_opnum4(struct xdr_stream *xdr, enum nfs_cb_opnum4 op) |
139 | { | 139 | { |
140 | __be32 *p; | 140 | __be32 *p; |
141 | 141 | ||
142 | p = xdr_reserve_space(xdr, 4); | 142 | p = xdr_reserve_space(xdr, 4); |
143 | *p = cpu_to_be32(op); | 143 | *p = cpu_to_be32(op); |
144 | } | 144 | } |
145 | 145 | ||
146 | /* | 146 | /* |
147 | * nfs_fh4 | 147 | * nfs_fh4 |
148 | * | 148 | * |
149 | * typedef opaque nfs_fh4<NFS4_FHSIZE>; | 149 | * typedef opaque nfs_fh4<NFS4_FHSIZE>; |
150 | */ | 150 | */ |
151 | static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh) | 151 | static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh) |
152 | { | 152 | { |
153 | u32 length = fh->fh_size; | 153 | u32 length = fh->fh_size; |
154 | __be32 *p; | 154 | __be32 *p; |
155 | 155 | ||
156 | BUG_ON(length > NFS4_FHSIZE); | 156 | BUG_ON(length > NFS4_FHSIZE); |
157 | p = xdr_reserve_space(xdr, 4 + length); | 157 | p = xdr_reserve_space(xdr, 4 + length); |
158 | xdr_encode_opaque(p, &fh->fh_base, length); | 158 | xdr_encode_opaque(p, &fh->fh_base, length); |
159 | } | 159 | } |
160 | 160 | ||
161 | /* | 161 | /* |
162 | * stateid4 | 162 | * stateid4 |
163 | * | 163 | * |
164 | * struct stateid4 { | 164 | * struct stateid4 { |
165 | * uint32_t seqid; | 165 | * uint32_t seqid; |
166 | * opaque other[12]; | 166 | * opaque other[12]; |
167 | * }; | 167 | * }; |
168 | */ | 168 | */ |
169 | static void encode_stateid4(struct xdr_stream *xdr, const stateid_t *sid) | 169 | static void encode_stateid4(struct xdr_stream *xdr, const stateid_t *sid) |
170 | { | 170 | { |
171 | __be32 *p; | 171 | __be32 *p; |
172 | 172 | ||
173 | p = xdr_reserve_space(xdr, NFS4_STATEID_SIZE); | 173 | p = xdr_reserve_space(xdr, NFS4_STATEID_SIZE); |
174 | *p++ = cpu_to_be32(sid->si_generation); | 174 | *p++ = cpu_to_be32(sid->si_generation); |
175 | xdr_encode_opaque_fixed(p, &sid->si_opaque, NFS4_STATEID_OTHER_SIZE); | 175 | xdr_encode_opaque_fixed(p, &sid->si_opaque, NFS4_STATEID_OTHER_SIZE); |
176 | } | 176 | } |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * sessionid4 | 179 | * sessionid4 |
180 | * | 180 | * |
181 | * typedef opaque sessionid4[NFS4_SESSIONID_SIZE]; | 181 | * typedef opaque sessionid4[NFS4_SESSIONID_SIZE]; |
182 | */ | 182 | */ |
183 | static void encode_sessionid4(struct xdr_stream *xdr, | 183 | static void encode_sessionid4(struct xdr_stream *xdr, |
184 | const struct nfsd4_session *session) | 184 | const struct nfsd4_session *session) |
185 | { | 185 | { |
186 | __be32 *p; | 186 | __be32 *p; |
187 | 187 | ||
188 | p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN); | 188 | p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN); |
189 | xdr_encode_opaque_fixed(p, session->se_sessionid.data, | 189 | xdr_encode_opaque_fixed(p, session->se_sessionid.data, |
190 | NFS4_MAX_SESSIONID_LEN); | 190 | NFS4_MAX_SESSIONID_LEN); |
191 | } | 191 | } |
192 | 192 | ||
193 | /* | 193 | /* |
194 | * nfsstat4 | 194 | * nfsstat4 |
195 | */ | 195 | */ |
196 | static const struct { | 196 | static const struct { |
197 | int stat; | 197 | int stat; |
198 | int errno; | 198 | int errno; |
199 | } nfs_cb_errtbl[] = { | 199 | } nfs_cb_errtbl[] = { |
200 | { NFS4_OK, 0 }, | 200 | { NFS4_OK, 0 }, |
201 | { NFS4ERR_PERM, -EPERM }, | 201 | { NFS4ERR_PERM, -EPERM }, |
202 | { NFS4ERR_NOENT, -ENOENT }, | 202 | { NFS4ERR_NOENT, -ENOENT }, |
203 | { NFS4ERR_IO, -EIO }, | 203 | { NFS4ERR_IO, -EIO }, |
204 | { NFS4ERR_NXIO, -ENXIO }, | 204 | { NFS4ERR_NXIO, -ENXIO }, |
205 | { NFS4ERR_ACCESS, -EACCES }, | 205 | { NFS4ERR_ACCESS, -EACCES }, |
206 | { NFS4ERR_EXIST, -EEXIST }, | 206 | { NFS4ERR_EXIST, -EEXIST }, |
207 | { NFS4ERR_XDEV, -EXDEV }, | 207 | { NFS4ERR_XDEV, -EXDEV }, |
208 | { NFS4ERR_NOTDIR, -ENOTDIR }, | 208 | { NFS4ERR_NOTDIR, -ENOTDIR }, |
209 | { NFS4ERR_ISDIR, -EISDIR }, | 209 | { NFS4ERR_ISDIR, -EISDIR }, |
210 | { NFS4ERR_INVAL, -EINVAL }, | 210 | { NFS4ERR_INVAL, -EINVAL }, |
211 | { NFS4ERR_FBIG, -EFBIG }, | 211 | { NFS4ERR_FBIG, -EFBIG }, |
212 | { NFS4ERR_NOSPC, -ENOSPC }, | 212 | { NFS4ERR_NOSPC, -ENOSPC }, |
213 | { NFS4ERR_ROFS, -EROFS }, | 213 | { NFS4ERR_ROFS, -EROFS }, |
214 | { NFS4ERR_MLINK, -EMLINK }, | 214 | { NFS4ERR_MLINK, -EMLINK }, |
215 | { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, | 215 | { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, |
216 | { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, | 216 | { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, |
217 | { NFS4ERR_DQUOT, -EDQUOT }, | 217 | { NFS4ERR_DQUOT, -EDQUOT }, |
218 | { NFS4ERR_STALE, -ESTALE }, | 218 | { NFS4ERR_STALE, -ESTALE }, |
219 | { NFS4ERR_BADHANDLE, -EBADHANDLE }, | 219 | { NFS4ERR_BADHANDLE, -EBADHANDLE }, |
220 | { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, | 220 | { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, |
221 | { NFS4ERR_NOTSUPP, -ENOTSUPP }, | 221 | { NFS4ERR_NOTSUPP, -ENOTSUPP }, |
222 | { NFS4ERR_TOOSMALL, -ETOOSMALL }, | 222 | { NFS4ERR_TOOSMALL, -ETOOSMALL }, |
223 | { NFS4ERR_SERVERFAULT, -ESERVERFAULT }, | 223 | { NFS4ERR_SERVERFAULT, -ESERVERFAULT }, |
224 | { NFS4ERR_BADTYPE, -EBADTYPE }, | 224 | { NFS4ERR_BADTYPE, -EBADTYPE }, |
225 | { NFS4ERR_LOCKED, -EAGAIN }, | 225 | { NFS4ERR_LOCKED, -EAGAIN }, |
226 | { NFS4ERR_RESOURCE, -EREMOTEIO }, | 226 | { NFS4ERR_RESOURCE, -EREMOTEIO }, |
227 | { NFS4ERR_SYMLINK, -ELOOP }, | 227 | { NFS4ERR_SYMLINK, -ELOOP }, |
228 | { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, | 228 | { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, |
229 | { NFS4ERR_DEADLOCK, -EDEADLK }, | 229 | { NFS4ERR_DEADLOCK, -EDEADLK }, |
230 | { -1, -EIO } | 230 | { -1, -EIO } |
231 | }; | 231 | }; |
232 | 232 | ||
233 | /* | 233 | /* |
234 | * If we cannot translate the error, the recovery routines should | 234 | * If we cannot translate the error, the recovery routines should |
235 | * handle it. | 235 | * handle it. |
236 | * | 236 | * |
237 | * Note: remaining NFSv4 error codes have values > 10000, so should | 237 | * Note: remaining NFSv4 error codes have values > 10000, so should |
238 | * not conflict with native Linux error codes. | 238 | * not conflict with native Linux error codes. |
239 | */ | 239 | */ |
240 | static int nfs_cb_stat_to_errno(int status) | 240 | static int nfs_cb_stat_to_errno(int status) |
241 | { | 241 | { |
242 | int i; | 242 | int i; |
243 | 243 | ||
244 | for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) { | 244 | for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) { |
245 | if (nfs_cb_errtbl[i].stat == status) | 245 | if (nfs_cb_errtbl[i].stat == status) |
246 | return nfs_cb_errtbl[i].errno; | 246 | return nfs_cb_errtbl[i].errno; |
247 | } | 247 | } |
248 | 248 | ||
249 | dprintk("NFSD: Unrecognized NFS CB status value: %u\n", status); | 249 | dprintk("NFSD: Unrecognized NFS CB status value: %u\n", status); |
250 | return -status; | 250 | return -status; |
251 | } | 251 | } |
252 | 252 | ||
253 | static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected, | 253 | static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected, |
254 | enum nfsstat4 *status) | 254 | enum nfsstat4 *status) |
255 | { | 255 | { |
256 | __be32 *p; | 256 | __be32 *p; |
257 | u32 op; | 257 | u32 op; |
258 | 258 | ||
259 | p = xdr_inline_decode(xdr, 4 + 4); | 259 | p = xdr_inline_decode(xdr, 4 + 4); |
260 | if (unlikely(p == NULL)) | 260 | if (unlikely(p == NULL)) |
261 | goto out_overflow; | 261 | goto out_overflow; |
262 | op = be32_to_cpup(p++); | 262 | op = be32_to_cpup(p++); |
263 | if (unlikely(op != expected)) | 263 | if (unlikely(op != expected)) |
264 | goto out_unexpected; | 264 | goto out_unexpected; |
265 | *status = be32_to_cpup(p); | 265 | *status = be32_to_cpup(p); |
266 | return 0; | 266 | return 0; |
267 | out_overflow: | 267 | out_overflow: |
268 | print_overflow_msg(__func__, xdr); | 268 | print_overflow_msg(__func__, xdr); |
269 | return -EIO; | 269 | return -EIO; |
270 | out_unexpected: | 270 | out_unexpected: |
271 | dprintk("NFSD: Callback server returned operation %d but " | 271 | dprintk("NFSD: Callback server returned operation %d but " |
272 | "we issued a request for %d\n", op, expected); | 272 | "we issued a request for %d\n", op, expected); |
273 | return -EIO; | 273 | return -EIO; |
274 | } | 274 | } |
275 | 275 | ||
276 | /* | 276 | /* |
277 | * CB_COMPOUND4args | 277 | * CB_COMPOUND4args |
278 | * | 278 | * |
279 | * struct CB_COMPOUND4args { | 279 | * struct CB_COMPOUND4args { |
280 | * utf8str_cs tag; | 280 | * utf8str_cs tag; |
281 | * uint32_t minorversion; | 281 | * uint32_t minorversion; |
282 | * uint32_t callback_ident; | 282 | * uint32_t callback_ident; |
283 | * nfs_cb_argop4 argarray<>; | 283 | * nfs_cb_argop4 argarray<>; |
284 | * }; | 284 | * }; |
285 | */ | 285 | */ |
286 | static void encode_cb_compound4args(struct xdr_stream *xdr, | 286 | static void encode_cb_compound4args(struct xdr_stream *xdr, |
287 | struct nfs4_cb_compound_hdr *hdr) | 287 | struct nfs4_cb_compound_hdr *hdr) |
288 | { | 288 | { |
289 | __be32 * p; | 289 | __be32 * p; |
290 | 290 | ||
291 | p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4); | 291 | p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4); |
292 | p = xdr_encode_empty_array(p); /* empty tag */ | 292 | p = xdr_encode_empty_array(p); /* empty tag */ |
293 | *p++ = cpu_to_be32(hdr->minorversion); | 293 | *p++ = cpu_to_be32(hdr->minorversion); |
294 | *p++ = cpu_to_be32(hdr->ident); | 294 | *p++ = cpu_to_be32(hdr->ident); |
295 | 295 | ||
296 | hdr->nops_p = p; | 296 | hdr->nops_p = p; |
297 | *p = cpu_to_be32(hdr->nops); /* argarray element count */ | 297 | *p = cpu_to_be32(hdr->nops); /* argarray element count */ |
298 | } | 298 | } |
299 | 299 | ||
300 | /* | 300 | /* |
301 | * Update argarray element count | 301 | * Update argarray element count |
302 | */ | 302 | */ |
303 | static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr) | 303 | static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr) |
304 | { | 304 | { |
305 | BUG_ON(hdr->nops > NFS4_MAX_BACK_CHANNEL_OPS); | 305 | BUG_ON(hdr->nops > NFS4_MAX_BACK_CHANNEL_OPS); |
306 | *hdr->nops_p = cpu_to_be32(hdr->nops); | 306 | *hdr->nops_p = cpu_to_be32(hdr->nops); |
307 | } | 307 | } |
308 | 308 | ||
309 | /* | 309 | /* |
310 | * CB_COMPOUND4res | 310 | * CB_COMPOUND4res |
311 | * | 311 | * |
312 | * struct CB_COMPOUND4res { | 312 | * struct CB_COMPOUND4res { |
313 | * nfsstat4 status; | 313 | * nfsstat4 status; |
314 | * utf8str_cs tag; | 314 | * utf8str_cs tag; |
315 | * nfs_cb_resop4 resarray<>; | 315 | * nfs_cb_resop4 resarray<>; |
316 | * }; | 316 | * }; |
317 | */ | 317 | */ |
318 | static int decode_cb_compound4res(struct xdr_stream *xdr, | 318 | static int decode_cb_compound4res(struct xdr_stream *xdr, |
319 | struct nfs4_cb_compound_hdr *hdr) | 319 | struct nfs4_cb_compound_hdr *hdr) |
320 | { | 320 | { |
321 | u32 length; | 321 | u32 length; |
322 | __be32 *p; | 322 | __be32 *p; |
323 | 323 | ||
324 | p = xdr_inline_decode(xdr, 4 + 4); | 324 | p = xdr_inline_decode(xdr, 4 + 4); |
325 | if (unlikely(p == NULL)) | 325 | if (unlikely(p == NULL)) |
326 | goto out_overflow; | 326 | goto out_overflow; |
327 | hdr->status = be32_to_cpup(p++); | 327 | hdr->status = be32_to_cpup(p++); |
328 | /* Ignore the tag */ | 328 | /* Ignore the tag */ |
329 | length = be32_to_cpup(p++); | 329 | length = be32_to_cpup(p++); |
330 | p = xdr_inline_decode(xdr, length + 4); | 330 | p = xdr_inline_decode(xdr, length + 4); |
331 | if (unlikely(p == NULL)) | 331 | if (unlikely(p == NULL)) |
332 | goto out_overflow; | 332 | goto out_overflow; |
333 | hdr->nops = be32_to_cpup(p); | 333 | hdr->nops = be32_to_cpup(p); |
334 | return 0; | 334 | return 0; |
335 | out_overflow: | 335 | out_overflow: |
336 | print_overflow_msg(__func__, xdr); | 336 | print_overflow_msg(__func__, xdr); |
337 | return -EIO; | 337 | return -EIO; |
338 | } | 338 | } |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * CB_RECALL4args | 341 | * CB_RECALL4args |
342 | * | 342 | * |
343 | * struct CB_RECALL4args { | 343 | * struct CB_RECALL4args { |
344 | * stateid4 stateid; | 344 | * stateid4 stateid; |
345 | * bool truncate; | 345 | * bool truncate; |
346 | * nfs_fh4 fh; | 346 | * nfs_fh4 fh; |
347 | * }; | 347 | * }; |
348 | */ | 348 | */ |
349 | static void encode_cb_recall4args(struct xdr_stream *xdr, | 349 | static void encode_cb_recall4args(struct xdr_stream *xdr, |
350 | const struct nfs4_delegation *dp, | 350 | const struct nfs4_delegation *dp, |
351 | struct nfs4_cb_compound_hdr *hdr) | 351 | struct nfs4_cb_compound_hdr *hdr) |
352 | { | 352 | { |
353 | __be32 *p; | 353 | __be32 *p; |
354 | 354 | ||
355 | encode_nfs_cb_opnum4(xdr, OP_CB_RECALL); | 355 | encode_nfs_cb_opnum4(xdr, OP_CB_RECALL); |
356 | encode_stateid4(xdr, &dp->dl_stid.sc_stateid); | 356 | encode_stateid4(xdr, &dp->dl_stid.sc_stateid); |
357 | 357 | ||
358 | p = xdr_reserve_space(xdr, 4); | 358 | p = xdr_reserve_space(xdr, 4); |
359 | *p++ = xdr_zero; /* truncate */ | 359 | *p++ = xdr_zero; /* truncate */ |
360 | 360 | ||
361 | encode_nfs_fh4(xdr, &dp->dl_fh); | 361 | encode_nfs_fh4(xdr, &dp->dl_fh); |
362 | 362 | ||
363 | hdr->nops++; | 363 | hdr->nops++; |
364 | } | 364 | } |
365 | 365 | ||
366 | /* | 366 | /* |
367 | * CB_SEQUENCE4args | 367 | * CB_SEQUENCE4args |
368 | * | 368 | * |
369 | * struct CB_SEQUENCE4args { | 369 | * struct CB_SEQUENCE4args { |
370 | * sessionid4 csa_sessionid; | 370 | * sessionid4 csa_sessionid; |
371 | * sequenceid4 csa_sequenceid; | 371 | * sequenceid4 csa_sequenceid; |
372 | * slotid4 csa_slotid; | 372 | * slotid4 csa_slotid; |
373 | * slotid4 csa_highest_slotid; | 373 | * slotid4 csa_highest_slotid; |
374 | * bool csa_cachethis; | 374 | * bool csa_cachethis; |
375 | * referring_call_list4 csa_referring_call_lists<>; | 375 | * referring_call_list4 csa_referring_call_lists<>; |
376 | * }; | 376 | * }; |
377 | */ | 377 | */ |
378 | static void encode_cb_sequence4args(struct xdr_stream *xdr, | 378 | static void encode_cb_sequence4args(struct xdr_stream *xdr, |
379 | const struct nfsd4_callback *cb, | 379 | const struct nfsd4_callback *cb, |
380 | struct nfs4_cb_compound_hdr *hdr) | 380 | struct nfs4_cb_compound_hdr *hdr) |
381 | { | 381 | { |
382 | struct nfsd4_session *session = cb->cb_clp->cl_cb_session; | 382 | struct nfsd4_session *session = cb->cb_clp->cl_cb_session; |
383 | __be32 *p; | 383 | __be32 *p; |
384 | 384 | ||
385 | if (hdr->minorversion == 0) | 385 | if (hdr->minorversion == 0) |
386 | return; | 386 | return; |
387 | 387 | ||
388 | encode_nfs_cb_opnum4(xdr, OP_CB_SEQUENCE); | 388 | encode_nfs_cb_opnum4(xdr, OP_CB_SEQUENCE); |
389 | encode_sessionid4(xdr, session); | 389 | encode_sessionid4(xdr, session); |
390 | 390 | ||
391 | p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4 + 4); | 391 | p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4 + 4); |
392 | *p++ = cpu_to_be32(session->se_cb_seq_nr); /* csa_sequenceid */ | 392 | *p++ = cpu_to_be32(session->se_cb_seq_nr); /* csa_sequenceid */ |
393 | *p++ = xdr_zero; /* csa_slotid */ | 393 | *p++ = xdr_zero; /* csa_slotid */ |
394 | *p++ = xdr_zero; /* csa_highest_slotid */ | 394 | *p++ = xdr_zero; /* csa_highest_slotid */ |
395 | *p++ = xdr_zero; /* csa_cachethis */ | 395 | *p++ = xdr_zero; /* csa_cachethis */ |
396 | xdr_encode_empty_array(p); /* csa_referring_call_lists */ | 396 | xdr_encode_empty_array(p); /* csa_referring_call_lists */ |
397 | 397 | ||
398 | hdr->nops++; | 398 | hdr->nops++; |
399 | } | 399 | } |
400 | 400 | ||
401 | /* | 401 | /* |
402 | * CB_SEQUENCE4resok | 402 | * CB_SEQUENCE4resok |
403 | * | 403 | * |
404 | * struct CB_SEQUENCE4resok { | 404 | * struct CB_SEQUENCE4resok { |
405 | * sessionid4 csr_sessionid; | 405 | * sessionid4 csr_sessionid; |
406 | * sequenceid4 csr_sequenceid; | 406 | * sequenceid4 csr_sequenceid; |
407 | * slotid4 csr_slotid; | 407 | * slotid4 csr_slotid; |
408 | * slotid4 csr_highest_slotid; | 408 | * slotid4 csr_highest_slotid; |
409 | * slotid4 csr_target_highest_slotid; | 409 | * slotid4 csr_target_highest_slotid; |
410 | * }; | 410 | * }; |
411 | * | 411 | * |
412 | * union CB_SEQUENCE4res switch (nfsstat4 csr_status) { | 412 | * union CB_SEQUENCE4res switch (nfsstat4 csr_status) { |
413 | * case NFS4_OK: | 413 | * case NFS4_OK: |
414 | * CB_SEQUENCE4resok csr_resok4; | 414 | * CB_SEQUENCE4resok csr_resok4; |
415 | * default: | 415 | * default: |
416 | * void; | 416 | * void; |
417 | * }; | 417 | * }; |
418 | * | 418 | * |
419 | * Our current back channel implmentation supports a single backchannel | 419 | * Our current back channel implmentation supports a single backchannel |
420 | * with a single slot. | 420 | * with a single slot. |
421 | */ | 421 | */ |
422 | static int decode_cb_sequence4resok(struct xdr_stream *xdr, | 422 | static int decode_cb_sequence4resok(struct xdr_stream *xdr, |
423 | struct nfsd4_callback *cb) | 423 | struct nfsd4_callback *cb) |
424 | { | 424 | { |
425 | struct nfsd4_session *session = cb->cb_clp->cl_cb_session; | 425 | struct nfsd4_session *session = cb->cb_clp->cl_cb_session; |
426 | struct nfs4_sessionid id; | 426 | struct nfs4_sessionid id; |
427 | int status; | 427 | int status; |
428 | __be32 *p; | 428 | __be32 *p; |
429 | u32 dummy; | 429 | u32 dummy; |
430 | 430 | ||
431 | status = -ESERVERFAULT; | 431 | status = -ESERVERFAULT; |
432 | 432 | ||
433 | /* | 433 | /* |
434 | * If the server returns different values for sessionID, slotID or | 434 | * If the server returns different values for sessionID, slotID or |
435 | * sequence number, the server is looney tunes. | 435 | * sequence number, the server is looney tunes. |
436 | */ | 436 | */ |
437 | p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4); | 437 | p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4); |
438 | if (unlikely(p == NULL)) | 438 | if (unlikely(p == NULL)) |
439 | goto out_overflow; | 439 | goto out_overflow; |
440 | memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN); | 440 | memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN); |
441 | if (memcmp(id.data, session->se_sessionid.data, | 441 | if (memcmp(id.data, session->se_sessionid.data, |
442 | NFS4_MAX_SESSIONID_LEN) != 0) { | 442 | NFS4_MAX_SESSIONID_LEN) != 0) { |
443 | dprintk("NFS: %s Invalid session id\n", __func__); | 443 | dprintk("NFS: %s Invalid session id\n", __func__); |
444 | goto out; | 444 | goto out; |
445 | } | 445 | } |
446 | p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN); | 446 | p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN); |
447 | 447 | ||
448 | dummy = be32_to_cpup(p++); | 448 | dummy = be32_to_cpup(p++); |
449 | if (dummy != session->se_cb_seq_nr) { | 449 | if (dummy != session->se_cb_seq_nr) { |
450 | dprintk("NFS: %s Invalid sequence number\n", __func__); | 450 | dprintk("NFS: %s Invalid sequence number\n", __func__); |
451 | goto out; | 451 | goto out; |
452 | } | 452 | } |
453 | 453 | ||
454 | dummy = be32_to_cpup(p++); | 454 | dummy = be32_to_cpup(p++); |
455 | if (dummy != 0) { | 455 | if (dummy != 0) { |
456 | dprintk("NFS: %s Invalid slotid\n", __func__); | 456 | dprintk("NFS: %s Invalid slotid\n", __func__); |
457 | goto out; | 457 | goto out; |
458 | } | 458 | } |
459 | 459 | ||
460 | /* | 460 | /* |
461 | * FIXME: process highest slotid and target highest slotid | 461 | * FIXME: process highest slotid and target highest slotid |
462 | */ | 462 | */ |
463 | status = 0; | 463 | status = 0; |
464 | out: | 464 | out: |
465 | if (status) | 465 | if (status) |
466 | nfsd4_mark_cb_fault(cb->cb_clp, status); | 466 | nfsd4_mark_cb_fault(cb->cb_clp, status); |
467 | return status; | 467 | return status; |
468 | out_overflow: | 468 | out_overflow: |
469 | print_overflow_msg(__func__, xdr); | 469 | print_overflow_msg(__func__, xdr); |
470 | return -EIO; | 470 | return -EIO; |
471 | } | 471 | } |
472 | 472 | ||
473 | static int decode_cb_sequence4res(struct xdr_stream *xdr, | 473 | static int decode_cb_sequence4res(struct xdr_stream *xdr, |
474 | struct nfsd4_callback *cb) | 474 | struct nfsd4_callback *cb) |
475 | { | 475 | { |
476 | enum nfsstat4 nfserr; | 476 | enum nfsstat4 nfserr; |
477 | int status; | 477 | int status; |
478 | 478 | ||
479 | if (cb->cb_minorversion == 0) | 479 | if (cb->cb_minorversion == 0) |
480 | return 0; | 480 | return 0; |
481 | 481 | ||
482 | status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &nfserr); | 482 | status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &nfserr); |
483 | if (unlikely(status)) | 483 | if (unlikely(status)) |
484 | goto out; | 484 | goto out; |
485 | if (unlikely(nfserr != NFS4_OK)) | 485 | if (unlikely(nfserr != NFS4_OK)) |
486 | goto out_default; | 486 | goto out_default; |
487 | status = decode_cb_sequence4resok(xdr, cb); | 487 | status = decode_cb_sequence4resok(xdr, cb); |
488 | out: | 488 | out: |
489 | return status; | 489 | return status; |
490 | out_default: | 490 | out_default: |
491 | return nfs_cb_stat_to_errno(nfserr); | 491 | return nfs_cb_stat_to_errno(nfserr); |
492 | } | 492 | } |
493 | 493 | ||
494 | /* | 494 | /* |
495 | * NFSv4.0 and NFSv4.1 XDR encode functions | 495 | * NFSv4.0 and NFSv4.1 XDR encode functions |
496 | * | 496 | * |
497 | * NFSv4.0 callback argument types are defined in section 15 of RFC | 497 | * NFSv4.0 callback argument types are defined in section 15 of RFC |
498 | * 3530: "Network File System (NFS) version 4 Protocol" and section 20 | 498 | * 3530: "Network File System (NFS) version 4 Protocol" and section 20 |
499 | * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1 | 499 | * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1 |
500 | * Protocol". | 500 | * Protocol". |
501 | */ | 501 | */ |
502 | 502 | ||
503 | /* | 503 | /* |
504 | * NB: Without this zero space reservation, callbacks over krb5p fail | 504 | * NB: Without this zero space reservation, callbacks over krb5p fail |
505 | */ | 505 | */ |
506 | static void nfs4_xdr_enc_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr, | 506 | static void nfs4_xdr_enc_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr, |
507 | void *__unused) | 507 | void *__unused) |
508 | { | 508 | { |
509 | xdr_reserve_space(xdr, 0); | 509 | xdr_reserve_space(xdr, 0); |
510 | } | 510 | } |
511 | 511 | ||
512 | /* | 512 | /* |
513 | * 20.2. Operation 4: CB_RECALL - Recall a Delegation | 513 | * 20.2. Operation 4: CB_RECALL - Recall a Delegation |
514 | */ | 514 | */ |
515 | static void nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, struct xdr_stream *xdr, | 515 | static void nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, struct xdr_stream *xdr, |
516 | const struct nfsd4_callback *cb) | 516 | const struct nfsd4_callback *cb) |
517 | { | 517 | { |
518 | const struct nfs4_delegation *args = cb->cb_op; | 518 | const struct nfs4_delegation *args = cb->cb_op; |
519 | struct nfs4_cb_compound_hdr hdr = { | 519 | struct nfs4_cb_compound_hdr hdr = { |
520 | .ident = cb->cb_clp->cl_cb_ident, | 520 | .ident = cb->cb_clp->cl_cb_ident, |
521 | .minorversion = cb->cb_minorversion, | 521 | .minorversion = cb->cb_minorversion, |
522 | }; | 522 | }; |
523 | 523 | ||
524 | encode_cb_compound4args(xdr, &hdr); | 524 | encode_cb_compound4args(xdr, &hdr); |
525 | encode_cb_sequence4args(xdr, cb, &hdr); | 525 | encode_cb_sequence4args(xdr, cb, &hdr); |
526 | encode_cb_recall4args(xdr, args, &hdr); | 526 | encode_cb_recall4args(xdr, args, &hdr); |
527 | encode_cb_nops(&hdr); | 527 | encode_cb_nops(&hdr); |
528 | } | 528 | } |
529 | 529 | ||
530 | 530 | ||
531 | /* | 531 | /* |
532 | * NFSv4.0 and NFSv4.1 XDR decode functions | 532 | * NFSv4.0 and NFSv4.1 XDR decode functions |
533 | * | 533 | * |
534 | * NFSv4.0 callback result types are defined in section 15 of RFC | 534 | * NFSv4.0 callback result types are defined in section 15 of RFC |
535 | * 3530: "Network File System (NFS) version 4 Protocol" and section 20 | 535 | * 3530: "Network File System (NFS) version 4 Protocol" and section 20 |
536 | * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1 | 536 | * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1 |
537 | * Protocol". | 537 | * Protocol". |
538 | */ | 538 | */ |
539 | 539 | ||
540 | static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr, | 540 | static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr, |
541 | void *__unused) | 541 | void *__unused) |
542 | { | 542 | { |
543 | return 0; | 543 | return 0; |
544 | } | 544 | } |
545 | 545 | ||
546 | /* | 546 | /* |
547 | * 20.2. Operation 4: CB_RECALL - Recall a Delegation | 547 | * 20.2. Operation 4: CB_RECALL - Recall a Delegation |
548 | */ | 548 | */ |
549 | static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, | 549 | static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, |
550 | struct xdr_stream *xdr, | 550 | struct xdr_stream *xdr, |
551 | struct nfsd4_callback *cb) | 551 | struct nfsd4_callback *cb) |
552 | { | 552 | { |
553 | struct nfs4_cb_compound_hdr hdr; | 553 | struct nfs4_cb_compound_hdr hdr; |
554 | enum nfsstat4 nfserr; | 554 | enum nfsstat4 nfserr; |
555 | int status; | 555 | int status; |
556 | 556 | ||
557 | status = decode_cb_compound4res(xdr, &hdr); | 557 | status = decode_cb_compound4res(xdr, &hdr); |
558 | if (unlikely(status)) | 558 | if (unlikely(status)) |
559 | goto out; | 559 | goto out; |
560 | 560 | ||
561 | if (cb != NULL) { | 561 | if (cb != NULL) { |
562 | status = decode_cb_sequence4res(xdr, cb); | 562 | status = decode_cb_sequence4res(xdr, cb); |
563 | if (unlikely(status)) | 563 | if (unlikely(status)) |
564 | goto out; | 564 | goto out; |
565 | } | 565 | } |
566 | 566 | ||
567 | status = decode_cb_op_status(xdr, OP_CB_RECALL, &nfserr); | 567 | status = decode_cb_op_status(xdr, OP_CB_RECALL, &nfserr); |
568 | if (unlikely(status)) | 568 | if (unlikely(status)) |
569 | goto out; | 569 | goto out; |
570 | if (unlikely(nfserr != NFS4_OK)) | 570 | if (unlikely(nfserr != NFS4_OK)) |
571 | status = nfs_cb_stat_to_errno(nfserr); | 571 | status = nfs_cb_stat_to_errno(nfserr); |
572 | out: | 572 | out: |
573 | return status; | 573 | return status; |
574 | } | 574 | } |
575 | 575 | ||
576 | /* | 576 | /* |
577 | * RPC procedure tables | 577 | * RPC procedure tables |
578 | */ | 578 | */ |
579 | #define PROC(proc, call, argtype, restype) \ | 579 | #define PROC(proc, call, argtype, restype) \ |
580 | [NFSPROC4_CLNT_##proc] = { \ | 580 | [NFSPROC4_CLNT_##proc] = { \ |
581 | .p_proc = NFSPROC4_CB_##call, \ | 581 | .p_proc = NFSPROC4_CB_##call, \ |
582 | .p_encode = (kxdreproc_t)nfs4_xdr_enc_##argtype, \ | 582 | .p_encode = (kxdreproc_t)nfs4_xdr_enc_##argtype, \ |
583 | .p_decode = (kxdrdproc_t)nfs4_xdr_dec_##restype, \ | 583 | .p_decode = (kxdrdproc_t)nfs4_xdr_dec_##restype, \ |
584 | .p_arglen = NFS4_enc_##argtype##_sz, \ | 584 | .p_arglen = NFS4_enc_##argtype##_sz, \ |
585 | .p_replen = NFS4_dec_##restype##_sz, \ | 585 | .p_replen = NFS4_dec_##restype##_sz, \ |
586 | .p_statidx = NFSPROC4_CB_##call, \ | 586 | .p_statidx = NFSPROC4_CB_##call, \ |
587 | .p_name = #proc, \ | 587 | .p_name = #proc, \ |
588 | } | 588 | } |
589 | 589 | ||
590 | static struct rpc_procinfo nfs4_cb_procedures[] = { | 590 | static struct rpc_procinfo nfs4_cb_procedures[] = { |
591 | PROC(CB_NULL, NULL, cb_null, cb_null), | 591 | PROC(CB_NULL, NULL, cb_null, cb_null), |
592 | PROC(CB_RECALL, COMPOUND, cb_recall, cb_recall), | 592 | PROC(CB_RECALL, COMPOUND, cb_recall, cb_recall), |
593 | }; | 593 | }; |
594 | 594 | ||
595 | static struct rpc_version nfs_cb_version4 = { | 595 | static struct rpc_version nfs_cb_version4 = { |
596 | /* | 596 | /* |
597 | * Note on the callback rpc program version number: despite language in rfc | 597 | * Note on the callback rpc program version number: despite language in rfc |
598 | * 5661 section 18.36.3 requiring servers to use 4 in this field, the | 598 | * 5661 section 18.36.3 requiring servers to use 4 in this field, the |
599 | * official xdr descriptions for both 4.0 and 4.1 specify version 1, and | 599 | * official xdr descriptions for both 4.0 and 4.1 specify version 1, and |
600 | * in practice that appears to be what implementations use. The section | 600 | * in practice that appears to be what implementations use. The section |
601 | * 18.36.3 language is expected to be fixed in an erratum. | 601 | * 18.36.3 language is expected to be fixed in an erratum. |
602 | */ | 602 | */ |
603 | .number = 1, | 603 | .number = 1, |
604 | .nrprocs = ARRAY_SIZE(nfs4_cb_procedures), | 604 | .nrprocs = ARRAY_SIZE(nfs4_cb_procedures), |
605 | .procs = nfs4_cb_procedures | 605 | .procs = nfs4_cb_procedures |
606 | }; | 606 | }; |
607 | 607 | ||
608 | static struct rpc_version *nfs_cb_version[] = { | 608 | static const struct rpc_version *nfs_cb_version[] = { |
609 | &nfs_cb_version4, | 609 | &nfs_cb_version4, |
610 | }; | 610 | }; |
611 | 611 | ||
612 | static struct rpc_program cb_program; | 612 | static const struct rpc_program cb_program; |
613 | 613 | ||
614 | static struct rpc_stat cb_stats = { | 614 | static struct rpc_stat cb_stats = { |
615 | .program = &cb_program | 615 | .program = &cb_program |
616 | }; | 616 | }; |
617 | 617 | ||
618 | #define NFS4_CALLBACK 0x40000000 | 618 | #define NFS4_CALLBACK 0x40000000 |
619 | static struct rpc_program cb_program = { | 619 | static const struct rpc_program cb_program = { |
620 | .name = "nfs4_cb", | 620 | .name = "nfs4_cb", |
621 | .number = NFS4_CALLBACK, | 621 | .number = NFS4_CALLBACK, |
622 | .nrvers = ARRAY_SIZE(nfs_cb_version), | 622 | .nrvers = ARRAY_SIZE(nfs_cb_version), |
623 | .version = nfs_cb_version, | 623 | .version = nfs_cb_version, |
624 | .stats = &cb_stats, | 624 | .stats = &cb_stats, |
625 | .pipe_dir_name = "nfsd4_cb", | 625 | .pipe_dir_name = "nfsd4_cb", |
626 | }; | 626 | }; |
627 | 627 | ||
628 | static int max_cb_time(void) | 628 | static int max_cb_time(void) |
629 | { | 629 | { |
630 | return max(nfsd4_lease/10, (time_t)1) * HZ; | 630 | return max(nfsd4_lease/10, (time_t)1) * HZ; |
631 | } | 631 | } |
632 | 632 | ||
633 | 633 | ||
634 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) | 634 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) |
635 | { | 635 | { |
636 | struct rpc_timeout timeparms = { | 636 | struct rpc_timeout timeparms = { |
637 | .to_initval = max_cb_time(), | 637 | .to_initval = max_cb_time(), |
638 | .to_retries = 0, | 638 | .to_retries = 0, |
639 | }; | 639 | }; |
640 | struct rpc_create_args args = { | 640 | struct rpc_create_args args = { |
641 | .net = &init_net, | 641 | .net = &init_net, |
642 | .address = (struct sockaddr *) &conn->cb_addr, | 642 | .address = (struct sockaddr *) &conn->cb_addr, |
643 | .addrsize = conn->cb_addrlen, | 643 | .addrsize = conn->cb_addrlen, |
644 | .saddress = (struct sockaddr *) &conn->cb_saddr, | 644 | .saddress = (struct sockaddr *) &conn->cb_saddr, |
645 | .timeout = &timeparms, | 645 | .timeout = &timeparms, |
646 | .program = &cb_program, | 646 | .program = &cb_program, |
647 | .version = 0, | 647 | .version = 0, |
648 | .authflavor = clp->cl_flavor, | 648 | .authflavor = clp->cl_flavor, |
649 | .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), | 649 | .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), |
650 | }; | 650 | }; |
651 | struct rpc_clnt *client; | 651 | struct rpc_clnt *client; |
652 | 652 | ||
653 | if (clp->cl_minorversion == 0) { | 653 | if (clp->cl_minorversion == 0) { |
654 | if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) | 654 | if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) |
655 | return -EINVAL; | 655 | return -EINVAL; |
656 | args.client_name = clp->cl_principal; | 656 | args.client_name = clp->cl_principal; |
657 | args.prognumber = conn->cb_prog, | 657 | args.prognumber = conn->cb_prog, |
658 | args.protocol = XPRT_TRANSPORT_TCP; | 658 | args.protocol = XPRT_TRANSPORT_TCP; |
659 | clp->cl_cb_ident = conn->cb_ident; | 659 | clp->cl_cb_ident = conn->cb_ident; |
660 | } else { | 660 | } else { |
661 | if (!conn->cb_xprt) | 661 | if (!conn->cb_xprt) |
662 | return -EINVAL; | 662 | return -EINVAL; |
663 | clp->cl_cb_conn.cb_xprt = conn->cb_xprt; | 663 | clp->cl_cb_conn.cb_xprt = conn->cb_xprt; |
664 | clp->cl_cb_session = ses; | 664 | clp->cl_cb_session = ses; |
665 | args.bc_xprt = conn->cb_xprt; | 665 | args.bc_xprt = conn->cb_xprt; |
666 | args.prognumber = clp->cl_cb_session->se_cb_prog; | 666 | args.prognumber = clp->cl_cb_session->se_cb_prog; |
667 | args.protocol = XPRT_TRANSPORT_BC_TCP; | 667 | args.protocol = XPRT_TRANSPORT_BC_TCP; |
668 | } | 668 | } |
669 | /* Create RPC client */ | 669 | /* Create RPC client */ |
670 | client = rpc_create(&args); | 670 | client = rpc_create(&args); |
671 | if (IS_ERR(client)) { | 671 | if (IS_ERR(client)) { |
672 | dprintk("NFSD: couldn't create callback client: %ld\n", | 672 | dprintk("NFSD: couldn't create callback client: %ld\n", |
673 | PTR_ERR(client)); | 673 | PTR_ERR(client)); |
674 | return PTR_ERR(client); | 674 | return PTR_ERR(client); |
675 | } | 675 | } |
676 | clp->cl_cb_client = client; | 676 | clp->cl_cb_client = client; |
677 | return 0; | 677 | return 0; |
678 | 678 | ||
679 | } | 679 | } |
680 | 680 | ||
681 | static void warn_no_callback_path(struct nfs4_client *clp, int reason) | 681 | static void warn_no_callback_path(struct nfs4_client *clp, int reason) |
682 | { | 682 | { |
683 | dprintk("NFSD: warning: no callback path to client %.*s: error %d\n", | 683 | dprintk("NFSD: warning: no callback path to client %.*s: error %d\n", |
684 | (int)clp->cl_name.len, clp->cl_name.data, reason); | 684 | (int)clp->cl_name.len, clp->cl_name.data, reason); |
685 | } | 685 | } |
686 | 686 | ||
687 | static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason) | 687 | static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason) |
688 | { | 688 | { |
689 | clp->cl_cb_state = NFSD4_CB_DOWN; | 689 | clp->cl_cb_state = NFSD4_CB_DOWN; |
690 | warn_no_callback_path(clp, reason); | 690 | warn_no_callback_path(clp, reason); |
691 | } | 691 | } |
692 | 692 | ||
693 | static void nfsd4_mark_cb_fault(struct nfs4_client *clp, int reason) | 693 | static void nfsd4_mark_cb_fault(struct nfs4_client *clp, int reason) |
694 | { | 694 | { |
695 | clp->cl_cb_state = NFSD4_CB_FAULT; | 695 | clp->cl_cb_state = NFSD4_CB_FAULT; |
696 | warn_no_callback_path(clp, reason); | 696 | warn_no_callback_path(clp, reason); |
697 | } | 697 | } |
698 | 698 | ||
699 | static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) | 699 | static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) |
700 | { | 700 | { |
701 | struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); | 701 | struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); |
702 | 702 | ||
703 | if (task->tk_status) | 703 | if (task->tk_status) |
704 | nfsd4_mark_cb_down(clp, task->tk_status); | 704 | nfsd4_mark_cb_down(clp, task->tk_status); |
705 | else | 705 | else |
706 | clp->cl_cb_state = NFSD4_CB_UP; | 706 | clp->cl_cb_state = NFSD4_CB_UP; |
707 | } | 707 | } |
708 | 708 | ||
709 | static const struct rpc_call_ops nfsd4_cb_probe_ops = { | 709 | static const struct rpc_call_ops nfsd4_cb_probe_ops = { |
710 | /* XXX: release method to ensure we set the cb channel down if | 710 | /* XXX: release method to ensure we set the cb channel down if |
711 | * necessary on early failure? */ | 711 | * necessary on early failure? */ |
712 | .rpc_call_done = nfsd4_cb_probe_done, | 712 | .rpc_call_done = nfsd4_cb_probe_done, |
713 | }; | 713 | }; |
714 | 714 | ||
715 | static struct rpc_cred *callback_cred; | 715 | static struct rpc_cred *callback_cred; |
716 | 716 | ||
717 | int set_callback_cred(void) | 717 | int set_callback_cred(void) |
718 | { | 718 | { |
719 | if (callback_cred) | 719 | if (callback_cred) |
720 | return 0; | 720 | return 0; |
721 | callback_cred = rpc_lookup_machine_cred("nfs"); | 721 | callback_cred = rpc_lookup_machine_cred("nfs"); |
722 | if (!callback_cred) | 722 | if (!callback_cred) |
723 | return -ENOMEM; | 723 | return -ENOMEM; |
724 | return 0; | 724 | return 0; |
725 | } | 725 | } |
726 | 726 | ||
727 | static struct workqueue_struct *callback_wq; | 727 | static struct workqueue_struct *callback_wq; |
728 | 728 | ||
729 | static void run_nfsd4_cb(struct nfsd4_callback *cb) | 729 | static void run_nfsd4_cb(struct nfsd4_callback *cb) |
730 | { | 730 | { |
731 | queue_work(callback_wq, &cb->cb_work); | 731 | queue_work(callback_wq, &cb->cb_work); |
732 | } | 732 | } |
733 | 733 | ||
734 | static void do_probe_callback(struct nfs4_client *clp) | 734 | static void do_probe_callback(struct nfs4_client *clp) |
735 | { | 735 | { |
736 | struct nfsd4_callback *cb = &clp->cl_cb_null; | 736 | struct nfsd4_callback *cb = &clp->cl_cb_null; |
737 | 737 | ||
738 | cb->cb_op = NULL; | 738 | cb->cb_op = NULL; |
739 | cb->cb_clp = clp; | 739 | cb->cb_clp = clp; |
740 | 740 | ||
741 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL]; | 741 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL]; |
742 | cb->cb_msg.rpc_argp = NULL; | 742 | cb->cb_msg.rpc_argp = NULL; |
743 | cb->cb_msg.rpc_resp = NULL; | 743 | cb->cb_msg.rpc_resp = NULL; |
744 | cb->cb_msg.rpc_cred = callback_cred; | 744 | cb->cb_msg.rpc_cred = callback_cred; |
745 | 745 | ||
746 | cb->cb_ops = &nfsd4_cb_probe_ops; | 746 | cb->cb_ops = &nfsd4_cb_probe_ops; |
747 | 747 | ||
748 | run_nfsd4_cb(cb); | 748 | run_nfsd4_cb(cb); |
749 | } | 749 | } |
750 | 750 | ||
751 | /* | 751 | /* |
752 | * Poke the callback thread to process any updates to the callback | 752 | * Poke the callback thread to process any updates to the callback |
753 | * parameters, and send a null probe. | 753 | * parameters, and send a null probe. |
754 | */ | 754 | */ |
755 | void nfsd4_probe_callback(struct nfs4_client *clp) | 755 | void nfsd4_probe_callback(struct nfs4_client *clp) |
756 | { | 756 | { |
757 | /* XXX: atomicity? Also, should we be using cl_cb_flags? */ | 757 | /* XXX: atomicity? Also, should we be using cl_cb_flags? */ |
758 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; | 758 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
759 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); | 759 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); |
760 | do_probe_callback(clp); | 760 | do_probe_callback(clp); |
761 | } | 761 | } |
762 | 762 | ||
763 | void nfsd4_probe_callback_sync(struct nfs4_client *clp) | 763 | void nfsd4_probe_callback_sync(struct nfs4_client *clp) |
764 | { | 764 | { |
765 | nfsd4_probe_callback(clp); | 765 | nfsd4_probe_callback(clp); |
766 | flush_workqueue(callback_wq); | 766 | flush_workqueue(callback_wq); |
767 | } | 767 | } |
768 | 768 | ||
769 | void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) | 769 | void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) |
770 | { | 770 | { |
771 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; | 771 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
772 | spin_lock(&clp->cl_lock); | 772 | spin_lock(&clp->cl_lock); |
773 | memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn)); | 773 | memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn)); |
774 | spin_unlock(&clp->cl_lock); | 774 | spin_unlock(&clp->cl_lock); |
775 | } | 775 | } |
776 | 776 | ||
777 | /* | 777 | /* |
778 | * There's currently a single callback channel slot. | 778 | * There's currently a single callback channel slot. |
779 | * If the slot is available, then mark it busy. Otherwise, set the | 779 | * If the slot is available, then mark it busy. Otherwise, set the |
780 | * thread for sleeping on the callback RPC wait queue. | 780 | * thread for sleeping on the callback RPC wait queue. |
781 | */ | 781 | */ |
782 | static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) | 782 | static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) |
783 | { | 783 | { |
784 | if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { | 784 | if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { |
785 | rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); | 785 | rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); |
786 | dprintk("%s slot is busy\n", __func__); | 786 | dprintk("%s slot is busy\n", __func__); |
787 | return false; | 787 | return false; |
788 | } | 788 | } |
789 | return true; | 789 | return true; |
790 | } | 790 | } |
791 | 791 | ||
792 | /* | 792 | /* |
793 | * TODO: cb_sequence should support referring call lists, cachethis, multiple | 793 | * TODO: cb_sequence should support referring call lists, cachethis, multiple |
794 | * slots, and mark callback channel down on communication errors. | 794 | * slots, and mark callback channel down on communication errors. |
795 | */ | 795 | */ |
796 | static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata) | 796 | static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata) |
797 | { | 797 | { |
798 | struct nfsd4_callback *cb = calldata; | 798 | struct nfsd4_callback *cb = calldata; |
799 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); | 799 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); |
800 | struct nfs4_client *clp = dp->dl_stid.sc_client; | 800 | struct nfs4_client *clp = dp->dl_stid.sc_client; |
801 | u32 minorversion = clp->cl_minorversion; | 801 | u32 minorversion = clp->cl_minorversion; |
802 | 802 | ||
803 | cb->cb_minorversion = minorversion; | 803 | cb->cb_minorversion = minorversion; |
804 | if (minorversion) { | 804 | if (minorversion) { |
805 | if (!nfsd41_cb_get_slot(clp, task)) | 805 | if (!nfsd41_cb_get_slot(clp, task)) |
806 | return; | 806 | return; |
807 | } | 807 | } |
808 | spin_lock(&clp->cl_lock); | 808 | spin_lock(&clp->cl_lock); |
809 | if (list_empty(&cb->cb_per_client)) { | 809 | if (list_empty(&cb->cb_per_client)) { |
810 | /* This is the first call, not a restart */ | 810 | /* This is the first call, not a restart */ |
811 | cb->cb_done = false; | 811 | cb->cb_done = false; |
812 | list_add(&cb->cb_per_client, &clp->cl_callbacks); | 812 | list_add(&cb->cb_per_client, &clp->cl_callbacks); |
813 | } | 813 | } |
814 | spin_unlock(&clp->cl_lock); | 814 | spin_unlock(&clp->cl_lock); |
815 | rpc_call_start(task); | 815 | rpc_call_start(task); |
816 | } | 816 | } |
817 | 817 | ||
818 | static void nfsd4_cb_done(struct rpc_task *task, void *calldata) | 818 | static void nfsd4_cb_done(struct rpc_task *task, void *calldata) |
819 | { | 819 | { |
820 | struct nfsd4_callback *cb = calldata; | 820 | struct nfsd4_callback *cb = calldata; |
821 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); | 821 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); |
822 | struct nfs4_client *clp = dp->dl_stid.sc_client; | 822 | struct nfs4_client *clp = dp->dl_stid.sc_client; |
823 | 823 | ||
824 | dprintk("%s: minorversion=%d\n", __func__, | 824 | dprintk("%s: minorversion=%d\n", __func__, |
825 | clp->cl_minorversion); | 825 | clp->cl_minorversion); |
826 | 826 | ||
827 | if (clp->cl_minorversion) { | 827 | if (clp->cl_minorversion) { |
828 | /* No need for lock, access serialized in nfsd4_cb_prepare */ | 828 | /* No need for lock, access serialized in nfsd4_cb_prepare */ |
829 | ++clp->cl_cb_session->se_cb_seq_nr; | 829 | ++clp->cl_cb_session->se_cb_seq_nr; |
830 | clear_bit(0, &clp->cl_cb_slot_busy); | 830 | clear_bit(0, &clp->cl_cb_slot_busy); |
831 | rpc_wake_up_next(&clp->cl_cb_waitq); | 831 | rpc_wake_up_next(&clp->cl_cb_waitq); |
832 | dprintk("%s: freed slot, new seqid=%d\n", __func__, | 832 | dprintk("%s: freed slot, new seqid=%d\n", __func__, |
833 | clp->cl_cb_session->se_cb_seq_nr); | 833 | clp->cl_cb_session->se_cb_seq_nr); |
834 | 834 | ||
835 | /* We're done looking into the sequence information */ | 835 | /* We're done looking into the sequence information */ |
836 | task->tk_msg.rpc_resp = NULL; | 836 | task->tk_msg.rpc_resp = NULL; |
837 | } | 837 | } |
838 | } | 838 | } |
839 | 839 | ||
840 | 840 | ||
841 | static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) | 841 | static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) |
842 | { | 842 | { |
843 | struct nfsd4_callback *cb = calldata; | 843 | struct nfsd4_callback *cb = calldata; |
844 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); | 844 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); |
845 | struct nfs4_client *clp = dp->dl_stid.sc_client; | 845 | struct nfs4_client *clp = dp->dl_stid.sc_client; |
846 | struct rpc_clnt *current_rpc_client = clp->cl_cb_client; | 846 | struct rpc_clnt *current_rpc_client = clp->cl_cb_client; |
847 | 847 | ||
848 | nfsd4_cb_done(task, calldata); | 848 | nfsd4_cb_done(task, calldata); |
849 | 849 | ||
850 | if (current_rpc_client != task->tk_client) { | 850 | if (current_rpc_client != task->tk_client) { |
851 | /* We're shutting down or changing cl_cb_client; leave | 851 | /* We're shutting down or changing cl_cb_client; leave |
852 | * it to nfsd4_process_cb_update to restart the call if | 852 | * it to nfsd4_process_cb_update to restart the call if |
853 | * necessary. */ | 853 | * necessary. */ |
854 | return; | 854 | return; |
855 | } | 855 | } |
856 | 856 | ||
857 | if (cb->cb_done) | 857 | if (cb->cb_done) |
858 | return; | 858 | return; |
859 | switch (task->tk_status) { | 859 | switch (task->tk_status) { |
860 | case 0: | 860 | case 0: |
861 | cb->cb_done = true; | 861 | cb->cb_done = true; |
862 | return; | 862 | return; |
863 | case -EBADHANDLE: | 863 | case -EBADHANDLE: |
864 | case -NFS4ERR_BAD_STATEID: | 864 | case -NFS4ERR_BAD_STATEID: |
865 | /* Race: client probably got cb_recall | 865 | /* Race: client probably got cb_recall |
866 | * before open reply granting delegation */ | 866 | * before open reply granting delegation */ |
867 | break; | 867 | break; |
868 | default: | 868 | default: |
869 | /* Network partition? */ | 869 | /* Network partition? */ |
870 | nfsd4_mark_cb_down(clp, task->tk_status); | 870 | nfsd4_mark_cb_down(clp, task->tk_status); |
871 | } | 871 | } |
872 | if (dp->dl_retries--) { | 872 | if (dp->dl_retries--) { |
873 | rpc_delay(task, 2*HZ); | 873 | rpc_delay(task, 2*HZ); |
874 | task->tk_status = 0; | 874 | task->tk_status = 0; |
875 | rpc_restart_call_prepare(task); | 875 | rpc_restart_call_prepare(task); |
876 | return; | 876 | return; |
877 | } | 877 | } |
878 | nfsd4_mark_cb_down(clp, task->tk_status); | 878 | nfsd4_mark_cb_down(clp, task->tk_status); |
879 | cb->cb_done = true; | 879 | cb->cb_done = true; |
880 | } | 880 | } |
881 | 881 | ||
882 | static void nfsd4_cb_recall_release(void *calldata) | 882 | static void nfsd4_cb_recall_release(void *calldata) |
883 | { | 883 | { |
884 | struct nfsd4_callback *cb = calldata; | 884 | struct nfsd4_callback *cb = calldata; |
885 | struct nfs4_client *clp = cb->cb_clp; | 885 | struct nfs4_client *clp = cb->cb_clp; |
886 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); | 886 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); |
887 | 887 | ||
888 | if (cb->cb_done) { | 888 | if (cb->cb_done) { |
889 | spin_lock(&clp->cl_lock); | 889 | spin_lock(&clp->cl_lock); |
890 | list_del(&cb->cb_per_client); | 890 | list_del(&cb->cb_per_client); |
891 | spin_unlock(&clp->cl_lock); | 891 | spin_unlock(&clp->cl_lock); |
892 | nfs4_put_delegation(dp); | 892 | nfs4_put_delegation(dp); |
893 | } | 893 | } |
894 | } | 894 | } |
895 | 895 | ||
896 | static const struct rpc_call_ops nfsd4_cb_recall_ops = { | 896 | static const struct rpc_call_ops nfsd4_cb_recall_ops = { |
897 | .rpc_call_prepare = nfsd4_cb_prepare, | 897 | .rpc_call_prepare = nfsd4_cb_prepare, |
898 | .rpc_call_done = nfsd4_cb_recall_done, | 898 | .rpc_call_done = nfsd4_cb_recall_done, |
899 | .rpc_release = nfsd4_cb_recall_release, | 899 | .rpc_release = nfsd4_cb_recall_release, |
900 | }; | 900 | }; |
901 | 901 | ||
902 | int nfsd4_create_callback_queue(void) | 902 | int nfsd4_create_callback_queue(void) |
903 | { | 903 | { |
904 | callback_wq = create_singlethread_workqueue("nfsd4_callbacks"); | 904 | callback_wq = create_singlethread_workqueue("nfsd4_callbacks"); |
905 | if (!callback_wq) | 905 | if (!callback_wq) |
906 | return -ENOMEM; | 906 | return -ENOMEM; |
907 | return 0; | 907 | return 0; |
908 | } | 908 | } |
909 | 909 | ||
910 | void nfsd4_destroy_callback_queue(void) | 910 | void nfsd4_destroy_callback_queue(void) |
911 | { | 911 | { |
912 | destroy_workqueue(callback_wq); | 912 | destroy_workqueue(callback_wq); |
913 | } | 913 | } |
914 | 914 | ||
915 | /* must be called under the state lock */ | 915 | /* must be called under the state lock */ |
916 | void nfsd4_shutdown_callback(struct nfs4_client *clp) | 916 | void nfsd4_shutdown_callback(struct nfs4_client *clp) |
917 | { | 917 | { |
918 | set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags); | 918 | set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags); |
919 | /* | 919 | /* |
920 | * Note this won't actually result in a null callback; | 920 | * Note this won't actually result in a null callback; |
921 | * instead, nfsd4_do_callback_rpc() will detect the killed | 921 | * instead, nfsd4_do_callback_rpc() will detect the killed |
922 | * client, destroy the rpc client, and stop: | 922 | * client, destroy the rpc client, and stop: |
923 | */ | 923 | */ |
924 | do_probe_callback(clp); | 924 | do_probe_callback(clp); |
925 | flush_workqueue(callback_wq); | 925 | flush_workqueue(callback_wq); |
926 | } | 926 | } |
927 | 927 | ||
928 | static void nfsd4_release_cb(struct nfsd4_callback *cb) | 928 | static void nfsd4_release_cb(struct nfsd4_callback *cb) |
929 | { | 929 | { |
930 | if (cb->cb_ops->rpc_release) | 930 | if (cb->cb_ops->rpc_release) |
931 | cb->cb_ops->rpc_release(cb); | 931 | cb->cb_ops->rpc_release(cb); |
932 | } | 932 | } |
933 | 933 | ||
934 | /* requires cl_lock: */ | 934 | /* requires cl_lock: */ |
935 | static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp) | 935 | static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp) |
936 | { | 936 | { |
937 | struct nfsd4_session *s; | 937 | struct nfsd4_session *s; |
938 | struct nfsd4_conn *c; | 938 | struct nfsd4_conn *c; |
939 | 939 | ||
940 | list_for_each_entry(s, &clp->cl_sessions, se_perclnt) { | 940 | list_for_each_entry(s, &clp->cl_sessions, se_perclnt) { |
941 | list_for_each_entry(c, &s->se_conns, cn_persession) { | 941 | list_for_each_entry(c, &s->se_conns, cn_persession) { |
942 | if (c->cn_flags & NFS4_CDFC4_BACK) | 942 | if (c->cn_flags & NFS4_CDFC4_BACK) |
943 | return c; | 943 | return c; |
944 | } | 944 | } |
945 | } | 945 | } |
946 | return NULL; | 946 | return NULL; |
947 | } | 947 | } |
948 | 948 | ||
949 | static void nfsd4_process_cb_update(struct nfsd4_callback *cb) | 949 | static void nfsd4_process_cb_update(struct nfsd4_callback *cb) |
950 | { | 950 | { |
951 | struct nfs4_cb_conn conn; | 951 | struct nfs4_cb_conn conn; |
952 | struct nfs4_client *clp = cb->cb_clp; | 952 | struct nfs4_client *clp = cb->cb_clp; |
953 | struct nfsd4_session *ses = NULL; | 953 | struct nfsd4_session *ses = NULL; |
954 | struct nfsd4_conn *c; | 954 | struct nfsd4_conn *c; |
955 | int err; | 955 | int err; |
956 | 956 | ||
957 | /* | 957 | /* |
958 | * This is either an update, or the client dying; in either case, | 958 | * This is either an update, or the client dying; in either case, |
959 | * kill the old client: | 959 | * kill the old client: |
960 | */ | 960 | */ |
961 | if (clp->cl_cb_client) { | 961 | if (clp->cl_cb_client) { |
962 | rpc_shutdown_client(clp->cl_cb_client); | 962 | rpc_shutdown_client(clp->cl_cb_client); |
963 | clp->cl_cb_client = NULL; | 963 | clp->cl_cb_client = NULL; |
964 | } | 964 | } |
965 | if (clp->cl_cb_conn.cb_xprt) { | 965 | if (clp->cl_cb_conn.cb_xprt) { |
966 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); | 966 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); |
967 | clp->cl_cb_conn.cb_xprt = NULL; | 967 | clp->cl_cb_conn.cb_xprt = NULL; |
968 | } | 968 | } |
969 | if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags)) | 969 | if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags)) |
970 | return; | 970 | return; |
971 | spin_lock(&clp->cl_lock); | 971 | spin_lock(&clp->cl_lock); |
972 | /* | 972 | /* |
973 | * Only serialized callback code is allowed to clear these | 973 | * Only serialized callback code is allowed to clear these |
974 | * flags; main nfsd code can only set them: | 974 | * flags; main nfsd code can only set them: |
975 | */ | 975 | */ |
976 | BUG_ON(!clp->cl_cb_flags); | 976 | BUG_ON(!clp->cl_cb_flags); |
977 | clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); | 977 | clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); |
978 | memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); | 978 | memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); |
979 | c = __nfsd4_find_backchannel(clp); | 979 | c = __nfsd4_find_backchannel(clp); |
980 | if (c) { | 980 | if (c) { |
981 | svc_xprt_get(c->cn_xprt); | 981 | svc_xprt_get(c->cn_xprt); |
982 | conn.cb_xprt = c->cn_xprt; | 982 | conn.cb_xprt = c->cn_xprt; |
983 | ses = c->cn_session; | 983 | ses = c->cn_session; |
984 | } | 984 | } |
985 | spin_unlock(&clp->cl_lock); | 985 | spin_unlock(&clp->cl_lock); |
986 | 986 | ||
987 | err = setup_callback_client(clp, &conn, ses); | 987 | err = setup_callback_client(clp, &conn, ses); |
988 | if (err) { | 988 | if (err) { |
989 | warn_no_callback_path(clp, err); | 989 | warn_no_callback_path(clp, err); |
990 | return; | 990 | return; |
991 | } | 991 | } |
992 | /* Yay, the callback channel's back! Restart any callbacks: */ | 992 | /* Yay, the callback channel's back! Restart any callbacks: */ |
993 | list_for_each_entry(cb, &clp->cl_callbacks, cb_per_client) | 993 | list_for_each_entry(cb, &clp->cl_callbacks, cb_per_client) |
994 | run_nfsd4_cb(cb); | 994 | run_nfsd4_cb(cb); |
995 | } | 995 | } |
996 | 996 | ||
997 | void nfsd4_do_callback_rpc(struct work_struct *w) | 997 | void nfsd4_do_callback_rpc(struct work_struct *w) |
998 | { | 998 | { |
999 | struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work); | 999 | struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work); |
1000 | struct nfs4_client *clp = cb->cb_clp; | 1000 | struct nfs4_client *clp = cb->cb_clp; |
1001 | struct rpc_clnt *clnt; | 1001 | struct rpc_clnt *clnt; |
1002 | 1002 | ||
1003 | if (clp->cl_cb_flags) | 1003 | if (clp->cl_cb_flags) |
1004 | nfsd4_process_cb_update(cb); | 1004 | nfsd4_process_cb_update(cb); |
1005 | 1005 | ||
1006 | clnt = clp->cl_cb_client; | 1006 | clnt = clp->cl_cb_client; |
1007 | if (!clnt) { | 1007 | if (!clnt) { |
1008 | /* Callback channel broken, or client killed; give up: */ | 1008 | /* Callback channel broken, or client killed; give up: */ |
1009 | nfsd4_release_cb(cb); | 1009 | nfsd4_release_cb(cb); |
1010 | return; | 1010 | return; |
1011 | } | 1011 | } |
1012 | rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN, | 1012 | rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN, |
1013 | cb->cb_ops, cb); | 1013 | cb->cb_ops, cb); |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | void nfsd4_cb_recall(struct nfs4_delegation *dp) | 1016 | void nfsd4_cb_recall(struct nfs4_delegation *dp) |
1017 | { | 1017 | { |
1018 | struct nfsd4_callback *cb = &dp->dl_recall; | 1018 | struct nfsd4_callback *cb = &dp->dl_recall; |
1019 | struct nfs4_client *clp = dp->dl_stid.sc_client; | 1019 | struct nfs4_client *clp = dp->dl_stid.sc_client; |
1020 | 1020 | ||
1021 | dp->dl_retries = 1; | 1021 | dp->dl_retries = 1; |
1022 | cb->cb_op = dp; | 1022 | cb->cb_op = dp; |
1023 | cb->cb_clp = clp; | 1023 | cb->cb_clp = clp; |
1024 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL]; | 1024 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL]; |
1025 | cb->cb_msg.rpc_argp = cb; | 1025 | cb->cb_msg.rpc_argp = cb; |
1026 | cb->cb_msg.rpc_resp = cb; | 1026 | cb->cb_msg.rpc_resp = cb; |
1027 | cb->cb_msg.rpc_cred = callback_cred; | 1027 | cb->cb_msg.rpc_cred = callback_cred; |
1028 | 1028 | ||
1029 | cb->cb_ops = &nfsd4_cb_recall_ops; | 1029 | cb->cb_ops = &nfsd4_cb_recall_ops; |
1030 | dp->dl_retries = 1; | 1030 | dp->dl_retries = 1; |
1031 | 1031 | ||
1032 | INIT_LIST_HEAD(&cb->cb_per_client); | 1032 | INIT_LIST_HEAD(&cb->cb_per_client); |
1033 | cb->cb_done = true; | 1033 | cb->cb_done = true; |
1034 | 1034 | ||
1035 | run_nfsd4_cb(&dp->dl_recall); | 1035 | run_nfsd4_cb(&dp->dl_recall); |
1036 | } | 1036 | } |
1037 | 1037 |
include/linux/lockd/lockd.h
1 | /* | 1 | /* |
2 | * linux/include/linux/lockd/lockd.h | 2 | * linux/include/linux/lockd/lockd.h |
3 | * | 3 | * |
4 | * General-purpose lockd include file. | 4 | * General-purpose lockd include file. |
5 | * | 5 | * |
6 | * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef LINUX_LOCKD_LOCKD_H | 9 | #ifndef LINUX_LOCKD_LOCKD_H |
10 | #define LINUX_LOCKD_LOCKD_H | 10 | #define LINUX_LOCKD_LOCKD_H |
11 | 11 | ||
12 | #ifdef __KERNEL__ | 12 | #ifdef __KERNEL__ |
13 | 13 | ||
14 | #include <linux/in.h> | 14 | #include <linux/in.h> |
15 | #include <linux/in6.h> | 15 | #include <linux/in6.h> |
16 | #include <net/ipv6.h> | 16 | #include <net/ipv6.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/kref.h> | 18 | #include <linux/kref.h> |
19 | #include <linux/utsname.h> | 19 | #include <linux/utsname.h> |
20 | #include <linux/nfsd/nfsfh.h> | 20 | #include <linux/nfsd/nfsfh.h> |
21 | #include <linux/lockd/bind.h> | 21 | #include <linux/lockd/bind.h> |
22 | #include <linux/lockd/xdr.h> | 22 | #include <linux/lockd/xdr.h> |
23 | #ifdef CONFIG_LOCKD_V4 | 23 | #ifdef CONFIG_LOCKD_V4 |
24 | #include <linux/lockd/xdr4.h> | 24 | #include <linux/lockd/xdr4.h> |
25 | #endif | 25 | #endif |
26 | #include <linux/lockd/debug.h> | 26 | #include <linux/lockd/debug.h> |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * Version string | 29 | * Version string |
30 | */ | 30 | */ |
31 | #define LOCKD_VERSION "0.5" | 31 | #define LOCKD_VERSION "0.5" |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Default timeout for RPC calls (seconds) | 34 | * Default timeout for RPC calls (seconds) |
35 | */ | 35 | */ |
36 | #define LOCKD_DFLT_TIMEO 10 | 36 | #define LOCKD_DFLT_TIMEO 10 |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Lockd host handle (used both by the client and server personality). | 39 | * Lockd host handle (used both by the client and server personality). |
40 | */ | 40 | */ |
41 | struct nlm_host { | 41 | struct nlm_host { |
42 | struct hlist_node h_hash; /* doubly linked list */ | 42 | struct hlist_node h_hash; /* doubly linked list */ |
43 | struct sockaddr_storage h_addr; /* peer address */ | 43 | struct sockaddr_storage h_addr; /* peer address */ |
44 | size_t h_addrlen; | 44 | size_t h_addrlen; |
45 | struct sockaddr_storage h_srcaddr; /* our address (optional) */ | 45 | struct sockaddr_storage h_srcaddr; /* our address (optional) */ |
46 | size_t h_srcaddrlen; | 46 | size_t h_srcaddrlen; |
47 | struct rpc_clnt *h_rpcclnt; /* RPC client to talk to peer */ | 47 | struct rpc_clnt *h_rpcclnt; /* RPC client to talk to peer */ |
48 | char *h_name; /* remote hostname */ | 48 | char *h_name; /* remote hostname */ |
49 | u32 h_version; /* interface version */ | 49 | u32 h_version; /* interface version */ |
50 | unsigned short h_proto; /* transport proto */ | 50 | unsigned short h_proto; /* transport proto */ |
51 | unsigned short h_reclaiming : 1, | 51 | unsigned short h_reclaiming : 1, |
52 | h_server : 1, /* server side, not client side */ | 52 | h_server : 1, /* server side, not client side */ |
53 | h_noresvport : 1, | 53 | h_noresvport : 1, |
54 | h_inuse : 1; | 54 | h_inuse : 1; |
55 | wait_queue_head_t h_gracewait; /* wait while reclaiming */ | 55 | wait_queue_head_t h_gracewait; /* wait while reclaiming */ |
56 | struct rw_semaphore h_rwsem; /* Reboot recovery lock */ | 56 | struct rw_semaphore h_rwsem; /* Reboot recovery lock */ |
57 | u32 h_state; /* pseudo-state counter */ | 57 | u32 h_state; /* pseudo-state counter */ |
58 | u32 h_nsmstate; /* true remote NSM state */ | 58 | u32 h_nsmstate; /* true remote NSM state */ |
59 | u32 h_pidcount; /* Pseudopids */ | 59 | u32 h_pidcount; /* Pseudopids */ |
60 | atomic_t h_count; /* reference count */ | 60 | atomic_t h_count; /* reference count */ |
61 | struct mutex h_mutex; /* mutex for pmap binding */ | 61 | struct mutex h_mutex; /* mutex for pmap binding */ |
62 | unsigned long h_nextrebind; /* next portmap call */ | 62 | unsigned long h_nextrebind; /* next portmap call */ |
63 | unsigned long h_expires; /* eligible for GC */ | 63 | unsigned long h_expires; /* eligible for GC */ |
64 | struct list_head h_lockowners; /* Lockowners for the client */ | 64 | struct list_head h_lockowners; /* Lockowners for the client */ |
65 | spinlock_t h_lock; | 65 | spinlock_t h_lock; |
66 | struct list_head h_granted; /* Locks in GRANTED state */ | 66 | struct list_head h_granted; /* Locks in GRANTED state */ |
67 | struct list_head h_reclaim; /* Locks in RECLAIM state */ | 67 | struct list_head h_reclaim; /* Locks in RECLAIM state */ |
68 | struct nsm_handle *h_nsmhandle; /* NSM status handle */ | 68 | struct nsm_handle *h_nsmhandle; /* NSM status handle */ |
69 | char *h_addrbuf; /* address eyecatcher */ | 69 | char *h_addrbuf; /* address eyecatcher */ |
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * The largest string sm_addrbuf should hold is a full-size IPv6 address | 73 | * The largest string sm_addrbuf should hold is a full-size IPv6 address |
74 | * (no "::" anywhere) with a scope ID. The buffer size is computed to | 74 | * (no "::" anywhere) with a scope ID. The buffer size is computed to |
75 | * hold eight groups of colon-separated four-hex-digit numbers, a | 75 | * hold eight groups of colon-separated four-hex-digit numbers, a |
76 | * percent sign, a scope id (at most 32 bits, in decimal), and NUL. | 76 | * percent sign, a scope id (at most 32 bits, in decimal), and NUL. |
77 | */ | 77 | */ |
78 | #define NSM_ADDRBUF ((8 * 4 + 7) + (1 + 10) + 1) | 78 | #define NSM_ADDRBUF ((8 * 4 + 7) + (1 + 10) + 1) |
79 | 79 | ||
80 | struct nsm_handle { | 80 | struct nsm_handle { |
81 | struct list_head sm_link; | 81 | struct list_head sm_link; |
82 | atomic_t sm_count; | 82 | atomic_t sm_count; |
83 | char *sm_mon_name; | 83 | char *sm_mon_name; |
84 | char *sm_name; | 84 | char *sm_name; |
85 | struct sockaddr_storage sm_addr; | 85 | struct sockaddr_storage sm_addr; |
86 | size_t sm_addrlen; | 86 | size_t sm_addrlen; |
87 | unsigned int sm_monitored : 1, | 87 | unsigned int sm_monitored : 1, |
88 | sm_sticky : 1; /* don't unmonitor */ | 88 | sm_sticky : 1; /* don't unmonitor */ |
89 | struct nsm_private sm_priv; | 89 | struct nsm_private sm_priv; |
90 | char sm_addrbuf[NSM_ADDRBUF]; | 90 | char sm_addrbuf[NSM_ADDRBUF]; |
91 | }; | 91 | }; |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Rigorous type checking on sockaddr type conversions | 94 | * Rigorous type checking on sockaddr type conversions |
95 | */ | 95 | */ |
96 | static inline struct sockaddr_in *nlm_addr_in(const struct nlm_host *host) | 96 | static inline struct sockaddr_in *nlm_addr_in(const struct nlm_host *host) |
97 | { | 97 | { |
98 | return (struct sockaddr_in *)&host->h_addr; | 98 | return (struct sockaddr_in *)&host->h_addr; |
99 | } | 99 | } |
100 | 100 | ||
101 | static inline struct sockaddr *nlm_addr(const struct nlm_host *host) | 101 | static inline struct sockaddr *nlm_addr(const struct nlm_host *host) |
102 | { | 102 | { |
103 | return (struct sockaddr *)&host->h_addr; | 103 | return (struct sockaddr *)&host->h_addr; |
104 | } | 104 | } |
105 | 105 | ||
106 | static inline struct sockaddr_in *nlm_srcaddr_in(const struct nlm_host *host) | 106 | static inline struct sockaddr_in *nlm_srcaddr_in(const struct nlm_host *host) |
107 | { | 107 | { |
108 | return (struct sockaddr_in *)&host->h_srcaddr; | 108 | return (struct sockaddr_in *)&host->h_srcaddr; |
109 | } | 109 | } |
110 | 110 | ||
111 | static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host) | 111 | static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host) |
112 | { | 112 | { |
113 | return (struct sockaddr *)&host->h_srcaddr; | 113 | return (struct sockaddr *)&host->h_srcaddr; |
114 | } | 114 | } |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * Map an fl_owner_t into a unique 32-bit "pid" | 117 | * Map an fl_owner_t into a unique 32-bit "pid" |
118 | */ | 118 | */ |
119 | struct nlm_lockowner { | 119 | struct nlm_lockowner { |
120 | struct list_head list; | 120 | struct list_head list; |
121 | atomic_t count; | 121 | atomic_t count; |
122 | 122 | ||
123 | struct nlm_host *host; | 123 | struct nlm_host *host; |
124 | fl_owner_t owner; | 124 | fl_owner_t owner; |
125 | uint32_t pid; | 125 | uint32_t pid; |
126 | }; | 126 | }; |
127 | 127 | ||
128 | struct nlm_wait; | 128 | struct nlm_wait; |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Memory chunk for NLM client RPC request. | 131 | * Memory chunk for NLM client RPC request. |
132 | */ | 132 | */ |
133 | #define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u) | 133 | #define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u) |
134 | struct nlm_rqst { | 134 | struct nlm_rqst { |
135 | atomic_t a_count; | 135 | atomic_t a_count; |
136 | unsigned int a_flags; /* initial RPC task flags */ | 136 | unsigned int a_flags; /* initial RPC task flags */ |
137 | struct nlm_host * a_host; /* host handle */ | 137 | struct nlm_host * a_host; /* host handle */ |
138 | struct nlm_args a_args; /* arguments */ | 138 | struct nlm_args a_args; /* arguments */ |
139 | struct nlm_res a_res; /* result */ | 139 | struct nlm_res a_res; /* result */ |
140 | struct nlm_block * a_block; | 140 | struct nlm_block * a_block; |
141 | unsigned int a_retries; /* Retry count */ | 141 | unsigned int a_retries; /* Retry count */ |
142 | u8 a_owner[NLMCLNT_OHSIZE]; | 142 | u8 a_owner[NLMCLNT_OHSIZE]; |
143 | }; | 143 | }; |
144 | 144 | ||
145 | /* | 145 | /* |
146 | * This struct describes a file held open by lockd on behalf of | 146 | * This struct describes a file held open by lockd on behalf of |
147 | * an NFS client. | 147 | * an NFS client. |
148 | */ | 148 | */ |
149 | struct nlm_file { | 149 | struct nlm_file { |
150 | struct hlist_node f_list; /* linked list */ | 150 | struct hlist_node f_list; /* linked list */ |
151 | struct nfs_fh f_handle; /* NFS file handle */ | 151 | struct nfs_fh f_handle; /* NFS file handle */ |
152 | struct file * f_file; /* VFS file pointer */ | 152 | struct file * f_file; /* VFS file pointer */ |
153 | struct nlm_share * f_shares; /* DOS shares */ | 153 | struct nlm_share * f_shares; /* DOS shares */ |
154 | struct list_head f_blocks; /* blocked locks */ | 154 | struct list_head f_blocks; /* blocked locks */ |
155 | unsigned int f_locks; /* guesstimate # of locks */ | 155 | unsigned int f_locks; /* guesstimate # of locks */ |
156 | unsigned int f_count; /* reference count */ | 156 | unsigned int f_count; /* reference count */ |
157 | struct mutex f_mutex; /* avoid concurrent access */ | 157 | struct mutex f_mutex; /* avoid concurrent access */ |
158 | }; | 158 | }; |
159 | 159 | ||
160 | /* | 160 | /* |
161 | * This is a server block (i.e. a lock requested by some client which | 161 | * This is a server block (i.e. a lock requested by some client which |
162 | * couldn't be granted because of a conflicting lock). | 162 | * couldn't be granted because of a conflicting lock). |
163 | */ | 163 | */ |
164 | #define NLM_NEVER (~(unsigned long) 0) | 164 | #define NLM_NEVER (~(unsigned long) 0) |
165 | /* timeout on non-blocking call: */ | 165 | /* timeout on non-blocking call: */ |
166 | #define NLM_TIMEOUT (7 * HZ) | 166 | #define NLM_TIMEOUT (7 * HZ) |
167 | 167 | ||
168 | struct nlm_block { | 168 | struct nlm_block { |
169 | struct kref b_count; /* Reference count */ | 169 | struct kref b_count; /* Reference count */ |
170 | struct list_head b_list; /* linked list of all blocks */ | 170 | struct list_head b_list; /* linked list of all blocks */ |
171 | struct list_head b_flist; /* linked list (per file) */ | 171 | struct list_head b_flist; /* linked list (per file) */ |
172 | struct nlm_rqst * b_call; /* RPC args & callback info */ | 172 | struct nlm_rqst * b_call; /* RPC args & callback info */ |
173 | struct svc_serv * b_daemon; /* NLM service */ | 173 | struct svc_serv * b_daemon; /* NLM service */ |
174 | struct nlm_host * b_host; /* host handle for RPC clnt */ | 174 | struct nlm_host * b_host; /* host handle for RPC clnt */ |
175 | unsigned long b_when; /* next re-xmit */ | 175 | unsigned long b_when; /* next re-xmit */ |
176 | unsigned int b_id; /* block id */ | 176 | unsigned int b_id; /* block id */ |
177 | unsigned char b_granted; /* VFS granted lock */ | 177 | unsigned char b_granted; /* VFS granted lock */ |
178 | struct nlm_file * b_file; /* file in question */ | 178 | struct nlm_file * b_file; /* file in question */ |
179 | struct cache_req * b_cache_req; /* deferred request handling */ | 179 | struct cache_req * b_cache_req; /* deferred request handling */ |
180 | struct file_lock * b_fl; /* set for GETLK */ | 180 | struct file_lock * b_fl; /* set for GETLK */ |
181 | struct cache_deferred_req * b_deferred_req; | 181 | struct cache_deferred_req * b_deferred_req; |
182 | unsigned int b_flags; /* block flags */ | 182 | unsigned int b_flags; /* block flags */ |
183 | #define B_QUEUED 1 /* lock queued */ | 183 | #define B_QUEUED 1 /* lock queued */ |
184 | #define B_GOT_CALLBACK 2 /* got lock or conflicting lock */ | 184 | #define B_GOT_CALLBACK 2 /* got lock or conflicting lock */ |
185 | #define B_TIMED_OUT 4 /* filesystem too slow to respond */ | 185 | #define B_TIMED_OUT 4 /* filesystem too slow to respond */ |
186 | }; | 186 | }; |
187 | 187 | ||
188 | /* | 188 | /* |
189 | * Global variables | 189 | * Global variables |
190 | */ | 190 | */ |
191 | extern struct rpc_program nlm_program; | 191 | extern const struct rpc_program nlm_program; |
192 | extern struct svc_procedure nlmsvc_procedures[]; | 192 | extern struct svc_procedure nlmsvc_procedures[]; |
193 | #ifdef CONFIG_LOCKD_V4 | 193 | #ifdef CONFIG_LOCKD_V4 |
194 | extern struct svc_procedure nlmsvc_procedures4[]; | 194 | extern struct svc_procedure nlmsvc_procedures4[]; |
195 | #endif | 195 | #endif |
196 | extern int nlmsvc_grace_period; | 196 | extern int nlmsvc_grace_period; |
197 | extern unsigned long nlmsvc_timeout; | 197 | extern unsigned long nlmsvc_timeout; |
198 | extern bool nsm_use_hostnames; | 198 | extern bool nsm_use_hostnames; |
199 | extern u32 nsm_local_state; | 199 | extern u32 nsm_local_state; |
200 | 200 | ||
201 | /* | 201 | /* |
202 | * Lockd client functions | 202 | * Lockd client functions |
203 | */ | 203 | */ |
204 | struct nlm_rqst * nlm_alloc_call(struct nlm_host *host); | 204 | struct nlm_rqst * nlm_alloc_call(struct nlm_host *host); |
205 | int nlm_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); | 205 | int nlm_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); |
206 | int nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *); | 206 | int nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *); |
207 | void nlmclnt_release_call(struct nlm_rqst *); | 207 | void nlmclnt_release_call(struct nlm_rqst *); |
208 | struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); | 208 | struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); |
209 | void nlmclnt_finish_block(struct nlm_wait *block); | 209 | void nlmclnt_finish_block(struct nlm_wait *block); |
210 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); | 210 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); |
211 | __be32 nlmclnt_grant(const struct sockaddr *addr, | 211 | __be32 nlmclnt_grant(const struct sockaddr *addr, |
212 | const struct nlm_lock *lock); | 212 | const struct nlm_lock *lock); |
213 | void nlmclnt_recovery(struct nlm_host *); | 213 | void nlmclnt_recovery(struct nlm_host *); |
214 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); | 214 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); |
215 | void nlmclnt_next_cookie(struct nlm_cookie *); | 215 | void nlmclnt_next_cookie(struct nlm_cookie *); |
216 | 216 | ||
217 | /* | 217 | /* |
218 | * Host cache | 218 | * Host cache |
219 | */ | 219 | */ |
220 | struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, | 220 | struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, |
221 | const size_t salen, | 221 | const size_t salen, |
222 | const unsigned short protocol, | 222 | const unsigned short protocol, |
223 | const u32 version, | 223 | const u32 version, |
224 | const char *hostname, | 224 | const char *hostname, |
225 | int noresvport); | 225 | int noresvport); |
226 | void nlmclnt_release_host(struct nlm_host *); | 226 | void nlmclnt_release_host(struct nlm_host *); |
227 | struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | 227 | struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, |
228 | const char *hostname, | 228 | const char *hostname, |
229 | const size_t hostname_len); | 229 | const size_t hostname_len); |
230 | void nlmsvc_release_host(struct nlm_host *); | 230 | void nlmsvc_release_host(struct nlm_host *); |
231 | struct rpc_clnt * nlm_bind_host(struct nlm_host *); | 231 | struct rpc_clnt * nlm_bind_host(struct nlm_host *); |
232 | void nlm_rebind_host(struct nlm_host *); | 232 | void nlm_rebind_host(struct nlm_host *); |
233 | struct nlm_host * nlm_get_host(struct nlm_host *); | 233 | struct nlm_host * nlm_get_host(struct nlm_host *); |
234 | void nlm_shutdown_hosts(void); | 234 | void nlm_shutdown_hosts(void); |
235 | void nlm_host_rebooted(const struct nlm_reboot *); | 235 | void nlm_host_rebooted(const struct nlm_reboot *); |
236 | 236 | ||
237 | /* | 237 | /* |
238 | * Host monitoring | 238 | * Host monitoring |
239 | */ | 239 | */ |
240 | int nsm_monitor(const struct nlm_host *host); | 240 | int nsm_monitor(const struct nlm_host *host); |
241 | void nsm_unmonitor(const struct nlm_host *host); | 241 | void nsm_unmonitor(const struct nlm_host *host); |
242 | 242 | ||
243 | struct nsm_handle *nsm_get_handle(const struct sockaddr *sap, | 243 | struct nsm_handle *nsm_get_handle(const struct sockaddr *sap, |
244 | const size_t salen, | 244 | const size_t salen, |
245 | const char *hostname, | 245 | const char *hostname, |
246 | const size_t hostname_len); | 246 | const size_t hostname_len); |
247 | struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info); | 247 | struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info); |
248 | void nsm_release(struct nsm_handle *nsm); | 248 | void nsm_release(struct nsm_handle *nsm); |
249 | 249 | ||
250 | /* | 250 | /* |
251 | * This is used in garbage collection and resource reclaim | 251 | * This is used in garbage collection and resource reclaim |
252 | * A return value != 0 means destroy the lock/block/share | 252 | * A return value != 0 means destroy the lock/block/share |
253 | */ | 253 | */ |
254 | typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref); | 254 | typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref); |
255 | 255 | ||
256 | /* | 256 | /* |
257 | * Server-side lock handling | 257 | * Server-side lock handling |
258 | */ | 258 | */ |
259 | __be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, | 259 | __be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, |
260 | struct nlm_host *, struct nlm_lock *, int, | 260 | struct nlm_host *, struct nlm_lock *, int, |
261 | struct nlm_cookie *, int); | 261 | struct nlm_cookie *, int); |
262 | __be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); | 262 | __be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); |
263 | __be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *, | 263 | __be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *, |
264 | struct nlm_host *, struct nlm_lock *, | 264 | struct nlm_host *, struct nlm_lock *, |
265 | struct nlm_lock *, struct nlm_cookie *); | 265 | struct nlm_lock *, struct nlm_cookie *); |
266 | __be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *); | 266 | __be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *); |
267 | unsigned long nlmsvc_retry_blocked(void); | 267 | unsigned long nlmsvc_retry_blocked(void); |
268 | void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, | 268 | void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, |
269 | nlm_host_match_fn_t match); | 269 | nlm_host_match_fn_t match); |
270 | void nlmsvc_grant_reply(struct nlm_cookie *, __be32); | 270 | void nlmsvc_grant_reply(struct nlm_cookie *, __be32); |
271 | void nlmsvc_release_call(struct nlm_rqst *); | 271 | void nlmsvc_release_call(struct nlm_rqst *); |
272 | 272 | ||
273 | /* | 273 | /* |
274 | * File handling for the server personality | 274 | * File handling for the server personality |
275 | */ | 275 | */ |
276 | __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, | 276 | __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, |
277 | struct nfs_fh *); | 277 | struct nfs_fh *); |
278 | void nlm_release_file(struct nlm_file *); | 278 | void nlm_release_file(struct nlm_file *); |
279 | void nlmsvc_mark_resources(void); | 279 | void nlmsvc_mark_resources(void); |
280 | void nlmsvc_free_host_resources(struct nlm_host *); | 280 | void nlmsvc_free_host_resources(struct nlm_host *); |
281 | void nlmsvc_invalidate_all(void); | 281 | void nlmsvc_invalidate_all(void); |
282 | 282 | ||
283 | /* | 283 | /* |
284 | * Cluster failover support | 284 | * Cluster failover support |
285 | */ | 285 | */ |
286 | int nlmsvc_unlock_all_by_sb(struct super_block *sb); | 286 | int nlmsvc_unlock_all_by_sb(struct super_block *sb); |
287 | int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr); | 287 | int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr); |
288 | 288 | ||
289 | static inline struct inode *nlmsvc_file_inode(struct nlm_file *file) | 289 | static inline struct inode *nlmsvc_file_inode(struct nlm_file *file) |
290 | { | 290 | { |
291 | return file->f_file->f_path.dentry->d_inode; | 291 | return file->f_file->f_path.dentry->d_inode; |
292 | } | 292 | } |
293 | 293 | ||
294 | static inline int __nlm_privileged_request4(const struct sockaddr *sap) | 294 | static inline int __nlm_privileged_request4(const struct sockaddr *sap) |
295 | { | 295 | { |
296 | const struct sockaddr_in *sin = (struct sockaddr_in *)sap; | 296 | const struct sockaddr_in *sin = (struct sockaddr_in *)sap; |
297 | 297 | ||
298 | if (ntohs(sin->sin_port) > 1023) | 298 | if (ntohs(sin->sin_port) > 1023) |
299 | return 0; | 299 | return 0; |
300 | 300 | ||
301 | return ipv4_is_loopback(sin->sin_addr.s_addr); | 301 | return ipv4_is_loopback(sin->sin_addr.s_addr); |
302 | } | 302 | } |
303 | 303 | ||
304 | #if IS_ENABLED(CONFIG_IPV6) | 304 | #if IS_ENABLED(CONFIG_IPV6) |
305 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) | 305 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) |
306 | { | 306 | { |
307 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | 307 | const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; |
308 | 308 | ||
309 | if (ntohs(sin6->sin6_port) > 1023) | 309 | if (ntohs(sin6->sin6_port) > 1023) |
310 | return 0; | 310 | return 0; |
311 | 311 | ||
312 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) | 312 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) |
313 | return ipv4_is_loopback(sin6->sin6_addr.s6_addr32[3]); | 313 | return ipv4_is_loopback(sin6->sin6_addr.s6_addr32[3]); |
314 | 314 | ||
315 | return ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK; | 315 | return ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK; |
316 | } | 316 | } |
317 | #else /* IS_ENABLED(CONFIG_IPV6) */ | 317 | #else /* IS_ENABLED(CONFIG_IPV6) */ |
318 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) | 318 | static inline int __nlm_privileged_request6(const struct sockaddr *sap) |
319 | { | 319 | { |
320 | return 0; | 320 | return 0; |
321 | } | 321 | } |
322 | #endif /* IS_ENABLED(CONFIG_IPV6) */ | 322 | #endif /* IS_ENABLED(CONFIG_IPV6) */ |
323 | 323 | ||
324 | /* | 324 | /* |
325 | * Ensure incoming requests are from local privileged callers. | 325 | * Ensure incoming requests are from local privileged callers. |
326 | * | 326 | * |
327 | * Return TRUE if sender is local and is connecting via a privileged port; | 327 | * Return TRUE if sender is local and is connecting via a privileged port; |
328 | * otherwise return FALSE. | 328 | * otherwise return FALSE. |
329 | */ | 329 | */ |
330 | static inline int nlm_privileged_requester(const struct svc_rqst *rqstp) | 330 | static inline int nlm_privileged_requester(const struct svc_rqst *rqstp) |
331 | { | 331 | { |
332 | const struct sockaddr *sap = svc_addr(rqstp); | 332 | const struct sockaddr *sap = svc_addr(rqstp); |
333 | 333 | ||
334 | switch (sap->sa_family) { | 334 | switch (sap->sa_family) { |
335 | case AF_INET: | 335 | case AF_INET: |
336 | return __nlm_privileged_request4(sap); | 336 | return __nlm_privileged_request4(sap); |
337 | case AF_INET6: | 337 | case AF_INET6: |
338 | return __nlm_privileged_request6(sap); | 338 | return __nlm_privileged_request6(sap); |
339 | default: | 339 | default: |
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | } | 342 | } |
343 | 343 | ||
344 | /* | 344 | /* |
345 | * Compare two NLM locks. | 345 | * Compare two NLM locks. |
346 | * When the second lock is of type F_UNLCK, this acts like a wildcard. | 346 | * When the second lock is of type F_UNLCK, this acts like a wildcard. |
347 | */ | 347 | */ |
348 | static inline int nlm_compare_locks(const struct file_lock *fl1, | 348 | static inline int nlm_compare_locks(const struct file_lock *fl1, |
349 | const struct file_lock *fl2) | 349 | const struct file_lock *fl2) |
350 | { | 350 | { |
351 | return fl1->fl_pid == fl2->fl_pid | 351 | return fl1->fl_pid == fl2->fl_pid |
352 | && fl1->fl_owner == fl2->fl_owner | 352 | && fl1->fl_owner == fl2->fl_owner |
353 | && fl1->fl_start == fl2->fl_start | 353 | && fl1->fl_start == fl2->fl_start |
354 | && fl1->fl_end == fl2->fl_end | 354 | && fl1->fl_end == fl2->fl_end |
355 | &&(fl1->fl_type == fl2->fl_type || fl2->fl_type == F_UNLCK); | 355 | &&(fl1->fl_type == fl2->fl_type || fl2->fl_type == F_UNLCK); |
356 | } | 356 | } |
357 | 357 | ||
358 | extern const struct lock_manager_operations nlmsvc_lock_operations; | 358 | extern const struct lock_manager_operations nlmsvc_lock_operations; |
359 | 359 | ||
360 | #endif /* __KERNEL__ */ | 360 | #endif /* __KERNEL__ */ |
361 | 361 | ||
362 | #endif /* LINUX_LOCKD_LOCKD_H */ | 362 | #endif /* LINUX_LOCKD_LOCKD_H */ |
363 | 363 |
include/linux/lockd/xdr4.h
1 | /* | 1 | /* |
2 | * linux/include/linux/lockd/xdr4.h | 2 | * linux/include/linux/lockd/xdr4.h |
3 | * | 3 | * |
4 | * XDR types for the NLM protocol | 4 | * XDR types for the NLM protocol |
5 | * | 5 | * |
6 | * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef LOCKD_XDR4_H | 9 | #ifndef LOCKD_XDR4_H |
10 | #define LOCKD_XDR4_H | 10 | #define LOCKD_XDR4_H |
11 | 11 | ||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/nfs.h> | 13 | #include <linux/nfs.h> |
14 | #include <linux/sunrpc/xdr.h> | 14 | #include <linux/sunrpc/xdr.h> |
15 | #include <linux/lockd/xdr.h> | 15 | #include <linux/lockd/xdr.h> |
16 | 16 | ||
17 | /* error codes new to NLMv4 */ | 17 | /* error codes new to NLMv4 */ |
18 | #define nlm4_deadlock cpu_to_be32(NLM_DEADLCK) | 18 | #define nlm4_deadlock cpu_to_be32(NLM_DEADLCK) |
19 | #define nlm4_rofs cpu_to_be32(NLM_ROFS) | 19 | #define nlm4_rofs cpu_to_be32(NLM_ROFS) |
20 | #define nlm4_stale_fh cpu_to_be32(NLM_STALE_FH) | 20 | #define nlm4_stale_fh cpu_to_be32(NLM_STALE_FH) |
21 | #define nlm4_fbig cpu_to_be32(NLM_FBIG) | 21 | #define nlm4_fbig cpu_to_be32(NLM_FBIG) |
22 | #define nlm4_failed cpu_to_be32(NLM_FAILED) | 22 | #define nlm4_failed cpu_to_be32(NLM_FAILED) |
23 | 23 | ||
24 | 24 | ||
25 | 25 | ||
26 | int nlm4svc_decode_testargs(struct svc_rqst *, __be32 *, struct nlm_args *); | 26 | int nlm4svc_decode_testargs(struct svc_rqst *, __be32 *, struct nlm_args *); |
27 | int nlm4svc_encode_testres(struct svc_rqst *, __be32 *, struct nlm_res *); | 27 | int nlm4svc_encode_testres(struct svc_rqst *, __be32 *, struct nlm_res *); |
28 | int nlm4svc_decode_lockargs(struct svc_rqst *, __be32 *, struct nlm_args *); | 28 | int nlm4svc_decode_lockargs(struct svc_rqst *, __be32 *, struct nlm_args *); |
29 | int nlm4svc_decode_cancargs(struct svc_rqst *, __be32 *, struct nlm_args *); | 29 | int nlm4svc_decode_cancargs(struct svc_rqst *, __be32 *, struct nlm_args *); |
30 | int nlm4svc_decode_unlockargs(struct svc_rqst *, __be32 *, struct nlm_args *); | 30 | int nlm4svc_decode_unlockargs(struct svc_rqst *, __be32 *, struct nlm_args *); |
31 | int nlm4svc_encode_res(struct svc_rqst *, __be32 *, struct nlm_res *); | 31 | int nlm4svc_encode_res(struct svc_rqst *, __be32 *, struct nlm_res *); |
32 | int nlm4svc_decode_res(struct svc_rqst *, __be32 *, struct nlm_res *); | 32 | int nlm4svc_decode_res(struct svc_rqst *, __be32 *, struct nlm_res *); |
33 | int nlm4svc_encode_void(struct svc_rqst *, __be32 *, void *); | 33 | int nlm4svc_encode_void(struct svc_rqst *, __be32 *, void *); |
34 | int nlm4svc_decode_void(struct svc_rqst *, __be32 *, void *); | 34 | int nlm4svc_decode_void(struct svc_rqst *, __be32 *, void *); |
35 | int nlm4svc_decode_shareargs(struct svc_rqst *, __be32 *, struct nlm_args *); | 35 | int nlm4svc_decode_shareargs(struct svc_rqst *, __be32 *, struct nlm_args *); |
36 | int nlm4svc_encode_shareres(struct svc_rqst *, __be32 *, struct nlm_res *); | 36 | int nlm4svc_encode_shareres(struct svc_rqst *, __be32 *, struct nlm_res *); |
37 | int nlm4svc_decode_notify(struct svc_rqst *, __be32 *, struct nlm_args *); | 37 | int nlm4svc_decode_notify(struct svc_rqst *, __be32 *, struct nlm_args *); |
38 | int nlm4svc_decode_reboot(struct svc_rqst *, __be32 *, struct nlm_reboot *); | 38 | int nlm4svc_decode_reboot(struct svc_rqst *, __be32 *, struct nlm_reboot *); |
39 | /* | 39 | /* |
40 | int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); | 40 | int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); |
41 | int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); | 41 | int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); |
42 | int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *); | 42 | int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *); |
43 | int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *); | 43 | int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *); |
44 | */ | 44 | */ |
45 | extern struct rpc_version nlm_version4; | 45 | extern const struct rpc_version nlm_version4; |
46 | 46 | ||
47 | #endif /* LOCKD_XDR4_H */ | 47 | #endif /* LOCKD_XDR4_H */ |
48 | 48 |
include/linux/nfs_xdr.h
1 | #ifndef _LINUX_NFS_XDR_H | 1 | #ifndef _LINUX_NFS_XDR_H |
2 | #define _LINUX_NFS_XDR_H | 2 | #define _LINUX_NFS_XDR_H |
3 | 3 | ||
4 | #include <linux/nfsacl.h> | 4 | #include <linux/nfsacl.h> |
5 | #include <linux/sunrpc/gss_api.h> | 5 | #include <linux/sunrpc/gss_api.h> |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * To change the maximum rsize and wsize supported by the NFS client, adjust | 8 | * To change the maximum rsize and wsize supported by the NFS client, adjust |
9 | * NFS_MAX_FILE_IO_SIZE. 64KB is a typical maximum, but some servers can | 9 | * NFS_MAX_FILE_IO_SIZE. 64KB is a typical maximum, but some servers can |
10 | * support a megabyte or more. The default is left at 4096 bytes, which is | 10 | * support a megabyte or more. The default is left at 4096 bytes, which is |
11 | * reasonable for NFS over UDP. | 11 | * reasonable for NFS over UDP. |
12 | */ | 12 | */ |
13 | #define NFS_MAX_FILE_IO_SIZE (1048576U) | 13 | #define NFS_MAX_FILE_IO_SIZE (1048576U) |
14 | #define NFS_DEF_FILE_IO_SIZE (4096U) | 14 | #define NFS_DEF_FILE_IO_SIZE (4096U) |
15 | #define NFS_MIN_FILE_IO_SIZE (1024U) | 15 | #define NFS_MIN_FILE_IO_SIZE (1024U) |
16 | 16 | ||
17 | /* Forward declaration for NFS v3 */ | 17 | /* Forward declaration for NFS v3 */ |
18 | struct nfs4_secinfo_flavors; | 18 | struct nfs4_secinfo_flavors; |
19 | 19 | ||
20 | struct nfs4_string { | 20 | struct nfs4_string { |
21 | unsigned int len; | 21 | unsigned int len; |
22 | char *data; | 22 | char *data; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | struct nfs_fsid { | 25 | struct nfs_fsid { |
26 | uint64_t major; | 26 | uint64_t major; |
27 | uint64_t minor; | 27 | uint64_t minor; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Helper for checking equality between 2 fsids. | 31 | * Helper for checking equality between 2 fsids. |
32 | */ | 32 | */ |
33 | static inline int nfs_fsid_equal(const struct nfs_fsid *a, const struct nfs_fsid *b) | 33 | static inline int nfs_fsid_equal(const struct nfs_fsid *a, const struct nfs_fsid *b) |
34 | { | 34 | { |
35 | return a->major == b->major && a->minor == b->minor; | 35 | return a->major == b->major && a->minor == b->minor; |
36 | } | 36 | } |
37 | 37 | ||
38 | struct nfs_fattr { | 38 | struct nfs_fattr { |
39 | unsigned int valid; /* which fields are valid */ | 39 | unsigned int valid; /* which fields are valid */ |
40 | umode_t mode; | 40 | umode_t mode; |
41 | __u32 nlink; | 41 | __u32 nlink; |
42 | __u32 uid; | 42 | __u32 uid; |
43 | __u32 gid; | 43 | __u32 gid; |
44 | dev_t rdev; | 44 | dev_t rdev; |
45 | __u64 size; | 45 | __u64 size; |
46 | union { | 46 | union { |
47 | struct { | 47 | struct { |
48 | __u32 blocksize; | 48 | __u32 blocksize; |
49 | __u32 blocks; | 49 | __u32 blocks; |
50 | } nfs2; | 50 | } nfs2; |
51 | struct { | 51 | struct { |
52 | __u64 used; | 52 | __u64 used; |
53 | } nfs3; | 53 | } nfs3; |
54 | } du; | 54 | } du; |
55 | struct nfs_fsid fsid; | 55 | struct nfs_fsid fsid; |
56 | __u64 fileid; | 56 | __u64 fileid; |
57 | __u64 mounted_on_fileid; | 57 | __u64 mounted_on_fileid; |
58 | struct timespec atime; | 58 | struct timespec atime; |
59 | struct timespec mtime; | 59 | struct timespec mtime; |
60 | struct timespec ctime; | 60 | struct timespec ctime; |
61 | __u64 change_attr; /* NFSv4 change attribute */ | 61 | __u64 change_attr; /* NFSv4 change attribute */ |
62 | __u64 pre_change_attr;/* pre-op NFSv4 change attribute */ | 62 | __u64 pre_change_attr;/* pre-op NFSv4 change attribute */ |
63 | __u64 pre_size; /* pre_op_attr.size */ | 63 | __u64 pre_size; /* pre_op_attr.size */ |
64 | struct timespec pre_mtime; /* pre_op_attr.mtime */ | 64 | struct timespec pre_mtime; /* pre_op_attr.mtime */ |
65 | struct timespec pre_ctime; /* pre_op_attr.ctime */ | 65 | struct timespec pre_ctime; /* pre_op_attr.ctime */ |
66 | unsigned long time_start; | 66 | unsigned long time_start; |
67 | unsigned long gencount; | 67 | unsigned long gencount; |
68 | struct nfs4_string *owner_name; | 68 | struct nfs4_string *owner_name; |
69 | struct nfs4_string *group_name; | 69 | struct nfs4_string *group_name; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | #define NFS_ATTR_FATTR_TYPE (1U << 0) | 72 | #define NFS_ATTR_FATTR_TYPE (1U << 0) |
73 | #define NFS_ATTR_FATTR_MODE (1U << 1) | 73 | #define NFS_ATTR_FATTR_MODE (1U << 1) |
74 | #define NFS_ATTR_FATTR_NLINK (1U << 2) | 74 | #define NFS_ATTR_FATTR_NLINK (1U << 2) |
75 | #define NFS_ATTR_FATTR_OWNER (1U << 3) | 75 | #define NFS_ATTR_FATTR_OWNER (1U << 3) |
76 | #define NFS_ATTR_FATTR_GROUP (1U << 4) | 76 | #define NFS_ATTR_FATTR_GROUP (1U << 4) |
77 | #define NFS_ATTR_FATTR_RDEV (1U << 5) | 77 | #define NFS_ATTR_FATTR_RDEV (1U << 5) |
78 | #define NFS_ATTR_FATTR_SIZE (1U << 6) | 78 | #define NFS_ATTR_FATTR_SIZE (1U << 6) |
79 | #define NFS_ATTR_FATTR_PRESIZE (1U << 7) | 79 | #define NFS_ATTR_FATTR_PRESIZE (1U << 7) |
80 | #define NFS_ATTR_FATTR_BLOCKS_USED (1U << 8) | 80 | #define NFS_ATTR_FATTR_BLOCKS_USED (1U << 8) |
81 | #define NFS_ATTR_FATTR_SPACE_USED (1U << 9) | 81 | #define NFS_ATTR_FATTR_SPACE_USED (1U << 9) |
82 | #define NFS_ATTR_FATTR_FSID (1U << 10) | 82 | #define NFS_ATTR_FATTR_FSID (1U << 10) |
83 | #define NFS_ATTR_FATTR_FILEID (1U << 11) | 83 | #define NFS_ATTR_FATTR_FILEID (1U << 11) |
84 | #define NFS_ATTR_FATTR_ATIME (1U << 12) | 84 | #define NFS_ATTR_FATTR_ATIME (1U << 12) |
85 | #define NFS_ATTR_FATTR_MTIME (1U << 13) | 85 | #define NFS_ATTR_FATTR_MTIME (1U << 13) |
86 | #define NFS_ATTR_FATTR_CTIME (1U << 14) | 86 | #define NFS_ATTR_FATTR_CTIME (1U << 14) |
87 | #define NFS_ATTR_FATTR_PREMTIME (1U << 15) | 87 | #define NFS_ATTR_FATTR_PREMTIME (1U << 15) |
88 | #define NFS_ATTR_FATTR_PRECTIME (1U << 16) | 88 | #define NFS_ATTR_FATTR_PRECTIME (1U << 16) |
89 | #define NFS_ATTR_FATTR_CHANGE (1U << 17) | 89 | #define NFS_ATTR_FATTR_CHANGE (1U << 17) |
90 | #define NFS_ATTR_FATTR_PRECHANGE (1U << 18) | 90 | #define NFS_ATTR_FATTR_PRECHANGE (1U << 18) |
91 | #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ | 91 | #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ |
92 | #define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20) /* Treat as mountpoint */ | 92 | #define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20) /* Treat as mountpoint */ |
93 | #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 21) | 93 | #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 21) |
94 | #define NFS_ATTR_FATTR_OWNER_NAME (1U << 22) | 94 | #define NFS_ATTR_FATTR_OWNER_NAME (1U << 22) |
95 | #define NFS_ATTR_FATTR_GROUP_NAME (1U << 23) | 95 | #define NFS_ATTR_FATTR_GROUP_NAME (1U << 23) |
96 | 96 | ||
97 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ | 97 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ |
98 | | NFS_ATTR_FATTR_MODE \ | 98 | | NFS_ATTR_FATTR_MODE \ |
99 | | NFS_ATTR_FATTR_NLINK \ | 99 | | NFS_ATTR_FATTR_NLINK \ |
100 | | NFS_ATTR_FATTR_OWNER \ | 100 | | NFS_ATTR_FATTR_OWNER \ |
101 | | NFS_ATTR_FATTR_GROUP \ | 101 | | NFS_ATTR_FATTR_GROUP \ |
102 | | NFS_ATTR_FATTR_RDEV \ | 102 | | NFS_ATTR_FATTR_RDEV \ |
103 | | NFS_ATTR_FATTR_SIZE \ | 103 | | NFS_ATTR_FATTR_SIZE \ |
104 | | NFS_ATTR_FATTR_FSID \ | 104 | | NFS_ATTR_FATTR_FSID \ |
105 | | NFS_ATTR_FATTR_FILEID \ | 105 | | NFS_ATTR_FATTR_FILEID \ |
106 | | NFS_ATTR_FATTR_ATIME \ | 106 | | NFS_ATTR_FATTR_ATIME \ |
107 | | NFS_ATTR_FATTR_MTIME \ | 107 | | NFS_ATTR_FATTR_MTIME \ |
108 | | NFS_ATTR_FATTR_CTIME) | 108 | | NFS_ATTR_FATTR_CTIME) |
109 | #define NFS_ATTR_FATTR_V2 (NFS_ATTR_FATTR \ | 109 | #define NFS_ATTR_FATTR_V2 (NFS_ATTR_FATTR \ |
110 | | NFS_ATTR_FATTR_BLOCKS_USED) | 110 | | NFS_ATTR_FATTR_BLOCKS_USED) |
111 | #define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \ | 111 | #define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \ |
112 | | NFS_ATTR_FATTR_SPACE_USED) | 112 | | NFS_ATTR_FATTR_SPACE_USED) |
113 | #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ | 113 | #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ |
114 | | NFS_ATTR_FATTR_SPACE_USED \ | 114 | | NFS_ATTR_FATTR_SPACE_USED \ |
115 | | NFS_ATTR_FATTR_CHANGE) | 115 | | NFS_ATTR_FATTR_CHANGE) |
116 | 116 | ||
117 | /* | 117 | /* |
118 | * Info on the file system | 118 | * Info on the file system |
119 | */ | 119 | */ |
120 | struct nfs_fsinfo { | 120 | struct nfs_fsinfo { |
121 | struct nfs_fattr *fattr; /* Post-op attributes */ | 121 | struct nfs_fattr *fattr; /* Post-op attributes */ |
122 | __u32 rtmax; /* max. read transfer size */ | 122 | __u32 rtmax; /* max. read transfer size */ |
123 | __u32 rtpref; /* pref. read transfer size */ | 123 | __u32 rtpref; /* pref. read transfer size */ |
124 | __u32 rtmult; /* reads should be multiple of this */ | 124 | __u32 rtmult; /* reads should be multiple of this */ |
125 | __u32 wtmax; /* max. write transfer size */ | 125 | __u32 wtmax; /* max. write transfer size */ |
126 | __u32 wtpref; /* pref. write transfer size */ | 126 | __u32 wtpref; /* pref. write transfer size */ |
127 | __u32 wtmult; /* writes should be multiple of this */ | 127 | __u32 wtmult; /* writes should be multiple of this */ |
128 | __u32 dtpref; /* pref. readdir transfer size */ | 128 | __u32 dtpref; /* pref. readdir transfer size */ |
129 | __u64 maxfilesize; | 129 | __u64 maxfilesize; |
130 | struct timespec time_delta; /* server time granularity */ | 130 | struct timespec time_delta; /* server time granularity */ |
131 | __u32 lease_time; /* in seconds */ | 131 | __u32 lease_time; /* in seconds */ |
132 | __u32 layouttype; /* supported pnfs layout driver */ | 132 | __u32 layouttype; /* supported pnfs layout driver */ |
133 | __u32 blksize; /* preferred pnfs io block size */ | 133 | __u32 blksize; /* preferred pnfs io block size */ |
134 | }; | 134 | }; |
135 | 135 | ||
136 | struct nfs_fsstat { | 136 | struct nfs_fsstat { |
137 | struct nfs_fattr *fattr; /* Post-op attributes */ | 137 | struct nfs_fattr *fattr; /* Post-op attributes */ |
138 | __u64 tbytes; /* total size in bytes */ | 138 | __u64 tbytes; /* total size in bytes */ |
139 | __u64 fbytes; /* # of free bytes */ | 139 | __u64 fbytes; /* # of free bytes */ |
140 | __u64 abytes; /* # of bytes available to user */ | 140 | __u64 abytes; /* # of bytes available to user */ |
141 | __u64 tfiles; /* # of files */ | 141 | __u64 tfiles; /* # of files */ |
142 | __u64 ffiles; /* # of free files */ | 142 | __u64 ffiles; /* # of free files */ |
143 | __u64 afiles; /* # of files available to user */ | 143 | __u64 afiles; /* # of files available to user */ |
144 | }; | 144 | }; |
145 | 145 | ||
146 | struct nfs2_fsstat { | 146 | struct nfs2_fsstat { |
147 | __u32 tsize; /* Server transfer size */ | 147 | __u32 tsize; /* Server transfer size */ |
148 | __u32 bsize; /* Filesystem block size */ | 148 | __u32 bsize; /* Filesystem block size */ |
149 | __u32 blocks; /* No. of "bsize" blocks on filesystem */ | 149 | __u32 blocks; /* No. of "bsize" blocks on filesystem */ |
150 | __u32 bfree; /* No. of free "bsize" blocks */ | 150 | __u32 bfree; /* No. of free "bsize" blocks */ |
151 | __u32 bavail; /* No. of available "bsize" blocks */ | 151 | __u32 bavail; /* No. of available "bsize" blocks */ |
152 | }; | 152 | }; |
153 | 153 | ||
154 | struct nfs_pathconf { | 154 | struct nfs_pathconf { |
155 | struct nfs_fattr *fattr; /* Post-op attributes */ | 155 | struct nfs_fattr *fattr; /* Post-op attributes */ |
156 | __u32 max_link; /* max # of hard links */ | 156 | __u32 max_link; /* max # of hard links */ |
157 | __u32 max_namelen; /* max name length */ | 157 | __u32 max_namelen; /* max name length */ |
158 | }; | 158 | }; |
159 | 159 | ||
160 | struct nfs4_change_info { | 160 | struct nfs4_change_info { |
161 | u32 atomic; | 161 | u32 atomic; |
162 | u64 before; | 162 | u64 before; |
163 | u64 after; | 163 | u64 after; |
164 | }; | 164 | }; |
165 | 165 | ||
166 | struct nfs_seqid; | 166 | struct nfs_seqid; |
167 | 167 | ||
168 | /* nfs41 sessions channel attributes */ | 168 | /* nfs41 sessions channel attributes */ |
169 | struct nfs4_channel_attrs { | 169 | struct nfs4_channel_attrs { |
170 | u32 max_rqst_sz; | 170 | u32 max_rqst_sz; |
171 | u32 max_resp_sz; | 171 | u32 max_resp_sz; |
172 | u32 max_resp_sz_cached; | 172 | u32 max_resp_sz_cached; |
173 | u32 max_ops; | 173 | u32 max_ops; |
174 | u32 max_reqs; | 174 | u32 max_reqs; |
175 | }; | 175 | }; |
176 | 176 | ||
177 | /* nfs41 sessions slot seqid */ | 177 | /* nfs41 sessions slot seqid */ |
178 | struct nfs4_slot { | 178 | struct nfs4_slot { |
179 | u32 seq_nr; | 179 | u32 seq_nr; |
180 | }; | 180 | }; |
181 | 181 | ||
182 | struct nfs4_sequence_args { | 182 | struct nfs4_sequence_args { |
183 | struct nfs4_session *sa_session; | 183 | struct nfs4_session *sa_session; |
184 | u8 sa_slotid; | 184 | u8 sa_slotid; |
185 | u8 sa_cache_this; | 185 | u8 sa_cache_this; |
186 | }; | 186 | }; |
187 | 187 | ||
188 | struct nfs4_sequence_res { | 188 | struct nfs4_sequence_res { |
189 | struct nfs4_session *sr_session; | 189 | struct nfs4_session *sr_session; |
190 | struct nfs4_slot *sr_slot; /* slot used to send request */ | 190 | struct nfs4_slot *sr_slot; /* slot used to send request */ |
191 | int sr_status; /* sequence operation status */ | 191 | int sr_status; /* sequence operation status */ |
192 | unsigned long sr_renewal_time; | 192 | unsigned long sr_renewal_time; |
193 | u32 sr_status_flags; | 193 | u32 sr_status_flags; |
194 | }; | 194 | }; |
195 | 195 | ||
196 | struct nfs4_get_lease_time_args { | 196 | struct nfs4_get_lease_time_args { |
197 | struct nfs4_sequence_args la_seq_args; | 197 | struct nfs4_sequence_args la_seq_args; |
198 | }; | 198 | }; |
199 | 199 | ||
200 | struct nfs4_get_lease_time_res { | 200 | struct nfs4_get_lease_time_res { |
201 | struct nfs_fsinfo *lr_fsinfo; | 201 | struct nfs_fsinfo *lr_fsinfo; |
202 | struct nfs4_sequence_res lr_seq_res; | 202 | struct nfs4_sequence_res lr_seq_res; |
203 | }; | 203 | }; |
204 | 204 | ||
205 | #define PNFS_LAYOUT_MAXSIZE 4096 | 205 | #define PNFS_LAYOUT_MAXSIZE 4096 |
206 | 206 | ||
207 | struct nfs4_layoutdriver_data { | 207 | struct nfs4_layoutdriver_data { |
208 | struct page **pages; | 208 | struct page **pages; |
209 | __u32 pglen; | 209 | __u32 pglen; |
210 | __u32 len; | 210 | __u32 len; |
211 | }; | 211 | }; |
212 | 212 | ||
213 | struct pnfs_layout_range { | 213 | struct pnfs_layout_range { |
214 | u32 iomode; | 214 | u32 iomode; |
215 | u64 offset; | 215 | u64 offset; |
216 | u64 length; | 216 | u64 length; |
217 | }; | 217 | }; |
218 | 218 | ||
219 | struct nfs4_layoutget_args { | 219 | struct nfs4_layoutget_args { |
220 | __u32 type; | 220 | __u32 type; |
221 | struct pnfs_layout_range range; | 221 | struct pnfs_layout_range range; |
222 | __u64 minlength; | 222 | __u64 minlength; |
223 | __u32 maxcount; | 223 | __u32 maxcount; |
224 | struct inode *inode; | 224 | struct inode *inode; |
225 | struct nfs_open_context *ctx; | 225 | struct nfs_open_context *ctx; |
226 | struct nfs4_sequence_args seq_args; | 226 | struct nfs4_sequence_args seq_args; |
227 | nfs4_stateid stateid; | 227 | nfs4_stateid stateid; |
228 | struct nfs4_layoutdriver_data layout; | 228 | struct nfs4_layoutdriver_data layout; |
229 | }; | 229 | }; |
230 | 230 | ||
231 | struct nfs4_layoutget_res { | 231 | struct nfs4_layoutget_res { |
232 | __u32 return_on_close; | 232 | __u32 return_on_close; |
233 | struct pnfs_layout_range range; | 233 | struct pnfs_layout_range range; |
234 | __u32 type; | 234 | __u32 type; |
235 | nfs4_stateid stateid; | 235 | nfs4_stateid stateid; |
236 | struct nfs4_sequence_res seq_res; | 236 | struct nfs4_sequence_res seq_res; |
237 | struct nfs4_layoutdriver_data *layoutp; | 237 | struct nfs4_layoutdriver_data *layoutp; |
238 | }; | 238 | }; |
239 | 239 | ||
240 | struct nfs4_layoutget { | 240 | struct nfs4_layoutget { |
241 | struct nfs4_layoutget_args args; | 241 | struct nfs4_layoutget_args args; |
242 | struct nfs4_layoutget_res res; | 242 | struct nfs4_layoutget_res res; |
243 | struct pnfs_layout_segment **lsegpp; | 243 | struct pnfs_layout_segment **lsegpp; |
244 | gfp_t gfp_flags; | 244 | gfp_t gfp_flags; |
245 | }; | 245 | }; |
246 | 246 | ||
247 | struct nfs4_getdevicelist_args { | 247 | struct nfs4_getdevicelist_args { |
248 | const struct nfs_fh *fh; | 248 | const struct nfs_fh *fh; |
249 | u32 layoutclass; | 249 | u32 layoutclass; |
250 | struct nfs4_sequence_args seq_args; | 250 | struct nfs4_sequence_args seq_args; |
251 | }; | 251 | }; |
252 | 252 | ||
253 | struct nfs4_getdevicelist_res { | 253 | struct nfs4_getdevicelist_res { |
254 | struct pnfs_devicelist *devlist; | 254 | struct pnfs_devicelist *devlist; |
255 | struct nfs4_sequence_res seq_res; | 255 | struct nfs4_sequence_res seq_res; |
256 | }; | 256 | }; |
257 | 257 | ||
258 | struct nfs4_getdeviceinfo_args { | 258 | struct nfs4_getdeviceinfo_args { |
259 | struct pnfs_device *pdev; | 259 | struct pnfs_device *pdev; |
260 | struct nfs4_sequence_args seq_args; | 260 | struct nfs4_sequence_args seq_args; |
261 | }; | 261 | }; |
262 | 262 | ||
263 | struct nfs4_getdeviceinfo_res { | 263 | struct nfs4_getdeviceinfo_res { |
264 | struct pnfs_device *pdev; | 264 | struct pnfs_device *pdev; |
265 | struct nfs4_sequence_res seq_res; | 265 | struct nfs4_sequence_res seq_res; |
266 | }; | 266 | }; |
267 | 267 | ||
268 | struct nfs4_layoutcommit_args { | 268 | struct nfs4_layoutcommit_args { |
269 | nfs4_stateid stateid; | 269 | nfs4_stateid stateid; |
270 | __u64 lastbytewritten; | 270 | __u64 lastbytewritten; |
271 | struct inode *inode; | 271 | struct inode *inode; |
272 | const u32 *bitmask; | 272 | const u32 *bitmask; |
273 | struct nfs4_sequence_args seq_args; | 273 | struct nfs4_sequence_args seq_args; |
274 | }; | 274 | }; |
275 | 275 | ||
276 | struct nfs4_layoutcommit_res { | 276 | struct nfs4_layoutcommit_res { |
277 | struct nfs_fattr *fattr; | 277 | struct nfs_fattr *fattr; |
278 | const struct nfs_server *server; | 278 | const struct nfs_server *server; |
279 | struct nfs4_sequence_res seq_res; | 279 | struct nfs4_sequence_res seq_res; |
280 | int status; | 280 | int status; |
281 | }; | 281 | }; |
282 | 282 | ||
283 | struct nfs4_layoutcommit_data { | 283 | struct nfs4_layoutcommit_data { |
284 | struct rpc_task task; | 284 | struct rpc_task task; |
285 | struct nfs_fattr fattr; | 285 | struct nfs_fattr fattr; |
286 | struct list_head lseg_list; | 286 | struct list_head lseg_list; |
287 | struct rpc_cred *cred; | 287 | struct rpc_cred *cred; |
288 | struct nfs4_layoutcommit_args args; | 288 | struct nfs4_layoutcommit_args args; |
289 | struct nfs4_layoutcommit_res res; | 289 | struct nfs4_layoutcommit_res res; |
290 | }; | 290 | }; |
291 | 291 | ||
292 | struct nfs4_layoutreturn_args { | 292 | struct nfs4_layoutreturn_args { |
293 | struct pnfs_layout_hdr *layout; | 293 | struct pnfs_layout_hdr *layout; |
294 | struct inode *inode; | 294 | struct inode *inode; |
295 | nfs4_stateid stateid; | 295 | nfs4_stateid stateid; |
296 | __u32 layout_type; | 296 | __u32 layout_type; |
297 | struct nfs4_sequence_args seq_args; | 297 | struct nfs4_sequence_args seq_args; |
298 | }; | 298 | }; |
299 | 299 | ||
300 | struct nfs4_layoutreturn_res { | 300 | struct nfs4_layoutreturn_res { |
301 | struct nfs4_sequence_res seq_res; | 301 | struct nfs4_sequence_res seq_res; |
302 | u32 lrs_present; | 302 | u32 lrs_present; |
303 | nfs4_stateid stateid; | 303 | nfs4_stateid stateid; |
304 | }; | 304 | }; |
305 | 305 | ||
306 | struct nfs4_layoutreturn { | 306 | struct nfs4_layoutreturn { |
307 | struct nfs4_layoutreturn_args args; | 307 | struct nfs4_layoutreturn_args args; |
308 | struct nfs4_layoutreturn_res res; | 308 | struct nfs4_layoutreturn_res res; |
309 | struct rpc_cred *cred; | 309 | struct rpc_cred *cred; |
310 | struct nfs_client *clp; | 310 | struct nfs_client *clp; |
311 | int rpc_status; | 311 | int rpc_status; |
312 | }; | 312 | }; |
313 | 313 | ||
314 | /* | 314 | /* |
315 | * Arguments to the open call. | 315 | * Arguments to the open call. |
316 | */ | 316 | */ |
317 | struct nfs_openargs { | 317 | struct nfs_openargs { |
318 | const struct nfs_fh * fh; | 318 | const struct nfs_fh * fh; |
319 | struct nfs_seqid * seqid; | 319 | struct nfs_seqid * seqid; |
320 | int open_flags; | 320 | int open_flags; |
321 | fmode_t fmode; | 321 | fmode_t fmode; |
322 | __u64 clientid; | 322 | __u64 clientid; |
323 | __u64 id; | 323 | __u64 id; |
324 | union { | 324 | union { |
325 | struct { | 325 | struct { |
326 | struct iattr * attrs; /* UNCHECKED, GUARDED */ | 326 | struct iattr * attrs; /* UNCHECKED, GUARDED */ |
327 | nfs4_verifier verifier; /* EXCLUSIVE */ | 327 | nfs4_verifier verifier; /* EXCLUSIVE */ |
328 | }; | 328 | }; |
329 | nfs4_stateid delegation; /* CLAIM_DELEGATE_CUR */ | 329 | nfs4_stateid delegation; /* CLAIM_DELEGATE_CUR */ |
330 | fmode_t delegation_type; /* CLAIM_PREVIOUS */ | 330 | fmode_t delegation_type; /* CLAIM_PREVIOUS */ |
331 | } u; | 331 | } u; |
332 | const struct qstr * name; | 332 | const struct qstr * name; |
333 | const struct nfs_server *server; /* Needed for ID mapping */ | 333 | const struct nfs_server *server; /* Needed for ID mapping */ |
334 | const u32 * bitmask; | 334 | const u32 * bitmask; |
335 | const u32 * dir_bitmask; | 335 | const u32 * dir_bitmask; |
336 | __u32 claim; | 336 | __u32 claim; |
337 | struct nfs4_sequence_args seq_args; | 337 | struct nfs4_sequence_args seq_args; |
338 | }; | 338 | }; |
339 | 339 | ||
340 | struct nfs_openres { | 340 | struct nfs_openres { |
341 | nfs4_stateid stateid; | 341 | nfs4_stateid stateid; |
342 | struct nfs_fh fh; | 342 | struct nfs_fh fh; |
343 | struct nfs4_change_info cinfo; | 343 | struct nfs4_change_info cinfo; |
344 | __u32 rflags; | 344 | __u32 rflags; |
345 | struct nfs_fattr * f_attr; | 345 | struct nfs_fattr * f_attr; |
346 | struct nfs_fattr * dir_attr; | 346 | struct nfs_fattr * dir_attr; |
347 | struct nfs_seqid * seqid; | 347 | struct nfs_seqid * seqid; |
348 | const struct nfs_server *server; | 348 | const struct nfs_server *server; |
349 | fmode_t delegation_type; | 349 | fmode_t delegation_type; |
350 | nfs4_stateid delegation; | 350 | nfs4_stateid delegation; |
351 | __u32 do_recall; | 351 | __u32 do_recall; |
352 | __u64 maxsize; | 352 | __u64 maxsize; |
353 | __u32 attrset[NFS4_BITMAP_SIZE]; | 353 | __u32 attrset[NFS4_BITMAP_SIZE]; |
354 | struct nfs4_string *owner; | 354 | struct nfs4_string *owner; |
355 | struct nfs4_string *group_owner; | 355 | struct nfs4_string *group_owner; |
356 | struct nfs4_sequence_res seq_res; | 356 | struct nfs4_sequence_res seq_res; |
357 | }; | 357 | }; |
358 | 358 | ||
359 | /* | 359 | /* |
360 | * Arguments to the open_confirm call. | 360 | * Arguments to the open_confirm call. |
361 | */ | 361 | */ |
362 | struct nfs_open_confirmargs { | 362 | struct nfs_open_confirmargs { |
363 | const struct nfs_fh * fh; | 363 | const struct nfs_fh * fh; |
364 | nfs4_stateid * stateid; | 364 | nfs4_stateid * stateid; |
365 | struct nfs_seqid * seqid; | 365 | struct nfs_seqid * seqid; |
366 | }; | 366 | }; |
367 | 367 | ||
368 | struct nfs_open_confirmres { | 368 | struct nfs_open_confirmres { |
369 | nfs4_stateid stateid; | 369 | nfs4_stateid stateid; |
370 | struct nfs_seqid * seqid; | 370 | struct nfs_seqid * seqid; |
371 | }; | 371 | }; |
372 | 372 | ||
373 | /* | 373 | /* |
374 | * Arguments to the close call. | 374 | * Arguments to the close call. |
375 | */ | 375 | */ |
376 | struct nfs_closeargs { | 376 | struct nfs_closeargs { |
377 | struct nfs_fh * fh; | 377 | struct nfs_fh * fh; |
378 | nfs4_stateid * stateid; | 378 | nfs4_stateid * stateid; |
379 | struct nfs_seqid * seqid; | 379 | struct nfs_seqid * seqid; |
380 | fmode_t fmode; | 380 | fmode_t fmode; |
381 | const u32 * bitmask; | 381 | const u32 * bitmask; |
382 | struct nfs4_sequence_args seq_args; | 382 | struct nfs4_sequence_args seq_args; |
383 | }; | 383 | }; |
384 | 384 | ||
385 | struct nfs_closeres { | 385 | struct nfs_closeres { |
386 | nfs4_stateid stateid; | 386 | nfs4_stateid stateid; |
387 | struct nfs_fattr * fattr; | 387 | struct nfs_fattr * fattr; |
388 | struct nfs_seqid * seqid; | 388 | struct nfs_seqid * seqid; |
389 | const struct nfs_server *server; | 389 | const struct nfs_server *server; |
390 | struct nfs4_sequence_res seq_res; | 390 | struct nfs4_sequence_res seq_res; |
391 | }; | 391 | }; |
392 | /* | 392 | /* |
393 | * * Arguments to the lock,lockt, and locku call. | 393 | * * Arguments to the lock,lockt, and locku call. |
394 | * */ | 394 | * */ |
395 | struct nfs_lowner { | 395 | struct nfs_lowner { |
396 | __u64 clientid; | 396 | __u64 clientid; |
397 | __u64 id; | 397 | __u64 id; |
398 | dev_t s_dev; | 398 | dev_t s_dev; |
399 | }; | 399 | }; |
400 | 400 | ||
401 | struct nfs_lock_args { | 401 | struct nfs_lock_args { |
402 | struct nfs_fh * fh; | 402 | struct nfs_fh * fh; |
403 | struct file_lock * fl; | 403 | struct file_lock * fl; |
404 | struct nfs_seqid * lock_seqid; | 404 | struct nfs_seqid * lock_seqid; |
405 | nfs4_stateid * lock_stateid; | 405 | nfs4_stateid * lock_stateid; |
406 | struct nfs_seqid * open_seqid; | 406 | struct nfs_seqid * open_seqid; |
407 | nfs4_stateid * open_stateid; | 407 | nfs4_stateid * open_stateid; |
408 | struct nfs_lowner lock_owner; | 408 | struct nfs_lowner lock_owner; |
409 | unsigned char block : 1; | 409 | unsigned char block : 1; |
410 | unsigned char reclaim : 1; | 410 | unsigned char reclaim : 1; |
411 | unsigned char new_lock_owner : 1; | 411 | unsigned char new_lock_owner : 1; |
412 | struct nfs4_sequence_args seq_args; | 412 | struct nfs4_sequence_args seq_args; |
413 | }; | 413 | }; |
414 | 414 | ||
415 | struct nfs_lock_res { | 415 | struct nfs_lock_res { |
416 | nfs4_stateid stateid; | 416 | nfs4_stateid stateid; |
417 | struct nfs_seqid * lock_seqid; | 417 | struct nfs_seqid * lock_seqid; |
418 | struct nfs_seqid * open_seqid; | 418 | struct nfs_seqid * open_seqid; |
419 | struct nfs4_sequence_res seq_res; | 419 | struct nfs4_sequence_res seq_res; |
420 | }; | 420 | }; |
421 | 421 | ||
422 | struct nfs_locku_args { | 422 | struct nfs_locku_args { |
423 | struct nfs_fh * fh; | 423 | struct nfs_fh * fh; |
424 | struct file_lock * fl; | 424 | struct file_lock * fl; |
425 | struct nfs_seqid * seqid; | 425 | struct nfs_seqid * seqid; |
426 | nfs4_stateid * stateid; | 426 | nfs4_stateid * stateid; |
427 | struct nfs4_sequence_args seq_args; | 427 | struct nfs4_sequence_args seq_args; |
428 | }; | 428 | }; |
429 | 429 | ||
430 | struct nfs_locku_res { | 430 | struct nfs_locku_res { |
431 | nfs4_stateid stateid; | 431 | nfs4_stateid stateid; |
432 | struct nfs_seqid * seqid; | 432 | struct nfs_seqid * seqid; |
433 | struct nfs4_sequence_res seq_res; | 433 | struct nfs4_sequence_res seq_res; |
434 | }; | 434 | }; |
435 | 435 | ||
436 | struct nfs_lockt_args { | 436 | struct nfs_lockt_args { |
437 | struct nfs_fh * fh; | 437 | struct nfs_fh * fh; |
438 | struct file_lock * fl; | 438 | struct file_lock * fl; |
439 | struct nfs_lowner lock_owner; | 439 | struct nfs_lowner lock_owner; |
440 | struct nfs4_sequence_args seq_args; | 440 | struct nfs4_sequence_args seq_args; |
441 | }; | 441 | }; |
442 | 442 | ||
443 | struct nfs_lockt_res { | 443 | struct nfs_lockt_res { |
444 | struct file_lock * denied; /* LOCK, LOCKT failed */ | 444 | struct file_lock * denied; /* LOCK, LOCKT failed */ |
445 | struct nfs4_sequence_res seq_res; | 445 | struct nfs4_sequence_res seq_res; |
446 | }; | 446 | }; |
447 | 447 | ||
448 | struct nfs_release_lockowner_args { | 448 | struct nfs_release_lockowner_args { |
449 | struct nfs_lowner lock_owner; | 449 | struct nfs_lowner lock_owner; |
450 | }; | 450 | }; |
451 | 451 | ||
452 | struct nfs4_delegreturnargs { | 452 | struct nfs4_delegreturnargs { |
453 | const struct nfs_fh *fhandle; | 453 | const struct nfs_fh *fhandle; |
454 | const nfs4_stateid *stateid; | 454 | const nfs4_stateid *stateid; |
455 | const u32 * bitmask; | 455 | const u32 * bitmask; |
456 | struct nfs4_sequence_args seq_args; | 456 | struct nfs4_sequence_args seq_args; |
457 | }; | 457 | }; |
458 | 458 | ||
459 | struct nfs4_delegreturnres { | 459 | struct nfs4_delegreturnres { |
460 | struct nfs_fattr * fattr; | 460 | struct nfs_fattr * fattr; |
461 | const struct nfs_server *server; | 461 | const struct nfs_server *server; |
462 | struct nfs4_sequence_res seq_res; | 462 | struct nfs4_sequence_res seq_res; |
463 | }; | 463 | }; |
464 | 464 | ||
465 | /* | 465 | /* |
466 | * Arguments to the read call. | 466 | * Arguments to the read call. |
467 | */ | 467 | */ |
468 | struct nfs_readargs { | 468 | struct nfs_readargs { |
469 | struct nfs_fh * fh; | 469 | struct nfs_fh * fh; |
470 | struct nfs_open_context *context; | 470 | struct nfs_open_context *context; |
471 | struct nfs_lock_context *lock_context; | 471 | struct nfs_lock_context *lock_context; |
472 | __u64 offset; | 472 | __u64 offset; |
473 | __u32 count; | 473 | __u32 count; |
474 | unsigned int pgbase; | 474 | unsigned int pgbase; |
475 | struct page ** pages; | 475 | struct page ** pages; |
476 | struct nfs4_sequence_args seq_args; | 476 | struct nfs4_sequence_args seq_args; |
477 | }; | 477 | }; |
478 | 478 | ||
479 | struct nfs_readres { | 479 | struct nfs_readres { |
480 | struct nfs_fattr * fattr; | 480 | struct nfs_fattr * fattr; |
481 | __u32 count; | 481 | __u32 count; |
482 | int eof; | 482 | int eof; |
483 | struct nfs4_sequence_res seq_res; | 483 | struct nfs4_sequence_res seq_res; |
484 | }; | 484 | }; |
485 | 485 | ||
486 | /* | 486 | /* |
487 | * Arguments to the write call. | 487 | * Arguments to the write call. |
488 | */ | 488 | */ |
489 | struct nfs_writeargs { | 489 | struct nfs_writeargs { |
490 | struct nfs_fh * fh; | 490 | struct nfs_fh * fh; |
491 | struct nfs_open_context *context; | 491 | struct nfs_open_context *context; |
492 | struct nfs_lock_context *lock_context; | 492 | struct nfs_lock_context *lock_context; |
493 | __u64 offset; | 493 | __u64 offset; |
494 | __u32 count; | 494 | __u32 count; |
495 | enum nfs3_stable_how stable; | 495 | enum nfs3_stable_how stable; |
496 | unsigned int pgbase; | 496 | unsigned int pgbase; |
497 | struct page ** pages; | 497 | struct page ** pages; |
498 | const u32 * bitmask; | 498 | const u32 * bitmask; |
499 | struct nfs4_sequence_args seq_args; | 499 | struct nfs4_sequence_args seq_args; |
500 | }; | 500 | }; |
501 | 501 | ||
502 | struct nfs_writeverf { | 502 | struct nfs_writeverf { |
503 | enum nfs3_stable_how committed; | 503 | enum nfs3_stable_how committed; |
504 | __be32 verifier[2]; | 504 | __be32 verifier[2]; |
505 | }; | 505 | }; |
506 | 506 | ||
507 | struct nfs_writeres { | 507 | struct nfs_writeres { |
508 | struct nfs_fattr * fattr; | 508 | struct nfs_fattr * fattr; |
509 | struct nfs_writeverf * verf; | 509 | struct nfs_writeverf * verf; |
510 | __u32 count; | 510 | __u32 count; |
511 | const struct nfs_server *server; | 511 | const struct nfs_server *server; |
512 | struct nfs4_sequence_res seq_res; | 512 | struct nfs4_sequence_res seq_res; |
513 | }; | 513 | }; |
514 | 514 | ||
515 | /* | 515 | /* |
516 | * Common arguments to the unlink call | 516 | * Common arguments to the unlink call |
517 | */ | 517 | */ |
518 | struct nfs_removeargs { | 518 | struct nfs_removeargs { |
519 | const struct nfs_fh *fh; | 519 | const struct nfs_fh *fh; |
520 | struct qstr name; | 520 | struct qstr name; |
521 | const u32 * bitmask; | 521 | const u32 * bitmask; |
522 | struct nfs4_sequence_args seq_args; | 522 | struct nfs4_sequence_args seq_args; |
523 | }; | 523 | }; |
524 | 524 | ||
525 | struct nfs_removeres { | 525 | struct nfs_removeres { |
526 | const struct nfs_server *server; | 526 | const struct nfs_server *server; |
527 | struct nfs_fattr *dir_attr; | 527 | struct nfs_fattr *dir_attr; |
528 | struct nfs4_change_info cinfo; | 528 | struct nfs4_change_info cinfo; |
529 | struct nfs4_sequence_res seq_res; | 529 | struct nfs4_sequence_res seq_res; |
530 | }; | 530 | }; |
531 | 531 | ||
532 | /* | 532 | /* |
533 | * Common arguments to the rename call | 533 | * Common arguments to the rename call |
534 | */ | 534 | */ |
535 | struct nfs_renameargs { | 535 | struct nfs_renameargs { |
536 | const struct nfs_fh *old_dir; | 536 | const struct nfs_fh *old_dir; |
537 | const struct nfs_fh *new_dir; | 537 | const struct nfs_fh *new_dir; |
538 | const struct qstr *old_name; | 538 | const struct qstr *old_name; |
539 | const struct qstr *new_name; | 539 | const struct qstr *new_name; |
540 | const u32 *bitmask; | 540 | const u32 *bitmask; |
541 | struct nfs4_sequence_args seq_args; | 541 | struct nfs4_sequence_args seq_args; |
542 | }; | 542 | }; |
543 | 543 | ||
544 | struct nfs_renameres { | 544 | struct nfs_renameres { |
545 | const struct nfs_server *server; | 545 | const struct nfs_server *server; |
546 | struct nfs4_change_info old_cinfo; | 546 | struct nfs4_change_info old_cinfo; |
547 | struct nfs_fattr *old_fattr; | 547 | struct nfs_fattr *old_fattr; |
548 | struct nfs4_change_info new_cinfo; | 548 | struct nfs4_change_info new_cinfo; |
549 | struct nfs_fattr *new_fattr; | 549 | struct nfs_fattr *new_fattr; |
550 | struct nfs4_sequence_res seq_res; | 550 | struct nfs4_sequence_res seq_res; |
551 | }; | 551 | }; |
552 | 552 | ||
553 | /* | 553 | /* |
554 | * Argument struct for decode_entry function | 554 | * Argument struct for decode_entry function |
555 | */ | 555 | */ |
556 | struct nfs_entry { | 556 | struct nfs_entry { |
557 | __u64 ino; | 557 | __u64 ino; |
558 | __u64 cookie, | 558 | __u64 cookie, |
559 | prev_cookie; | 559 | prev_cookie; |
560 | const char * name; | 560 | const char * name; |
561 | unsigned int len; | 561 | unsigned int len; |
562 | int eof; | 562 | int eof; |
563 | struct nfs_fh * fh; | 563 | struct nfs_fh * fh; |
564 | struct nfs_fattr * fattr; | 564 | struct nfs_fattr * fattr; |
565 | unsigned char d_type; | 565 | unsigned char d_type; |
566 | struct nfs_server * server; | 566 | struct nfs_server * server; |
567 | }; | 567 | }; |
568 | 568 | ||
569 | /* | 569 | /* |
570 | * The following types are for NFSv2 only. | 570 | * The following types are for NFSv2 only. |
571 | */ | 571 | */ |
572 | struct nfs_sattrargs { | 572 | struct nfs_sattrargs { |
573 | struct nfs_fh * fh; | 573 | struct nfs_fh * fh; |
574 | struct iattr * sattr; | 574 | struct iattr * sattr; |
575 | }; | 575 | }; |
576 | 576 | ||
577 | struct nfs_diropargs { | 577 | struct nfs_diropargs { |
578 | struct nfs_fh * fh; | 578 | struct nfs_fh * fh; |
579 | const char * name; | 579 | const char * name; |
580 | unsigned int len; | 580 | unsigned int len; |
581 | }; | 581 | }; |
582 | 582 | ||
583 | struct nfs_createargs { | 583 | struct nfs_createargs { |
584 | struct nfs_fh * fh; | 584 | struct nfs_fh * fh; |
585 | const char * name; | 585 | const char * name; |
586 | unsigned int len; | 586 | unsigned int len; |
587 | struct iattr * sattr; | 587 | struct iattr * sattr; |
588 | }; | 588 | }; |
589 | 589 | ||
590 | struct nfs_setattrargs { | 590 | struct nfs_setattrargs { |
591 | struct nfs_fh * fh; | 591 | struct nfs_fh * fh; |
592 | nfs4_stateid stateid; | 592 | nfs4_stateid stateid; |
593 | struct iattr * iap; | 593 | struct iattr * iap; |
594 | const struct nfs_server * server; /* Needed for name mapping */ | 594 | const struct nfs_server * server; /* Needed for name mapping */ |
595 | const u32 * bitmask; | 595 | const u32 * bitmask; |
596 | struct nfs4_sequence_args seq_args; | 596 | struct nfs4_sequence_args seq_args; |
597 | }; | 597 | }; |
598 | 598 | ||
599 | struct nfs_setaclargs { | 599 | struct nfs_setaclargs { |
600 | struct nfs_fh * fh; | 600 | struct nfs_fh * fh; |
601 | size_t acl_len; | 601 | size_t acl_len; |
602 | unsigned int acl_pgbase; | 602 | unsigned int acl_pgbase; |
603 | struct page ** acl_pages; | 603 | struct page ** acl_pages; |
604 | struct nfs4_sequence_args seq_args; | 604 | struct nfs4_sequence_args seq_args; |
605 | }; | 605 | }; |
606 | 606 | ||
607 | struct nfs_setaclres { | 607 | struct nfs_setaclres { |
608 | struct nfs4_sequence_res seq_res; | 608 | struct nfs4_sequence_res seq_res; |
609 | }; | 609 | }; |
610 | 610 | ||
611 | struct nfs_getaclargs { | 611 | struct nfs_getaclargs { |
612 | struct nfs_fh * fh; | 612 | struct nfs_fh * fh; |
613 | size_t acl_len; | 613 | size_t acl_len; |
614 | unsigned int acl_pgbase; | 614 | unsigned int acl_pgbase; |
615 | struct page ** acl_pages; | 615 | struct page ** acl_pages; |
616 | struct page * acl_scratch; | 616 | struct page * acl_scratch; |
617 | struct nfs4_sequence_args seq_args; | 617 | struct nfs4_sequence_args seq_args; |
618 | }; | 618 | }; |
619 | 619 | ||
620 | /* getxattr ACL interface flags */ | 620 | /* getxattr ACL interface flags */ |
621 | #define NFS4_ACL_LEN_REQUEST 0x0001 /* zero length getxattr buffer */ | 621 | #define NFS4_ACL_LEN_REQUEST 0x0001 /* zero length getxattr buffer */ |
622 | struct nfs_getaclres { | 622 | struct nfs_getaclres { |
623 | size_t acl_len; | 623 | size_t acl_len; |
624 | size_t acl_data_offset; | 624 | size_t acl_data_offset; |
625 | int acl_flags; | 625 | int acl_flags; |
626 | struct nfs4_sequence_res seq_res; | 626 | struct nfs4_sequence_res seq_res; |
627 | }; | 627 | }; |
628 | 628 | ||
629 | struct nfs_setattrres { | 629 | struct nfs_setattrres { |
630 | struct nfs_fattr * fattr; | 630 | struct nfs_fattr * fattr; |
631 | const struct nfs_server * server; | 631 | const struct nfs_server * server; |
632 | struct nfs4_sequence_res seq_res; | 632 | struct nfs4_sequence_res seq_res; |
633 | }; | 633 | }; |
634 | 634 | ||
635 | struct nfs_linkargs { | 635 | struct nfs_linkargs { |
636 | struct nfs_fh * fromfh; | 636 | struct nfs_fh * fromfh; |
637 | struct nfs_fh * tofh; | 637 | struct nfs_fh * tofh; |
638 | const char * toname; | 638 | const char * toname; |
639 | unsigned int tolen; | 639 | unsigned int tolen; |
640 | }; | 640 | }; |
641 | 641 | ||
642 | struct nfs_symlinkargs { | 642 | struct nfs_symlinkargs { |
643 | struct nfs_fh * fromfh; | 643 | struct nfs_fh * fromfh; |
644 | const char * fromname; | 644 | const char * fromname; |
645 | unsigned int fromlen; | 645 | unsigned int fromlen; |
646 | struct page ** pages; | 646 | struct page ** pages; |
647 | unsigned int pathlen; | 647 | unsigned int pathlen; |
648 | struct iattr * sattr; | 648 | struct iattr * sattr; |
649 | }; | 649 | }; |
650 | 650 | ||
651 | struct nfs_readdirargs { | 651 | struct nfs_readdirargs { |
652 | struct nfs_fh * fh; | 652 | struct nfs_fh * fh; |
653 | __u32 cookie; | 653 | __u32 cookie; |
654 | unsigned int count; | 654 | unsigned int count; |
655 | struct page ** pages; | 655 | struct page ** pages; |
656 | }; | 656 | }; |
657 | 657 | ||
658 | struct nfs3_getaclargs { | 658 | struct nfs3_getaclargs { |
659 | struct nfs_fh * fh; | 659 | struct nfs_fh * fh; |
660 | int mask; | 660 | int mask; |
661 | struct page ** pages; | 661 | struct page ** pages; |
662 | }; | 662 | }; |
663 | 663 | ||
664 | struct nfs3_setaclargs { | 664 | struct nfs3_setaclargs { |
665 | struct inode * inode; | 665 | struct inode * inode; |
666 | int mask; | 666 | int mask; |
667 | struct posix_acl * acl_access; | 667 | struct posix_acl * acl_access; |
668 | struct posix_acl * acl_default; | 668 | struct posix_acl * acl_default; |
669 | size_t len; | 669 | size_t len; |
670 | unsigned int npages; | 670 | unsigned int npages; |
671 | struct page ** pages; | 671 | struct page ** pages; |
672 | }; | 672 | }; |
673 | 673 | ||
674 | struct nfs_diropok { | 674 | struct nfs_diropok { |
675 | struct nfs_fh * fh; | 675 | struct nfs_fh * fh; |
676 | struct nfs_fattr * fattr; | 676 | struct nfs_fattr * fattr; |
677 | }; | 677 | }; |
678 | 678 | ||
679 | struct nfs_readlinkargs { | 679 | struct nfs_readlinkargs { |
680 | struct nfs_fh * fh; | 680 | struct nfs_fh * fh; |
681 | unsigned int pgbase; | 681 | unsigned int pgbase; |
682 | unsigned int pglen; | 682 | unsigned int pglen; |
683 | struct page ** pages; | 683 | struct page ** pages; |
684 | }; | 684 | }; |
685 | 685 | ||
686 | struct nfs3_sattrargs { | 686 | struct nfs3_sattrargs { |
687 | struct nfs_fh * fh; | 687 | struct nfs_fh * fh; |
688 | struct iattr * sattr; | 688 | struct iattr * sattr; |
689 | unsigned int guard; | 689 | unsigned int guard; |
690 | struct timespec guardtime; | 690 | struct timespec guardtime; |
691 | }; | 691 | }; |
692 | 692 | ||
693 | struct nfs3_diropargs { | 693 | struct nfs3_diropargs { |
694 | struct nfs_fh * fh; | 694 | struct nfs_fh * fh; |
695 | const char * name; | 695 | const char * name; |
696 | unsigned int len; | 696 | unsigned int len; |
697 | }; | 697 | }; |
698 | 698 | ||
699 | struct nfs3_accessargs { | 699 | struct nfs3_accessargs { |
700 | struct nfs_fh * fh; | 700 | struct nfs_fh * fh; |
701 | __u32 access; | 701 | __u32 access; |
702 | }; | 702 | }; |
703 | 703 | ||
704 | struct nfs3_createargs { | 704 | struct nfs3_createargs { |
705 | struct nfs_fh * fh; | 705 | struct nfs_fh * fh; |
706 | const char * name; | 706 | const char * name; |
707 | unsigned int len; | 707 | unsigned int len; |
708 | struct iattr * sattr; | 708 | struct iattr * sattr; |
709 | enum nfs3_createmode createmode; | 709 | enum nfs3_createmode createmode; |
710 | __be32 verifier[2]; | 710 | __be32 verifier[2]; |
711 | }; | 711 | }; |
712 | 712 | ||
713 | struct nfs3_mkdirargs { | 713 | struct nfs3_mkdirargs { |
714 | struct nfs_fh * fh; | 714 | struct nfs_fh * fh; |
715 | const char * name; | 715 | const char * name; |
716 | unsigned int len; | 716 | unsigned int len; |
717 | struct iattr * sattr; | 717 | struct iattr * sattr; |
718 | }; | 718 | }; |
719 | 719 | ||
720 | struct nfs3_symlinkargs { | 720 | struct nfs3_symlinkargs { |
721 | struct nfs_fh * fromfh; | 721 | struct nfs_fh * fromfh; |
722 | const char * fromname; | 722 | const char * fromname; |
723 | unsigned int fromlen; | 723 | unsigned int fromlen; |
724 | struct page ** pages; | 724 | struct page ** pages; |
725 | unsigned int pathlen; | 725 | unsigned int pathlen; |
726 | struct iattr * sattr; | 726 | struct iattr * sattr; |
727 | }; | 727 | }; |
728 | 728 | ||
729 | struct nfs3_mknodargs { | 729 | struct nfs3_mknodargs { |
730 | struct nfs_fh * fh; | 730 | struct nfs_fh * fh; |
731 | const char * name; | 731 | const char * name; |
732 | unsigned int len; | 732 | unsigned int len; |
733 | enum nfs3_ftype type; | 733 | enum nfs3_ftype type; |
734 | struct iattr * sattr; | 734 | struct iattr * sattr; |
735 | dev_t rdev; | 735 | dev_t rdev; |
736 | }; | 736 | }; |
737 | 737 | ||
738 | struct nfs3_linkargs { | 738 | struct nfs3_linkargs { |
739 | struct nfs_fh * fromfh; | 739 | struct nfs_fh * fromfh; |
740 | struct nfs_fh * tofh; | 740 | struct nfs_fh * tofh; |
741 | const char * toname; | 741 | const char * toname; |
742 | unsigned int tolen; | 742 | unsigned int tolen; |
743 | }; | 743 | }; |
744 | 744 | ||
745 | struct nfs3_readdirargs { | 745 | struct nfs3_readdirargs { |
746 | struct nfs_fh * fh; | 746 | struct nfs_fh * fh; |
747 | __u64 cookie; | 747 | __u64 cookie; |
748 | __be32 verf[2]; | 748 | __be32 verf[2]; |
749 | int plus; | 749 | int plus; |
750 | unsigned int count; | 750 | unsigned int count; |
751 | struct page ** pages; | 751 | struct page ** pages; |
752 | }; | 752 | }; |
753 | 753 | ||
754 | struct nfs3_diropres { | 754 | struct nfs3_diropres { |
755 | struct nfs_fattr * dir_attr; | 755 | struct nfs_fattr * dir_attr; |
756 | struct nfs_fh * fh; | 756 | struct nfs_fh * fh; |
757 | struct nfs_fattr * fattr; | 757 | struct nfs_fattr * fattr; |
758 | }; | 758 | }; |
759 | 759 | ||
760 | struct nfs3_accessres { | 760 | struct nfs3_accessres { |
761 | struct nfs_fattr * fattr; | 761 | struct nfs_fattr * fattr; |
762 | __u32 access; | 762 | __u32 access; |
763 | }; | 763 | }; |
764 | 764 | ||
765 | struct nfs3_readlinkargs { | 765 | struct nfs3_readlinkargs { |
766 | struct nfs_fh * fh; | 766 | struct nfs_fh * fh; |
767 | unsigned int pgbase; | 767 | unsigned int pgbase; |
768 | unsigned int pglen; | 768 | unsigned int pglen; |
769 | struct page ** pages; | 769 | struct page ** pages; |
770 | }; | 770 | }; |
771 | 771 | ||
772 | struct nfs3_linkres { | 772 | struct nfs3_linkres { |
773 | struct nfs_fattr * dir_attr; | 773 | struct nfs_fattr * dir_attr; |
774 | struct nfs_fattr * fattr; | 774 | struct nfs_fattr * fattr; |
775 | }; | 775 | }; |
776 | 776 | ||
777 | struct nfs3_readdirres { | 777 | struct nfs3_readdirres { |
778 | struct nfs_fattr * dir_attr; | 778 | struct nfs_fattr * dir_attr; |
779 | __be32 * verf; | 779 | __be32 * verf; |
780 | int plus; | 780 | int plus; |
781 | }; | 781 | }; |
782 | 782 | ||
783 | struct nfs3_getaclres { | 783 | struct nfs3_getaclres { |
784 | struct nfs_fattr * fattr; | 784 | struct nfs_fattr * fattr; |
785 | int mask; | 785 | int mask; |
786 | unsigned int acl_access_count; | 786 | unsigned int acl_access_count; |
787 | unsigned int acl_default_count; | 787 | unsigned int acl_default_count; |
788 | struct posix_acl * acl_access; | 788 | struct posix_acl * acl_access; |
789 | struct posix_acl * acl_default; | 789 | struct posix_acl * acl_default; |
790 | }; | 790 | }; |
791 | 791 | ||
792 | #ifdef CONFIG_NFS_V4 | 792 | #ifdef CONFIG_NFS_V4 |
793 | 793 | ||
794 | typedef u64 clientid4; | 794 | typedef u64 clientid4; |
795 | 795 | ||
796 | struct nfs4_accessargs { | 796 | struct nfs4_accessargs { |
797 | const struct nfs_fh * fh; | 797 | const struct nfs_fh * fh; |
798 | const u32 * bitmask; | 798 | const u32 * bitmask; |
799 | u32 access; | 799 | u32 access; |
800 | struct nfs4_sequence_args seq_args; | 800 | struct nfs4_sequence_args seq_args; |
801 | }; | 801 | }; |
802 | 802 | ||
803 | struct nfs4_accessres { | 803 | struct nfs4_accessres { |
804 | const struct nfs_server * server; | 804 | const struct nfs_server * server; |
805 | struct nfs_fattr * fattr; | 805 | struct nfs_fattr * fattr; |
806 | u32 supported; | 806 | u32 supported; |
807 | u32 access; | 807 | u32 access; |
808 | struct nfs4_sequence_res seq_res; | 808 | struct nfs4_sequence_res seq_res; |
809 | }; | 809 | }; |
810 | 810 | ||
811 | struct nfs4_create_arg { | 811 | struct nfs4_create_arg { |
812 | u32 ftype; | 812 | u32 ftype; |
813 | union { | 813 | union { |
814 | struct { | 814 | struct { |
815 | struct page ** pages; | 815 | struct page ** pages; |
816 | unsigned int len; | 816 | unsigned int len; |
817 | } symlink; /* NF4LNK */ | 817 | } symlink; /* NF4LNK */ |
818 | struct { | 818 | struct { |
819 | u32 specdata1; | 819 | u32 specdata1; |
820 | u32 specdata2; | 820 | u32 specdata2; |
821 | } device; /* NF4BLK, NF4CHR */ | 821 | } device; /* NF4BLK, NF4CHR */ |
822 | } u; | 822 | } u; |
823 | const struct qstr * name; | 823 | const struct qstr * name; |
824 | const struct nfs_server * server; | 824 | const struct nfs_server * server; |
825 | const struct iattr * attrs; | 825 | const struct iattr * attrs; |
826 | const struct nfs_fh * dir_fh; | 826 | const struct nfs_fh * dir_fh; |
827 | const u32 * bitmask; | 827 | const u32 * bitmask; |
828 | struct nfs4_sequence_args seq_args; | 828 | struct nfs4_sequence_args seq_args; |
829 | }; | 829 | }; |
830 | 830 | ||
831 | struct nfs4_create_res { | 831 | struct nfs4_create_res { |
832 | const struct nfs_server * server; | 832 | const struct nfs_server * server; |
833 | struct nfs_fh * fh; | 833 | struct nfs_fh * fh; |
834 | struct nfs_fattr * fattr; | 834 | struct nfs_fattr * fattr; |
835 | struct nfs4_change_info dir_cinfo; | 835 | struct nfs4_change_info dir_cinfo; |
836 | struct nfs_fattr * dir_fattr; | 836 | struct nfs_fattr * dir_fattr; |
837 | struct nfs4_sequence_res seq_res; | 837 | struct nfs4_sequence_res seq_res; |
838 | }; | 838 | }; |
839 | 839 | ||
840 | struct nfs4_fsinfo_arg { | 840 | struct nfs4_fsinfo_arg { |
841 | const struct nfs_fh * fh; | 841 | const struct nfs_fh * fh; |
842 | const u32 * bitmask; | 842 | const u32 * bitmask; |
843 | struct nfs4_sequence_args seq_args; | 843 | struct nfs4_sequence_args seq_args; |
844 | }; | 844 | }; |
845 | 845 | ||
846 | struct nfs4_fsinfo_res { | 846 | struct nfs4_fsinfo_res { |
847 | struct nfs_fsinfo *fsinfo; | 847 | struct nfs_fsinfo *fsinfo; |
848 | struct nfs4_sequence_res seq_res; | 848 | struct nfs4_sequence_res seq_res; |
849 | }; | 849 | }; |
850 | 850 | ||
851 | struct nfs4_getattr_arg { | 851 | struct nfs4_getattr_arg { |
852 | const struct nfs_fh * fh; | 852 | const struct nfs_fh * fh; |
853 | const u32 * bitmask; | 853 | const u32 * bitmask; |
854 | struct nfs4_sequence_args seq_args; | 854 | struct nfs4_sequence_args seq_args; |
855 | }; | 855 | }; |
856 | 856 | ||
857 | struct nfs4_getattr_res { | 857 | struct nfs4_getattr_res { |
858 | const struct nfs_server * server; | 858 | const struct nfs_server * server; |
859 | struct nfs_fattr * fattr; | 859 | struct nfs_fattr * fattr; |
860 | struct nfs4_sequence_res seq_res; | 860 | struct nfs4_sequence_res seq_res; |
861 | }; | 861 | }; |
862 | 862 | ||
863 | struct nfs4_link_arg { | 863 | struct nfs4_link_arg { |
864 | const struct nfs_fh * fh; | 864 | const struct nfs_fh * fh; |
865 | const struct nfs_fh * dir_fh; | 865 | const struct nfs_fh * dir_fh; |
866 | const struct qstr * name; | 866 | const struct qstr * name; |
867 | const u32 * bitmask; | 867 | const u32 * bitmask; |
868 | struct nfs4_sequence_args seq_args; | 868 | struct nfs4_sequence_args seq_args; |
869 | }; | 869 | }; |
870 | 870 | ||
871 | struct nfs4_link_res { | 871 | struct nfs4_link_res { |
872 | const struct nfs_server * server; | 872 | const struct nfs_server * server; |
873 | struct nfs_fattr * fattr; | 873 | struct nfs_fattr * fattr; |
874 | struct nfs4_change_info cinfo; | 874 | struct nfs4_change_info cinfo; |
875 | struct nfs_fattr * dir_attr; | 875 | struct nfs_fattr * dir_attr; |
876 | struct nfs4_sequence_res seq_res; | 876 | struct nfs4_sequence_res seq_res; |
877 | }; | 877 | }; |
878 | 878 | ||
879 | 879 | ||
880 | struct nfs4_lookup_arg { | 880 | struct nfs4_lookup_arg { |
881 | const struct nfs_fh * dir_fh; | 881 | const struct nfs_fh * dir_fh; |
882 | const struct qstr * name; | 882 | const struct qstr * name; |
883 | const u32 * bitmask; | 883 | const u32 * bitmask; |
884 | struct nfs4_sequence_args seq_args; | 884 | struct nfs4_sequence_args seq_args; |
885 | }; | 885 | }; |
886 | 886 | ||
887 | struct nfs4_lookup_res { | 887 | struct nfs4_lookup_res { |
888 | const struct nfs_server * server; | 888 | const struct nfs_server * server; |
889 | struct nfs_fattr * fattr; | 889 | struct nfs_fattr * fattr; |
890 | struct nfs_fh * fh; | 890 | struct nfs_fh * fh; |
891 | struct nfs4_sequence_res seq_res; | 891 | struct nfs4_sequence_res seq_res; |
892 | }; | 892 | }; |
893 | 893 | ||
894 | struct nfs4_lookup_root_arg { | 894 | struct nfs4_lookup_root_arg { |
895 | const u32 * bitmask; | 895 | const u32 * bitmask; |
896 | struct nfs4_sequence_args seq_args; | 896 | struct nfs4_sequence_args seq_args; |
897 | }; | 897 | }; |
898 | 898 | ||
899 | struct nfs4_pathconf_arg { | 899 | struct nfs4_pathconf_arg { |
900 | const struct nfs_fh * fh; | 900 | const struct nfs_fh * fh; |
901 | const u32 * bitmask; | 901 | const u32 * bitmask; |
902 | struct nfs4_sequence_args seq_args; | 902 | struct nfs4_sequence_args seq_args; |
903 | }; | 903 | }; |
904 | 904 | ||
905 | struct nfs4_pathconf_res { | 905 | struct nfs4_pathconf_res { |
906 | struct nfs_pathconf *pathconf; | 906 | struct nfs_pathconf *pathconf; |
907 | struct nfs4_sequence_res seq_res; | 907 | struct nfs4_sequence_res seq_res; |
908 | }; | 908 | }; |
909 | 909 | ||
910 | struct nfs4_readdir_arg { | 910 | struct nfs4_readdir_arg { |
911 | const struct nfs_fh * fh; | 911 | const struct nfs_fh * fh; |
912 | u64 cookie; | 912 | u64 cookie; |
913 | nfs4_verifier verifier; | 913 | nfs4_verifier verifier; |
914 | u32 count; | 914 | u32 count; |
915 | struct page ** pages; /* zero-copy data */ | 915 | struct page ** pages; /* zero-copy data */ |
916 | unsigned int pgbase; /* zero-copy data */ | 916 | unsigned int pgbase; /* zero-copy data */ |
917 | const u32 * bitmask; | 917 | const u32 * bitmask; |
918 | int plus; | 918 | int plus; |
919 | struct nfs4_sequence_args seq_args; | 919 | struct nfs4_sequence_args seq_args; |
920 | }; | 920 | }; |
921 | 921 | ||
922 | struct nfs4_readdir_res { | 922 | struct nfs4_readdir_res { |
923 | nfs4_verifier verifier; | 923 | nfs4_verifier verifier; |
924 | unsigned int pgbase; | 924 | unsigned int pgbase; |
925 | struct nfs4_sequence_res seq_res; | 925 | struct nfs4_sequence_res seq_res; |
926 | }; | 926 | }; |
927 | 927 | ||
928 | struct nfs4_readlink { | 928 | struct nfs4_readlink { |
929 | const struct nfs_fh * fh; | 929 | const struct nfs_fh * fh; |
930 | unsigned int pgbase; | 930 | unsigned int pgbase; |
931 | unsigned int pglen; /* zero-copy data */ | 931 | unsigned int pglen; /* zero-copy data */ |
932 | struct page ** pages; /* zero-copy data */ | 932 | struct page ** pages; /* zero-copy data */ |
933 | struct nfs4_sequence_args seq_args; | 933 | struct nfs4_sequence_args seq_args; |
934 | }; | 934 | }; |
935 | 935 | ||
936 | struct nfs4_readlink_res { | 936 | struct nfs4_readlink_res { |
937 | struct nfs4_sequence_res seq_res; | 937 | struct nfs4_sequence_res seq_res; |
938 | }; | 938 | }; |
939 | 939 | ||
940 | #define NFS4_SETCLIENTID_NAMELEN (127) | 940 | #define NFS4_SETCLIENTID_NAMELEN (127) |
941 | struct nfs4_setclientid { | 941 | struct nfs4_setclientid { |
942 | const nfs4_verifier * sc_verifier; | 942 | const nfs4_verifier * sc_verifier; |
943 | unsigned int sc_name_len; | 943 | unsigned int sc_name_len; |
944 | char sc_name[NFS4_SETCLIENTID_NAMELEN + 1]; | 944 | char sc_name[NFS4_SETCLIENTID_NAMELEN + 1]; |
945 | u32 sc_prog; | 945 | u32 sc_prog; |
946 | unsigned int sc_netid_len; | 946 | unsigned int sc_netid_len; |
947 | char sc_netid[RPCBIND_MAXNETIDLEN + 1]; | 947 | char sc_netid[RPCBIND_MAXNETIDLEN + 1]; |
948 | unsigned int sc_uaddr_len; | 948 | unsigned int sc_uaddr_len; |
949 | char sc_uaddr[RPCBIND_MAXUADDRLEN + 1]; | 949 | char sc_uaddr[RPCBIND_MAXUADDRLEN + 1]; |
950 | u32 sc_cb_ident; | 950 | u32 sc_cb_ident; |
951 | }; | 951 | }; |
952 | 952 | ||
953 | struct nfs4_setclientid_res { | 953 | struct nfs4_setclientid_res { |
954 | u64 clientid; | 954 | u64 clientid; |
955 | nfs4_verifier confirm; | 955 | nfs4_verifier confirm; |
956 | }; | 956 | }; |
957 | 957 | ||
958 | struct nfs4_statfs_arg { | 958 | struct nfs4_statfs_arg { |
959 | const struct nfs_fh * fh; | 959 | const struct nfs_fh * fh; |
960 | const u32 * bitmask; | 960 | const u32 * bitmask; |
961 | struct nfs4_sequence_args seq_args; | 961 | struct nfs4_sequence_args seq_args; |
962 | }; | 962 | }; |
963 | 963 | ||
964 | struct nfs4_statfs_res { | 964 | struct nfs4_statfs_res { |
965 | struct nfs_fsstat *fsstat; | 965 | struct nfs_fsstat *fsstat; |
966 | struct nfs4_sequence_res seq_res; | 966 | struct nfs4_sequence_res seq_res; |
967 | }; | 967 | }; |
968 | 968 | ||
969 | struct nfs4_server_caps_arg { | 969 | struct nfs4_server_caps_arg { |
970 | struct nfs_fh *fhandle; | 970 | struct nfs_fh *fhandle; |
971 | struct nfs4_sequence_args seq_args; | 971 | struct nfs4_sequence_args seq_args; |
972 | }; | 972 | }; |
973 | 973 | ||
974 | struct nfs4_server_caps_res { | 974 | struct nfs4_server_caps_res { |
975 | u32 attr_bitmask[3]; | 975 | u32 attr_bitmask[3]; |
976 | u32 acl_bitmask; | 976 | u32 acl_bitmask; |
977 | u32 has_links; | 977 | u32 has_links; |
978 | u32 has_symlinks; | 978 | u32 has_symlinks; |
979 | struct nfs4_sequence_res seq_res; | 979 | struct nfs4_sequence_res seq_res; |
980 | }; | 980 | }; |
981 | 981 | ||
982 | #define NFS4_PATHNAME_MAXCOMPONENTS 512 | 982 | #define NFS4_PATHNAME_MAXCOMPONENTS 512 |
983 | struct nfs4_pathname { | 983 | struct nfs4_pathname { |
984 | unsigned int ncomponents; | 984 | unsigned int ncomponents; |
985 | struct nfs4_string components[NFS4_PATHNAME_MAXCOMPONENTS]; | 985 | struct nfs4_string components[NFS4_PATHNAME_MAXCOMPONENTS]; |
986 | }; | 986 | }; |
987 | 987 | ||
988 | #define NFS4_FS_LOCATION_MAXSERVERS 10 | 988 | #define NFS4_FS_LOCATION_MAXSERVERS 10 |
989 | struct nfs4_fs_location { | 989 | struct nfs4_fs_location { |
990 | unsigned int nservers; | 990 | unsigned int nservers; |
991 | struct nfs4_string servers[NFS4_FS_LOCATION_MAXSERVERS]; | 991 | struct nfs4_string servers[NFS4_FS_LOCATION_MAXSERVERS]; |
992 | struct nfs4_pathname rootpath; | 992 | struct nfs4_pathname rootpath; |
993 | }; | 993 | }; |
994 | 994 | ||
995 | #define NFS4_FS_LOCATIONS_MAXENTRIES 10 | 995 | #define NFS4_FS_LOCATIONS_MAXENTRIES 10 |
996 | struct nfs4_fs_locations { | 996 | struct nfs4_fs_locations { |
997 | struct nfs_fattr fattr; | 997 | struct nfs_fattr fattr; |
998 | const struct nfs_server *server; | 998 | const struct nfs_server *server; |
999 | struct nfs4_pathname fs_path; | 999 | struct nfs4_pathname fs_path; |
1000 | int nlocations; | 1000 | int nlocations; |
1001 | struct nfs4_fs_location locations[NFS4_FS_LOCATIONS_MAXENTRIES]; | 1001 | struct nfs4_fs_location locations[NFS4_FS_LOCATIONS_MAXENTRIES]; |
1002 | }; | 1002 | }; |
1003 | 1003 | ||
1004 | struct nfs4_fs_locations_arg { | 1004 | struct nfs4_fs_locations_arg { |
1005 | const struct nfs_fh *dir_fh; | 1005 | const struct nfs_fh *dir_fh; |
1006 | const struct qstr *name; | 1006 | const struct qstr *name; |
1007 | struct page *page; | 1007 | struct page *page; |
1008 | const u32 *bitmask; | 1008 | const u32 *bitmask; |
1009 | struct nfs4_sequence_args seq_args; | 1009 | struct nfs4_sequence_args seq_args; |
1010 | }; | 1010 | }; |
1011 | 1011 | ||
1012 | struct nfs4_fs_locations_res { | 1012 | struct nfs4_fs_locations_res { |
1013 | struct nfs4_fs_locations *fs_locations; | 1013 | struct nfs4_fs_locations *fs_locations; |
1014 | struct nfs4_sequence_res seq_res; | 1014 | struct nfs4_sequence_res seq_res; |
1015 | }; | 1015 | }; |
1016 | 1016 | ||
1017 | struct nfs4_secinfo_oid { | 1017 | struct nfs4_secinfo_oid { |
1018 | unsigned int len; | 1018 | unsigned int len; |
1019 | char data[GSS_OID_MAX_LEN]; | 1019 | char data[GSS_OID_MAX_LEN]; |
1020 | }; | 1020 | }; |
1021 | 1021 | ||
1022 | struct nfs4_secinfo_gss { | 1022 | struct nfs4_secinfo_gss { |
1023 | struct nfs4_secinfo_oid sec_oid4; | 1023 | struct nfs4_secinfo_oid sec_oid4; |
1024 | unsigned int qop4; | 1024 | unsigned int qop4; |
1025 | unsigned int service; | 1025 | unsigned int service; |
1026 | }; | 1026 | }; |
1027 | 1027 | ||
1028 | struct nfs4_secinfo_flavor { | 1028 | struct nfs4_secinfo_flavor { |
1029 | unsigned int flavor; | 1029 | unsigned int flavor; |
1030 | struct nfs4_secinfo_gss gss; | 1030 | struct nfs4_secinfo_gss gss; |
1031 | }; | 1031 | }; |
1032 | 1032 | ||
1033 | struct nfs4_secinfo_flavors { | 1033 | struct nfs4_secinfo_flavors { |
1034 | unsigned int num_flavors; | 1034 | unsigned int num_flavors; |
1035 | struct nfs4_secinfo_flavor flavors[0]; | 1035 | struct nfs4_secinfo_flavor flavors[0]; |
1036 | }; | 1036 | }; |
1037 | 1037 | ||
1038 | struct nfs4_secinfo_arg { | 1038 | struct nfs4_secinfo_arg { |
1039 | const struct nfs_fh *dir_fh; | 1039 | const struct nfs_fh *dir_fh; |
1040 | const struct qstr *name; | 1040 | const struct qstr *name; |
1041 | struct nfs4_sequence_args seq_args; | 1041 | struct nfs4_sequence_args seq_args; |
1042 | }; | 1042 | }; |
1043 | 1043 | ||
1044 | struct nfs4_secinfo_res { | 1044 | struct nfs4_secinfo_res { |
1045 | struct nfs4_secinfo_flavors *flavors; | 1045 | struct nfs4_secinfo_flavors *flavors; |
1046 | struct nfs4_sequence_res seq_res; | 1046 | struct nfs4_sequence_res seq_res; |
1047 | }; | 1047 | }; |
1048 | 1048 | ||
1049 | #endif /* CONFIG_NFS_V4 */ | 1049 | #endif /* CONFIG_NFS_V4 */ |
1050 | 1050 | ||
1051 | struct nfstime4 { | 1051 | struct nfstime4 { |
1052 | u64 seconds; | 1052 | u64 seconds; |
1053 | u32 nseconds; | 1053 | u32 nseconds; |
1054 | }; | 1054 | }; |
1055 | 1055 | ||
1056 | #ifdef CONFIG_NFS_V4_1 | 1056 | #ifdef CONFIG_NFS_V4_1 |
1057 | struct nfs_impl_id4 { | 1057 | struct nfs_impl_id4 { |
1058 | u32 domain_len; | 1058 | u32 domain_len; |
1059 | char *domain; | 1059 | char *domain; |
1060 | u32 name_len; | 1060 | u32 name_len; |
1061 | char *name; | 1061 | char *name; |
1062 | struct nfstime4 date; | 1062 | struct nfstime4 date; |
1063 | }; | 1063 | }; |
1064 | 1064 | ||
1065 | #define NFS4_EXCHANGE_ID_LEN (48) | 1065 | #define NFS4_EXCHANGE_ID_LEN (48) |
1066 | struct nfs41_exchange_id_args { | 1066 | struct nfs41_exchange_id_args { |
1067 | struct nfs_client *client; | 1067 | struct nfs_client *client; |
1068 | nfs4_verifier *verifier; | 1068 | nfs4_verifier *verifier; |
1069 | unsigned int id_len; | 1069 | unsigned int id_len; |
1070 | char id[NFS4_EXCHANGE_ID_LEN]; | 1070 | char id[NFS4_EXCHANGE_ID_LEN]; |
1071 | u32 flags; | 1071 | u32 flags; |
1072 | }; | 1072 | }; |
1073 | 1073 | ||
1074 | struct server_owner { | 1074 | struct server_owner { |
1075 | uint64_t minor_id; | 1075 | uint64_t minor_id; |
1076 | uint32_t major_id_sz; | 1076 | uint32_t major_id_sz; |
1077 | char major_id[NFS4_OPAQUE_LIMIT]; | 1077 | char major_id[NFS4_OPAQUE_LIMIT]; |
1078 | }; | 1078 | }; |
1079 | 1079 | ||
1080 | struct server_scope { | 1080 | struct server_scope { |
1081 | uint32_t server_scope_sz; | 1081 | uint32_t server_scope_sz; |
1082 | char server_scope[NFS4_OPAQUE_LIMIT]; | 1082 | char server_scope[NFS4_OPAQUE_LIMIT]; |
1083 | }; | 1083 | }; |
1084 | 1084 | ||
1085 | struct nfs41_exchange_id_res { | 1085 | struct nfs41_exchange_id_res { |
1086 | struct nfs_client *client; | 1086 | struct nfs_client *client; |
1087 | u32 flags; | 1087 | u32 flags; |
1088 | struct server_scope *server_scope; | 1088 | struct server_scope *server_scope; |
1089 | }; | 1089 | }; |
1090 | 1090 | ||
1091 | struct nfs41_create_session_args { | 1091 | struct nfs41_create_session_args { |
1092 | struct nfs_client *client; | 1092 | struct nfs_client *client; |
1093 | uint32_t flags; | 1093 | uint32_t flags; |
1094 | uint32_t cb_program; | 1094 | uint32_t cb_program; |
1095 | struct nfs4_channel_attrs fc_attrs; /* Fore Channel */ | 1095 | struct nfs4_channel_attrs fc_attrs; /* Fore Channel */ |
1096 | struct nfs4_channel_attrs bc_attrs; /* Back Channel */ | 1096 | struct nfs4_channel_attrs bc_attrs; /* Back Channel */ |
1097 | }; | 1097 | }; |
1098 | 1098 | ||
1099 | struct nfs41_create_session_res { | 1099 | struct nfs41_create_session_res { |
1100 | struct nfs_client *client; | 1100 | struct nfs_client *client; |
1101 | }; | 1101 | }; |
1102 | 1102 | ||
1103 | struct nfs41_reclaim_complete_args { | 1103 | struct nfs41_reclaim_complete_args { |
1104 | /* In the future extend to include curr_fh for use with migration */ | 1104 | /* In the future extend to include curr_fh for use with migration */ |
1105 | unsigned char one_fs:1; | 1105 | unsigned char one_fs:1; |
1106 | struct nfs4_sequence_args seq_args; | 1106 | struct nfs4_sequence_args seq_args; |
1107 | }; | 1107 | }; |
1108 | 1108 | ||
1109 | struct nfs41_reclaim_complete_res { | 1109 | struct nfs41_reclaim_complete_res { |
1110 | struct nfs4_sequence_res seq_res; | 1110 | struct nfs4_sequence_res seq_res; |
1111 | }; | 1111 | }; |
1112 | 1112 | ||
1113 | #define SECINFO_STYLE_CURRENT_FH 0 | 1113 | #define SECINFO_STYLE_CURRENT_FH 0 |
1114 | #define SECINFO_STYLE_PARENT 1 | 1114 | #define SECINFO_STYLE_PARENT 1 |
1115 | struct nfs41_secinfo_no_name_args { | 1115 | struct nfs41_secinfo_no_name_args { |
1116 | int style; | 1116 | int style; |
1117 | struct nfs4_sequence_args seq_args; | 1117 | struct nfs4_sequence_args seq_args; |
1118 | }; | 1118 | }; |
1119 | 1119 | ||
1120 | struct nfs41_test_stateid_args { | 1120 | struct nfs41_test_stateid_args { |
1121 | nfs4_stateid *stateid; | 1121 | nfs4_stateid *stateid; |
1122 | struct nfs4_sequence_args seq_args; | 1122 | struct nfs4_sequence_args seq_args; |
1123 | }; | 1123 | }; |
1124 | 1124 | ||
1125 | struct nfs41_test_stateid_res { | 1125 | struct nfs41_test_stateid_res { |
1126 | unsigned int status; | 1126 | unsigned int status; |
1127 | struct nfs4_sequence_res seq_res; | 1127 | struct nfs4_sequence_res seq_res; |
1128 | }; | 1128 | }; |
1129 | 1129 | ||
1130 | struct nfs41_free_stateid_args { | 1130 | struct nfs41_free_stateid_args { |
1131 | nfs4_stateid *stateid; | 1131 | nfs4_stateid *stateid; |
1132 | struct nfs4_sequence_args seq_args; | 1132 | struct nfs4_sequence_args seq_args; |
1133 | }; | 1133 | }; |
1134 | 1134 | ||
1135 | struct nfs41_free_stateid_res { | 1135 | struct nfs41_free_stateid_res { |
1136 | unsigned int status; | 1136 | unsigned int status; |
1137 | struct nfs4_sequence_res seq_res; | 1137 | struct nfs4_sequence_res seq_res; |
1138 | }; | 1138 | }; |
1139 | 1139 | ||
1140 | #endif /* CONFIG_NFS_V4_1 */ | 1140 | #endif /* CONFIG_NFS_V4_1 */ |
1141 | 1141 | ||
1142 | struct nfs_page; | 1142 | struct nfs_page; |
1143 | 1143 | ||
1144 | #define NFS_PAGEVEC_SIZE (8U) | 1144 | #define NFS_PAGEVEC_SIZE (8U) |
1145 | 1145 | ||
1146 | struct nfs_read_data { | 1146 | struct nfs_read_data { |
1147 | struct rpc_task task; | 1147 | struct rpc_task task; |
1148 | struct inode *inode; | 1148 | struct inode *inode; |
1149 | struct rpc_cred *cred; | 1149 | struct rpc_cred *cred; |
1150 | struct nfs_fattr fattr; /* fattr storage */ | 1150 | struct nfs_fattr fattr; /* fattr storage */ |
1151 | struct list_head pages; /* Coalesced read requests */ | 1151 | struct list_head pages; /* Coalesced read requests */ |
1152 | struct list_head list; /* lists of struct nfs_read_data */ | 1152 | struct list_head list; /* lists of struct nfs_read_data */ |
1153 | struct nfs_page *req; /* multi ops per nfs_page */ | 1153 | struct nfs_page *req; /* multi ops per nfs_page */ |
1154 | struct page **pagevec; | 1154 | struct page **pagevec; |
1155 | unsigned int npages; /* Max length of pagevec */ | 1155 | unsigned int npages; /* Max length of pagevec */ |
1156 | struct nfs_readargs args; | 1156 | struct nfs_readargs args; |
1157 | struct nfs_readres res; | 1157 | struct nfs_readres res; |
1158 | unsigned long timestamp; /* For lease renewal */ | 1158 | unsigned long timestamp; /* For lease renewal */ |
1159 | struct pnfs_layout_segment *lseg; | 1159 | struct pnfs_layout_segment *lseg; |
1160 | struct nfs_client *ds_clp; /* pNFS data server */ | 1160 | struct nfs_client *ds_clp; /* pNFS data server */ |
1161 | const struct rpc_call_ops *mds_ops; | 1161 | const struct rpc_call_ops *mds_ops; |
1162 | int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data); | 1162 | int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data); |
1163 | __u64 mds_offset; | 1163 | __u64 mds_offset; |
1164 | int pnfs_error; | 1164 | int pnfs_error; |
1165 | struct page *page_array[NFS_PAGEVEC_SIZE]; | 1165 | struct page *page_array[NFS_PAGEVEC_SIZE]; |
1166 | }; | 1166 | }; |
1167 | 1167 | ||
1168 | struct nfs_write_data { | 1168 | struct nfs_write_data { |
1169 | struct rpc_task task; | 1169 | struct rpc_task task; |
1170 | struct inode *inode; | 1170 | struct inode *inode; |
1171 | struct rpc_cred *cred; | 1171 | struct rpc_cred *cred; |
1172 | struct nfs_fattr fattr; | 1172 | struct nfs_fattr fattr; |
1173 | struct nfs_writeverf verf; | 1173 | struct nfs_writeverf verf; |
1174 | struct list_head pages; /* Coalesced requests we wish to flush */ | 1174 | struct list_head pages; /* Coalesced requests we wish to flush */ |
1175 | struct list_head list; /* lists of struct nfs_write_data */ | 1175 | struct list_head list; /* lists of struct nfs_write_data */ |
1176 | struct nfs_page *req; /* multi ops per nfs_page */ | 1176 | struct nfs_page *req; /* multi ops per nfs_page */ |
1177 | struct page **pagevec; | 1177 | struct page **pagevec; |
1178 | unsigned int npages; /* Max length of pagevec */ | 1178 | unsigned int npages; /* Max length of pagevec */ |
1179 | struct nfs_writeargs args; /* argument struct */ | 1179 | struct nfs_writeargs args; /* argument struct */ |
1180 | struct nfs_writeres res; /* result struct */ | 1180 | struct nfs_writeres res; /* result struct */ |
1181 | struct pnfs_layout_segment *lseg; | 1181 | struct pnfs_layout_segment *lseg; |
1182 | struct nfs_client *ds_clp; /* pNFS data server */ | 1182 | struct nfs_client *ds_clp; /* pNFS data server */ |
1183 | int ds_commit_index; | 1183 | int ds_commit_index; |
1184 | const struct rpc_call_ops *mds_ops; | 1184 | const struct rpc_call_ops *mds_ops; |
1185 | int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data); | 1185 | int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data); |
1186 | #ifdef CONFIG_NFS_V4 | 1186 | #ifdef CONFIG_NFS_V4 |
1187 | unsigned long timestamp; /* For lease renewal */ | 1187 | unsigned long timestamp; /* For lease renewal */ |
1188 | #endif | 1188 | #endif |
1189 | __u64 mds_offset; /* Filelayout dense stripe */ | 1189 | __u64 mds_offset; /* Filelayout dense stripe */ |
1190 | int pnfs_error; | 1190 | int pnfs_error; |
1191 | struct page *page_array[NFS_PAGEVEC_SIZE]; | 1191 | struct page *page_array[NFS_PAGEVEC_SIZE]; |
1192 | }; | 1192 | }; |
1193 | 1193 | ||
1194 | struct nfs_access_entry; | 1194 | struct nfs_access_entry; |
1195 | struct nfs_client; | 1195 | struct nfs_client; |
1196 | struct rpc_timeout; | 1196 | struct rpc_timeout; |
1197 | 1197 | ||
1198 | /* | 1198 | /* |
1199 | * RPC procedure vector for NFSv2/NFSv3 demuxing | 1199 | * RPC procedure vector for NFSv2/NFSv3 demuxing |
1200 | */ | 1200 | */ |
1201 | struct nfs_rpc_ops { | 1201 | struct nfs_rpc_ops { |
1202 | u32 version; /* Protocol version */ | 1202 | u32 version; /* Protocol version */ |
1203 | const struct dentry_operations *dentry_ops; | 1203 | const struct dentry_operations *dentry_ops; |
1204 | const struct inode_operations *dir_inode_ops; | 1204 | const struct inode_operations *dir_inode_ops; |
1205 | const struct inode_operations *file_inode_ops; | 1205 | const struct inode_operations *file_inode_ops; |
1206 | const struct file_operations *file_ops; | 1206 | const struct file_operations *file_ops; |
1207 | 1207 | ||
1208 | int (*getroot) (struct nfs_server *, struct nfs_fh *, | 1208 | int (*getroot) (struct nfs_server *, struct nfs_fh *, |
1209 | struct nfs_fsinfo *); | 1209 | struct nfs_fsinfo *); |
1210 | int (*getattr) (struct nfs_server *, struct nfs_fh *, | 1210 | int (*getattr) (struct nfs_server *, struct nfs_fh *, |
1211 | struct nfs_fattr *); | 1211 | struct nfs_fattr *); |
1212 | int (*setattr) (struct dentry *, struct nfs_fattr *, | 1212 | int (*setattr) (struct dentry *, struct nfs_fattr *, |
1213 | struct iattr *); | 1213 | struct iattr *); |
1214 | int (*lookup) (struct rpc_clnt *clnt, struct inode *, struct qstr *, | 1214 | int (*lookup) (struct rpc_clnt *clnt, struct inode *, struct qstr *, |
1215 | struct nfs_fh *, struct nfs_fattr *); | 1215 | struct nfs_fh *, struct nfs_fattr *); |
1216 | int (*access) (struct inode *, struct nfs_access_entry *); | 1216 | int (*access) (struct inode *, struct nfs_access_entry *); |
1217 | int (*readlink)(struct inode *, struct page *, unsigned int, | 1217 | int (*readlink)(struct inode *, struct page *, unsigned int, |
1218 | unsigned int); | 1218 | unsigned int); |
1219 | int (*create) (struct inode *, struct dentry *, | 1219 | int (*create) (struct inode *, struct dentry *, |
1220 | struct iattr *, int, struct nfs_open_context *); | 1220 | struct iattr *, int, struct nfs_open_context *); |
1221 | int (*remove) (struct inode *, struct qstr *); | 1221 | int (*remove) (struct inode *, struct qstr *); |
1222 | void (*unlink_setup) (struct rpc_message *, struct inode *dir); | 1222 | void (*unlink_setup) (struct rpc_message *, struct inode *dir); |
1223 | int (*unlink_done) (struct rpc_task *, struct inode *); | 1223 | int (*unlink_done) (struct rpc_task *, struct inode *); |
1224 | int (*rename) (struct inode *, struct qstr *, | 1224 | int (*rename) (struct inode *, struct qstr *, |
1225 | struct inode *, struct qstr *); | 1225 | struct inode *, struct qstr *); |
1226 | void (*rename_setup) (struct rpc_message *msg, struct inode *dir); | 1226 | void (*rename_setup) (struct rpc_message *msg, struct inode *dir); |
1227 | int (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir); | 1227 | int (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir); |
1228 | int (*link) (struct inode *, struct inode *, struct qstr *); | 1228 | int (*link) (struct inode *, struct inode *, struct qstr *); |
1229 | int (*symlink) (struct inode *, struct dentry *, struct page *, | 1229 | int (*symlink) (struct inode *, struct dentry *, struct page *, |
1230 | unsigned int, struct iattr *); | 1230 | unsigned int, struct iattr *); |
1231 | int (*mkdir) (struct inode *, struct dentry *, struct iattr *); | 1231 | int (*mkdir) (struct inode *, struct dentry *, struct iattr *); |
1232 | int (*rmdir) (struct inode *, struct qstr *); | 1232 | int (*rmdir) (struct inode *, struct qstr *); |
1233 | int (*readdir) (struct dentry *, struct rpc_cred *, | 1233 | int (*readdir) (struct dentry *, struct rpc_cred *, |
1234 | u64, struct page **, unsigned int, int); | 1234 | u64, struct page **, unsigned int, int); |
1235 | int (*mknod) (struct inode *, struct dentry *, struct iattr *, | 1235 | int (*mknod) (struct inode *, struct dentry *, struct iattr *, |
1236 | dev_t); | 1236 | dev_t); |
1237 | int (*statfs) (struct nfs_server *, struct nfs_fh *, | 1237 | int (*statfs) (struct nfs_server *, struct nfs_fh *, |
1238 | struct nfs_fsstat *); | 1238 | struct nfs_fsstat *); |
1239 | int (*fsinfo) (struct nfs_server *, struct nfs_fh *, | 1239 | int (*fsinfo) (struct nfs_server *, struct nfs_fh *, |
1240 | struct nfs_fsinfo *); | 1240 | struct nfs_fsinfo *); |
1241 | int (*pathconf) (struct nfs_server *, struct nfs_fh *, | 1241 | int (*pathconf) (struct nfs_server *, struct nfs_fh *, |
1242 | struct nfs_pathconf *); | 1242 | struct nfs_pathconf *); |
1243 | int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); | 1243 | int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); |
1244 | int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int); | 1244 | int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int); |
1245 | void (*read_setup) (struct nfs_read_data *, struct rpc_message *); | 1245 | void (*read_setup) (struct nfs_read_data *, struct rpc_message *); |
1246 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); | 1246 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); |
1247 | void (*write_setup) (struct nfs_write_data *, struct rpc_message *); | 1247 | void (*write_setup) (struct nfs_write_data *, struct rpc_message *); |
1248 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); | 1248 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); |
1249 | void (*commit_setup) (struct nfs_write_data *, struct rpc_message *); | 1249 | void (*commit_setup) (struct nfs_write_data *, struct rpc_message *); |
1250 | int (*commit_done) (struct rpc_task *, struct nfs_write_data *); | 1250 | int (*commit_done) (struct rpc_task *, struct nfs_write_data *); |
1251 | int (*lock)(struct file *, int, struct file_lock *); | 1251 | int (*lock)(struct file *, int, struct file_lock *); |
1252 | int (*lock_check_bounds)(const struct file_lock *); | 1252 | int (*lock_check_bounds)(const struct file_lock *); |
1253 | void (*clear_acl_cache)(struct inode *); | 1253 | void (*clear_acl_cache)(struct inode *); |
1254 | void (*close_context)(struct nfs_open_context *ctx, int); | 1254 | void (*close_context)(struct nfs_open_context *ctx, int); |
1255 | struct inode * (*open_context) (struct inode *dir, | 1255 | struct inode * (*open_context) (struct inode *dir, |
1256 | struct nfs_open_context *ctx, | 1256 | struct nfs_open_context *ctx, |
1257 | int open_flags, | 1257 | int open_flags, |
1258 | struct iattr *iattr); | 1258 | struct iattr *iattr); |
1259 | int (*init_client) (struct nfs_client *, const struct rpc_timeout *, | 1259 | int (*init_client) (struct nfs_client *, const struct rpc_timeout *, |
1260 | const char *, rpc_authflavor_t, int); | 1260 | const char *, rpc_authflavor_t, int); |
1261 | int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); | 1261 | int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); |
1262 | }; | 1262 | }; |
1263 | 1263 | ||
1264 | /* | 1264 | /* |
1265 | * NFS_CALL(getattr, inode, (fattr)); | 1265 | * NFS_CALL(getattr, inode, (fattr)); |
1266 | * into | 1266 | * into |
1267 | * NFS_PROTO(inode)->getattr(fattr); | 1267 | * NFS_PROTO(inode)->getattr(fattr); |
1268 | */ | 1268 | */ |
1269 | #define NFS_CALL(op, inode, args) NFS_PROTO(inode)->op args | 1269 | #define NFS_CALL(op, inode, args) NFS_PROTO(inode)->op args |
1270 | 1270 | ||
1271 | /* | 1271 | /* |
1272 | * Function vectors etc. for the NFS client | 1272 | * Function vectors etc. for the NFS client |
1273 | */ | 1273 | */ |
1274 | extern const struct nfs_rpc_ops nfs_v2_clientops; | 1274 | extern const struct nfs_rpc_ops nfs_v2_clientops; |
1275 | extern const struct nfs_rpc_ops nfs_v3_clientops; | 1275 | extern const struct nfs_rpc_ops nfs_v3_clientops; |
1276 | extern const struct nfs_rpc_ops nfs_v4_clientops; | 1276 | extern const struct nfs_rpc_ops nfs_v4_clientops; |
1277 | extern struct rpc_version nfs_version2; | 1277 | extern const struct rpc_version nfs_version2; |
1278 | extern struct rpc_version nfs_version3; | 1278 | extern const struct rpc_version nfs_version3; |
1279 | extern struct rpc_version nfs_version4; | 1279 | extern const struct rpc_version nfs_version4; |
1280 | 1280 | ||
1281 | extern struct rpc_version nfsacl_version3; | 1281 | extern const struct rpc_version nfsacl_version3; |
1282 | extern struct rpc_program nfsacl_program; | 1282 | extern const struct rpc_program nfsacl_program; |
1283 | 1283 | ||
1284 | #endif | 1284 | #endif |
1285 | 1285 |
include/linux/sunrpc/clnt.h
1 | /* | 1 | /* |
2 | * linux/include/linux/sunrpc/clnt.h | 2 | * linux/include/linux/sunrpc/clnt.h |
3 | * | 3 | * |
4 | * Declarations for the high-level RPC client interface | 4 | * Declarations for the high-level RPC client interface |
5 | * | 5 | * |
6 | * Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _LINUX_SUNRPC_CLNT_H | 9 | #ifndef _LINUX_SUNRPC_CLNT_H |
10 | #define _LINUX_SUNRPC_CLNT_H | 10 | #define _LINUX_SUNRPC_CLNT_H |
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/socket.h> | 13 | #include <linux/socket.h> |
14 | #include <linux/in.h> | 14 | #include <linux/in.h> |
15 | #include <linux/in6.h> | 15 | #include <linux/in6.h> |
16 | 16 | ||
17 | #include <linux/sunrpc/msg_prot.h> | 17 | #include <linux/sunrpc/msg_prot.h> |
18 | #include <linux/sunrpc/sched.h> | 18 | #include <linux/sunrpc/sched.h> |
19 | #include <linux/sunrpc/xprt.h> | 19 | #include <linux/sunrpc/xprt.h> |
20 | #include <linux/sunrpc/auth.h> | 20 | #include <linux/sunrpc/auth.h> |
21 | #include <linux/sunrpc/stats.h> | 21 | #include <linux/sunrpc/stats.h> |
22 | #include <linux/sunrpc/xdr.h> | 22 | #include <linux/sunrpc/xdr.h> |
23 | #include <linux/sunrpc/timer.h> | 23 | #include <linux/sunrpc/timer.h> |
24 | #include <asm/signal.h> | 24 | #include <asm/signal.h> |
25 | #include <linux/path.h> | 25 | #include <linux/path.h> |
26 | #include <net/ipv6.h> | 26 | #include <net/ipv6.h> |
27 | 27 | ||
28 | struct rpc_inode; | 28 | struct rpc_inode; |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * The high-level client handle | 31 | * The high-level client handle |
32 | */ | 32 | */ |
33 | struct rpc_clnt { | 33 | struct rpc_clnt { |
34 | atomic_t cl_count; /* Number of references */ | 34 | atomic_t cl_count; /* Number of references */ |
35 | struct list_head cl_clients; /* Global list of clients */ | 35 | struct list_head cl_clients; /* Global list of clients */ |
36 | struct list_head cl_tasks; /* List of tasks */ | 36 | struct list_head cl_tasks; /* List of tasks */ |
37 | spinlock_t cl_lock; /* spinlock */ | 37 | spinlock_t cl_lock; /* spinlock */ |
38 | struct rpc_xprt * cl_xprt; /* transport */ | 38 | struct rpc_xprt * cl_xprt; /* transport */ |
39 | struct rpc_procinfo * cl_procinfo; /* procedure info */ | 39 | struct rpc_procinfo * cl_procinfo; /* procedure info */ |
40 | u32 cl_prog, /* RPC program number */ | 40 | u32 cl_prog, /* RPC program number */ |
41 | cl_vers, /* RPC version number */ | 41 | cl_vers, /* RPC version number */ |
42 | cl_maxproc; /* max procedure number */ | 42 | cl_maxproc; /* max procedure number */ |
43 | 43 | ||
44 | const char * cl_server; /* server machine name */ | 44 | const char * cl_server; /* server machine name */ |
45 | const char * cl_protname; /* protocol name */ | 45 | const char * cl_protname; /* protocol name */ |
46 | struct rpc_auth * cl_auth; /* authenticator */ | 46 | struct rpc_auth * cl_auth; /* authenticator */ |
47 | struct rpc_stat * cl_stats; /* per-program statistics */ | 47 | struct rpc_stat * cl_stats; /* per-program statistics */ |
48 | struct rpc_iostats * cl_metrics; /* per-client statistics */ | 48 | struct rpc_iostats * cl_metrics; /* per-client statistics */ |
49 | 49 | ||
50 | unsigned int cl_softrtry : 1,/* soft timeouts */ | 50 | unsigned int cl_softrtry : 1,/* soft timeouts */ |
51 | cl_discrtry : 1,/* disconnect before retry */ | 51 | cl_discrtry : 1,/* disconnect before retry */ |
52 | cl_autobind : 1,/* use getport() */ | 52 | cl_autobind : 1,/* use getport() */ |
53 | cl_chatty : 1;/* be verbose */ | 53 | cl_chatty : 1;/* be verbose */ |
54 | 54 | ||
55 | struct rpc_rtt * cl_rtt; /* RTO estimator data */ | 55 | struct rpc_rtt * cl_rtt; /* RTO estimator data */ |
56 | const struct rpc_timeout *cl_timeout; /* Timeout strategy */ | 56 | const struct rpc_timeout *cl_timeout; /* Timeout strategy */ |
57 | 57 | ||
58 | int cl_nodelen; /* nodename length */ | 58 | int cl_nodelen; /* nodename length */ |
59 | char cl_nodename[UNX_MAXNODENAME]; | 59 | char cl_nodename[UNX_MAXNODENAME]; |
60 | struct dentry * cl_dentry; | 60 | struct dentry * cl_dentry; |
61 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ | 61 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ |
62 | struct rpc_rtt cl_rtt_default; | 62 | struct rpc_rtt cl_rtt_default; |
63 | struct rpc_timeout cl_timeout_default; | 63 | struct rpc_timeout cl_timeout_default; |
64 | struct rpc_program * cl_program; | 64 | const struct rpc_program *cl_program; |
65 | char *cl_principal; /* target to authenticate to */ | 65 | char *cl_principal; /* target to authenticate to */ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* | 68 | /* |
69 | * General RPC program info | 69 | * General RPC program info |
70 | */ | 70 | */ |
71 | #define RPC_MAXVERSION 4 | 71 | #define RPC_MAXVERSION 4 |
72 | struct rpc_program { | 72 | struct rpc_program { |
73 | const char * name; /* protocol name */ | 73 | const char * name; /* protocol name */ |
74 | u32 number; /* program number */ | 74 | u32 number; /* program number */ |
75 | unsigned int nrvers; /* number of versions */ | 75 | unsigned int nrvers; /* number of versions */ |
76 | struct rpc_version ** version; /* version array */ | 76 | const struct rpc_version ** version; /* version array */ |
77 | struct rpc_stat * stats; /* statistics */ | 77 | struct rpc_stat * stats; /* statistics */ |
78 | const char * pipe_dir_name; /* path to rpc_pipefs dir */ | 78 | const char * pipe_dir_name; /* path to rpc_pipefs dir */ |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct rpc_version { | 81 | struct rpc_version { |
82 | u32 number; /* version number */ | 82 | u32 number; /* version number */ |
83 | unsigned int nrprocs; /* number of procs */ | 83 | unsigned int nrprocs; /* number of procs */ |
84 | struct rpc_procinfo * procs; /* procedure array */ | 84 | struct rpc_procinfo * procs; /* procedure array */ |
85 | }; | 85 | }; |
86 | 86 | ||
87 | /* | 87 | /* |
88 | * Procedure information | 88 | * Procedure information |
89 | */ | 89 | */ |
90 | struct rpc_procinfo { | 90 | struct rpc_procinfo { |
91 | u32 p_proc; /* RPC procedure number */ | 91 | u32 p_proc; /* RPC procedure number */ |
92 | kxdreproc_t p_encode; /* XDR encode function */ | 92 | kxdreproc_t p_encode; /* XDR encode function */ |
93 | kxdrdproc_t p_decode; /* XDR decode function */ | 93 | kxdrdproc_t p_decode; /* XDR decode function */ |
94 | unsigned int p_arglen; /* argument hdr length (u32) */ | 94 | unsigned int p_arglen; /* argument hdr length (u32) */ |
95 | unsigned int p_replen; /* reply hdr length (u32) */ | 95 | unsigned int p_replen; /* reply hdr length (u32) */ |
96 | unsigned int p_count; /* call count */ | 96 | unsigned int p_count; /* call count */ |
97 | unsigned int p_timer; /* Which RTT timer to use */ | 97 | unsigned int p_timer; /* Which RTT timer to use */ |
98 | u32 p_statidx; /* Which procedure to account */ | 98 | u32 p_statidx; /* Which procedure to account */ |
99 | const char * p_name; /* name of procedure */ | 99 | const char * p_name; /* name of procedure */ |
100 | }; | 100 | }; |
101 | 101 | ||
102 | #ifdef __KERNEL__ | 102 | #ifdef __KERNEL__ |
103 | 103 | ||
104 | struct rpc_create_args { | 104 | struct rpc_create_args { |
105 | struct net *net; | 105 | struct net *net; |
106 | int protocol; | 106 | int protocol; |
107 | struct sockaddr *address; | 107 | struct sockaddr *address; |
108 | size_t addrsize; | 108 | size_t addrsize; |
109 | struct sockaddr *saddress; | 109 | struct sockaddr *saddress; |
110 | const struct rpc_timeout *timeout; | 110 | const struct rpc_timeout *timeout; |
111 | const char *servername; | 111 | const char *servername; |
112 | struct rpc_program *program; | 112 | const struct rpc_program *program; |
113 | u32 prognumber; /* overrides program->number */ | 113 | u32 prognumber; /* overrides program->number */ |
114 | u32 version; | 114 | u32 version; |
115 | rpc_authflavor_t authflavor; | 115 | rpc_authflavor_t authflavor; |
116 | unsigned long flags; | 116 | unsigned long flags; |
117 | char *client_name; | 117 | char *client_name; |
118 | struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */ | 118 | struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */ |
119 | }; | 119 | }; |
120 | 120 | ||
121 | /* Values for "flags" field */ | 121 | /* Values for "flags" field */ |
122 | #define RPC_CLNT_CREATE_HARDRTRY (1UL << 0) | 122 | #define RPC_CLNT_CREATE_HARDRTRY (1UL << 0) |
123 | #define RPC_CLNT_CREATE_AUTOBIND (1UL << 2) | 123 | #define RPC_CLNT_CREATE_AUTOBIND (1UL << 2) |
124 | #define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 3) | 124 | #define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 3) |
125 | #define RPC_CLNT_CREATE_NOPING (1UL << 4) | 125 | #define RPC_CLNT_CREATE_NOPING (1UL << 4) |
126 | #define RPC_CLNT_CREATE_DISCRTRY (1UL << 5) | 126 | #define RPC_CLNT_CREATE_DISCRTRY (1UL << 5) |
127 | #define RPC_CLNT_CREATE_QUIET (1UL << 6) | 127 | #define RPC_CLNT_CREATE_QUIET (1UL << 6) |
128 | 128 | ||
129 | struct rpc_clnt *rpc_create(struct rpc_create_args *args); | 129 | struct rpc_clnt *rpc_create(struct rpc_create_args *args); |
130 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, | 130 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, |
131 | struct rpc_program *, u32); | 131 | const struct rpc_program *, u32); |
132 | void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt); | 132 | void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt); |
133 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); | 133 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); |
134 | void rpc_shutdown_client(struct rpc_clnt *); | 134 | void rpc_shutdown_client(struct rpc_clnt *); |
135 | void rpc_release_client(struct rpc_clnt *); | 135 | void rpc_release_client(struct rpc_clnt *); |
136 | void rpc_task_release_client(struct rpc_task *); | 136 | void rpc_task_release_client(struct rpc_task *); |
137 | 137 | ||
138 | int rpcb_create_local(struct net *); | 138 | int rpcb_create_local(struct net *); |
139 | void rpcb_put_local(struct net *); | 139 | void rpcb_put_local(struct net *); |
140 | int rpcb_register(struct net *, u32, u32, int, unsigned short); | 140 | int rpcb_register(struct net *, u32, u32, int, unsigned short); |
141 | int rpcb_v4_register(struct net *net, const u32 program, | 141 | int rpcb_v4_register(struct net *net, const u32 program, |
142 | const u32 version, | 142 | const u32 version, |
143 | const struct sockaddr *address, | 143 | const struct sockaddr *address, |
144 | const char *netid); | 144 | const char *netid); |
145 | void rpcb_getport_async(struct rpc_task *); | 145 | void rpcb_getport_async(struct rpc_task *); |
146 | 146 | ||
147 | void rpc_call_start(struct rpc_task *); | 147 | void rpc_call_start(struct rpc_task *); |
148 | int rpc_call_async(struct rpc_clnt *clnt, | 148 | int rpc_call_async(struct rpc_clnt *clnt, |
149 | const struct rpc_message *msg, int flags, | 149 | const struct rpc_message *msg, int flags, |
150 | const struct rpc_call_ops *tk_ops, | 150 | const struct rpc_call_ops *tk_ops, |
151 | void *calldata); | 151 | void *calldata); |
152 | int rpc_call_sync(struct rpc_clnt *clnt, | 152 | int rpc_call_sync(struct rpc_clnt *clnt, |
153 | const struct rpc_message *msg, int flags); | 153 | const struct rpc_message *msg, int flags); |
154 | struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, | 154 | struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, |
155 | int flags); | 155 | int flags); |
156 | int rpc_restart_call_prepare(struct rpc_task *); | 156 | int rpc_restart_call_prepare(struct rpc_task *); |
157 | int rpc_restart_call(struct rpc_task *); | 157 | int rpc_restart_call(struct rpc_task *); |
158 | void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); | 158 | void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); |
159 | size_t rpc_max_payload(struct rpc_clnt *); | 159 | size_t rpc_max_payload(struct rpc_clnt *); |
160 | void rpc_force_rebind(struct rpc_clnt *); | 160 | void rpc_force_rebind(struct rpc_clnt *); |
161 | size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); | 161 | size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); |
162 | const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); | 162 | const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); |
163 | 163 | ||
164 | size_t rpc_ntop(const struct sockaddr *, char *, const size_t); | 164 | size_t rpc_ntop(const struct sockaddr *, char *, const size_t); |
165 | size_t rpc_pton(struct net *, const char *, const size_t, | 165 | size_t rpc_pton(struct net *, const char *, const size_t, |
166 | struct sockaddr *, const size_t); | 166 | struct sockaddr *, const size_t); |
167 | char * rpc_sockaddr2uaddr(const struct sockaddr *, gfp_t); | 167 | char * rpc_sockaddr2uaddr(const struct sockaddr *, gfp_t); |
168 | size_t rpc_uaddr2sockaddr(struct net *, const char *, const size_t, | 168 | size_t rpc_uaddr2sockaddr(struct net *, const char *, const size_t, |
169 | struct sockaddr *, const size_t); | 169 | struct sockaddr *, const size_t); |
170 | 170 | ||
171 | static inline unsigned short rpc_get_port(const struct sockaddr *sap) | 171 | static inline unsigned short rpc_get_port(const struct sockaddr *sap) |
172 | { | 172 | { |
173 | switch (sap->sa_family) { | 173 | switch (sap->sa_family) { |
174 | case AF_INET: | 174 | case AF_INET: |
175 | return ntohs(((struct sockaddr_in *)sap)->sin_port); | 175 | return ntohs(((struct sockaddr_in *)sap)->sin_port); |
176 | case AF_INET6: | 176 | case AF_INET6: |
177 | return ntohs(((struct sockaddr_in6 *)sap)->sin6_port); | 177 | return ntohs(((struct sockaddr_in6 *)sap)->sin6_port); |
178 | } | 178 | } |
179 | return 0; | 179 | return 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | static inline void rpc_set_port(struct sockaddr *sap, | 182 | static inline void rpc_set_port(struct sockaddr *sap, |
183 | const unsigned short port) | 183 | const unsigned short port) |
184 | { | 184 | { |
185 | switch (sap->sa_family) { | 185 | switch (sap->sa_family) { |
186 | case AF_INET: | 186 | case AF_INET: |
187 | ((struct sockaddr_in *)sap)->sin_port = htons(port); | 187 | ((struct sockaddr_in *)sap)->sin_port = htons(port); |
188 | break; | 188 | break; |
189 | case AF_INET6: | 189 | case AF_INET6: |
190 | ((struct sockaddr_in6 *)sap)->sin6_port = htons(port); | 190 | ((struct sockaddr_in6 *)sap)->sin6_port = htons(port); |
191 | break; | 191 | break; |
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
195 | #define IPV6_SCOPE_DELIMITER '%' | 195 | #define IPV6_SCOPE_DELIMITER '%' |
196 | #define IPV6_SCOPE_ID_LEN sizeof("%nnnnnnnnnn") | 196 | #define IPV6_SCOPE_ID_LEN sizeof("%nnnnnnnnnn") |
197 | 197 | ||
198 | static inline bool __rpc_cmp_addr4(const struct sockaddr *sap1, | 198 | static inline bool __rpc_cmp_addr4(const struct sockaddr *sap1, |
199 | const struct sockaddr *sap2) | 199 | const struct sockaddr *sap2) |
200 | { | 200 | { |
201 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1; | 201 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1; |
202 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2; | 202 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2; |
203 | 203 | ||
204 | return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; | 204 | return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; |
205 | } | 205 | } |
206 | 206 | ||
207 | static inline bool __rpc_copy_addr4(struct sockaddr *dst, | 207 | static inline bool __rpc_copy_addr4(struct sockaddr *dst, |
208 | const struct sockaddr *src) | 208 | const struct sockaddr *src) |
209 | { | 209 | { |
210 | const struct sockaddr_in *ssin = (struct sockaddr_in *) src; | 210 | const struct sockaddr_in *ssin = (struct sockaddr_in *) src; |
211 | struct sockaddr_in *dsin = (struct sockaddr_in *) dst; | 211 | struct sockaddr_in *dsin = (struct sockaddr_in *) dst; |
212 | 212 | ||
213 | dsin->sin_family = ssin->sin_family; | 213 | dsin->sin_family = ssin->sin_family; |
214 | dsin->sin_addr.s_addr = ssin->sin_addr.s_addr; | 214 | dsin->sin_addr.s_addr = ssin->sin_addr.s_addr; |
215 | return true; | 215 | return true; |
216 | } | 216 | } |
217 | 217 | ||
218 | #if IS_ENABLED(CONFIG_IPV6) | 218 | #if IS_ENABLED(CONFIG_IPV6) |
219 | static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1, | 219 | static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1, |
220 | const struct sockaddr *sap2) | 220 | const struct sockaddr *sap2) |
221 | { | 221 | { |
222 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1; | 222 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1; |
223 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2; | 223 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2; |
224 | 224 | ||
225 | if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) | 225 | if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) |
226 | return false; | 226 | return false; |
227 | else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 227 | else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
228 | return sin1->sin6_scope_id == sin2->sin6_scope_id; | 228 | return sin1->sin6_scope_id == sin2->sin6_scope_id; |
229 | 229 | ||
230 | return true; | 230 | return true; |
231 | } | 231 | } |
232 | 232 | ||
233 | static inline bool __rpc_copy_addr6(struct sockaddr *dst, | 233 | static inline bool __rpc_copy_addr6(struct sockaddr *dst, |
234 | const struct sockaddr *src) | 234 | const struct sockaddr *src) |
235 | { | 235 | { |
236 | const struct sockaddr_in6 *ssin6 = (const struct sockaddr_in6 *) src; | 236 | const struct sockaddr_in6 *ssin6 = (const struct sockaddr_in6 *) src; |
237 | struct sockaddr_in6 *dsin6 = (struct sockaddr_in6 *) dst; | 237 | struct sockaddr_in6 *dsin6 = (struct sockaddr_in6 *) dst; |
238 | 238 | ||
239 | dsin6->sin6_family = ssin6->sin6_family; | 239 | dsin6->sin6_family = ssin6->sin6_family; |
240 | dsin6->sin6_addr = ssin6->sin6_addr; | 240 | dsin6->sin6_addr = ssin6->sin6_addr; |
241 | return true; | 241 | return true; |
242 | } | 242 | } |
243 | #else /* !(IS_ENABLED(CONFIG_IPV6) */ | 243 | #else /* !(IS_ENABLED(CONFIG_IPV6) */ |
244 | static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1, | 244 | static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1, |
245 | const struct sockaddr *sap2) | 245 | const struct sockaddr *sap2) |
246 | { | 246 | { |
247 | return false; | 247 | return false; |
248 | } | 248 | } |
249 | 249 | ||
250 | static inline bool __rpc_copy_addr6(struct sockaddr *dst, | 250 | static inline bool __rpc_copy_addr6(struct sockaddr *dst, |
251 | const struct sockaddr *src) | 251 | const struct sockaddr *src) |
252 | { | 252 | { |
253 | return false; | 253 | return false; |
254 | } | 254 | } |
255 | #endif /* !(IS_ENABLED(CONFIG_IPV6) */ | 255 | #endif /* !(IS_ENABLED(CONFIG_IPV6) */ |
256 | 256 | ||
257 | /** | 257 | /** |
258 | * rpc_cmp_addr - compare the address portion of two sockaddrs. | 258 | * rpc_cmp_addr - compare the address portion of two sockaddrs. |
259 | * @sap1: first sockaddr | 259 | * @sap1: first sockaddr |
260 | * @sap2: second sockaddr | 260 | * @sap2: second sockaddr |
261 | * | 261 | * |
262 | * Just compares the family and address portion. Ignores port, scope, etc. | 262 | * Just compares the family and address portion. Ignores port, scope, etc. |
263 | * Returns true if the addrs are equal, false if they aren't. | 263 | * Returns true if the addrs are equal, false if they aren't. |
264 | */ | 264 | */ |
265 | static inline bool rpc_cmp_addr(const struct sockaddr *sap1, | 265 | static inline bool rpc_cmp_addr(const struct sockaddr *sap1, |
266 | const struct sockaddr *sap2) | 266 | const struct sockaddr *sap2) |
267 | { | 267 | { |
268 | if (sap1->sa_family == sap2->sa_family) { | 268 | if (sap1->sa_family == sap2->sa_family) { |
269 | switch (sap1->sa_family) { | 269 | switch (sap1->sa_family) { |
270 | case AF_INET: | 270 | case AF_INET: |
271 | return __rpc_cmp_addr4(sap1, sap2); | 271 | return __rpc_cmp_addr4(sap1, sap2); |
272 | case AF_INET6: | 272 | case AF_INET6: |
273 | return __rpc_cmp_addr6(sap1, sap2); | 273 | return __rpc_cmp_addr6(sap1, sap2); |
274 | } | 274 | } |
275 | } | 275 | } |
276 | return false; | 276 | return false; |
277 | } | 277 | } |
278 | 278 | ||
279 | /** | 279 | /** |
280 | * rpc_copy_addr - copy the address portion of one sockaddr to another | 280 | * rpc_copy_addr - copy the address portion of one sockaddr to another |
281 | * @dst: destination sockaddr | 281 | * @dst: destination sockaddr |
282 | * @src: source sockaddr | 282 | * @src: source sockaddr |
283 | * | 283 | * |
284 | * Just copies the address portion and family. Ignores port, scope, etc. | 284 | * Just copies the address portion and family. Ignores port, scope, etc. |
285 | * Caller is responsible for making certain that dst is large enough to hold | 285 | * Caller is responsible for making certain that dst is large enough to hold |
286 | * the address in src. Returns true if address family is supported. Returns | 286 | * the address in src. Returns true if address family is supported. Returns |
287 | * false otherwise. | 287 | * false otherwise. |
288 | */ | 288 | */ |
289 | static inline bool rpc_copy_addr(struct sockaddr *dst, | 289 | static inline bool rpc_copy_addr(struct sockaddr *dst, |
290 | const struct sockaddr *src) | 290 | const struct sockaddr *src) |
291 | { | 291 | { |
292 | switch (src->sa_family) { | 292 | switch (src->sa_family) { |
293 | case AF_INET: | 293 | case AF_INET: |
294 | return __rpc_copy_addr4(dst, src); | 294 | return __rpc_copy_addr4(dst, src); |
295 | case AF_INET6: | 295 | case AF_INET6: |
296 | return __rpc_copy_addr6(dst, src); | 296 | return __rpc_copy_addr6(dst, src); |
297 | } | 297 | } |
298 | return false; | 298 | return false; |
299 | } | 299 | } |
300 | 300 | ||
301 | /** | 301 | /** |
302 | * rpc_get_scope_id - return scopeid for a given sockaddr | 302 | * rpc_get_scope_id - return scopeid for a given sockaddr |
303 | * @sa: sockaddr to get scopeid from | 303 | * @sa: sockaddr to get scopeid from |
304 | * | 304 | * |
305 | * Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if | 305 | * Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if |
306 | * not an AF_INET6 address. | 306 | * not an AF_INET6 address. |
307 | */ | 307 | */ |
308 | static inline u32 rpc_get_scope_id(const struct sockaddr *sa) | 308 | static inline u32 rpc_get_scope_id(const struct sockaddr *sa) |
309 | { | 309 | { |
310 | if (sa->sa_family != AF_INET6) | 310 | if (sa->sa_family != AF_INET6) |
311 | return 0; | 311 | return 0; |
312 | 312 | ||
313 | return ((struct sockaddr_in6 *) sa)->sin6_scope_id; | 313 | return ((struct sockaddr_in6 *) sa)->sin6_scope_id; |
314 | } | 314 | } |
315 | 315 | ||
316 | #endif /* __KERNEL__ */ | 316 | #endif /* __KERNEL__ */ |
317 | #endif /* _LINUX_SUNRPC_CLNT_H */ | 317 | #endif /* _LINUX_SUNRPC_CLNT_H */ |
318 | 318 |
include/linux/sunrpc/stats.h
1 | /* | 1 | /* |
2 | * linux/include/linux/sunrpc/stats.h | 2 | * linux/include/linux/sunrpc/stats.h |
3 | * | 3 | * |
4 | * Client statistics collection for SUN RPC | 4 | * Client statistics collection for SUN RPC |
5 | * | 5 | * |
6 | * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _LINUX_SUNRPC_STATS_H | 9 | #ifndef _LINUX_SUNRPC_STATS_H |
10 | #define _LINUX_SUNRPC_STATS_H | 10 | #define _LINUX_SUNRPC_STATS_H |
11 | 11 | ||
12 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
13 | 13 | ||
14 | struct rpc_stat { | 14 | struct rpc_stat { |
15 | struct rpc_program * program; | 15 | const struct rpc_program *program; |
16 | 16 | ||
17 | unsigned int netcnt, | 17 | unsigned int netcnt, |
18 | netudpcnt, | 18 | netudpcnt, |
19 | nettcpcnt, | 19 | nettcpcnt, |
20 | nettcpconn, | 20 | nettcpconn, |
21 | netreconn; | 21 | netreconn; |
22 | unsigned int rpccnt, | 22 | unsigned int rpccnt, |
23 | rpcretrans, | 23 | rpcretrans, |
24 | rpcauthrefresh, | 24 | rpcauthrefresh, |
25 | rpcgarbage; | 25 | rpcgarbage; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | struct svc_stat { | 28 | struct svc_stat { |
29 | struct svc_program * program; | 29 | struct svc_program * program; |
30 | 30 | ||
31 | unsigned int netcnt, | 31 | unsigned int netcnt, |
32 | netudpcnt, | 32 | netudpcnt, |
33 | nettcpcnt, | 33 | nettcpcnt, |
34 | nettcpconn; | 34 | nettcpconn; |
35 | unsigned int rpccnt, | 35 | unsigned int rpccnt, |
36 | rpcbadfmt, | 36 | rpcbadfmt, |
37 | rpcbadauth, | 37 | rpcbadauth, |
38 | rpcbadclnt; | 38 | rpcbadclnt; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | struct net; | 41 | struct net; |
42 | #ifdef CONFIG_PROC_FS | 42 | #ifdef CONFIG_PROC_FS |
43 | int rpc_proc_init(struct net *); | 43 | int rpc_proc_init(struct net *); |
44 | void rpc_proc_exit(struct net *); | 44 | void rpc_proc_exit(struct net *); |
45 | #else | 45 | #else |
46 | static inline int rpc_proc_init(struct net *net) | 46 | static inline int rpc_proc_init(struct net *net) |
47 | { | 47 | { |
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | static inline void rpc_proc_exit(struct net *net) | 51 | static inline void rpc_proc_exit(struct net *net) |
52 | { | 52 | { |
53 | } | 53 | } |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #ifdef MODULE | 56 | #ifdef MODULE |
57 | void rpc_modcount(struct inode *, int); | 57 | void rpc_modcount(struct inode *, int); |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | #ifdef CONFIG_PROC_FS | 60 | #ifdef CONFIG_PROC_FS |
61 | struct proc_dir_entry * rpc_proc_register(struct net *,struct rpc_stat *); | 61 | struct proc_dir_entry * rpc_proc_register(struct net *,struct rpc_stat *); |
62 | void rpc_proc_unregister(struct net *,const char *); | 62 | void rpc_proc_unregister(struct net *,const char *); |
63 | void rpc_proc_zero(struct rpc_program *); | 63 | void rpc_proc_zero(const struct rpc_program *); |
64 | struct proc_dir_entry * svc_proc_register(struct net *, struct svc_stat *, | 64 | struct proc_dir_entry * svc_proc_register(struct net *, struct svc_stat *, |
65 | const struct file_operations *); | 65 | const struct file_operations *); |
66 | void svc_proc_unregister(struct net *, const char *); | 66 | void svc_proc_unregister(struct net *, const char *); |
67 | 67 | ||
68 | void svc_seq_show(struct seq_file *, | 68 | void svc_seq_show(struct seq_file *, |
69 | const struct svc_stat *); | 69 | const struct svc_stat *); |
70 | #else | 70 | #else |
71 | 71 | ||
72 | static inline struct proc_dir_entry *rpc_proc_register(struct net *net, struct rpc_stat *s) { return NULL; } | 72 | static inline struct proc_dir_entry *rpc_proc_register(struct net *net, struct rpc_stat *s) { return NULL; } |
73 | static inline void rpc_proc_unregister(struct net *net, const char *p) {} | 73 | static inline void rpc_proc_unregister(struct net *net, const char *p) {} |
74 | static inline void rpc_proc_zero(struct rpc_program *p) {} | 74 | static inline void rpc_proc_zero(const struct rpc_program *p) {} |
75 | 75 | ||
76 | static inline struct proc_dir_entry *svc_proc_register(struct net *net, struct svc_stat *s, | 76 | static inline struct proc_dir_entry *svc_proc_register(struct net *net, struct svc_stat *s, |
77 | const struct file_operations *f) { return NULL; } | 77 | const struct file_operations *f) { return NULL; } |
78 | static inline void svc_proc_unregister(struct net *net, const char *p) {} | 78 | static inline void svc_proc_unregister(struct net *net, const char *p) {} |
79 | 79 | ||
80 | static inline void svc_seq_show(struct seq_file *seq, | 80 | static inline void svc_seq_show(struct seq_file *seq, |
81 | const struct svc_stat *st) {} | 81 | const struct svc_stat *st) {} |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | #endif /* _LINUX_SUNRPC_STATS_H */ | 84 | #endif /* _LINUX_SUNRPC_STATS_H */ |
85 | 85 |
net/sunrpc/clnt.c
1 | /* | 1 | /* |
2 | * linux/net/sunrpc/clnt.c | 2 | * linux/net/sunrpc/clnt.c |
3 | * | 3 | * |
4 | * This file contains the high-level RPC interface. | 4 | * This file contains the high-level RPC interface. |
5 | * It is modeled as a finite state machine to support both synchronous | 5 | * It is modeled as a finite state machine to support both synchronous |
6 | * and asynchronous requests. | 6 | * and asynchronous requests. |
7 | * | 7 | * |
8 | * - RPC header generation and argument serialization. | 8 | * - RPC header generation and argument serialization. |
9 | * - Credential refresh. | 9 | * - Credential refresh. |
10 | * - TCP connect handling. | 10 | * - TCP connect handling. |
11 | * - Retry of operation when it is suspected the operation failed because | 11 | * - Retry of operation when it is suspected the operation failed because |
12 | * of uid squashing on the server, or when the credentials were stale | 12 | * of uid squashing on the server, or when the credentials were stale |
13 | * and need to be refreshed, or when a packet was damaged in transit. | 13 | * and need to be refreshed, or when a packet was damaged in transit. |
14 | * This may be have to be moved to the VFS layer. | 14 | * This may be have to be moved to the VFS layer. |
15 | * | 15 | * |
16 | * Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com> | 16 | * Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com> |
17 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> | 17 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <asm/system.h> | 20 | #include <asm/system.h> |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/kallsyms.h> | 24 | #include <linux/kallsyms.h> |
25 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
26 | #include <linux/namei.h> | 26 | #include <linux/namei.h> |
27 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
31 | #include <linux/in.h> | 31 | #include <linux/in.h> |
32 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
33 | #include <linux/un.h> | 33 | #include <linux/un.h> |
34 | 34 | ||
35 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
36 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
37 | #include <linux/sunrpc/metrics.h> | 37 | #include <linux/sunrpc/metrics.h> |
38 | #include <linux/sunrpc/bc_xprt.h> | 38 | #include <linux/sunrpc/bc_xprt.h> |
39 | 39 | ||
40 | #include "sunrpc.h" | 40 | #include "sunrpc.h" |
41 | #include "netns.h" | 41 | #include "netns.h" |
42 | 42 | ||
43 | #ifdef RPC_DEBUG | 43 | #ifdef RPC_DEBUG |
44 | # define RPCDBG_FACILITY RPCDBG_CALL | 44 | # define RPCDBG_FACILITY RPCDBG_CALL |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #define dprint_status(t) \ | 47 | #define dprint_status(t) \ |
48 | dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \ | 48 | dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \ |
49 | __func__, t->tk_status) | 49 | __func__, t->tk_status) |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * All RPC clients are linked into this list | 52 | * All RPC clients are linked into this list |
53 | */ | 53 | */ |
54 | 54 | ||
55 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); | 55 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); |
56 | 56 | ||
57 | 57 | ||
58 | static void call_start(struct rpc_task *task); | 58 | static void call_start(struct rpc_task *task); |
59 | static void call_reserve(struct rpc_task *task); | 59 | static void call_reserve(struct rpc_task *task); |
60 | static void call_reserveresult(struct rpc_task *task); | 60 | static void call_reserveresult(struct rpc_task *task); |
61 | static void call_allocate(struct rpc_task *task); | 61 | static void call_allocate(struct rpc_task *task); |
62 | static void call_decode(struct rpc_task *task); | 62 | static void call_decode(struct rpc_task *task); |
63 | static void call_bind(struct rpc_task *task); | 63 | static void call_bind(struct rpc_task *task); |
64 | static void call_bind_status(struct rpc_task *task); | 64 | static void call_bind_status(struct rpc_task *task); |
65 | static void call_transmit(struct rpc_task *task); | 65 | static void call_transmit(struct rpc_task *task); |
66 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) | 66 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) |
67 | static void call_bc_transmit(struct rpc_task *task); | 67 | static void call_bc_transmit(struct rpc_task *task); |
68 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 68 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
69 | static void call_status(struct rpc_task *task); | 69 | static void call_status(struct rpc_task *task); |
70 | static void call_transmit_status(struct rpc_task *task); | 70 | static void call_transmit_status(struct rpc_task *task); |
71 | static void call_refresh(struct rpc_task *task); | 71 | static void call_refresh(struct rpc_task *task); |
72 | static void call_refreshresult(struct rpc_task *task); | 72 | static void call_refreshresult(struct rpc_task *task); |
73 | static void call_timeout(struct rpc_task *task); | 73 | static void call_timeout(struct rpc_task *task); |
74 | static void call_connect(struct rpc_task *task); | 74 | static void call_connect(struct rpc_task *task); |
75 | static void call_connect_status(struct rpc_task *task); | 75 | static void call_connect_status(struct rpc_task *task); |
76 | 76 | ||
77 | static __be32 *rpc_encode_header(struct rpc_task *task); | 77 | static __be32 *rpc_encode_header(struct rpc_task *task); |
78 | static __be32 *rpc_verify_header(struct rpc_task *task); | 78 | static __be32 *rpc_verify_header(struct rpc_task *task); |
79 | static int rpc_ping(struct rpc_clnt *clnt); | 79 | static int rpc_ping(struct rpc_clnt *clnt); |
80 | 80 | ||
81 | static void rpc_register_client(struct rpc_clnt *clnt) | 81 | static void rpc_register_client(struct rpc_clnt *clnt) |
82 | { | 82 | { |
83 | struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); | 83 | struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); |
84 | 84 | ||
85 | spin_lock(&sn->rpc_client_lock); | 85 | spin_lock(&sn->rpc_client_lock); |
86 | list_add(&clnt->cl_clients, &sn->all_clients); | 86 | list_add(&clnt->cl_clients, &sn->all_clients); |
87 | spin_unlock(&sn->rpc_client_lock); | 87 | spin_unlock(&sn->rpc_client_lock); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void rpc_unregister_client(struct rpc_clnt *clnt) | 90 | static void rpc_unregister_client(struct rpc_clnt *clnt) |
91 | { | 91 | { |
92 | struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); | 92 | struct sunrpc_net *sn = net_generic(clnt->cl_xprt->xprt_net, sunrpc_net_id); |
93 | 93 | ||
94 | spin_lock(&sn->rpc_client_lock); | 94 | spin_lock(&sn->rpc_client_lock); |
95 | list_del(&clnt->cl_clients); | 95 | list_del(&clnt->cl_clients); |
96 | spin_unlock(&sn->rpc_client_lock); | 96 | spin_unlock(&sn->rpc_client_lock); |
97 | } | 97 | } |
98 | 98 | ||
99 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 99 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
100 | { | 100 | { |
101 | if (clnt->cl_dentry) { | 101 | if (clnt->cl_dentry) { |
102 | if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) | 102 | if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) |
103 | clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); | 103 | clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); |
104 | rpc_remove_client_dir(clnt->cl_dentry); | 104 | rpc_remove_client_dir(clnt->cl_dentry); |
105 | } | 105 | } |
106 | clnt->cl_dentry = NULL; | 106 | clnt->cl_dentry = NULL; |
107 | } | 107 | } |
108 | 108 | ||
109 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 109 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
110 | { | 110 | { |
111 | struct super_block *pipefs_sb; | 111 | struct super_block *pipefs_sb; |
112 | 112 | ||
113 | pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); | 113 | pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); |
114 | if (pipefs_sb) { | 114 | if (pipefs_sb) { |
115 | __rpc_clnt_remove_pipedir(clnt); | 115 | __rpc_clnt_remove_pipedir(clnt); |
116 | rpc_put_sb_net(clnt->cl_xprt->xprt_net); | 116 | rpc_put_sb_net(clnt->cl_xprt->xprt_net); |
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | 120 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, |
121 | struct rpc_clnt *clnt, | 121 | struct rpc_clnt *clnt, |
122 | const char *dir_name) | 122 | const char *dir_name) |
123 | { | 123 | { |
124 | static uint32_t clntid; | 124 | static uint32_t clntid; |
125 | char name[15]; | 125 | char name[15]; |
126 | struct qstr q = { | 126 | struct qstr q = { |
127 | .name = name, | 127 | .name = name, |
128 | }; | 128 | }; |
129 | struct dentry *dir, *dentry; | 129 | struct dentry *dir, *dentry; |
130 | int error; | 130 | int error; |
131 | 131 | ||
132 | dir = rpc_d_lookup_sb(sb, dir_name); | 132 | dir = rpc_d_lookup_sb(sb, dir_name); |
133 | if (dir == NULL) | 133 | if (dir == NULL) |
134 | return dir; | 134 | return dir; |
135 | for (;;) { | 135 | for (;;) { |
136 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); | 136 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); |
137 | name[sizeof(name) - 1] = '\0'; | 137 | name[sizeof(name) - 1] = '\0'; |
138 | q.hash = full_name_hash(q.name, q.len); | 138 | q.hash = full_name_hash(q.name, q.len); |
139 | dentry = rpc_create_client_dir(dir, &q, clnt); | 139 | dentry = rpc_create_client_dir(dir, &q, clnt); |
140 | if (!IS_ERR(dentry)) | 140 | if (!IS_ERR(dentry)) |
141 | break; | 141 | break; |
142 | error = PTR_ERR(dentry); | 142 | error = PTR_ERR(dentry); |
143 | if (error != -EEXIST) { | 143 | if (error != -EEXIST) { |
144 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" | 144 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" |
145 | " %s/%s, error %d\n", | 145 | " %s/%s, error %d\n", |
146 | dir_name, name, error); | 146 | dir_name, name, error); |
147 | break; | 147 | break; |
148 | } | 148 | } |
149 | } | 149 | } |
150 | dput(dir); | 150 | dput(dir); |
151 | return dentry; | 151 | return dentry; |
152 | } | 152 | } |
153 | 153 | ||
154 | static int | 154 | static int |
155 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) | 155 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) |
156 | { | 156 | { |
157 | struct super_block *pipefs_sb; | 157 | struct super_block *pipefs_sb; |
158 | struct dentry *dentry; | 158 | struct dentry *dentry; |
159 | 159 | ||
160 | clnt->cl_dentry = NULL; | 160 | clnt->cl_dentry = NULL; |
161 | if (dir_name == NULL) | 161 | if (dir_name == NULL) |
162 | return 0; | 162 | return 0; |
163 | pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); | 163 | pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net); |
164 | if (!pipefs_sb) | 164 | if (!pipefs_sb) |
165 | return 0; | 165 | return 0; |
166 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | 166 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); |
167 | rpc_put_sb_net(clnt->cl_xprt->xprt_net); | 167 | rpc_put_sb_net(clnt->cl_xprt->xprt_net); |
168 | if (IS_ERR(dentry)) | 168 | if (IS_ERR(dentry)) |
169 | return PTR_ERR(dentry); | 169 | return PTR_ERR(dentry); |
170 | clnt->cl_dentry = dentry; | 170 | clnt->cl_dentry = dentry; |
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, | 174 | static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, |
175 | struct super_block *sb) | 175 | struct super_block *sb) |
176 | { | 176 | { |
177 | struct dentry *dentry; | 177 | struct dentry *dentry; |
178 | int err = 0; | 178 | int err = 0; |
179 | 179 | ||
180 | switch (event) { | 180 | switch (event) { |
181 | case RPC_PIPEFS_MOUNT: | 181 | case RPC_PIPEFS_MOUNT: |
182 | if (clnt->cl_program->pipe_dir_name == NULL) | 182 | if (clnt->cl_program->pipe_dir_name == NULL) |
183 | break; | 183 | break; |
184 | dentry = rpc_setup_pipedir_sb(sb, clnt, | 184 | dentry = rpc_setup_pipedir_sb(sb, clnt, |
185 | clnt->cl_program->pipe_dir_name); | 185 | clnt->cl_program->pipe_dir_name); |
186 | BUG_ON(dentry == NULL); | 186 | BUG_ON(dentry == NULL); |
187 | if (IS_ERR(dentry)) | 187 | if (IS_ERR(dentry)) |
188 | return PTR_ERR(dentry); | 188 | return PTR_ERR(dentry); |
189 | clnt->cl_dentry = dentry; | 189 | clnt->cl_dentry = dentry; |
190 | if (clnt->cl_auth->au_ops->pipes_create) { | 190 | if (clnt->cl_auth->au_ops->pipes_create) { |
191 | err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); | 191 | err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); |
192 | if (err) | 192 | if (err) |
193 | __rpc_clnt_remove_pipedir(clnt); | 193 | __rpc_clnt_remove_pipedir(clnt); |
194 | } | 194 | } |
195 | break; | 195 | break; |
196 | case RPC_PIPEFS_UMOUNT: | 196 | case RPC_PIPEFS_UMOUNT: |
197 | __rpc_clnt_remove_pipedir(clnt); | 197 | __rpc_clnt_remove_pipedir(clnt); |
198 | break; | 198 | break; |
199 | default: | 199 | default: |
200 | printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event); | 200 | printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event); |
201 | return -ENOTSUPP; | 201 | return -ENOTSUPP; |
202 | } | 202 | } |
203 | return err; | 203 | return err; |
204 | } | 204 | } |
205 | 205 | ||
206 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | 206 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, |
207 | void *ptr) | 207 | void *ptr) |
208 | { | 208 | { |
209 | struct super_block *sb = ptr; | 209 | struct super_block *sb = ptr; |
210 | struct rpc_clnt *clnt; | 210 | struct rpc_clnt *clnt; |
211 | int error = 0; | 211 | int error = 0; |
212 | struct sunrpc_net *sn = net_generic(sb->s_fs_info, sunrpc_net_id); | 212 | struct sunrpc_net *sn = net_generic(sb->s_fs_info, sunrpc_net_id); |
213 | 213 | ||
214 | spin_lock(&sn->rpc_client_lock); | 214 | spin_lock(&sn->rpc_client_lock); |
215 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | 215 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
216 | error = __rpc_pipefs_event(clnt, event, sb); | 216 | error = __rpc_pipefs_event(clnt, event, sb); |
217 | if (error) | 217 | if (error) |
218 | break; | 218 | break; |
219 | } | 219 | } |
220 | spin_unlock(&sn->rpc_client_lock); | 220 | spin_unlock(&sn->rpc_client_lock); |
221 | return error; | 221 | return error; |
222 | } | 222 | } |
223 | 223 | ||
224 | static struct notifier_block rpc_clients_block = { | 224 | static struct notifier_block rpc_clients_block = { |
225 | .notifier_call = rpc_pipefs_event, | 225 | .notifier_call = rpc_pipefs_event, |
226 | .priority = SUNRPC_PIPEFS_RPC_PRIO, | 226 | .priority = SUNRPC_PIPEFS_RPC_PRIO, |
227 | }; | 227 | }; |
228 | 228 | ||
229 | int rpc_clients_notifier_register(void) | 229 | int rpc_clients_notifier_register(void) |
230 | { | 230 | { |
231 | return rpc_pipefs_notifier_register(&rpc_clients_block); | 231 | return rpc_pipefs_notifier_register(&rpc_clients_block); |
232 | } | 232 | } |
233 | 233 | ||
234 | void rpc_clients_notifier_unregister(void) | 234 | void rpc_clients_notifier_unregister(void) |
235 | { | 235 | { |
236 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); | 236 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); |
237 | } | 237 | } |
238 | 238 | ||
239 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 239 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
240 | { | 240 | { |
241 | struct rpc_program *program = args->program; | 241 | const struct rpc_program *program = args->program; |
242 | struct rpc_version *version; | 242 | const struct rpc_version *version; |
243 | struct rpc_clnt *clnt = NULL; | 243 | struct rpc_clnt *clnt = NULL; |
244 | struct rpc_auth *auth; | 244 | struct rpc_auth *auth; |
245 | int err; | 245 | int err; |
246 | size_t len; | 246 | size_t len; |
247 | 247 | ||
248 | /* sanity check the name before trying to print it */ | 248 | /* sanity check the name before trying to print it */ |
249 | err = -EINVAL; | 249 | err = -EINVAL; |
250 | len = strlen(args->servername); | 250 | len = strlen(args->servername); |
251 | if (len > RPC_MAXNETNAMELEN) | 251 | if (len > RPC_MAXNETNAMELEN) |
252 | goto out_no_rpciod; | 252 | goto out_no_rpciod; |
253 | len++; | 253 | len++; |
254 | 254 | ||
255 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 255 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
256 | program->name, args->servername, xprt); | 256 | program->name, args->servername, xprt); |
257 | 257 | ||
258 | err = rpciod_up(); | 258 | err = rpciod_up(); |
259 | if (err) | 259 | if (err) |
260 | goto out_no_rpciod; | 260 | goto out_no_rpciod; |
261 | err = -EINVAL; | 261 | err = -EINVAL; |
262 | if (!xprt) | 262 | if (!xprt) |
263 | goto out_no_xprt; | 263 | goto out_no_xprt; |
264 | 264 | ||
265 | if (args->version >= program->nrvers) | 265 | if (args->version >= program->nrvers) |
266 | goto out_err; | 266 | goto out_err; |
267 | version = program->version[args->version]; | 267 | version = program->version[args->version]; |
268 | if (version == NULL) | 268 | if (version == NULL) |
269 | goto out_err; | 269 | goto out_err; |
270 | 270 | ||
271 | err = -ENOMEM; | 271 | err = -ENOMEM; |
272 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); | 272 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); |
273 | if (!clnt) | 273 | if (!clnt) |
274 | goto out_err; | 274 | goto out_err; |
275 | clnt->cl_parent = clnt; | 275 | clnt->cl_parent = clnt; |
276 | 276 | ||
277 | clnt->cl_server = kstrdup(args->servername, GFP_KERNEL); | 277 | clnt->cl_server = kstrdup(args->servername, GFP_KERNEL); |
278 | if (clnt->cl_server == NULL) | 278 | if (clnt->cl_server == NULL) |
279 | goto out_no_server; | 279 | goto out_no_server; |
280 | 280 | ||
281 | clnt->cl_xprt = xprt; | 281 | clnt->cl_xprt = xprt; |
282 | clnt->cl_procinfo = version->procs; | 282 | clnt->cl_procinfo = version->procs; |
283 | clnt->cl_maxproc = version->nrprocs; | 283 | clnt->cl_maxproc = version->nrprocs; |
284 | clnt->cl_protname = program->name; | 284 | clnt->cl_protname = program->name; |
285 | clnt->cl_prog = args->prognumber ? : program->number; | 285 | clnt->cl_prog = args->prognumber ? : program->number; |
286 | clnt->cl_vers = version->number; | 286 | clnt->cl_vers = version->number; |
287 | clnt->cl_stats = program->stats; | 287 | clnt->cl_stats = program->stats; |
288 | clnt->cl_metrics = rpc_alloc_iostats(clnt); | 288 | clnt->cl_metrics = rpc_alloc_iostats(clnt); |
289 | err = -ENOMEM; | 289 | err = -ENOMEM; |
290 | if (clnt->cl_metrics == NULL) | 290 | if (clnt->cl_metrics == NULL) |
291 | goto out_no_stats; | 291 | goto out_no_stats; |
292 | clnt->cl_program = program; | 292 | clnt->cl_program = program; |
293 | INIT_LIST_HEAD(&clnt->cl_tasks); | 293 | INIT_LIST_HEAD(&clnt->cl_tasks); |
294 | spin_lock_init(&clnt->cl_lock); | 294 | spin_lock_init(&clnt->cl_lock); |
295 | 295 | ||
296 | if (!xprt_bound(clnt->cl_xprt)) | 296 | if (!xprt_bound(clnt->cl_xprt)) |
297 | clnt->cl_autobind = 1; | 297 | clnt->cl_autobind = 1; |
298 | 298 | ||
299 | clnt->cl_timeout = xprt->timeout; | 299 | clnt->cl_timeout = xprt->timeout; |
300 | if (args->timeout != NULL) { | 300 | if (args->timeout != NULL) { |
301 | memcpy(&clnt->cl_timeout_default, args->timeout, | 301 | memcpy(&clnt->cl_timeout_default, args->timeout, |
302 | sizeof(clnt->cl_timeout_default)); | 302 | sizeof(clnt->cl_timeout_default)); |
303 | clnt->cl_timeout = &clnt->cl_timeout_default; | 303 | clnt->cl_timeout = &clnt->cl_timeout_default; |
304 | } | 304 | } |
305 | 305 | ||
306 | clnt->cl_rtt = &clnt->cl_rtt_default; | 306 | clnt->cl_rtt = &clnt->cl_rtt_default; |
307 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); | 307 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); |
308 | clnt->cl_principal = NULL; | 308 | clnt->cl_principal = NULL; |
309 | if (args->client_name) { | 309 | if (args->client_name) { |
310 | clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL); | 310 | clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL); |
311 | if (!clnt->cl_principal) | 311 | if (!clnt->cl_principal) |
312 | goto out_no_principal; | 312 | goto out_no_principal; |
313 | } | 313 | } |
314 | 314 | ||
315 | atomic_set(&clnt->cl_count, 1); | 315 | atomic_set(&clnt->cl_count, 1); |
316 | 316 | ||
317 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 317 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
318 | if (err < 0) | 318 | if (err < 0) |
319 | goto out_no_path; | 319 | goto out_no_path; |
320 | 320 | ||
321 | auth = rpcauth_create(args->authflavor, clnt); | 321 | auth = rpcauth_create(args->authflavor, clnt); |
322 | if (IS_ERR(auth)) { | 322 | if (IS_ERR(auth)) { |
323 | printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", | 323 | printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", |
324 | args->authflavor); | 324 | args->authflavor); |
325 | err = PTR_ERR(auth); | 325 | err = PTR_ERR(auth); |
326 | goto out_no_auth; | 326 | goto out_no_auth; |
327 | } | 327 | } |
328 | 328 | ||
329 | /* save the nodename */ | 329 | /* save the nodename */ |
330 | clnt->cl_nodelen = strlen(init_utsname()->nodename); | 330 | clnt->cl_nodelen = strlen(init_utsname()->nodename); |
331 | if (clnt->cl_nodelen > UNX_MAXNODENAME) | 331 | if (clnt->cl_nodelen > UNX_MAXNODENAME) |
332 | clnt->cl_nodelen = UNX_MAXNODENAME; | 332 | clnt->cl_nodelen = UNX_MAXNODENAME; |
333 | memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen); | 333 | memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen); |
334 | rpc_register_client(clnt); | 334 | rpc_register_client(clnt); |
335 | return clnt; | 335 | return clnt; |
336 | 336 | ||
337 | out_no_auth: | 337 | out_no_auth: |
338 | rpc_clnt_remove_pipedir(clnt); | 338 | rpc_clnt_remove_pipedir(clnt); |
339 | out_no_path: | 339 | out_no_path: |
340 | kfree(clnt->cl_principal); | 340 | kfree(clnt->cl_principal); |
341 | out_no_principal: | 341 | out_no_principal: |
342 | rpc_free_iostats(clnt->cl_metrics); | 342 | rpc_free_iostats(clnt->cl_metrics); |
343 | out_no_stats: | 343 | out_no_stats: |
344 | kfree(clnt->cl_server); | 344 | kfree(clnt->cl_server); |
345 | out_no_server: | 345 | out_no_server: |
346 | kfree(clnt); | 346 | kfree(clnt); |
347 | out_err: | 347 | out_err: |
348 | xprt_put(xprt); | 348 | xprt_put(xprt); |
349 | out_no_xprt: | 349 | out_no_xprt: |
350 | rpciod_down(); | 350 | rpciod_down(); |
351 | out_no_rpciod: | 351 | out_no_rpciod: |
352 | return ERR_PTR(err); | 352 | return ERR_PTR(err); |
353 | } | 353 | } |
354 | 354 | ||
355 | /* | 355 | /* |
356 | * rpc_create - create an RPC client and transport with one call | 356 | * rpc_create - create an RPC client and transport with one call |
357 | * @args: rpc_clnt create argument structure | 357 | * @args: rpc_clnt create argument structure |
358 | * | 358 | * |
359 | * Creates and initializes an RPC transport and an RPC client. | 359 | * Creates and initializes an RPC transport and an RPC client. |
360 | * | 360 | * |
361 | * It can ping the server in order to determine if it is up, and to see if | 361 | * It can ping the server in order to determine if it is up, and to see if |
362 | * it supports this program and version. RPC_CLNT_CREATE_NOPING disables | 362 | * it supports this program and version. RPC_CLNT_CREATE_NOPING disables |
363 | * this behavior so asynchronous tasks can also use rpc_create. | 363 | * this behavior so asynchronous tasks can also use rpc_create. |
364 | */ | 364 | */ |
365 | struct rpc_clnt *rpc_create(struct rpc_create_args *args) | 365 | struct rpc_clnt *rpc_create(struct rpc_create_args *args) |
366 | { | 366 | { |
367 | struct rpc_xprt *xprt; | 367 | struct rpc_xprt *xprt; |
368 | struct rpc_clnt *clnt; | 368 | struct rpc_clnt *clnt; |
369 | struct xprt_create xprtargs = { | 369 | struct xprt_create xprtargs = { |
370 | .net = args->net, | 370 | .net = args->net, |
371 | .ident = args->protocol, | 371 | .ident = args->protocol, |
372 | .srcaddr = args->saddress, | 372 | .srcaddr = args->saddress, |
373 | .dstaddr = args->address, | 373 | .dstaddr = args->address, |
374 | .addrlen = args->addrsize, | 374 | .addrlen = args->addrsize, |
375 | .bc_xprt = args->bc_xprt, | 375 | .bc_xprt = args->bc_xprt, |
376 | }; | 376 | }; |
377 | char servername[48]; | 377 | char servername[48]; |
378 | 378 | ||
379 | /* | 379 | /* |
380 | * If the caller chooses not to specify a hostname, whip | 380 | * If the caller chooses not to specify a hostname, whip |
381 | * up a string representation of the passed-in address. | 381 | * up a string representation of the passed-in address. |
382 | */ | 382 | */ |
383 | if (args->servername == NULL) { | 383 | if (args->servername == NULL) { |
384 | struct sockaddr_un *sun = | 384 | struct sockaddr_un *sun = |
385 | (struct sockaddr_un *)args->address; | 385 | (struct sockaddr_un *)args->address; |
386 | struct sockaddr_in *sin = | 386 | struct sockaddr_in *sin = |
387 | (struct sockaddr_in *)args->address; | 387 | (struct sockaddr_in *)args->address; |
388 | struct sockaddr_in6 *sin6 = | 388 | struct sockaddr_in6 *sin6 = |
389 | (struct sockaddr_in6 *)args->address; | 389 | (struct sockaddr_in6 *)args->address; |
390 | 390 | ||
391 | servername[0] = '\0'; | 391 | servername[0] = '\0'; |
392 | switch (args->address->sa_family) { | 392 | switch (args->address->sa_family) { |
393 | case AF_LOCAL: | 393 | case AF_LOCAL: |
394 | snprintf(servername, sizeof(servername), "%s", | 394 | snprintf(servername, sizeof(servername), "%s", |
395 | sun->sun_path); | 395 | sun->sun_path); |
396 | break; | 396 | break; |
397 | case AF_INET: | 397 | case AF_INET: |
398 | snprintf(servername, sizeof(servername), "%pI4", | 398 | snprintf(servername, sizeof(servername), "%pI4", |
399 | &sin->sin_addr.s_addr); | 399 | &sin->sin_addr.s_addr); |
400 | break; | 400 | break; |
401 | case AF_INET6: | 401 | case AF_INET6: |
402 | snprintf(servername, sizeof(servername), "%pI6", | 402 | snprintf(servername, sizeof(servername), "%pI6", |
403 | &sin6->sin6_addr); | 403 | &sin6->sin6_addr); |
404 | break; | 404 | break; |
405 | default: | 405 | default: |
406 | /* caller wants default server name, but | 406 | /* caller wants default server name, but |
407 | * address family isn't recognized. */ | 407 | * address family isn't recognized. */ |
408 | return ERR_PTR(-EINVAL); | 408 | return ERR_PTR(-EINVAL); |
409 | } | 409 | } |
410 | args->servername = servername; | 410 | args->servername = servername; |
411 | } | 411 | } |
412 | 412 | ||
413 | xprt = xprt_create_transport(&xprtargs); | 413 | xprt = xprt_create_transport(&xprtargs); |
414 | if (IS_ERR(xprt)) | 414 | if (IS_ERR(xprt)) |
415 | return (struct rpc_clnt *)xprt; | 415 | return (struct rpc_clnt *)xprt; |
416 | 416 | ||
417 | /* | 417 | /* |
418 | * By default, kernel RPC client connects from a reserved port. | 418 | * By default, kernel RPC client connects from a reserved port. |
419 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, | 419 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, |
420 | * but it is always enabled for rpciod, which handles the connect | 420 | * but it is always enabled for rpciod, which handles the connect |
421 | * operation. | 421 | * operation. |
422 | */ | 422 | */ |
423 | xprt->resvport = 1; | 423 | xprt->resvport = 1; |
424 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | 424 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) |
425 | xprt->resvport = 0; | 425 | xprt->resvport = 0; |
426 | 426 | ||
427 | clnt = rpc_new_client(args, xprt); | 427 | clnt = rpc_new_client(args, xprt); |
428 | if (IS_ERR(clnt)) | 428 | if (IS_ERR(clnt)) |
429 | return clnt; | 429 | return clnt; |
430 | 430 | ||
431 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { | 431 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { |
432 | int err = rpc_ping(clnt); | 432 | int err = rpc_ping(clnt); |
433 | if (err != 0) { | 433 | if (err != 0) { |
434 | rpc_shutdown_client(clnt); | 434 | rpc_shutdown_client(clnt); |
435 | return ERR_PTR(err); | 435 | return ERR_PTR(err); |
436 | } | 436 | } |
437 | } | 437 | } |
438 | 438 | ||
439 | clnt->cl_softrtry = 1; | 439 | clnt->cl_softrtry = 1; |
440 | if (args->flags & RPC_CLNT_CREATE_HARDRTRY) | 440 | if (args->flags & RPC_CLNT_CREATE_HARDRTRY) |
441 | clnt->cl_softrtry = 0; | 441 | clnt->cl_softrtry = 0; |
442 | 442 | ||
443 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) | 443 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) |
444 | clnt->cl_autobind = 1; | 444 | clnt->cl_autobind = 1; |
445 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) | 445 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) |
446 | clnt->cl_discrtry = 1; | 446 | clnt->cl_discrtry = 1; |
447 | if (!(args->flags & RPC_CLNT_CREATE_QUIET)) | 447 | if (!(args->flags & RPC_CLNT_CREATE_QUIET)) |
448 | clnt->cl_chatty = 1; | 448 | clnt->cl_chatty = 1; |
449 | 449 | ||
450 | return clnt; | 450 | return clnt; |
451 | } | 451 | } |
452 | EXPORT_SYMBOL_GPL(rpc_create); | 452 | EXPORT_SYMBOL_GPL(rpc_create); |
453 | 453 | ||
454 | /* | 454 | /* |
455 | * This function clones the RPC client structure. It allows us to share the | 455 | * This function clones the RPC client structure. It allows us to share the |
456 | * same transport while varying parameters such as the authentication | 456 | * same transport while varying parameters such as the authentication |
457 | * flavour. | 457 | * flavour. |
458 | */ | 458 | */ |
459 | struct rpc_clnt * | 459 | struct rpc_clnt * |
460 | rpc_clone_client(struct rpc_clnt *clnt) | 460 | rpc_clone_client(struct rpc_clnt *clnt) |
461 | { | 461 | { |
462 | struct rpc_clnt *new; | 462 | struct rpc_clnt *new; |
463 | int err = -ENOMEM; | 463 | int err = -ENOMEM; |
464 | 464 | ||
465 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 465 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); |
466 | if (!new) | 466 | if (!new) |
467 | goto out_no_clnt; | 467 | goto out_no_clnt; |
468 | new->cl_server = kstrdup(clnt->cl_server, GFP_KERNEL); | 468 | new->cl_server = kstrdup(clnt->cl_server, GFP_KERNEL); |
469 | if (new->cl_server == NULL) | 469 | if (new->cl_server == NULL) |
470 | goto out_no_server; | 470 | goto out_no_server; |
471 | new->cl_parent = clnt; | 471 | new->cl_parent = clnt; |
472 | /* Turn off autobind on clones */ | 472 | /* Turn off autobind on clones */ |
473 | new->cl_autobind = 0; | 473 | new->cl_autobind = 0; |
474 | INIT_LIST_HEAD(&new->cl_tasks); | 474 | INIT_LIST_HEAD(&new->cl_tasks); |
475 | spin_lock_init(&new->cl_lock); | 475 | spin_lock_init(&new->cl_lock); |
476 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval); | 476 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval); |
477 | new->cl_metrics = rpc_alloc_iostats(clnt); | 477 | new->cl_metrics = rpc_alloc_iostats(clnt); |
478 | if (new->cl_metrics == NULL) | 478 | if (new->cl_metrics == NULL) |
479 | goto out_no_stats; | 479 | goto out_no_stats; |
480 | if (clnt->cl_principal) { | 480 | if (clnt->cl_principal) { |
481 | new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL); | 481 | new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL); |
482 | if (new->cl_principal == NULL) | 482 | if (new->cl_principal == NULL) |
483 | goto out_no_principal; | 483 | goto out_no_principal; |
484 | } | 484 | } |
485 | atomic_set(&new->cl_count, 1); | 485 | atomic_set(&new->cl_count, 1); |
486 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 486 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
487 | if (err != 0) | 487 | if (err != 0) |
488 | goto out_no_path; | 488 | goto out_no_path; |
489 | if (new->cl_auth) | 489 | if (new->cl_auth) |
490 | atomic_inc(&new->cl_auth->au_count); | 490 | atomic_inc(&new->cl_auth->au_count); |
491 | xprt_get(clnt->cl_xprt); | 491 | xprt_get(clnt->cl_xprt); |
492 | atomic_inc(&clnt->cl_count); | 492 | atomic_inc(&clnt->cl_count); |
493 | rpc_register_client(new); | 493 | rpc_register_client(new); |
494 | rpciod_up(); | 494 | rpciod_up(); |
495 | return new; | 495 | return new; |
496 | out_no_path: | 496 | out_no_path: |
497 | kfree(new->cl_principal); | 497 | kfree(new->cl_principal); |
498 | out_no_principal: | 498 | out_no_principal: |
499 | rpc_free_iostats(new->cl_metrics); | 499 | rpc_free_iostats(new->cl_metrics); |
500 | out_no_stats: | 500 | out_no_stats: |
501 | kfree(new->cl_server); | 501 | kfree(new->cl_server); |
502 | out_no_server: | 502 | out_no_server: |
503 | kfree(new); | 503 | kfree(new); |
504 | out_no_clnt: | 504 | out_no_clnt: |
505 | dprintk("RPC: %s: returned error %d\n", __func__, err); | 505 | dprintk("RPC: %s: returned error %d\n", __func__, err); |
506 | return ERR_PTR(err); | 506 | return ERR_PTR(err); |
507 | } | 507 | } |
508 | EXPORT_SYMBOL_GPL(rpc_clone_client); | 508 | EXPORT_SYMBOL_GPL(rpc_clone_client); |
509 | 509 | ||
510 | /* | 510 | /* |
511 | * Kill all tasks for the given client. | 511 | * Kill all tasks for the given client. |
512 | * XXX: kill their descendants as well? | 512 | * XXX: kill their descendants as well? |
513 | */ | 513 | */ |
514 | void rpc_killall_tasks(struct rpc_clnt *clnt) | 514 | void rpc_killall_tasks(struct rpc_clnt *clnt) |
515 | { | 515 | { |
516 | struct rpc_task *rovr; | 516 | struct rpc_task *rovr; |
517 | 517 | ||
518 | 518 | ||
519 | if (list_empty(&clnt->cl_tasks)) | 519 | if (list_empty(&clnt->cl_tasks)) |
520 | return; | 520 | return; |
521 | dprintk("RPC: killing all tasks for client %p\n", clnt); | 521 | dprintk("RPC: killing all tasks for client %p\n", clnt); |
522 | /* | 522 | /* |
523 | * Spin lock all_tasks to prevent changes... | 523 | * Spin lock all_tasks to prevent changes... |
524 | */ | 524 | */ |
525 | spin_lock(&clnt->cl_lock); | 525 | spin_lock(&clnt->cl_lock); |
526 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { | 526 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { |
527 | if (!RPC_IS_ACTIVATED(rovr)) | 527 | if (!RPC_IS_ACTIVATED(rovr)) |
528 | continue; | 528 | continue; |
529 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { | 529 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { |
530 | rovr->tk_flags |= RPC_TASK_KILLED; | 530 | rovr->tk_flags |= RPC_TASK_KILLED; |
531 | rpc_exit(rovr, -EIO); | 531 | rpc_exit(rovr, -EIO); |
532 | if (RPC_IS_QUEUED(rovr)) | 532 | if (RPC_IS_QUEUED(rovr)) |
533 | rpc_wake_up_queued_task(rovr->tk_waitqueue, | 533 | rpc_wake_up_queued_task(rovr->tk_waitqueue, |
534 | rovr); | 534 | rovr); |
535 | } | 535 | } |
536 | } | 536 | } |
537 | spin_unlock(&clnt->cl_lock); | 537 | spin_unlock(&clnt->cl_lock); |
538 | } | 538 | } |
539 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | 539 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); |
540 | 540 | ||
541 | /* | 541 | /* |
542 | * Properly shut down an RPC client, terminating all outstanding | 542 | * Properly shut down an RPC client, terminating all outstanding |
543 | * requests. | 543 | * requests. |
544 | */ | 544 | */ |
545 | void rpc_shutdown_client(struct rpc_clnt *clnt) | 545 | void rpc_shutdown_client(struct rpc_clnt *clnt) |
546 | { | 546 | { |
547 | dprintk("RPC: shutting down %s client for %s\n", | 547 | dprintk("RPC: shutting down %s client for %s\n", |
548 | clnt->cl_protname, clnt->cl_server); | 548 | clnt->cl_protname, clnt->cl_server); |
549 | 549 | ||
550 | while (!list_empty(&clnt->cl_tasks)) { | 550 | while (!list_empty(&clnt->cl_tasks)) { |
551 | rpc_killall_tasks(clnt); | 551 | rpc_killall_tasks(clnt); |
552 | wait_event_timeout(destroy_wait, | 552 | wait_event_timeout(destroy_wait, |
553 | list_empty(&clnt->cl_tasks), 1*HZ); | 553 | list_empty(&clnt->cl_tasks), 1*HZ); |
554 | } | 554 | } |
555 | 555 | ||
556 | rpc_release_client(clnt); | 556 | rpc_release_client(clnt); |
557 | } | 557 | } |
558 | EXPORT_SYMBOL_GPL(rpc_shutdown_client); | 558 | EXPORT_SYMBOL_GPL(rpc_shutdown_client); |
559 | 559 | ||
560 | /* | 560 | /* |
561 | * Free an RPC client | 561 | * Free an RPC client |
562 | */ | 562 | */ |
563 | static void | 563 | static void |
564 | rpc_free_client(struct rpc_clnt *clnt) | 564 | rpc_free_client(struct rpc_clnt *clnt) |
565 | { | 565 | { |
566 | dprintk("RPC: destroying %s client for %s\n", | 566 | dprintk("RPC: destroying %s client for %s\n", |
567 | clnt->cl_protname, clnt->cl_server); | 567 | clnt->cl_protname, clnt->cl_server); |
568 | if (clnt->cl_parent != clnt) | 568 | if (clnt->cl_parent != clnt) |
569 | rpc_release_client(clnt->cl_parent); | 569 | rpc_release_client(clnt->cl_parent); |
570 | kfree(clnt->cl_server); | 570 | kfree(clnt->cl_server); |
571 | rpc_unregister_client(clnt); | 571 | rpc_unregister_client(clnt); |
572 | rpc_clnt_remove_pipedir(clnt); | 572 | rpc_clnt_remove_pipedir(clnt); |
573 | rpc_free_iostats(clnt->cl_metrics); | 573 | rpc_free_iostats(clnt->cl_metrics); |
574 | kfree(clnt->cl_principal); | 574 | kfree(clnt->cl_principal); |
575 | clnt->cl_metrics = NULL; | 575 | clnt->cl_metrics = NULL; |
576 | xprt_put(clnt->cl_xprt); | 576 | xprt_put(clnt->cl_xprt); |
577 | rpciod_down(); | 577 | rpciod_down(); |
578 | kfree(clnt); | 578 | kfree(clnt); |
579 | } | 579 | } |
580 | 580 | ||
581 | /* | 581 | /* |
582 | * Free an RPC client | 582 | * Free an RPC client |
583 | */ | 583 | */ |
584 | static void | 584 | static void |
585 | rpc_free_auth(struct rpc_clnt *clnt) | 585 | rpc_free_auth(struct rpc_clnt *clnt) |
586 | { | 586 | { |
587 | if (clnt->cl_auth == NULL) { | 587 | if (clnt->cl_auth == NULL) { |
588 | rpc_free_client(clnt); | 588 | rpc_free_client(clnt); |
589 | return; | 589 | return; |
590 | } | 590 | } |
591 | 591 | ||
592 | /* | 592 | /* |
593 | * Note: RPCSEC_GSS may need to send NULL RPC calls in order to | 593 | * Note: RPCSEC_GSS may need to send NULL RPC calls in order to |
594 | * release remaining GSS contexts. This mechanism ensures | 594 | * release remaining GSS contexts. This mechanism ensures |
595 | * that it can do so safely. | 595 | * that it can do so safely. |
596 | */ | 596 | */ |
597 | atomic_inc(&clnt->cl_count); | 597 | atomic_inc(&clnt->cl_count); |
598 | rpcauth_release(clnt->cl_auth); | 598 | rpcauth_release(clnt->cl_auth); |
599 | clnt->cl_auth = NULL; | 599 | clnt->cl_auth = NULL; |
600 | if (atomic_dec_and_test(&clnt->cl_count)) | 600 | if (atomic_dec_and_test(&clnt->cl_count)) |
601 | rpc_free_client(clnt); | 601 | rpc_free_client(clnt); |
602 | } | 602 | } |
603 | 603 | ||
604 | /* | 604 | /* |
605 | * Release reference to the RPC client | 605 | * Release reference to the RPC client |
606 | */ | 606 | */ |
607 | void | 607 | void |
608 | rpc_release_client(struct rpc_clnt *clnt) | 608 | rpc_release_client(struct rpc_clnt *clnt) |
609 | { | 609 | { |
610 | dprintk("RPC: rpc_release_client(%p)\n", clnt); | 610 | dprintk("RPC: rpc_release_client(%p)\n", clnt); |
611 | 611 | ||
612 | if (list_empty(&clnt->cl_tasks)) | 612 | if (list_empty(&clnt->cl_tasks)) |
613 | wake_up(&destroy_wait); | 613 | wake_up(&destroy_wait); |
614 | if (atomic_dec_and_test(&clnt->cl_count)) | 614 | if (atomic_dec_and_test(&clnt->cl_count)) |
615 | rpc_free_auth(clnt); | 615 | rpc_free_auth(clnt); |
616 | } | 616 | } |
617 | 617 | ||
618 | /** | 618 | /** |
619 | * rpc_bind_new_program - bind a new RPC program to an existing client | 619 | * rpc_bind_new_program - bind a new RPC program to an existing client |
620 | * @old: old rpc_client | 620 | * @old: old rpc_client |
621 | * @program: rpc program to set | 621 | * @program: rpc program to set |
622 | * @vers: rpc program version | 622 | * @vers: rpc program version |
623 | * | 623 | * |
624 | * Clones the rpc client and sets up a new RPC program. This is mainly | 624 | * Clones the rpc client and sets up a new RPC program. This is mainly |
625 | * of use for enabling different RPC programs to share the same transport. | 625 | * of use for enabling different RPC programs to share the same transport. |
626 | * The Sun NFSv2/v3 ACL protocol can do this. | 626 | * The Sun NFSv2/v3 ACL protocol can do this. |
627 | */ | 627 | */ |
628 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | 628 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, |
629 | struct rpc_program *program, | 629 | const struct rpc_program *program, |
630 | u32 vers) | 630 | u32 vers) |
631 | { | 631 | { |
632 | struct rpc_clnt *clnt; | 632 | struct rpc_clnt *clnt; |
633 | struct rpc_version *version; | 633 | const struct rpc_version *version; |
634 | int err; | 634 | int err; |
635 | 635 | ||
636 | BUG_ON(vers >= program->nrvers || !program->version[vers]); | 636 | BUG_ON(vers >= program->nrvers || !program->version[vers]); |
637 | version = program->version[vers]; | 637 | version = program->version[vers]; |
638 | clnt = rpc_clone_client(old); | 638 | clnt = rpc_clone_client(old); |
639 | if (IS_ERR(clnt)) | 639 | if (IS_ERR(clnt)) |
640 | goto out; | 640 | goto out; |
641 | clnt->cl_procinfo = version->procs; | 641 | clnt->cl_procinfo = version->procs; |
642 | clnt->cl_maxproc = version->nrprocs; | 642 | clnt->cl_maxproc = version->nrprocs; |
643 | clnt->cl_protname = program->name; | 643 | clnt->cl_protname = program->name; |
644 | clnt->cl_prog = program->number; | 644 | clnt->cl_prog = program->number; |
645 | clnt->cl_vers = version->number; | 645 | clnt->cl_vers = version->number; |
646 | clnt->cl_stats = program->stats; | 646 | clnt->cl_stats = program->stats; |
647 | err = rpc_ping(clnt); | 647 | err = rpc_ping(clnt); |
648 | if (err != 0) { | 648 | if (err != 0) { |
649 | rpc_shutdown_client(clnt); | 649 | rpc_shutdown_client(clnt); |
650 | clnt = ERR_PTR(err); | 650 | clnt = ERR_PTR(err); |
651 | } | 651 | } |
652 | out: | 652 | out: |
653 | return clnt; | 653 | return clnt; |
654 | } | 654 | } |
655 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); | 655 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); |
656 | 656 | ||
657 | void rpc_task_release_client(struct rpc_task *task) | 657 | void rpc_task_release_client(struct rpc_task *task) |
658 | { | 658 | { |
659 | struct rpc_clnt *clnt = task->tk_client; | 659 | struct rpc_clnt *clnt = task->tk_client; |
660 | 660 | ||
661 | if (clnt != NULL) { | 661 | if (clnt != NULL) { |
662 | /* Remove from client task list */ | 662 | /* Remove from client task list */ |
663 | spin_lock(&clnt->cl_lock); | 663 | spin_lock(&clnt->cl_lock); |
664 | list_del(&task->tk_task); | 664 | list_del(&task->tk_task); |
665 | spin_unlock(&clnt->cl_lock); | 665 | spin_unlock(&clnt->cl_lock); |
666 | task->tk_client = NULL; | 666 | task->tk_client = NULL; |
667 | 667 | ||
668 | rpc_release_client(clnt); | 668 | rpc_release_client(clnt); |
669 | } | 669 | } |
670 | } | 670 | } |
671 | 671 | ||
672 | static | 672 | static |
673 | void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | 673 | void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) |
674 | { | 674 | { |
675 | if (clnt != NULL) { | 675 | if (clnt != NULL) { |
676 | rpc_task_release_client(task); | 676 | rpc_task_release_client(task); |
677 | task->tk_client = clnt; | 677 | task->tk_client = clnt; |
678 | atomic_inc(&clnt->cl_count); | 678 | atomic_inc(&clnt->cl_count); |
679 | if (clnt->cl_softrtry) | 679 | if (clnt->cl_softrtry) |
680 | task->tk_flags |= RPC_TASK_SOFT; | 680 | task->tk_flags |= RPC_TASK_SOFT; |
681 | /* Add to the client's list of all tasks */ | 681 | /* Add to the client's list of all tasks */ |
682 | spin_lock(&clnt->cl_lock); | 682 | spin_lock(&clnt->cl_lock); |
683 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | 683 | list_add_tail(&task->tk_task, &clnt->cl_tasks); |
684 | spin_unlock(&clnt->cl_lock); | 684 | spin_unlock(&clnt->cl_lock); |
685 | } | 685 | } |
686 | } | 686 | } |
687 | 687 | ||
688 | void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt) | 688 | void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt) |
689 | { | 689 | { |
690 | rpc_task_release_client(task); | 690 | rpc_task_release_client(task); |
691 | rpc_task_set_client(task, clnt); | 691 | rpc_task_set_client(task, clnt); |
692 | } | 692 | } |
693 | EXPORT_SYMBOL_GPL(rpc_task_reset_client); | 693 | EXPORT_SYMBOL_GPL(rpc_task_reset_client); |
694 | 694 | ||
695 | 695 | ||
696 | static void | 696 | static void |
697 | rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg) | 697 | rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg) |
698 | { | 698 | { |
699 | if (msg != NULL) { | 699 | if (msg != NULL) { |
700 | task->tk_msg.rpc_proc = msg->rpc_proc; | 700 | task->tk_msg.rpc_proc = msg->rpc_proc; |
701 | task->tk_msg.rpc_argp = msg->rpc_argp; | 701 | task->tk_msg.rpc_argp = msg->rpc_argp; |
702 | task->tk_msg.rpc_resp = msg->rpc_resp; | 702 | task->tk_msg.rpc_resp = msg->rpc_resp; |
703 | if (msg->rpc_cred != NULL) | 703 | if (msg->rpc_cred != NULL) |
704 | task->tk_msg.rpc_cred = get_rpccred(msg->rpc_cred); | 704 | task->tk_msg.rpc_cred = get_rpccred(msg->rpc_cred); |
705 | } | 705 | } |
706 | } | 706 | } |
707 | 707 | ||
708 | /* | 708 | /* |
709 | * Default callback for async RPC calls | 709 | * Default callback for async RPC calls |
710 | */ | 710 | */ |
711 | static void | 711 | static void |
712 | rpc_default_callback(struct rpc_task *task, void *data) | 712 | rpc_default_callback(struct rpc_task *task, void *data) |
713 | { | 713 | { |
714 | } | 714 | } |
715 | 715 | ||
716 | static const struct rpc_call_ops rpc_default_ops = { | 716 | static const struct rpc_call_ops rpc_default_ops = { |
717 | .rpc_call_done = rpc_default_callback, | 717 | .rpc_call_done = rpc_default_callback, |
718 | }; | 718 | }; |
719 | 719 | ||
720 | /** | 720 | /** |
721 | * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it | 721 | * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it |
722 | * @task_setup_data: pointer to task initialisation data | 722 | * @task_setup_data: pointer to task initialisation data |
723 | */ | 723 | */ |
724 | struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data) | 724 | struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data) |
725 | { | 725 | { |
726 | struct rpc_task *task; | 726 | struct rpc_task *task; |
727 | 727 | ||
728 | task = rpc_new_task(task_setup_data); | 728 | task = rpc_new_task(task_setup_data); |
729 | if (IS_ERR(task)) | 729 | if (IS_ERR(task)) |
730 | goto out; | 730 | goto out; |
731 | 731 | ||
732 | rpc_task_set_client(task, task_setup_data->rpc_client); | 732 | rpc_task_set_client(task, task_setup_data->rpc_client); |
733 | rpc_task_set_rpc_message(task, task_setup_data->rpc_message); | 733 | rpc_task_set_rpc_message(task, task_setup_data->rpc_message); |
734 | 734 | ||
735 | if (task->tk_action == NULL) | 735 | if (task->tk_action == NULL) |
736 | rpc_call_start(task); | 736 | rpc_call_start(task); |
737 | 737 | ||
738 | atomic_inc(&task->tk_count); | 738 | atomic_inc(&task->tk_count); |
739 | rpc_execute(task); | 739 | rpc_execute(task); |
740 | out: | 740 | out: |
741 | return task; | 741 | return task; |
742 | } | 742 | } |
743 | EXPORT_SYMBOL_GPL(rpc_run_task); | 743 | EXPORT_SYMBOL_GPL(rpc_run_task); |
744 | 744 | ||
745 | /** | 745 | /** |
746 | * rpc_call_sync - Perform a synchronous RPC call | 746 | * rpc_call_sync - Perform a synchronous RPC call |
747 | * @clnt: pointer to RPC client | 747 | * @clnt: pointer to RPC client |
748 | * @msg: RPC call parameters | 748 | * @msg: RPC call parameters |
749 | * @flags: RPC call flags | 749 | * @flags: RPC call flags |
750 | */ | 750 | */ |
751 | int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags) | 751 | int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags) |
752 | { | 752 | { |
753 | struct rpc_task *task; | 753 | struct rpc_task *task; |
754 | struct rpc_task_setup task_setup_data = { | 754 | struct rpc_task_setup task_setup_data = { |
755 | .rpc_client = clnt, | 755 | .rpc_client = clnt, |
756 | .rpc_message = msg, | 756 | .rpc_message = msg, |
757 | .callback_ops = &rpc_default_ops, | 757 | .callback_ops = &rpc_default_ops, |
758 | .flags = flags, | 758 | .flags = flags, |
759 | }; | 759 | }; |
760 | int status; | 760 | int status; |
761 | 761 | ||
762 | BUG_ON(flags & RPC_TASK_ASYNC); | 762 | BUG_ON(flags & RPC_TASK_ASYNC); |
763 | 763 | ||
764 | task = rpc_run_task(&task_setup_data); | 764 | task = rpc_run_task(&task_setup_data); |
765 | if (IS_ERR(task)) | 765 | if (IS_ERR(task)) |
766 | return PTR_ERR(task); | 766 | return PTR_ERR(task); |
767 | status = task->tk_status; | 767 | status = task->tk_status; |
768 | rpc_put_task(task); | 768 | rpc_put_task(task); |
769 | return status; | 769 | return status; |
770 | } | 770 | } |
771 | EXPORT_SYMBOL_GPL(rpc_call_sync); | 771 | EXPORT_SYMBOL_GPL(rpc_call_sync); |
772 | 772 | ||
773 | /** | 773 | /** |
774 | * rpc_call_async - Perform an asynchronous RPC call | 774 | * rpc_call_async - Perform an asynchronous RPC call |
775 | * @clnt: pointer to RPC client | 775 | * @clnt: pointer to RPC client |
776 | * @msg: RPC call parameters | 776 | * @msg: RPC call parameters |
777 | * @flags: RPC call flags | 777 | * @flags: RPC call flags |
778 | * @tk_ops: RPC call ops | 778 | * @tk_ops: RPC call ops |
779 | * @data: user call data | 779 | * @data: user call data |
780 | */ | 780 | */ |
781 | int | 781 | int |
782 | rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags, | 782 | rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags, |
783 | const struct rpc_call_ops *tk_ops, void *data) | 783 | const struct rpc_call_ops *tk_ops, void *data) |
784 | { | 784 | { |
785 | struct rpc_task *task; | 785 | struct rpc_task *task; |
786 | struct rpc_task_setup task_setup_data = { | 786 | struct rpc_task_setup task_setup_data = { |
787 | .rpc_client = clnt, | 787 | .rpc_client = clnt, |
788 | .rpc_message = msg, | 788 | .rpc_message = msg, |
789 | .callback_ops = tk_ops, | 789 | .callback_ops = tk_ops, |
790 | .callback_data = data, | 790 | .callback_data = data, |
791 | .flags = flags|RPC_TASK_ASYNC, | 791 | .flags = flags|RPC_TASK_ASYNC, |
792 | }; | 792 | }; |
793 | 793 | ||
794 | task = rpc_run_task(&task_setup_data); | 794 | task = rpc_run_task(&task_setup_data); |
795 | if (IS_ERR(task)) | 795 | if (IS_ERR(task)) |
796 | return PTR_ERR(task); | 796 | return PTR_ERR(task); |
797 | rpc_put_task(task); | 797 | rpc_put_task(task); |
798 | return 0; | 798 | return 0; |
799 | } | 799 | } |
800 | EXPORT_SYMBOL_GPL(rpc_call_async); | 800 | EXPORT_SYMBOL_GPL(rpc_call_async); |
801 | 801 | ||
802 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) | 802 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) |
803 | /** | 803 | /** |
804 | * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run | 804 | * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run |
805 | * rpc_execute against it | 805 | * rpc_execute against it |
806 | * @req: RPC request | 806 | * @req: RPC request |
807 | * @tk_ops: RPC call ops | 807 | * @tk_ops: RPC call ops |
808 | */ | 808 | */ |
809 | struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, | 809 | struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, |
810 | const struct rpc_call_ops *tk_ops) | 810 | const struct rpc_call_ops *tk_ops) |
811 | { | 811 | { |
812 | struct rpc_task *task; | 812 | struct rpc_task *task; |
813 | struct xdr_buf *xbufp = &req->rq_snd_buf; | 813 | struct xdr_buf *xbufp = &req->rq_snd_buf; |
814 | struct rpc_task_setup task_setup_data = { | 814 | struct rpc_task_setup task_setup_data = { |
815 | .callback_ops = tk_ops, | 815 | .callback_ops = tk_ops, |
816 | }; | 816 | }; |
817 | 817 | ||
818 | dprintk("RPC: rpc_run_bc_task req= %p\n", req); | 818 | dprintk("RPC: rpc_run_bc_task req= %p\n", req); |
819 | /* | 819 | /* |
820 | * Create an rpc_task to send the data | 820 | * Create an rpc_task to send the data |
821 | */ | 821 | */ |
822 | task = rpc_new_task(&task_setup_data); | 822 | task = rpc_new_task(&task_setup_data); |
823 | if (IS_ERR(task)) { | 823 | if (IS_ERR(task)) { |
824 | xprt_free_bc_request(req); | 824 | xprt_free_bc_request(req); |
825 | goto out; | 825 | goto out; |
826 | } | 826 | } |
827 | task->tk_rqstp = req; | 827 | task->tk_rqstp = req; |
828 | 828 | ||
829 | /* | 829 | /* |
830 | * Set up the xdr_buf length. | 830 | * Set up the xdr_buf length. |
831 | * This also indicates that the buffer is XDR encoded already. | 831 | * This also indicates that the buffer is XDR encoded already. |
832 | */ | 832 | */ |
833 | xbufp->len = xbufp->head[0].iov_len + xbufp->page_len + | 833 | xbufp->len = xbufp->head[0].iov_len + xbufp->page_len + |
834 | xbufp->tail[0].iov_len; | 834 | xbufp->tail[0].iov_len; |
835 | 835 | ||
836 | task->tk_action = call_bc_transmit; | 836 | task->tk_action = call_bc_transmit; |
837 | atomic_inc(&task->tk_count); | 837 | atomic_inc(&task->tk_count); |
838 | BUG_ON(atomic_read(&task->tk_count) != 2); | 838 | BUG_ON(atomic_read(&task->tk_count) != 2); |
839 | rpc_execute(task); | 839 | rpc_execute(task); |
840 | 840 | ||
841 | out: | 841 | out: |
842 | dprintk("RPC: rpc_run_bc_task: task= %p\n", task); | 842 | dprintk("RPC: rpc_run_bc_task: task= %p\n", task); |
843 | return task; | 843 | return task; |
844 | } | 844 | } |
845 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 845 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
846 | 846 | ||
847 | void | 847 | void |
848 | rpc_call_start(struct rpc_task *task) | 848 | rpc_call_start(struct rpc_task *task) |
849 | { | 849 | { |
850 | task->tk_action = call_start; | 850 | task->tk_action = call_start; |
851 | } | 851 | } |
852 | EXPORT_SYMBOL_GPL(rpc_call_start); | 852 | EXPORT_SYMBOL_GPL(rpc_call_start); |
853 | 853 | ||
854 | /** | 854 | /** |
855 | * rpc_peeraddr - extract remote peer address from clnt's xprt | 855 | * rpc_peeraddr - extract remote peer address from clnt's xprt |
856 | * @clnt: RPC client structure | 856 | * @clnt: RPC client structure |
857 | * @buf: target buffer | 857 | * @buf: target buffer |
858 | * @bufsize: length of target buffer | 858 | * @bufsize: length of target buffer |
859 | * | 859 | * |
860 | * Returns the number of bytes that are actually in the stored address. | 860 | * Returns the number of bytes that are actually in the stored address. |
861 | */ | 861 | */ |
862 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) | 862 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) |
863 | { | 863 | { |
864 | size_t bytes; | 864 | size_t bytes; |
865 | struct rpc_xprt *xprt = clnt->cl_xprt; | 865 | struct rpc_xprt *xprt = clnt->cl_xprt; |
866 | 866 | ||
867 | bytes = sizeof(xprt->addr); | 867 | bytes = sizeof(xprt->addr); |
868 | if (bytes > bufsize) | 868 | if (bytes > bufsize) |
869 | bytes = bufsize; | 869 | bytes = bufsize; |
870 | memcpy(buf, &clnt->cl_xprt->addr, bytes); | 870 | memcpy(buf, &clnt->cl_xprt->addr, bytes); |
871 | return xprt->addrlen; | 871 | return xprt->addrlen; |
872 | } | 872 | } |
873 | EXPORT_SYMBOL_GPL(rpc_peeraddr); | 873 | EXPORT_SYMBOL_GPL(rpc_peeraddr); |
874 | 874 | ||
875 | /** | 875 | /** |
876 | * rpc_peeraddr2str - return remote peer address in printable format | 876 | * rpc_peeraddr2str - return remote peer address in printable format |
877 | * @clnt: RPC client structure | 877 | * @clnt: RPC client structure |
878 | * @format: address format | 878 | * @format: address format |
879 | * | 879 | * |
880 | */ | 880 | */ |
881 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, | 881 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, |
882 | enum rpc_display_format_t format) | 882 | enum rpc_display_format_t format) |
883 | { | 883 | { |
884 | struct rpc_xprt *xprt = clnt->cl_xprt; | 884 | struct rpc_xprt *xprt = clnt->cl_xprt; |
885 | 885 | ||
886 | if (xprt->address_strings[format] != NULL) | 886 | if (xprt->address_strings[format] != NULL) |
887 | return xprt->address_strings[format]; | 887 | return xprt->address_strings[format]; |
888 | else | 888 | else |
889 | return "unprintable"; | 889 | return "unprintable"; |
890 | } | 890 | } |
891 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); | 891 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); |
892 | 892 | ||
893 | void | 893 | void |
894 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) | 894 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) |
895 | { | 895 | { |
896 | struct rpc_xprt *xprt = clnt->cl_xprt; | 896 | struct rpc_xprt *xprt = clnt->cl_xprt; |
897 | if (xprt->ops->set_buffer_size) | 897 | if (xprt->ops->set_buffer_size) |
898 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); | 898 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); |
899 | } | 899 | } |
900 | EXPORT_SYMBOL_GPL(rpc_setbufsize); | 900 | EXPORT_SYMBOL_GPL(rpc_setbufsize); |
901 | 901 | ||
902 | /* | 902 | /* |
903 | * Return size of largest payload RPC client can support, in bytes | 903 | * Return size of largest payload RPC client can support, in bytes |
904 | * | 904 | * |
905 | * For stream transports, this is one RPC record fragment (see RFC | 905 | * For stream transports, this is one RPC record fragment (see RFC |
906 | * 1831), as we don't support multi-record requests yet. For datagram | 906 | * 1831), as we don't support multi-record requests yet. For datagram |
907 | * transports, this is the size of an IP packet minus the IP, UDP, and | 907 | * transports, this is the size of an IP packet minus the IP, UDP, and |
908 | * RPC header sizes. | 908 | * RPC header sizes. |
909 | */ | 909 | */ |
910 | size_t rpc_max_payload(struct rpc_clnt *clnt) | 910 | size_t rpc_max_payload(struct rpc_clnt *clnt) |
911 | { | 911 | { |
912 | return clnt->cl_xprt->max_payload; | 912 | return clnt->cl_xprt->max_payload; |
913 | } | 913 | } |
914 | EXPORT_SYMBOL_GPL(rpc_max_payload); | 914 | EXPORT_SYMBOL_GPL(rpc_max_payload); |
915 | 915 | ||
916 | /** | 916 | /** |
917 | * rpc_force_rebind - force transport to check that remote port is unchanged | 917 | * rpc_force_rebind - force transport to check that remote port is unchanged |
918 | * @clnt: client to rebind | 918 | * @clnt: client to rebind |
919 | * | 919 | * |
920 | */ | 920 | */ |
921 | void rpc_force_rebind(struct rpc_clnt *clnt) | 921 | void rpc_force_rebind(struct rpc_clnt *clnt) |
922 | { | 922 | { |
923 | if (clnt->cl_autobind) | 923 | if (clnt->cl_autobind) |
924 | xprt_clear_bound(clnt->cl_xprt); | 924 | xprt_clear_bound(clnt->cl_xprt); |
925 | } | 925 | } |
926 | EXPORT_SYMBOL_GPL(rpc_force_rebind); | 926 | EXPORT_SYMBOL_GPL(rpc_force_rebind); |
927 | 927 | ||
928 | /* | 928 | /* |
929 | * Restart an (async) RPC call from the call_prepare state. | 929 | * Restart an (async) RPC call from the call_prepare state. |
930 | * Usually called from within the exit handler. | 930 | * Usually called from within the exit handler. |
931 | */ | 931 | */ |
932 | int | 932 | int |
933 | rpc_restart_call_prepare(struct rpc_task *task) | 933 | rpc_restart_call_prepare(struct rpc_task *task) |
934 | { | 934 | { |
935 | if (RPC_ASSASSINATED(task)) | 935 | if (RPC_ASSASSINATED(task)) |
936 | return 0; | 936 | return 0; |
937 | task->tk_action = call_start; | 937 | task->tk_action = call_start; |
938 | if (task->tk_ops->rpc_call_prepare != NULL) | 938 | if (task->tk_ops->rpc_call_prepare != NULL) |
939 | task->tk_action = rpc_prepare_task; | 939 | task->tk_action = rpc_prepare_task; |
940 | return 1; | 940 | return 1; |
941 | } | 941 | } |
942 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | 942 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); |
943 | 943 | ||
944 | /* | 944 | /* |
945 | * Restart an (async) RPC call. Usually called from within the | 945 | * Restart an (async) RPC call. Usually called from within the |
946 | * exit handler. | 946 | * exit handler. |
947 | */ | 947 | */ |
948 | int | 948 | int |
949 | rpc_restart_call(struct rpc_task *task) | 949 | rpc_restart_call(struct rpc_task *task) |
950 | { | 950 | { |
951 | if (RPC_ASSASSINATED(task)) | 951 | if (RPC_ASSASSINATED(task)) |
952 | return 0; | 952 | return 0; |
953 | task->tk_action = call_start; | 953 | task->tk_action = call_start; |
954 | return 1; | 954 | return 1; |
955 | } | 955 | } |
956 | EXPORT_SYMBOL_GPL(rpc_restart_call); | 956 | EXPORT_SYMBOL_GPL(rpc_restart_call); |
957 | 957 | ||
958 | #ifdef RPC_DEBUG | 958 | #ifdef RPC_DEBUG |
959 | static const char *rpc_proc_name(const struct rpc_task *task) | 959 | static const char *rpc_proc_name(const struct rpc_task *task) |
960 | { | 960 | { |
961 | const struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 961 | const struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
962 | 962 | ||
963 | if (proc) { | 963 | if (proc) { |
964 | if (proc->p_name) | 964 | if (proc->p_name) |
965 | return proc->p_name; | 965 | return proc->p_name; |
966 | else | 966 | else |
967 | return "NULL"; | 967 | return "NULL"; |
968 | } else | 968 | } else |
969 | return "no proc"; | 969 | return "no proc"; |
970 | } | 970 | } |
971 | #endif | 971 | #endif |
972 | 972 | ||
973 | /* | 973 | /* |
974 | * 0. Initial state | 974 | * 0. Initial state |
975 | * | 975 | * |
976 | * Other FSM states can be visited zero or more times, but | 976 | * Other FSM states can be visited zero or more times, but |
977 | * this state is visited exactly once for each RPC. | 977 | * this state is visited exactly once for each RPC. |
978 | */ | 978 | */ |
979 | static void | 979 | static void |
980 | call_start(struct rpc_task *task) | 980 | call_start(struct rpc_task *task) |
981 | { | 981 | { |
982 | struct rpc_clnt *clnt = task->tk_client; | 982 | struct rpc_clnt *clnt = task->tk_client; |
983 | 983 | ||
984 | dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid, | 984 | dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid, |
985 | clnt->cl_protname, clnt->cl_vers, | 985 | clnt->cl_protname, clnt->cl_vers, |
986 | rpc_proc_name(task), | 986 | rpc_proc_name(task), |
987 | (RPC_IS_ASYNC(task) ? "async" : "sync")); | 987 | (RPC_IS_ASYNC(task) ? "async" : "sync")); |
988 | 988 | ||
989 | /* Increment call count */ | 989 | /* Increment call count */ |
990 | task->tk_msg.rpc_proc->p_count++; | 990 | task->tk_msg.rpc_proc->p_count++; |
991 | clnt->cl_stats->rpccnt++; | 991 | clnt->cl_stats->rpccnt++; |
992 | task->tk_action = call_reserve; | 992 | task->tk_action = call_reserve; |
993 | } | 993 | } |
994 | 994 | ||
995 | /* | 995 | /* |
996 | * 1. Reserve an RPC call slot | 996 | * 1. Reserve an RPC call slot |
997 | */ | 997 | */ |
998 | static void | 998 | static void |
999 | call_reserve(struct rpc_task *task) | 999 | call_reserve(struct rpc_task *task) |
1000 | { | 1000 | { |
1001 | dprint_status(task); | 1001 | dprint_status(task); |
1002 | 1002 | ||
1003 | task->tk_status = 0; | 1003 | task->tk_status = 0; |
1004 | task->tk_action = call_reserveresult; | 1004 | task->tk_action = call_reserveresult; |
1005 | xprt_reserve(task); | 1005 | xprt_reserve(task); |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | /* | 1008 | /* |
1009 | * 1b. Grok the result of xprt_reserve() | 1009 | * 1b. Grok the result of xprt_reserve() |
1010 | */ | 1010 | */ |
1011 | static void | 1011 | static void |
1012 | call_reserveresult(struct rpc_task *task) | 1012 | call_reserveresult(struct rpc_task *task) |
1013 | { | 1013 | { |
1014 | int status = task->tk_status; | 1014 | int status = task->tk_status; |
1015 | 1015 | ||
1016 | dprint_status(task); | 1016 | dprint_status(task); |
1017 | 1017 | ||
1018 | /* | 1018 | /* |
1019 | * After a call to xprt_reserve(), we must have either | 1019 | * After a call to xprt_reserve(), we must have either |
1020 | * a request slot or else an error status. | 1020 | * a request slot or else an error status. |
1021 | */ | 1021 | */ |
1022 | task->tk_status = 0; | 1022 | task->tk_status = 0; |
1023 | if (status >= 0) { | 1023 | if (status >= 0) { |
1024 | if (task->tk_rqstp) { | 1024 | if (task->tk_rqstp) { |
1025 | task->tk_action = call_refresh; | 1025 | task->tk_action = call_refresh; |
1026 | return; | 1026 | return; |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | printk(KERN_ERR "%s: status=%d, but no request slot, exiting\n", | 1029 | printk(KERN_ERR "%s: status=%d, but no request slot, exiting\n", |
1030 | __func__, status); | 1030 | __func__, status); |
1031 | rpc_exit(task, -EIO); | 1031 | rpc_exit(task, -EIO); |
1032 | return; | 1032 | return; |
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | /* | 1035 | /* |
1036 | * Even though there was an error, we may have acquired | 1036 | * Even though there was an error, we may have acquired |
1037 | * a request slot somehow. Make sure not to leak it. | 1037 | * a request slot somehow. Make sure not to leak it. |
1038 | */ | 1038 | */ |
1039 | if (task->tk_rqstp) { | 1039 | if (task->tk_rqstp) { |
1040 | printk(KERN_ERR "%s: status=%d, request allocated anyway\n", | 1040 | printk(KERN_ERR "%s: status=%d, request allocated anyway\n", |
1041 | __func__, status); | 1041 | __func__, status); |
1042 | xprt_release(task); | 1042 | xprt_release(task); |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | switch (status) { | 1045 | switch (status) { |
1046 | case -EAGAIN: /* woken up; retry */ | 1046 | case -EAGAIN: /* woken up; retry */ |
1047 | task->tk_action = call_reserve; | 1047 | task->tk_action = call_reserve; |
1048 | return; | 1048 | return; |
1049 | case -EIO: /* probably a shutdown */ | 1049 | case -EIO: /* probably a shutdown */ |
1050 | break; | 1050 | break; |
1051 | default: | 1051 | default: |
1052 | printk(KERN_ERR "%s: unrecognized error %d, exiting\n", | 1052 | printk(KERN_ERR "%s: unrecognized error %d, exiting\n", |
1053 | __func__, status); | 1053 | __func__, status); |
1054 | break; | 1054 | break; |
1055 | } | 1055 | } |
1056 | rpc_exit(task, status); | 1056 | rpc_exit(task, status); |
1057 | } | 1057 | } |
1058 | 1058 | ||
1059 | /* | 1059 | /* |
1060 | * 2. Bind and/or refresh the credentials | 1060 | * 2. Bind and/or refresh the credentials |
1061 | */ | 1061 | */ |
1062 | static void | 1062 | static void |
1063 | call_refresh(struct rpc_task *task) | 1063 | call_refresh(struct rpc_task *task) |
1064 | { | 1064 | { |
1065 | dprint_status(task); | 1065 | dprint_status(task); |
1066 | 1066 | ||
1067 | task->tk_action = call_refreshresult; | 1067 | task->tk_action = call_refreshresult; |
1068 | task->tk_status = 0; | 1068 | task->tk_status = 0; |
1069 | task->tk_client->cl_stats->rpcauthrefresh++; | 1069 | task->tk_client->cl_stats->rpcauthrefresh++; |
1070 | rpcauth_refreshcred(task); | 1070 | rpcauth_refreshcred(task); |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | /* | 1073 | /* |
1074 | * 2a. Process the results of a credential refresh | 1074 | * 2a. Process the results of a credential refresh |
1075 | */ | 1075 | */ |
1076 | static void | 1076 | static void |
1077 | call_refreshresult(struct rpc_task *task) | 1077 | call_refreshresult(struct rpc_task *task) |
1078 | { | 1078 | { |
1079 | int status = task->tk_status; | 1079 | int status = task->tk_status; |
1080 | 1080 | ||
1081 | dprint_status(task); | 1081 | dprint_status(task); |
1082 | 1082 | ||
1083 | task->tk_status = 0; | 1083 | task->tk_status = 0; |
1084 | task->tk_action = call_refresh; | 1084 | task->tk_action = call_refresh; |
1085 | switch (status) { | 1085 | switch (status) { |
1086 | case 0: | 1086 | case 0: |
1087 | if (rpcauth_uptodatecred(task)) | 1087 | if (rpcauth_uptodatecred(task)) |
1088 | task->tk_action = call_allocate; | 1088 | task->tk_action = call_allocate; |
1089 | return; | 1089 | return; |
1090 | case -ETIMEDOUT: | 1090 | case -ETIMEDOUT: |
1091 | rpc_delay(task, 3*HZ); | 1091 | rpc_delay(task, 3*HZ); |
1092 | case -EAGAIN: | 1092 | case -EAGAIN: |
1093 | status = -EACCES; | 1093 | status = -EACCES; |
1094 | if (!task->tk_cred_retry) | 1094 | if (!task->tk_cred_retry) |
1095 | break; | 1095 | break; |
1096 | task->tk_cred_retry--; | 1096 | task->tk_cred_retry--; |
1097 | dprintk("RPC: %5u %s: retry refresh creds\n", | 1097 | dprintk("RPC: %5u %s: retry refresh creds\n", |
1098 | task->tk_pid, __func__); | 1098 | task->tk_pid, __func__); |
1099 | return; | 1099 | return; |
1100 | } | 1100 | } |
1101 | dprintk("RPC: %5u %s: refresh creds failed with error %d\n", | 1101 | dprintk("RPC: %5u %s: refresh creds failed with error %d\n", |
1102 | task->tk_pid, __func__, status); | 1102 | task->tk_pid, __func__, status); |
1103 | rpc_exit(task, status); | 1103 | rpc_exit(task, status); |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | /* | 1106 | /* |
1107 | * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. | 1107 | * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. |
1108 | * (Note: buffer memory is freed in xprt_release). | 1108 | * (Note: buffer memory is freed in xprt_release). |
1109 | */ | 1109 | */ |
1110 | static void | 1110 | static void |
1111 | call_allocate(struct rpc_task *task) | 1111 | call_allocate(struct rpc_task *task) |
1112 | { | 1112 | { |
1113 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; | 1113 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; |
1114 | struct rpc_rqst *req = task->tk_rqstp; | 1114 | struct rpc_rqst *req = task->tk_rqstp; |
1115 | struct rpc_xprt *xprt = task->tk_xprt; | 1115 | struct rpc_xprt *xprt = task->tk_xprt; |
1116 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 1116 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
1117 | 1117 | ||
1118 | dprint_status(task); | 1118 | dprint_status(task); |
1119 | 1119 | ||
1120 | task->tk_status = 0; | 1120 | task->tk_status = 0; |
1121 | task->tk_action = call_bind; | 1121 | task->tk_action = call_bind; |
1122 | 1122 | ||
1123 | if (req->rq_buffer) | 1123 | if (req->rq_buffer) |
1124 | return; | 1124 | return; |
1125 | 1125 | ||
1126 | if (proc->p_proc != 0) { | 1126 | if (proc->p_proc != 0) { |
1127 | BUG_ON(proc->p_arglen == 0); | 1127 | BUG_ON(proc->p_arglen == 0); |
1128 | if (proc->p_decode != NULL) | 1128 | if (proc->p_decode != NULL) |
1129 | BUG_ON(proc->p_replen == 0); | 1129 | BUG_ON(proc->p_replen == 0); |
1130 | } | 1130 | } |
1131 | 1131 | ||
1132 | /* | 1132 | /* |
1133 | * Calculate the size (in quads) of the RPC call | 1133 | * Calculate the size (in quads) of the RPC call |
1134 | * and reply headers, and convert both values | 1134 | * and reply headers, and convert both values |
1135 | * to byte sizes. | 1135 | * to byte sizes. |
1136 | */ | 1136 | */ |
1137 | req->rq_callsize = RPC_CALLHDRSIZE + (slack << 1) + proc->p_arglen; | 1137 | req->rq_callsize = RPC_CALLHDRSIZE + (slack << 1) + proc->p_arglen; |
1138 | req->rq_callsize <<= 2; | 1138 | req->rq_callsize <<= 2; |
1139 | req->rq_rcvsize = RPC_REPHDRSIZE + slack + proc->p_replen; | 1139 | req->rq_rcvsize = RPC_REPHDRSIZE + slack + proc->p_replen; |
1140 | req->rq_rcvsize <<= 2; | 1140 | req->rq_rcvsize <<= 2; |
1141 | 1141 | ||
1142 | req->rq_buffer = xprt->ops->buf_alloc(task, | 1142 | req->rq_buffer = xprt->ops->buf_alloc(task, |
1143 | req->rq_callsize + req->rq_rcvsize); | 1143 | req->rq_callsize + req->rq_rcvsize); |
1144 | if (req->rq_buffer != NULL) | 1144 | if (req->rq_buffer != NULL) |
1145 | return; | 1145 | return; |
1146 | 1146 | ||
1147 | dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); | 1147 | dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); |
1148 | 1148 | ||
1149 | if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) { | 1149 | if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) { |
1150 | task->tk_action = call_allocate; | 1150 | task->tk_action = call_allocate; |
1151 | rpc_delay(task, HZ>>4); | 1151 | rpc_delay(task, HZ>>4); |
1152 | return; | 1152 | return; |
1153 | } | 1153 | } |
1154 | 1154 | ||
1155 | rpc_exit(task, -ERESTARTSYS); | 1155 | rpc_exit(task, -ERESTARTSYS); |
1156 | } | 1156 | } |
1157 | 1157 | ||
1158 | static inline int | 1158 | static inline int |
1159 | rpc_task_need_encode(struct rpc_task *task) | 1159 | rpc_task_need_encode(struct rpc_task *task) |
1160 | { | 1160 | { |
1161 | return task->tk_rqstp->rq_snd_buf.len == 0; | 1161 | return task->tk_rqstp->rq_snd_buf.len == 0; |
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | static inline void | 1164 | static inline void |
1165 | rpc_task_force_reencode(struct rpc_task *task) | 1165 | rpc_task_force_reencode(struct rpc_task *task) |
1166 | { | 1166 | { |
1167 | task->tk_rqstp->rq_snd_buf.len = 0; | 1167 | task->tk_rqstp->rq_snd_buf.len = 0; |
1168 | task->tk_rqstp->rq_bytes_sent = 0; | 1168 | task->tk_rqstp->rq_bytes_sent = 0; |
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | static inline void | 1171 | static inline void |
1172 | rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) | 1172 | rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) |
1173 | { | 1173 | { |
1174 | buf->head[0].iov_base = start; | 1174 | buf->head[0].iov_base = start; |
1175 | buf->head[0].iov_len = len; | 1175 | buf->head[0].iov_len = len; |
1176 | buf->tail[0].iov_len = 0; | 1176 | buf->tail[0].iov_len = 0; |
1177 | buf->page_len = 0; | 1177 | buf->page_len = 0; |
1178 | buf->flags = 0; | 1178 | buf->flags = 0; |
1179 | buf->len = 0; | 1179 | buf->len = 0; |
1180 | buf->buflen = len; | 1180 | buf->buflen = len; |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | /* | 1183 | /* |
1184 | * 3. Encode arguments of an RPC call | 1184 | * 3. Encode arguments of an RPC call |
1185 | */ | 1185 | */ |
1186 | static void | 1186 | static void |
1187 | rpc_xdr_encode(struct rpc_task *task) | 1187 | rpc_xdr_encode(struct rpc_task *task) |
1188 | { | 1188 | { |
1189 | struct rpc_rqst *req = task->tk_rqstp; | 1189 | struct rpc_rqst *req = task->tk_rqstp; |
1190 | kxdreproc_t encode; | 1190 | kxdreproc_t encode; |
1191 | __be32 *p; | 1191 | __be32 *p; |
1192 | 1192 | ||
1193 | dprint_status(task); | 1193 | dprint_status(task); |
1194 | 1194 | ||
1195 | rpc_xdr_buf_init(&req->rq_snd_buf, | 1195 | rpc_xdr_buf_init(&req->rq_snd_buf, |
1196 | req->rq_buffer, | 1196 | req->rq_buffer, |
1197 | req->rq_callsize); | 1197 | req->rq_callsize); |
1198 | rpc_xdr_buf_init(&req->rq_rcv_buf, | 1198 | rpc_xdr_buf_init(&req->rq_rcv_buf, |
1199 | (char *)req->rq_buffer + req->rq_callsize, | 1199 | (char *)req->rq_buffer + req->rq_callsize, |
1200 | req->rq_rcvsize); | 1200 | req->rq_rcvsize); |
1201 | 1201 | ||
1202 | p = rpc_encode_header(task); | 1202 | p = rpc_encode_header(task); |
1203 | if (p == NULL) { | 1203 | if (p == NULL) { |
1204 | printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n"); | 1204 | printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n"); |
1205 | rpc_exit(task, -EIO); | 1205 | rpc_exit(task, -EIO); |
1206 | return; | 1206 | return; |
1207 | } | 1207 | } |
1208 | 1208 | ||
1209 | encode = task->tk_msg.rpc_proc->p_encode; | 1209 | encode = task->tk_msg.rpc_proc->p_encode; |
1210 | if (encode == NULL) | 1210 | if (encode == NULL) |
1211 | return; | 1211 | return; |
1212 | 1212 | ||
1213 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, | 1213 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, |
1214 | task->tk_msg.rpc_argp); | 1214 | task->tk_msg.rpc_argp); |
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | /* | 1217 | /* |
1218 | * 4. Get the server port number if not yet set | 1218 | * 4. Get the server port number if not yet set |
1219 | */ | 1219 | */ |
1220 | static void | 1220 | static void |
1221 | call_bind(struct rpc_task *task) | 1221 | call_bind(struct rpc_task *task) |
1222 | { | 1222 | { |
1223 | struct rpc_xprt *xprt = task->tk_xprt; | 1223 | struct rpc_xprt *xprt = task->tk_xprt; |
1224 | 1224 | ||
1225 | dprint_status(task); | 1225 | dprint_status(task); |
1226 | 1226 | ||
1227 | task->tk_action = call_connect; | 1227 | task->tk_action = call_connect; |
1228 | if (!xprt_bound(xprt)) { | 1228 | if (!xprt_bound(xprt)) { |
1229 | task->tk_action = call_bind_status; | 1229 | task->tk_action = call_bind_status; |
1230 | task->tk_timeout = xprt->bind_timeout; | 1230 | task->tk_timeout = xprt->bind_timeout; |
1231 | xprt->ops->rpcbind(task); | 1231 | xprt->ops->rpcbind(task); |
1232 | } | 1232 | } |
1233 | } | 1233 | } |
1234 | 1234 | ||
1235 | /* | 1235 | /* |
1236 | * 4a. Sort out bind result | 1236 | * 4a. Sort out bind result |
1237 | */ | 1237 | */ |
1238 | static void | 1238 | static void |
1239 | call_bind_status(struct rpc_task *task) | 1239 | call_bind_status(struct rpc_task *task) |
1240 | { | 1240 | { |
1241 | int status = -EIO; | 1241 | int status = -EIO; |
1242 | 1242 | ||
1243 | if (task->tk_status >= 0) { | 1243 | if (task->tk_status >= 0) { |
1244 | dprint_status(task); | 1244 | dprint_status(task); |
1245 | task->tk_status = 0; | 1245 | task->tk_status = 0; |
1246 | task->tk_action = call_connect; | 1246 | task->tk_action = call_connect; |
1247 | return; | 1247 | return; |
1248 | } | 1248 | } |
1249 | 1249 | ||
1250 | switch (task->tk_status) { | 1250 | switch (task->tk_status) { |
1251 | case -ENOMEM: | 1251 | case -ENOMEM: |
1252 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); | 1252 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); |
1253 | rpc_delay(task, HZ >> 2); | 1253 | rpc_delay(task, HZ >> 2); |
1254 | goto retry_timeout; | 1254 | goto retry_timeout; |
1255 | case -EACCES: | 1255 | case -EACCES: |
1256 | dprintk("RPC: %5u remote rpcbind: RPC program/version " | 1256 | dprintk("RPC: %5u remote rpcbind: RPC program/version " |
1257 | "unavailable\n", task->tk_pid); | 1257 | "unavailable\n", task->tk_pid); |
1258 | /* fail immediately if this is an RPC ping */ | 1258 | /* fail immediately if this is an RPC ping */ |
1259 | if (task->tk_msg.rpc_proc->p_proc == 0) { | 1259 | if (task->tk_msg.rpc_proc->p_proc == 0) { |
1260 | status = -EOPNOTSUPP; | 1260 | status = -EOPNOTSUPP; |
1261 | break; | 1261 | break; |
1262 | } | 1262 | } |
1263 | if (task->tk_rebind_retry == 0) | 1263 | if (task->tk_rebind_retry == 0) |
1264 | break; | 1264 | break; |
1265 | task->tk_rebind_retry--; | 1265 | task->tk_rebind_retry--; |
1266 | rpc_delay(task, 3*HZ); | 1266 | rpc_delay(task, 3*HZ); |
1267 | goto retry_timeout; | 1267 | goto retry_timeout; |
1268 | case -ETIMEDOUT: | 1268 | case -ETIMEDOUT: |
1269 | dprintk("RPC: %5u rpcbind request timed out\n", | 1269 | dprintk("RPC: %5u rpcbind request timed out\n", |
1270 | task->tk_pid); | 1270 | task->tk_pid); |
1271 | goto retry_timeout; | 1271 | goto retry_timeout; |
1272 | case -EPFNOSUPPORT: | 1272 | case -EPFNOSUPPORT: |
1273 | /* server doesn't support any rpcbind version we know of */ | 1273 | /* server doesn't support any rpcbind version we know of */ |
1274 | dprintk("RPC: %5u unrecognized remote rpcbind service\n", | 1274 | dprintk("RPC: %5u unrecognized remote rpcbind service\n", |
1275 | task->tk_pid); | 1275 | task->tk_pid); |
1276 | break; | 1276 | break; |
1277 | case -EPROTONOSUPPORT: | 1277 | case -EPROTONOSUPPORT: |
1278 | dprintk("RPC: %5u remote rpcbind version unavailable, retrying\n", | 1278 | dprintk("RPC: %5u remote rpcbind version unavailable, retrying\n", |
1279 | task->tk_pid); | 1279 | task->tk_pid); |
1280 | task->tk_status = 0; | 1280 | task->tk_status = 0; |
1281 | task->tk_action = call_bind; | 1281 | task->tk_action = call_bind; |
1282 | return; | 1282 | return; |
1283 | case -ECONNREFUSED: /* connection problems */ | 1283 | case -ECONNREFUSED: /* connection problems */ |
1284 | case -ECONNRESET: | 1284 | case -ECONNRESET: |
1285 | case -ENOTCONN: | 1285 | case -ENOTCONN: |
1286 | case -EHOSTDOWN: | 1286 | case -EHOSTDOWN: |
1287 | case -EHOSTUNREACH: | 1287 | case -EHOSTUNREACH: |
1288 | case -ENETUNREACH: | 1288 | case -ENETUNREACH: |
1289 | case -EPIPE: | 1289 | case -EPIPE: |
1290 | dprintk("RPC: %5u remote rpcbind unreachable: %d\n", | 1290 | dprintk("RPC: %5u remote rpcbind unreachable: %d\n", |
1291 | task->tk_pid, task->tk_status); | 1291 | task->tk_pid, task->tk_status); |
1292 | if (!RPC_IS_SOFTCONN(task)) { | 1292 | if (!RPC_IS_SOFTCONN(task)) { |
1293 | rpc_delay(task, 5*HZ); | 1293 | rpc_delay(task, 5*HZ); |
1294 | goto retry_timeout; | 1294 | goto retry_timeout; |
1295 | } | 1295 | } |
1296 | status = task->tk_status; | 1296 | status = task->tk_status; |
1297 | break; | 1297 | break; |
1298 | default: | 1298 | default: |
1299 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", | 1299 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", |
1300 | task->tk_pid, -task->tk_status); | 1300 | task->tk_pid, -task->tk_status); |
1301 | } | 1301 | } |
1302 | 1302 | ||
1303 | rpc_exit(task, status); | 1303 | rpc_exit(task, status); |
1304 | return; | 1304 | return; |
1305 | 1305 | ||
1306 | retry_timeout: | 1306 | retry_timeout: |
1307 | task->tk_action = call_timeout; | 1307 | task->tk_action = call_timeout; |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | /* | 1310 | /* |
1311 | * 4b. Connect to the RPC server | 1311 | * 4b. Connect to the RPC server |
1312 | */ | 1312 | */ |
1313 | static void | 1313 | static void |
1314 | call_connect(struct rpc_task *task) | 1314 | call_connect(struct rpc_task *task) |
1315 | { | 1315 | { |
1316 | struct rpc_xprt *xprt = task->tk_xprt; | 1316 | struct rpc_xprt *xprt = task->tk_xprt; |
1317 | 1317 | ||
1318 | dprintk("RPC: %5u call_connect xprt %p %s connected\n", | 1318 | dprintk("RPC: %5u call_connect xprt %p %s connected\n", |
1319 | task->tk_pid, xprt, | 1319 | task->tk_pid, xprt, |
1320 | (xprt_connected(xprt) ? "is" : "is not")); | 1320 | (xprt_connected(xprt) ? "is" : "is not")); |
1321 | 1321 | ||
1322 | task->tk_action = call_transmit; | 1322 | task->tk_action = call_transmit; |
1323 | if (!xprt_connected(xprt)) { | 1323 | if (!xprt_connected(xprt)) { |
1324 | task->tk_action = call_connect_status; | 1324 | task->tk_action = call_connect_status; |
1325 | if (task->tk_status < 0) | 1325 | if (task->tk_status < 0) |
1326 | return; | 1326 | return; |
1327 | xprt_connect(task); | 1327 | xprt_connect(task); |
1328 | } | 1328 | } |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | /* | 1331 | /* |
1332 | * 4c. Sort out connect result | 1332 | * 4c. Sort out connect result |
1333 | */ | 1333 | */ |
1334 | static void | 1334 | static void |
1335 | call_connect_status(struct rpc_task *task) | 1335 | call_connect_status(struct rpc_task *task) |
1336 | { | 1336 | { |
1337 | struct rpc_clnt *clnt = task->tk_client; | 1337 | struct rpc_clnt *clnt = task->tk_client; |
1338 | int status = task->tk_status; | 1338 | int status = task->tk_status; |
1339 | 1339 | ||
1340 | dprint_status(task); | 1340 | dprint_status(task); |
1341 | 1341 | ||
1342 | task->tk_status = 0; | 1342 | task->tk_status = 0; |
1343 | if (status >= 0 || status == -EAGAIN) { | 1343 | if (status >= 0 || status == -EAGAIN) { |
1344 | clnt->cl_stats->netreconn++; | 1344 | clnt->cl_stats->netreconn++; |
1345 | task->tk_action = call_transmit; | 1345 | task->tk_action = call_transmit; |
1346 | return; | 1346 | return; |
1347 | } | 1347 | } |
1348 | 1348 | ||
1349 | switch (status) { | 1349 | switch (status) { |
1350 | /* if soft mounted, test if we've timed out */ | 1350 | /* if soft mounted, test if we've timed out */ |
1351 | case -ETIMEDOUT: | 1351 | case -ETIMEDOUT: |
1352 | task->tk_action = call_timeout; | 1352 | task->tk_action = call_timeout; |
1353 | break; | 1353 | break; |
1354 | default: | 1354 | default: |
1355 | rpc_exit(task, -EIO); | 1355 | rpc_exit(task, -EIO); |
1356 | } | 1356 | } |
1357 | } | 1357 | } |
1358 | 1358 | ||
1359 | /* | 1359 | /* |
1360 | * 5. Transmit the RPC request, and wait for reply | 1360 | * 5. Transmit the RPC request, and wait for reply |
1361 | */ | 1361 | */ |
1362 | static void | 1362 | static void |
1363 | call_transmit(struct rpc_task *task) | 1363 | call_transmit(struct rpc_task *task) |
1364 | { | 1364 | { |
1365 | dprint_status(task); | 1365 | dprint_status(task); |
1366 | 1366 | ||
1367 | task->tk_action = call_status; | 1367 | task->tk_action = call_status; |
1368 | if (task->tk_status < 0) | 1368 | if (task->tk_status < 0) |
1369 | return; | 1369 | return; |
1370 | task->tk_status = xprt_prepare_transmit(task); | 1370 | task->tk_status = xprt_prepare_transmit(task); |
1371 | if (task->tk_status != 0) | 1371 | if (task->tk_status != 0) |
1372 | return; | 1372 | return; |
1373 | task->tk_action = call_transmit_status; | 1373 | task->tk_action = call_transmit_status; |
1374 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 1374 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
1375 | if (rpc_task_need_encode(task)) { | 1375 | if (rpc_task_need_encode(task)) { |
1376 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); | 1376 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); |
1377 | rpc_xdr_encode(task); | 1377 | rpc_xdr_encode(task); |
1378 | /* Did the encode result in an error condition? */ | 1378 | /* Did the encode result in an error condition? */ |
1379 | if (task->tk_status != 0) { | 1379 | if (task->tk_status != 0) { |
1380 | /* Was the error nonfatal? */ | 1380 | /* Was the error nonfatal? */ |
1381 | if (task->tk_status == -EAGAIN) | 1381 | if (task->tk_status == -EAGAIN) |
1382 | rpc_delay(task, HZ >> 4); | 1382 | rpc_delay(task, HZ >> 4); |
1383 | else | 1383 | else |
1384 | rpc_exit(task, task->tk_status); | 1384 | rpc_exit(task, task->tk_status); |
1385 | return; | 1385 | return; |
1386 | } | 1386 | } |
1387 | } | 1387 | } |
1388 | xprt_transmit(task); | 1388 | xprt_transmit(task); |
1389 | if (task->tk_status < 0) | 1389 | if (task->tk_status < 0) |
1390 | return; | 1390 | return; |
1391 | /* | 1391 | /* |
1392 | * On success, ensure that we call xprt_end_transmit() before sleeping | 1392 | * On success, ensure that we call xprt_end_transmit() before sleeping |
1393 | * in order to allow access to the socket to other RPC requests. | 1393 | * in order to allow access to the socket to other RPC requests. |
1394 | */ | 1394 | */ |
1395 | call_transmit_status(task); | 1395 | call_transmit_status(task); |
1396 | if (rpc_reply_expected(task)) | 1396 | if (rpc_reply_expected(task)) |
1397 | return; | 1397 | return; |
1398 | task->tk_action = rpc_exit_task; | 1398 | task->tk_action = rpc_exit_task; |
1399 | rpc_wake_up_queued_task(&task->tk_xprt->pending, task); | 1399 | rpc_wake_up_queued_task(&task->tk_xprt->pending, task); |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | /* | 1402 | /* |
1403 | * 5a. Handle cleanup after a transmission | 1403 | * 5a. Handle cleanup after a transmission |
1404 | */ | 1404 | */ |
1405 | static void | 1405 | static void |
1406 | call_transmit_status(struct rpc_task *task) | 1406 | call_transmit_status(struct rpc_task *task) |
1407 | { | 1407 | { |
1408 | task->tk_action = call_status; | 1408 | task->tk_action = call_status; |
1409 | 1409 | ||
1410 | /* | 1410 | /* |
1411 | * Common case: success. Force the compiler to put this | 1411 | * Common case: success. Force the compiler to put this |
1412 | * test first. | 1412 | * test first. |
1413 | */ | 1413 | */ |
1414 | if (task->tk_status == 0) { | 1414 | if (task->tk_status == 0) { |
1415 | xprt_end_transmit(task); | 1415 | xprt_end_transmit(task); |
1416 | rpc_task_force_reencode(task); | 1416 | rpc_task_force_reencode(task); |
1417 | return; | 1417 | return; |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | switch (task->tk_status) { | 1420 | switch (task->tk_status) { |
1421 | case -EAGAIN: | 1421 | case -EAGAIN: |
1422 | break; | 1422 | break; |
1423 | default: | 1423 | default: |
1424 | dprint_status(task); | 1424 | dprint_status(task); |
1425 | xprt_end_transmit(task); | 1425 | xprt_end_transmit(task); |
1426 | rpc_task_force_reencode(task); | 1426 | rpc_task_force_reencode(task); |
1427 | break; | 1427 | break; |
1428 | /* | 1428 | /* |
1429 | * Special cases: if we've been waiting on the | 1429 | * Special cases: if we've been waiting on the |
1430 | * socket's write_space() callback, or if the | 1430 | * socket's write_space() callback, or if the |
1431 | * socket just returned a connection error, | 1431 | * socket just returned a connection error, |
1432 | * then hold onto the transport lock. | 1432 | * then hold onto the transport lock. |
1433 | */ | 1433 | */ |
1434 | case -ECONNREFUSED: | 1434 | case -ECONNREFUSED: |
1435 | case -EHOSTDOWN: | 1435 | case -EHOSTDOWN: |
1436 | case -EHOSTUNREACH: | 1436 | case -EHOSTUNREACH: |
1437 | case -ENETUNREACH: | 1437 | case -ENETUNREACH: |
1438 | if (RPC_IS_SOFTCONN(task)) { | 1438 | if (RPC_IS_SOFTCONN(task)) { |
1439 | xprt_end_transmit(task); | 1439 | xprt_end_transmit(task); |
1440 | rpc_exit(task, task->tk_status); | 1440 | rpc_exit(task, task->tk_status); |
1441 | break; | 1441 | break; |
1442 | } | 1442 | } |
1443 | case -ECONNRESET: | 1443 | case -ECONNRESET: |
1444 | case -ENOTCONN: | 1444 | case -ENOTCONN: |
1445 | case -EPIPE: | 1445 | case -EPIPE: |
1446 | rpc_task_force_reencode(task); | 1446 | rpc_task_force_reencode(task); |
1447 | } | 1447 | } |
1448 | } | 1448 | } |
1449 | 1449 | ||
1450 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) | 1450 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) |
1451 | /* | 1451 | /* |
1452 | * 5b. Send the backchannel RPC reply. On error, drop the reply. In | 1452 | * 5b. Send the backchannel RPC reply. On error, drop the reply. In |
1453 | * addition, disconnect on connectivity errors. | 1453 | * addition, disconnect on connectivity errors. |
1454 | */ | 1454 | */ |
1455 | static void | 1455 | static void |
1456 | call_bc_transmit(struct rpc_task *task) | 1456 | call_bc_transmit(struct rpc_task *task) |
1457 | { | 1457 | { |
1458 | struct rpc_rqst *req = task->tk_rqstp; | 1458 | struct rpc_rqst *req = task->tk_rqstp; |
1459 | 1459 | ||
1460 | BUG_ON(task->tk_status != 0); | 1460 | BUG_ON(task->tk_status != 0); |
1461 | task->tk_status = xprt_prepare_transmit(task); | 1461 | task->tk_status = xprt_prepare_transmit(task); |
1462 | if (task->tk_status == -EAGAIN) { | 1462 | if (task->tk_status == -EAGAIN) { |
1463 | /* | 1463 | /* |
1464 | * Could not reserve the transport. Try again after the | 1464 | * Could not reserve the transport. Try again after the |
1465 | * transport is released. | 1465 | * transport is released. |
1466 | */ | 1466 | */ |
1467 | task->tk_status = 0; | 1467 | task->tk_status = 0; |
1468 | task->tk_action = call_bc_transmit; | 1468 | task->tk_action = call_bc_transmit; |
1469 | return; | 1469 | return; |
1470 | } | 1470 | } |
1471 | 1471 | ||
1472 | task->tk_action = rpc_exit_task; | 1472 | task->tk_action = rpc_exit_task; |
1473 | if (task->tk_status < 0) { | 1473 | if (task->tk_status < 0) { |
1474 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | 1474 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " |
1475 | "error: %d\n", task->tk_status); | 1475 | "error: %d\n", task->tk_status); |
1476 | return; | 1476 | return; |
1477 | } | 1477 | } |
1478 | 1478 | ||
1479 | xprt_transmit(task); | 1479 | xprt_transmit(task); |
1480 | xprt_end_transmit(task); | 1480 | xprt_end_transmit(task); |
1481 | dprint_status(task); | 1481 | dprint_status(task); |
1482 | switch (task->tk_status) { | 1482 | switch (task->tk_status) { |
1483 | case 0: | 1483 | case 0: |
1484 | /* Success */ | 1484 | /* Success */ |
1485 | break; | 1485 | break; |
1486 | case -EHOSTDOWN: | 1486 | case -EHOSTDOWN: |
1487 | case -EHOSTUNREACH: | 1487 | case -EHOSTUNREACH: |
1488 | case -ENETUNREACH: | 1488 | case -ENETUNREACH: |
1489 | case -ETIMEDOUT: | 1489 | case -ETIMEDOUT: |
1490 | /* | 1490 | /* |
1491 | * Problem reaching the server. Disconnect and let the | 1491 | * Problem reaching the server. Disconnect and let the |
1492 | * forechannel reestablish the connection. The server will | 1492 | * forechannel reestablish the connection. The server will |
1493 | * have to retransmit the backchannel request and we'll | 1493 | * have to retransmit the backchannel request and we'll |
1494 | * reprocess it. Since these ops are idempotent, there's no | 1494 | * reprocess it. Since these ops are idempotent, there's no |
1495 | * need to cache our reply at this time. | 1495 | * need to cache our reply at this time. |
1496 | */ | 1496 | */ |
1497 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | 1497 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " |
1498 | "error: %d\n", task->tk_status); | 1498 | "error: %d\n", task->tk_status); |
1499 | xprt_conditional_disconnect(task->tk_xprt, | 1499 | xprt_conditional_disconnect(task->tk_xprt, |
1500 | req->rq_connect_cookie); | 1500 | req->rq_connect_cookie); |
1501 | break; | 1501 | break; |
1502 | default: | 1502 | default: |
1503 | /* | 1503 | /* |
1504 | * We were unable to reply and will have to drop the | 1504 | * We were unable to reply and will have to drop the |
1505 | * request. The server should reconnect and retransmit. | 1505 | * request. The server should reconnect and retransmit. |
1506 | */ | 1506 | */ |
1507 | BUG_ON(task->tk_status == -EAGAIN); | 1507 | BUG_ON(task->tk_status == -EAGAIN); |
1508 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | 1508 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " |
1509 | "error: %d\n", task->tk_status); | 1509 | "error: %d\n", task->tk_status); |
1510 | break; | 1510 | break; |
1511 | } | 1511 | } |
1512 | rpc_wake_up_queued_task(&req->rq_xprt->pending, task); | 1512 | rpc_wake_up_queued_task(&req->rq_xprt->pending, task); |
1513 | } | 1513 | } |
1514 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 1514 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1515 | 1515 | ||
1516 | /* | 1516 | /* |
1517 | * 6. Sort out the RPC call status | 1517 | * 6. Sort out the RPC call status |
1518 | */ | 1518 | */ |
1519 | static void | 1519 | static void |
1520 | call_status(struct rpc_task *task) | 1520 | call_status(struct rpc_task *task) |
1521 | { | 1521 | { |
1522 | struct rpc_clnt *clnt = task->tk_client; | 1522 | struct rpc_clnt *clnt = task->tk_client; |
1523 | struct rpc_rqst *req = task->tk_rqstp; | 1523 | struct rpc_rqst *req = task->tk_rqstp; |
1524 | int status; | 1524 | int status; |
1525 | 1525 | ||
1526 | if (req->rq_reply_bytes_recvd > 0 && !req->rq_bytes_sent) | 1526 | if (req->rq_reply_bytes_recvd > 0 && !req->rq_bytes_sent) |
1527 | task->tk_status = req->rq_reply_bytes_recvd; | 1527 | task->tk_status = req->rq_reply_bytes_recvd; |
1528 | 1528 | ||
1529 | dprint_status(task); | 1529 | dprint_status(task); |
1530 | 1530 | ||
1531 | status = task->tk_status; | 1531 | status = task->tk_status; |
1532 | if (status >= 0) { | 1532 | if (status >= 0) { |
1533 | task->tk_action = call_decode; | 1533 | task->tk_action = call_decode; |
1534 | return; | 1534 | return; |
1535 | } | 1535 | } |
1536 | 1536 | ||
1537 | task->tk_status = 0; | 1537 | task->tk_status = 0; |
1538 | switch(status) { | 1538 | switch(status) { |
1539 | case -EHOSTDOWN: | 1539 | case -EHOSTDOWN: |
1540 | case -EHOSTUNREACH: | 1540 | case -EHOSTUNREACH: |
1541 | case -ENETUNREACH: | 1541 | case -ENETUNREACH: |
1542 | /* | 1542 | /* |
1543 | * Delay any retries for 3 seconds, then handle as if it | 1543 | * Delay any retries for 3 seconds, then handle as if it |
1544 | * were a timeout. | 1544 | * were a timeout. |
1545 | */ | 1545 | */ |
1546 | rpc_delay(task, 3*HZ); | 1546 | rpc_delay(task, 3*HZ); |
1547 | case -ETIMEDOUT: | 1547 | case -ETIMEDOUT: |
1548 | task->tk_action = call_timeout; | 1548 | task->tk_action = call_timeout; |
1549 | if (task->tk_client->cl_discrtry) | 1549 | if (task->tk_client->cl_discrtry) |
1550 | xprt_conditional_disconnect(task->tk_xprt, | 1550 | xprt_conditional_disconnect(task->tk_xprt, |
1551 | req->rq_connect_cookie); | 1551 | req->rq_connect_cookie); |
1552 | break; | 1552 | break; |
1553 | case -ECONNRESET: | 1553 | case -ECONNRESET: |
1554 | case -ECONNREFUSED: | 1554 | case -ECONNREFUSED: |
1555 | rpc_force_rebind(clnt); | 1555 | rpc_force_rebind(clnt); |
1556 | rpc_delay(task, 3*HZ); | 1556 | rpc_delay(task, 3*HZ); |
1557 | case -EPIPE: | 1557 | case -EPIPE: |
1558 | case -ENOTCONN: | 1558 | case -ENOTCONN: |
1559 | task->tk_action = call_bind; | 1559 | task->tk_action = call_bind; |
1560 | break; | 1560 | break; |
1561 | case -EAGAIN: | 1561 | case -EAGAIN: |
1562 | task->tk_action = call_transmit; | 1562 | task->tk_action = call_transmit; |
1563 | break; | 1563 | break; |
1564 | case -EIO: | 1564 | case -EIO: |
1565 | /* shutdown or soft timeout */ | 1565 | /* shutdown or soft timeout */ |
1566 | rpc_exit(task, status); | 1566 | rpc_exit(task, status); |
1567 | break; | 1567 | break; |
1568 | default: | 1568 | default: |
1569 | if (clnt->cl_chatty) | 1569 | if (clnt->cl_chatty) |
1570 | printk("%s: RPC call returned error %d\n", | 1570 | printk("%s: RPC call returned error %d\n", |
1571 | clnt->cl_protname, -status); | 1571 | clnt->cl_protname, -status); |
1572 | rpc_exit(task, status); | 1572 | rpc_exit(task, status); |
1573 | } | 1573 | } |
1574 | } | 1574 | } |
1575 | 1575 | ||
1576 | /* | 1576 | /* |
1577 | * 6a. Handle RPC timeout | 1577 | * 6a. Handle RPC timeout |
1578 | * We do not release the request slot, so we keep using the | 1578 | * We do not release the request slot, so we keep using the |
1579 | * same XID for all retransmits. | 1579 | * same XID for all retransmits. |
1580 | */ | 1580 | */ |
1581 | static void | 1581 | static void |
1582 | call_timeout(struct rpc_task *task) | 1582 | call_timeout(struct rpc_task *task) |
1583 | { | 1583 | { |
1584 | struct rpc_clnt *clnt = task->tk_client; | 1584 | struct rpc_clnt *clnt = task->tk_client; |
1585 | 1585 | ||
1586 | if (xprt_adjust_timeout(task->tk_rqstp) == 0) { | 1586 | if (xprt_adjust_timeout(task->tk_rqstp) == 0) { |
1587 | dprintk("RPC: %5u call_timeout (minor)\n", task->tk_pid); | 1587 | dprintk("RPC: %5u call_timeout (minor)\n", task->tk_pid); |
1588 | goto retry; | 1588 | goto retry; |
1589 | } | 1589 | } |
1590 | 1590 | ||
1591 | dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); | 1591 | dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); |
1592 | task->tk_timeouts++; | 1592 | task->tk_timeouts++; |
1593 | 1593 | ||
1594 | if (RPC_IS_SOFTCONN(task)) { | 1594 | if (RPC_IS_SOFTCONN(task)) { |
1595 | rpc_exit(task, -ETIMEDOUT); | 1595 | rpc_exit(task, -ETIMEDOUT); |
1596 | return; | 1596 | return; |
1597 | } | 1597 | } |
1598 | if (RPC_IS_SOFT(task)) { | 1598 | if (RPC_IS_SOFT(task)) { |
1599 | if (clnt->cl_chatty) | 1599 | if (clnt->cl_chatty) |
1600 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1600 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1601 | clnt->cl_protname, clnt->cl_server); | 1601 | clnt->cl_protname, clnt->cl_server); |
1602 | if (task->tk_flags & RPC_TASK_TIMEOUT) | 1602 | if (task->tk_flags & RPC_TASK_TIMEOUT) |
1603 | rpc_exit(task, -ETIMEDOUT); | 1603 | rpc_exit(task, -ETIMEDOUT); |
1604 | else | 1604 | else |
1605 | rpc_exit(task, -EIO); | 1605 | rpc_exit(task, -EIO); |
1606 | return; | 1606 | return; |
1607 | } | 1607 | } |
1608 | 1608 | ||
1609 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { | 1609 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { |
1610 | task->tk_flags |= RPC_CALL_MAJORSEEN; | 1610 | task->tk_flags |= RPC_CALL_MAJORSEEN; |
1611 | if (clnt->cl_chatty) | 1611 | if (clnt->cl_chatty) |
1612 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1612 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
1613 | clnt->cl_protname, clnt->cl_server); | 1613 | clnt->cl_protname, clnt->cl_server); |
1614 | } | 1614 | } |
1615 | rpc_force_rebind(clnt); | 1615 | rpc_force_rebind(clnt); |
1616 | /* | 1616 | /* |
1617 | * Did our request time out due to an RPCSEC_GSS out-of-sequence | 1617 | * Did our request time out due to an RPCSEC_GSS out-of-sequence |
1618 | * event? RFC2203 requires the server to drop all such requests. | 1618 | * event? RFC2203 requires the server to drop all such requests. |
1619 | */ | 1619 | */ |
1620 | rpcauth_invalcred(task); | 1620 | rpcauth_invalcred(task); |
1621 | 1621 | ||
1622 | retry: | 1622 | retry: |
1623 | clnt->cl_stats->rpcretrans++; | 1623 | clnt->cl_stats->rpcretrans++; |
1624 | task->tk_action = call_bind; | 1624 | task->tk_action = call_bind; |
1625 | task->tk_status = 0; | 1625 | task->tk_status = 0; |
1626 | } | 1626 | } |
1627 | 1627 | ||
1628 | /* | 1628 | /* |
1629 | * 7. Decode the RPC reply | 1629 | * 7. Decode the RPC reply |
1630 | */ | 1630 | */ |
1631 | static void | 1631 | static void |
1632 | call_decode(struct rpc_task *task) | 1632 | call_decode(struct rpc_task *task) |
1633 | { | 1633 | { |
1634 | struct rpc_clnt *clnt = task->tk_client; | 1634 | struct rpc_clnt *clnt = task->tk_client; |
1635 | struct rpc_rqst *req = task->tk_rqstp; | 1635 | struct rpc_rqst *req = task->tk_rqstp; |
1636 | kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode; | 1636 | kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode; |
1637 | __be32 *p; | 1637 | __be32 *p; |
1638 | 1638 | ||
1639 | dprint_status(task); | 1639 | dprint_status(task); |
1640 | 1640 | ||
1641 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { | 1641 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { |
1642 | if (clnt->cl_chatty) | 1642 | if (clnt->cl_chatty) |
1643 | printk(KERN_NOTICE "%s: server %s OK\n", | 1643 | printk(KERN_NOTICE "%s: server %s OK\n", |
1644 | clnt->cl_protname, clnt->cl_server); | 1644 | clnt->cl_protname, clnt->cl_server); |
1645 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; | 1645 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; |
1646 | } | 1646 | } |
1647 | 1647 | ||
1648 | /* | 1648 | /* |
1649 | * Ensure that we see all writes made by xprt_complete_rqst() | 1649 | * Ensure that we see all writes made by xprt_complete_rqst() |
1650 | * before it changed req->rq_reply_bytes_recvd. | 1650 | * before it changed req->rq_reply_bytes_recvd. |
1651 | */ | 1651 | */ |
1652 | smp_rmb(); | 1652 | smp_rmb(); |
1653 | req->rq_rcv_buf.len = req->rq_private_buf.len; | 1653 | req->rq_rcv_buf.len = req->rq_private_buf.len; |
1654 | 1654 | ||
1655 | /* Check that the softirq receive buffer is valid */ | 1655 | /* Check that the softirq receive buffer is valid */ |
1656 | WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf, | 1656 | WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf, |
1657 | sizeof(req->rq_rcv_buf)) != 0); | 1657 | sizeof(req->rq_rcv_buf)) != 0); |
1658 | 1658 | ||
1659 | if (req->rq_rcv_buf.len < 12) { | 1659 | if (req->rq_rcv_buf.len < 12) { |
1660 | if (!RPC_IS_SOFT(task)) { | 1660 | if (!RPC_IS_SOFT(task)) { |
1661 | task->tk_action = call_bind; | 1661 | task->tk_action = call_bind; |
1662 | clnt->cl_stats->rpcretrans++; | 1662 | clnt->cl_stats->rpcretrans++; |
1663 | goto out_retry; | 1663 | goto out_retry; |
1664 | } | 1664 | } |
1665 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", | 1665 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", |
1666 | clnt->cl_protname, task->tk_status); | 1666 | clnt->cl_protname, task->tk_status); |
1667 | task->tk_action = call_timeout; | 1667 | task->tk_action = call_timeout; |
1668 | goto out_retry; | 1668 | goto out_retry; |
1669 | } | 1669 | } |
1670 | 1670 | ||
1671 | p = rpc_verify_header(task); | 1671 | p = rpc_verify_header(task); |
1672 | if (IS_ERR(p)) { | 1672 | if (IS_ERR(p)) { |
1673 | if (p == ERR_PTR(-EAGAIN)) | 1673 | if (p == ERR_PTR(-EAGAIN)) |
1674 | goto out_retry; | 1674 | goto out_retry; |
1675 | return; | 1675 | return; |
1676 | } | 1676 | } |
1677 | 1677 | ||
1678 | task->tk_action = rpc_exit_task; | 1678 | task->tk_action = rpc_exit_task; |
1679 | 1679 | ||
1680 | if (decode) { | 1680 | if (decode) { |
1681 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, | 1681 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, |
1682 | task->tk_msg.rpc_resp); | 1682 | task->tk_msg.rpc_resp); |
1683 | } | 1683 | } |
1684 | dprintk("RPC: %5u call_decode result %d\n", task->tk_pid, | 1684 | dprintk("RPC: %5u call_decode result %d\n", task->tk_pid, |
1685 | task->tk_status); | 1685 | task->tk_status); |
1686 | return; | 1686 | return; |
1687 | out_retry: | 1687 | out_retry: |
1688 | task->tk_status = 0; | 1688 | task->tk_status = 0; |
1689 | /* Note: rpc_verify_header() may have freed the RPC slot */ | 1689 | /* Note: rpc_verify_header() may have freed the RPC slot */ |
1690 | if (task->tk_rqstp == req) { | 1690 | if (task->tk_rqstp == req) { |
1691 | req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0; | 1691 | req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0; |
1692 | if (task->tk_client->cl_discrtry) | 1692 | if (task->tk_client->cl_discrtry) |
1693 | xprt_conditional_disconnect(task->tk_xprt, | 1693 | xprt_conditional_disconnect(task->tk_xprt, |
1694 | req->rq_connect_cookie); | 1694 | req->rq_connect_cookie); |
1695 | } | 1695 | } |
1696 | } | 1696 | } |
1697 | 1697 | ||
1698 | static __be32 * | 1698 | static __be32 * |
1699 | rpc_encode_header(struct rpc_task *task) | 1699 | rpc_encode_header(struct rpc_task *task) |
1700 | { | 1700 | { |
1701 | struct rpc_clnt *clnt = task->tk_client; | 1701 | struct rpc_clnt *clnt = task->tk_client; |
1702 | struct rpc_rqst *req = task->tk_rqstp; | 1702 | struct rpc_rqst *req = task->tk_rqstp; |
1703 | __be32 *p = req->rq_svec[0].iov_base; | 1703 | __be32 *p = req->rq_svec[0].iov_base; |
1704 | 1704 | ||
1705 | /* FIXME: check buffer size? */ | 1705 | /* FIXME: check buffer size? */ |
1706 | 1706 | ||
1707 | p = xprt_skip_transport_header(task->tk_xprt, p); | 1707 | p = xprt_skip_transport_header(task->tk_xprt, p); |
1708 | *p++ = req->rq_xid; /* XID */ | 1708 | *p++ = req->rq_xid; /* XID */ |
1709 | *p++ = htonl(RPC_CALL); /* CALL */ | 1709 | *p++ = htonl(RPC_CALL); /* CALL */ |
1710 | *p++ = htonl(RPC_VERSION); /* RPC version */ | 1710 | *p++ = htonl(RPC_VERSION); /* RPC version */ |
1711 | *p++ = htonl(clnt->cl_prog); /* program number */ | 1711 | *p++ = htonl(clnt->cl_prog); /* program number */ |
1712 | *p++ = htonl(clnt->cl_vers); /* program version */ | 1712 | *p++ = htonl(clnt->cl_vers); /* program version */ |
1713 | *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */ | 1713 | *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */ |
1714 | p = rpcauth_marshcred(task, p); | 1714 | p = rpcauth_marshcred(task, p); |
1715 | req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p); | 1715 | req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p); |
1716 | return p; | 1716 | return p; |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | static __be32 * | 1719 | static __be32 * |
1720 | rpc_verify_header(struct rpc_task *task) | 1720 | rpc_verify_header(struct rpc_task *task) |
1721 | { | 1721 | { |
1722 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; | 1722 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; |
1723 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; | 1723 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; |
1724 | __be32 *p = iov->iov_base; | 1724 | __be32 *p = iov->iov_base; |
1725 | u32 n; | 1725 | u32 n; |
1726 | int error = -EACCES; | 1726 | int error = -EACCES; |
1727 | 1727 | ||
1728 | if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { | 1728 | if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { |
1729 | /* RFC-1014 says that the representation of XDR data must be a | 1729 | /* RFC-1014 says that the representation of XDR data must be a |
1730 | * multiple of four bytes | 1730 | * multiple of four bytes |
1731 | * - if it isn't pointer subtraction in the NFS client may give | 1731 | * - if it isn't pointer subtraction in the NFS client may give |
1732 | * undefined results | 1732 | * undefined results |
1733 | */ | 1733 | */ |
1734 | dprintk("RPC: %5u %s: XDR representation not a multiple of" | 1734 | dprintk("RPC: %5u %s: XDR representation not a multiple of" |
1735 | " 4 bytes: 0x%x\n", task->tk_pid, __func__, | 1735 | " 4 bytes: 0x%x\n", task->tk_pid, __func__, |
1736 | task->tk_rqstp->rq_rcv_buf.len); | 1736 | task->tk_rqstp->rq_rcv_buf.len); |
1737 | goto out_eio; | 1737 | goto out_eio; |
1738 | } | 1738 | } |
1739 | if ((len -= 3) < 0) | 1739 | if ((len -= 3) < 0) |
1740 | goto out_overflow; | 1740 | goto out_overflow; |
1741 | 1741 | ||
1742 | p += 1; /* skip XID */ | 1742 | p += 1; /* skip XID */ |
1743 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 1743 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
1744 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", | 1744 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", |
1745 | task->tk_pid, __func__, n); | 1745 | task->tk_pid, __func__, n); |
1746 | goto out_garbage; | 1746 | goto out_garbage; |
1747 | } | 1747 | } |
1748 | 1748 | ||
1749 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { | 1749 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { |
1750 | if (--len < 0) | 1750 | if (--len < 0) |
1751 | goto out_overflow; | 1751 | goto out_overflow; |
1752 | switch ((n = ntohl(*p++))) { | 1752 | switch ((n = ntohl(*p++))) { |
1753 | case RPC_AUTH_ERROR: | 1753 | case RPC_AUTH_ERROR: |
1754 | break; | 1754 | break; |
1755 | case RPC_MISMATCH: | 1755 | case RPC_MISMATCH: |
1756 | dprintk("RPC: %5u %s: RPC call version mismatch!\n", | 1756 | dprintk("RPC: %5u %s: RPC call version mismatch!\n", |
1757 | task->tk_pid, __func__); | 1757 | task->tk_pid, __func__); |
1758 | error = -EPROTONOSUPPORT; | 1758 | error = -EPROTONOSUPPORT; |
1759 | goto out_err; | 1759 | goto out_err; |
1760 | default: | 1760 | default: |
1761 | dprintk("RPC: %5u %s: RPC call rejected, " | 1761 | dprintk("RPC: %5u %s: RPC call rejected, " |
1762 | "unknown error: %x\n", | 1762 | "unknown error: %x\n", |
1763 | task->tk_pid, __func__, n); | 1763 | task->tk_pid, __func__, n); |
1764 | goto out_eio; | 1764 | goto out_eio; |
1765 | } | 1765 | } |
1766 | if (--len < 0) | 1766 | if (--len < 0) |
1767 | goto out_overflow; | 1767 | goto out_overflow; |
1768 | switch ((n = ntohl(*p++))) { | 1768 | switch ((n = ntohl(*p++))) { |
1769 | case RPC_AUTH_REJECTEDCRED: | 1769 | case RPC_AUTH_REJECTEDCRED: |
1770 | case RPC_AUTH_REJECTEDVERF: | 1770 | case RPC_AUTH_REJECTEDVERF: |
1771 | case RPCSEC_GSS_CREDPROBLEM: | 1771 | case RPCSEC_GSS_CREDPROBLEM: |
1772 | case RPCSEC_GSS_CTXPROBLEM: | 1772 | case RPCSEC_GSS_CTXPROBLEM: |
1773 | if (!task->tk_cred_retry) | 1773 | if (!task->tk_cred_retry) |
1774 | break; | 1774 | break; |
1775 | task->tk_cred_retry--; | 1775 | task->tk_cred_retry--; |
1776 | dprintk("RPC: %5u %s: retry stale creds\n", | 1776 | dprintk("RPC: %5u %s: retry stale creds\n", |
1777 | task->tk_pid, __func__); | 1777 | task->tk_pid, __func__); |
1778 | rpcauth_invalcred(task); | 1778 | rpcauth_invalcred(task); |
1779 | /* Ensure we obtain a new XID! */ | 1779 | /* Ensure we obtain a new XID! */ |
1780 | xprt_release(task); | 1780 | xprt_release(task); |
1781 | task->tk_action = call_reserve; | 1781 | task->tk_action = call_reserve; |
1782 | goto out_retry; | 1782 | goto out_retry; |
1783 | case RPC_AUTH_BADCRED: | 1783 | case RPC_AUTH_BADCRED: |
1784 | case RPC_AUTH_BADVERF: | 1784 | case RPC_AUTH_BADVERF: |
1785 | /* possibly garbled cred/verf? */ | 1785 | /* possibly garbled cred/verf? */ |
1786 | if (!task->tk_garb_retry) | 1786 | if (!task->tk_garb_retry) |
1787 | break; | 1787 | break; |
1788 | task->tk_garb_retry--; | 1788 | task->tk_garb_retry--; |
1789 | dprintk("RPC: %5u %s: retry garbled creds\n", | 1789 | dprintk("RPC: %5u %s: retry garbled creds\n", |
1790 | task->tk_pid, __func__); | 1790 | task->tk_pid, __func__); |
1791 | task->tk_action = call_bind; | 1791 | task->tk_action = call_bind; |
1792 | goto out_retry; | 1792 | goto out_retry; |
1793 | case RPC_AUTH_TOOWEAK: | 1793 | case RPC_AUTH_TOOWEAK: |
1794 | printk(KERN_NOTICE "RPC: server %s requires stronger " | 1794 | printk(KERN_NOTICE "RPC: server %s requires stronger " |
1795 | "authentication.\n", task->tk_client->cl_server); | 1795 | "authentication.\n", task->tk_client->cl_server); |
1796 | break; | 1796 | break; |
1797 | default: | 1797 | default: |
1798 | dprintk("RPC: %5u %s: unknown auth error: %x\n", | 1798 | dprintk("RPC: %5u %s: unknown auth error: %x\n", |
1799 | task->tk_pid, __func__, n); | 1799 | task->tk_pid, __func__, n); |
1800 | error = -EIO; | 1800 | error = -EIO; |
1801 | } | 1801 | } |
1802 | dprintk("RPC: %5u %s: call rejected %d\n", | 1802 | dprintk("RPC: %5u %s: call rejected %d\n", |
1803 | task->tk_pid, __func__, n); | 1803 | task->tk_pid, __func__, n); |
1804 | goto out_err; | 1804 | goto out_err; |
1805 | } | 1805 | } |
1806 | if (!(p = rpcauth_checkverf(task, p))) { | 1806 | if (!(p = rpcauth_checkverf(task, p))) { |
1807 | dprintk("RPC: %5u %s: auth check failed\n", | 1807 | dprintk("RPC: %5u %s: auth check failed\n", |
1808 | task->tk_pid, __func__); | 1808 | task->tk_pid, __func__); |
1809 | goto out_garbage; /* bad verifier, retry */ | 1809 | goto out_garbage; /* bad verifier, retry */ |
1810 | } | 1810 | } |
1811 | len = p - (__be32 *)iov->iov_base - 1; | 1811 | len = p - (__be32 *)iov->iov_base - 1; |
1812 | if (len < 0) | 1812 | if (len < 0) |
1813 | goto out_overflow; | 1813 | goto out_overflow; |
1814 | switch ((n = ntohl(*p++))) { | 1814 | switch ((n = ntohl(*p++))) { |
1815 | case RPC_SUCCESS: | 1815 | case RPC_SUCCESS: |
1816 | return p; | 1816 | return p; |
1817 | case RPC_PROG_UNAVAIL: | 1817 | case RPC_PROG_UNAVAIL: |
1818 | dprintk("RPC: %5u %s: program %u is unsupported by server %s\n", | 1818 | dprintk("RPC: %5u %s: program %u is unsupported by server %s\n", |
1819 | task->tk_pid, __func__, | 1819 | task->tk_pid, __func__, |
1820 | (unsigned int)task->tk_client->cl_prog, | 1820 | (unsigned int)task->tk_client->cl_prog, |
1821 | task->tk_client->cl_server); | 1821 | task->tk_client->cl_server); |
1822 | error = -EPFNOSUPPORT; | 1822 | error = -EPFNOSUPPORT; |
1823 | goto out_err; | 1823 | goto out_err; |
1824 | case RPC_PROG_MISMATCH: | 1824 | case RPC_PROG_MISMATCH: |
1825 | dprintk("RPC: %5u %s: program %u, version %u unsupported by " | 1825 | dprintk("RPC: %5u %s: program %u, version %u unsupported by " |
1826 | "server %s\n", task->tk_pid, __func__, | 1826 | "server %s\n", task->tk_pid, __func__, |
1827 | (unsigned int)task->tk_client->cl_prog, | 1827 | (unsigned int)task->tk_client->cl_prog, |
1828 | (unsigned int)task->tk_client->cl_vers, | 1828 | (unsigned int)task->tk_client->cl_vers, |
1829 | task->tk_client->cl_server); | 1829 | task->tk_client->cl_server); |
1830 | error = -EPROTONOSUPPORT; | 1830 | error = -EPROTONOSUPPORT; |
1831 | goto out_err; | 1831 | goto out_err; |
1832 | case RPC_PROC_UNAVAIL: | 1832 | case RPC_PROC_UNAVAIL: |
1833 | dprintk("RPC: %5u %s: proc %s unsupported by program %u, " | 1833 | dprintk("RPC: %5u %s: proc %s unsupported by program %u, " |
1834 | "version %u on server %s\n", | 1834 | "version %u on server %s\n", |
1835 | task->tk_pid, __func__, | 1835 | task->tk_pid, __func__, |
1836 | rpc_proc_name(task), | 1836 | rpc_proc_name(task), |
1837 | task->tk_client->cl_prog, | 1837 | task->tk_client->cl_prog, |
1838 | task->tk_client->cl_vers, | 1838 | task->tk_client->cl_vers, |
1839 | task->tk_client->cl_server); | 1839 | task->tk_client->cl_server); |
1840 | error = -EOPNOTSUPP; | 1840 | error = -EOPNOTSUPP; |
1841 | goto out_err; | 1841 | goto out_err; |
1842 | case RPC_GARBAGE_ARGS: | 1842 | case RPC_GARBAGE_ARGS: |
1843 | dprintk("RPC: %5u %s: server saw garbage\n", | 1843 | dprintk("RPC: %5u %s: server saw garbage\n", |
1844 | task->tk_pid, __func__); | 1844 | task->tk_pid, __func__); |
1845 | break; /* retry */ | 1845 | break; /* retry */ |
1846 | default: | 1846 | default: |
1847 | dprintk("RPC: %5u %s: server accept status: %x\n", | 1847 | dprintk("RPC: %5u %s: server accept status: %x\n", |
1848 | task->tk_pid, __func__, n); | 1848 | task->tk_pid, __func__, n); |
1849 | /* Also retry */ | 1849 | /* Also retry */ |
1850 | } | 1850 | } |
1851 | 1851 | ||
1852 | out_garbage: | 1852 | out_garbage: |
1853 | task->tk_client->cl_stats->rpcgarbage++; | 1853 | task->tk_client->cl_stats->rpcgarbage++; |
1854 | if (task->tk_garb_retry) { | 1854 | if (task->tk_garb_retry) { |
1855 | task->tk_garb_retry--; | 1855 | task->tk_garb_retry--; |
1856 | dprintk("RPC: %5u %s: retrying\n", | 1856 | dprintk("RPC: %5u %s: retrying\n", |
1857 | task->tk_pid, __func__); | 1857 | task->tk_pid, __func__); |
1858 | task->tk_action = call_bind; | 1858 | task->tk_action = call_bind; |
1859 | out_retry: | 1859 | out_retry: |
1860 | return ERR_PTR(-EAGAIN); | 1860 | return ERR_PTR(-EAGAIN); |
1861 | } | 1861 | } |
1862 | out_eio: | 1862 | out_eio: |
1863 | error = -EIO; | 1863 | error = -EIO; |
1864 | out_err: | 1864 | out_err: |
1865 | rpc_exit(task, error); | 1865 | rpc_exit(task, error); |
1866 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, | 1866 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, |
1867 | __func__, error); | 1867 | __func__, error); |
1868 | return ERR_PTR(error); | 1868 | return ERR_PTR(error); |
1869 | out_overflow: | 1869 | out_overflow: |
1870 | dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid, | 1870 | dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid, |
1871 | __func__); | 1871 | __func__); |
1872 | goto out_garbage; | 1872 | goto out_garbage; |
1873 | } | 1873 | } |
1874 | 1874 | ||
1875 | static void rpcproc_encode_null(void *rqstp, struct xdr_stream *xdr, void *obj) | 1875 | static void rpcproc_encode_null(void *rqstp, struct xdr_stream *xdr, void *obj) |
1876 | { | 1876 | { |
1877 | } | 1877 | } |
1878 | 1878 | ||
1879 | static int rpcproc_decode_null(void *rqstp, struct xdr_stream *xdr, void *obj) | 1879 | static int rpcproc_decode_null(void *rqstp, struct xdr_stream *xdr, void *obj) |
1880 | { | 1880 | { |
1881 | return 0; | 1881 | return 0; |
1882 | } | 1882 | } |
1883 | 1883 | ||
1884 | static struct rpc_procinfo rpcproc_null = { | 1884 | static struct rpc_procinfo rpcproc_null = { |
1885 | .p_encode = rpcproc_encode_null, | 1885 | .p_encode = rpcproc_encode_null, |
1886 | .p_decode = rpcproc_decode_null, | 1886 | .p_decode = rpcproc_decode_null, |
1887 | }; | 1887 | }; |
1888 | 1888 | ||
1889 | static int rpc_ping(struct rpc_clnt *clnt) | 1889 | static int rpc_ping(struct rpc_clnt *clnt) |
1890 | { | 1890 | { |
1891 | struct rpc_message msg = { | 1891 | struct rpc_message msg = { |
1892 | .rpc_proc = &rpcproc_null, | 1892 | .rpc_proc = &rpcproc_null, |
1893 | }; | 1893 | }; |
1894 | int err; | 1894 | int err; |
1895 | msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0); | 1895 | msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0); |
1896 | err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN); | 1896 | err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN); |
1897 | put_rpccred(msg.rpc_cred); | 1897 | put_rpccred(msg.rpc_cred); |
1898 | return err; | 1898 | return err; |
1899 | } | 1899 | } |
1900 | 1900 | ||
1901 | struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags) | 1901 | struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags) |
1902 | { | 1902 | { |
1903 | struct rpc_message msg = { | 1903 | struct rpc_message msg = { |
1904 | .rpc_proc = &rpcproc_null, | 1904 | .rpc_proc = &rpcproc_null, |
1905 | .rpc_cred = cred, | 1905 | .rpc_cred = cred, |
1906 | }; | 1906 | }; |
1907 | struct rpc_task_setup task_setup_data = { | 1907 | struct rpc_task_setup task_setup_data = { |
1908 | .rpc_client = clnt, | 1908 | .rpc_client = clnt, |
1909 | .rpc_message = &msg, | 1909 | .rpc_message = &msg, |
1910 | .callback_ops = &rpc_default_ops, | 1910 | .callback_ops = &rpc_default_ops, |
1911 | .flags = flags, | 1911 | .flags = flags, |
1912 | }; | 1912 | }; |
1913 | return rpc_run_task(&task_setup_data); | 1913 | return rpc_run_task(&task_setup_data); |
1914 | } | 1914 | } |
1915 | EXPORT_SYMBOL_GPL(rpc_call_null); | 1915 | EXPORT_SYMBOL_GPL(rpc_call_null); |
1916 | 1916 | ||
1917 | #ifdef RPC_DEBUG | 1917 | #ifdef RPC_DEBUG |
1918 | static void rpc_show_header(void) | 1918 | static void rpc_show_header(void) |
1919 | { | 1919 | { |
1920 | printk(KERN_INFO "-pid- flgs status -client- --rqstp- " | 1920 | printk(KERN_INFO "-pid- flgs status -client- --rqstp- " |
1921 | "-timeout ---ops--\n"); | 1921 | "-timeout ---ops--\n"); |
1922 | } | 1922 | } |
1923 | 1923 | ||
1924 | static void rpc_show_task(const struct rpc_clnt *clnt, | 1924 | static void rpc_show_task(const struct rpc_clnt *clnt, |
1925 | const struct rpc_task *task) | 1925 | const struct rpc_task *task) |
1926 | { | 1926 | { |
1927 | const char *rpc_waitq = "none"; | 1927 | const char *rpc_waitq = "none"; |
1928 | 1928 | ||
1929 | if (RPC_IS_QUEUED(task)) | 1929 | if (RPC_IS_QUEUED(task)) |
1930 | rpc_waitq = rpc_qname(task->tk_waitqueue); | 1930 | rpc_waitq = rpc_qname(task->tk_waitqueue); |
1931 | 1931 | ||
1932 | printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n", | 1932 | printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n", |
1933 | task->tk_pid, task->tk_flags, task->tk_status, | 1933 | task->tk_pid, task->tk_flags, task->tk_status, |
1934 | clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops, | 1934 | clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops, |
1935 | clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task), | 1935 | clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task), |
1936 | task->tk_action, rpc_waitq); | 1936 | task->tk_action, rpc_waitq); |
1937 | } | 1937 | } |
1938 | 1938 | ||
1939 | void rpc_show_tasks(struct net *net) | 1939 | void rpc_show_tasks(struct net *net) |
1940 | { | 1940 | { |
1941 | struct rpc_clnt *clnt; | 1941 | struct rpc_clnt *clnt; |
1942 | struct rpc_task *task; | 1942 | struct rpc_task *task; |
1943 | int header = 0; | 1943 | int header = 0; |
1944 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1944 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1945 | 1945 | ||
1946 | spin_lock(&sn->rpc_client_lock); | 1946 | spin_lock(&sn->rpc_client_lock); |
1947 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | 1947 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
1948 | spin_lock(&clnt->cl_lock); | 1948 | spin_lock(&clnt->cl_lock); |
1949 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { | 1949 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { |
1950 | if (!header) { | 1950 | if (!header) { |
1951 | rpc_show_header(); | 1951 | rpc_show_header(); |
1952 | header++; | 1952 | header++; |
1953 | } | 1953 | } |
1954 | rpc_show_task(clnt, task); | 1954 | rpc_show_task(clnt, task); |
1955 | } | 1955 | } |
1956 | spin_unlock(&clnt->cl_lock); | 1956 | spin_unlock(&clnt->cl_lock); |
1957 | } | 1957 | } |
1958 | spin_unlock(&sn->rpc_client_lock); | 1958 | spin_unlock(&sn->rpc_client_lock); |
1959 | } | 1959 | } |
1960 | #endif | 1960 | #endif |
1961 | 1961 |
net/sunrpc/rpcb_clnt.c
1 | /* | 1 | /* |
2 | * In-kernel rpcbind client supporting versions 2, 3, and 4 of the rpcbind | 2 | * In-kernel rpcbind client supporting versions 2, 3, and 4 of the rpcbind |
3 | * protocol | 3 | * protocol |
4 | * | 4 | * |
5 | * Based on RFC 1833: "Binding Protocols for ONC RPC Version 2" and | 5 | * Based on RFC 1833: "Binding Protocols for ONC RPC Version 2" and |
6 | * RFC 3530: "Network File System (NFS) version 4 Protocol" | 6 | * RFC 3530: "Network File System (NFS) version 4 Protocol" |
7 | * | 7 | * |
8 | * Original: Gilles Quillard, Bull Open Source, 2005 <gilles.quillard@bull.net> | 8 | * Original: Gilles Quillard, Bull Open Source, 2005 <gilles.quillard@bull.net> |
9 | * Updated: Chuck Lever, Oracle Corporation, 2007 <chuck.lever@oracle.com> | 9 | * Updated: Chuck Lever, Oracle Corporation, 2007 <chuck.lever@oracle.com> |
10 | * | 10 | * |
11 | * Descended from net/sunrpc/pmap_clnt.c, | 11 | * Descended from net/sunrpc/pmap_clnt.c, |
12 | * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> | 12 | * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | 16 | ||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/socket.h> | 18 | #include <linux/socket.h> |
19 | #include <linux/un.h> | 19 | #include <linux/un.h> |
20 | #include <linux/in.h> | 20 | #include <linux/in.h> |
21 | #include <linux/in6.h> | 21 | #include <linux/in6.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/nsproxy.h> | 26 | #include <linux/nsproxy.h> |
27 | #include <net/ipv6.h> | 27 | #include <net/ipv6.h> |
28 | 28 | ||
29 | #include <linux/sunrpc/clnt.h> | 29 | #include <linux/sunrpc/clnt.h> |
30 | #include <linux/sunrpc/sched.h> | 30 | #include <linux/sunrpc/sched.h> |
31 | #include <linux/sunrpc/xprtsock.h> | 31 | #include <linux/sunrpc/xprtsock.h> |
32 | 32 | ||
33 | #include "netns.h" | 33 | #include "netns.h" |
34 | 34 | ||
35 | #ifdef RPC_DEBUG | 35 | #ifdef RPC_DEBUG |
36 | # define RPCDBG_FACILITY RPCDBG_BIND | 36 | # define RPCDBG_FACILITY RPCDBG_BIND |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | #define RPCBIND_SOCK_PATHNAME "/var/run/rpcbind.sock" | 39 | #define RPCBIND_SOCK_PATHNAME "/var/run/rpcbind.sock" |
40 | 40 | ||
41 | #define RPCBIND_PROGRAM (100000u) | 41 | #define RPCBIND_PROGRAM (100000u) |
42 | #define RPCBIND_PORT (111u) | 42 | #define RPCBIND_PORT (111u) |
43 | 43 | ||
44 | #define RPCBVERS_2 (2u) | 44 | #define RPCBVERS_2 (2u) |
45 | #define RPCBVERS_3 (3u) | 45 | #define RPCBVERS_3 (3u) |
46 | #define RPCBVERS_4 (4u) | 46 | #define RPCBVERS_4 (4u) |
47 | 47 | ||
48 | enum { | 48 | enum { |
49 | RPCBPROC_NULL, | 49 | RPCBPROC_NULL, |
50 | RPCBPROC_SET, | 50 | RPCBPROC_SET, |
51 | RPCBPROC_UNSET, | 51 | RPCBPROC_UNSET, |
52 | RPCBPROC_GETPORT, | 52 | RPCBPROC_GETPORT, |
53 | RPCBPROC_GETADDR = 3, /* alias for GETPORT */ | 53 | RPCBPROC_GETADDR = 3, /* alias for GETPORT */ |
54 | RPCBPROC_DUMP, | 54 | RPCBPROC_DUMP, |
55 | RPCBPROC_CALLIT, | 55 | RPCBPROC_CALLIT, |
56 | RPCBPROC_BCAST = 5, /* alias for CALLIT */ | 56 | RPCBPROC_BCAST = 5, /* alias for CALLIT */ |
57 | RPCBPROC_GETTIME, | 57 | RPCBPROC_GETTIME, |
58 | RPCBPROC_UADDR2TADDR, | 58 | RPCBPROC_UADDR2TADDR, |
59 | RPCBPROC_TADDR2UADDR, | 59 | RPCBPROC_TADDR2UADDR, |
60 | RPCBPROC_GETVERSADDR, | 60 | RPCBPROC_GETVERSADDR, |
61 | RPCBPROC_INDIRECT, | 61 | RPCBPROC_INDIRECT, |
62 | RPCBPROC_GETADDRLIST, | 62 | RPCBPROC_GETADDRLIST, |
63 | RPCBPROC_GETSTAT, | 63 | RPCBPROC_GETSTAT, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * r_owner | 67 | * r_owner |
68 | * | 68 | * |
69 | * The "owner" is allowed to unset a service in the rpcbind database. | 69 | * The "owner" is allowed to unset a service in the rpcbind database. |
70 | * | 70 | * |
71 | * For AF_LOCAL SET/UNSET requests, rpcbind treats this string as a | 71 | * For AF_LOCAL SET/UNSET requests, rpcbind treats this string as a |
72 | * UID which it maps to a local user name via a password lookup. | 72 | * UID which it maps to a local user name via a password lookup. |
73 | * In all other cases it is ignored. | 73 | * In all other cases it is ignored. |
74 | * | 74 | * |
75 | * For SET/UNSET requests, user space provides a value, even for | 75 | * For SET/UNSET requests, user space provides a value, even for |
76 | * network requests, and GETADDR uses an empty string. We follow | 76 | * network requests, and GETADDR uses an empty string. We follow |
77 | * those precedents here. | 77 | * those precedents here. |
78 | */ | 78 | */ |
79 | #define RPCB_OWNER_STRING "0" | 79 | #define RPCB_OWNER_STRING "0" |
80 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) | 80 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * XDR data type sizes | 83 | * XDR data type sizes |
84 | */ | 84 | */ |
85 | #define RPCB_program_sz (1) | 85 | #define RPCB_program_sz (1) |
86 | #define RPCB_version_sz (1) | 86 | #define RPCB_version_sz (1) |
87 | #define RPCB_protocol_sz (1) | 87 | #define RPCB_protocol_sz (1) |
88 | #define RPCB_port_sz (1) | 88 | #define RPCB_port_sz (1) |
89 | #define RPCB_boolean_sz (1) | 89 | #define RPCB_boolean_sz (1) |
90 | 90 | ||
91 | #define RPCB_netid_sz (1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) | 91 | #define RPCB_netid_sz (1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) |
92 | #define RPCB_addr_sz (1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) | 92 | #define RPCB_addr_sz (1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) |
93 | #define RPCB_ownerstring_sz (1 + XDR_QUADLEN(RPCB_MAXOWNERLEN)) | 93 | #define RPCB_ownerstring_sz (1 + XDR_QUADLEN(RPCB_MAXOWNERLEN)) |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * XDR argument and result sizes | 96 | * XDR argument and result sizes |
97 | */ | 97 | */ |
98 | #define RPCB_mappingargs_sz (RPCB_program_sz + RPCB_version_sz + \ | 98 | #define RPCB_mappingargs_sz (RPCB_program_sz + RPCB_version_sz + \ |
99 | RPCB_protocol_sz + RPCB_port_sz) | 99 | RPCB_protocol_sz + RPCB_port_sz) |
100 | #define RPCB_getaddrargs_sz (RPCB_program_sz + RPCB_version_sz + \ | 100 | #define RPCB_getaddrargs_sz (RPCB_program_sz + RPCB_version_sz + \ |
101 | RPCB_netid_sz + RPCB_addr_sz + \ | 101 | RPCB_netid_sz + RPCB_addr_sz + \ |
102 | RPCB_ownerstring_sz) | 102 | RPCB_ownerstring_sz) |
103 | 103 | ||
104 | #define RPCB_getportres_sz RPCB_port_sz | 104 | #define RPCB_getportres_sz RPCB_port_sz |
105 | #define RPCB_setres_sz RPCB_boolean_sz | 105 | #define RPCB_setres_sz RPCB_boolean_sz |
106 | 106 | ||
107 | /* | 107 | /* |
108 | * Note that RFC 1833 does not put any size restrictions on the | 108 | * Note that RFC 1833 does not put any size restrictions on the |
109 | * address string returned by the remote rpcbind database. | 109 | * address string returned by the remote rpcbind database. |
110 | */ | 110 | */ |
111 | #define RPCB_getaddrres_sz RPCB_addr_sz | 111 | #define RPCB_getaddrres_sz RPCB_addr_sz |
112 | 112 | ||
113 | static void rpcb_getport_done(struct rpc_task *, void *); | 113 | static void rpcb_getport_done(struct rpc_task *, void *); |
114 | static void rpcb_map_release(void *data); | 114 | static void rpcb_map_release(void *data); |
115 | static struct rpc_program rpcb_program; | 115 | static const struct rpc_program rpcb_program; |
116 | 116 | ||
117 | struct rpcbind_args { | 117 | struct rpcbind_args { |
118 | struct rpc_xprt * r_xprt; | 118 | struct rpc_xprt * r_xprt; |
119 | 119 | ||
120 | u32 r_prog; | 120 | u32 r_prog; |
121 | u32 r_vers; | 121 | u32 r_vers; |
122 | u32 r_prot; | 122 | u32 r_prot; |
123 | unsigned short r_port; | 123 | unsigned short r_port; |
124 | const char * r_netid; | 124 | const char * r_netid; |
125 | const char * r_addr; | 125 | const char * r_addr; |
126 | const char * r_owner; | 126 | const char * r_owner; |
127 | 127 | ||
128 | int r_status; | 128 | int r_status; |
129 | }; | 129 | }; |
130 | 130 | ||
131 | static struct rpc_procinfo rpcb_procedures2[]; | 131 | static struct rpc_procinfo rpcb_procedures2[]; |
132 | static struct rpc_procinfo rpcb_procedures3[]; | 132 | static struct rpc_procinfo rpcb_procedures3[]; |
133 | static struct rpc_procinfo rpcb_procedures4[]; | 133 | static struct rpc_procinfo rpcb_procedures4[]; |
134 | 134 | ||
135 | struct rpcb_info { | 135 | struct rpcb_info { |
136 | u32 rpc_vers; | 136 | u32 rpc_vers; |
137 | struct rpc_procinfo * rpc_proc; | 137 | struct rpc_procinfo * rpc_proc; |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static struct rpcb_info rpcb_next_version[]; | 140 | static const struct rpcb_info rpcb_next_version[]; |
141 | static struct rpcb_info rpcb_next_version6[]; | 141 | static const struct rpcb_info rpcb_next_version6[]; |
142 | 142 | ||
143 | static const struct rpc_call_ops rpcb_getport_ops = { | 143 | static const struct rpc_call_ops rpcb_getport_ops = { |
144 | .rpc_call_done = rpcb_getport_done, | 144 | .rpc_call_done = rpcb_getport_done, |
145 | .rpc_release = rpcb_map_release, | 145 | .rpc_release = rpcb_map_release, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status) | 148 | static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status) |
149 | { | 149 | { |
150 | xprt_clear_binding(xprt); | 150 | xprt_clear_binding(xprt); |
151 | rpc_wake_up_status(&xprt->binding, status); | 151 | rpc_wake_up_status(&xprt->binding, status); |
152 | } | 152 | } |
153 | 153 | ||
154 | static void rpcb_map_release(void *data) | 154 | static void rpcb_map_release(void *data) |
155 | { | 155 | { |
156 | struct rpcbind_args *map = data; | 156 | struct rpcbind_args *map = data; |
157 | 157 | ||
158 | rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status); | 158 | rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status); |
159 | xprt_put(map->r_xprt); | 159 | xprt_put(map->r_xprt); |
160 | kfree(map->r_addr); | 160 | kfree(map->r_addr); |
161 | kfree(map); | 161 | kfree(map); |
162 | } | 162 | } |
163 | 163 | ||
164 | static int rpcb_get_local(struct net *net) | 164 | static int rpcb_get_local(struct net *net) |
165 | { | 165 | { |
166 | int cnt; | 166 | int cnt; |
167 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 167 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
168 | 168 | ||
169 | spin_lock(&sn->rpcb_clnt_lock); | 169 | spin_lock(&sn->rpcb_clnt_lock); |
170 | if (sn->rpcb_users) | 170 | if (sn->rpcb_users) |
171 | sn->rpcb_users++; | 171 | sn->rpcb_users++; |
172 | cnt = sn->rpcb_users; | 172 | cnt = sn->rpcb_users; |
173 | spin_unlock(&sn->rpcb_clnt_lock); | 173 | spin_unlock(&sn->rpcb_clnt_lock); |
174 | 174 | ||
175 | return cnt; | 175 | return cnt; |
176 | } | 176 | } |
177 | 177 | ||
178 | void rpcb_put_local(struct net *net) | 178 | void rpcb_put_local(struct net *net) |
179 | { | 179 | { |
180 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 180 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
181 | struct rpc_clnt *clnt = sn->rpcb_local_clnt; | 181 | struct rpc_clnt *clnt = sn->rpcb_local_clnt; |
182 | struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; | 182 | struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; |
183 | int shutdown; | 183 | int shutdown; |
184 | 184 | ||
185 | spin_lock(&sn->rpcb_clnt_lock); | 185 | spin_lock(&sn->rpcb_clnt_lock); |
186 | if (--sn->rpcb_users == 0) { | 186 | if (--sn->rpcb_users == 0) { |
187 | sn->rpcb_local_clnt = NULL; | 187 | sn->rpcb_local_clnt = NULL; |
188 | sn->rpcb_local_clnt4 = NULL; | 188 | sn->rpcb_local_clnt4 = NULL; |
189 | } | 189 | } |
190 | shutdown = !sn->rpcb_users; | 190 | shutdown = !sn->rpcb_users; |
191 | spin_unlock(&sn->rpcb_clnt_lock); | 191 | spin_unlock(&sn->rpcb_clnt_lock); |
192 | 192 | ||
193 | if (shutdown) { | 193 | if (shutdown) { |
194 | /* | 194 | /* |
195 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | 195 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister |
196 | */ | 196 | */ |
197 | if (clnt4) | 197 | if (clnt4) |
198 | rpc_shutdown_client(clnt4); | 198 | rpc_shutdown_client(clnt4); |
199 | if (clnt) | 199 | if (clnt) |
200 | rpc_shutdown_client(clnt); | 200 | rpc_shutdown_client(clnt); |
201 | } | 201 | } |
202 | } | 202 | } |
203 | 203 | ||
204 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, | 204 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, |
205 | struct rpc_clnt *clnt4) | 205 | struct rpc_clnt *clnt4) |
206 | { | 206 | { |
207 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 207 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
208 | 208 | ||
209 | /* Protected by rpcb_create_local_mutex */ | 209 | /* Protected by rpcb_create_local_mutex */ |
210 | sn->rpcb_local_clnt = clnt; | 210 | sn->rpcb_local_clnt = clnt; |
211 | sn->rpcb_local_clnt4 = clnt4; | 211 | sn->rpcb_local_clnt4 = clnt4; |
212 | smp_wmb(); | 212 | smp_wmb(); |
213 | sn->rpcb_users = 1; | 213 | sn->rpcb_users = 1; |
214 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | 214 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " |
215 | "%p, rpcb_local_clnt4: %p) for net %p%s\n", | 215 | "%p, rpcb_local_clnt4: %p) for net %p%s\n", |
216 | sn->rpcb_local_clnt, sn->rpcb_local_clnt4, | 216 | sn->rpcb_local_clnt, sn->rpcb_local_clnt4, |
217 | net, (net == &init_net) ? " (init_net)" : ""); | 217 | net, (net == &init_net) ? " (init_net)" : ""); |
218 | } | 218 | } |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Returns zero on success, otherwise a negative errno value | 221 | * Returns zero on success, otherwise a negative errno value |
222 | * is returned. | 222 | * is returned. |
223 | */ | 223 | */ |
224 | static int rpcb_create_local_unix(struct net *net) | 224 | static int rpcb_create_local_unix(struct net *net) |
225 | { | 225 | { |
226 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { | 226 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { |
227 | .sun_family = AF_LOCAL, | 227 | .sun_family = AF_LOCAL, |
228 | .sun_path = RPCBIND_SOCK_PATHNAME, | 228 | .sun_path = RPCBIND_SOCK_PATHNAME, |
229 | }; | 229 | }; |
230 | struct rpc_create_args args = { | 230 | struct rpc_create_args args = { |
231 | .net = net, | 231 | .net = net, |
232 | .protocol = XPRT_TRANSPORT_LOCAL, | 232 | .protocol = XPRT_TRANSPORT_LOCAL, |
233 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, | 233 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, |
234 | .addrsize = sizeof(rpcb_localaddr_rpcbind), | 234 | .addrsize = sizeof(rpcb_localaddr_rpcbind), |
235 | .servername = "localhost", | 235 | .servername = "localhost", |
236 | .program = &rpcb_program, | 236 | .program = &rpcb_program, |
237 | .version = RPCBVERS_2, | 237 | .version = RPCBVERS_2, |
238 | .authflavor = RPC_AUTH_NULL, | 238 | .authflavor = RPC_AUTH_NULL, |
239 | }; | 239 | }; |
240 | struct rpc_clnt *clnt, *clnt4; | 240 | struct rpc_clnt *clnt, *clnt4; |
241 | int result = 0; | 241 | int result = 0; |
242 | 242 | ||
243 | /* | 243 | /* |
244 | * Because we requested an RPC PING at transport creation time, | 244 | * Because we requested an RPC PING at transport creation time, |
245 | * this works only if the user space portmapper is rpcbind, and | 245 | * this works only if the user space portmapper is rpcbind, and |
246 | * it's listening on AF_LOCAL on the named socket. | 246 | * it's listening on AF_LOCAL on the named socket. |
247 | */ | 247 | */ |
248 | clnt = rpc_create(&args); | 248 | clnt = rpc_create(&args); |
249 | if (IS_ERR(clnt)) { | 249 | if (IS_ERR(clnt)) { |
250 | dprintk("RPC: failed to create AF_LOCAL rpcbind " | 250 | dprintk("RPC: failed to create AF_LOCAL rpcbind " |
251 | "client (errno %ld).\n", PTR_ERR(clnt)); | 251 | "client (errno %ld).\n", PTR_ERR(clnt)); |
252 | result = -PTR_ERR(clnt); | 252 | result = -PTR_ERR(clnt); |
253 | goto out; | 253 | goto out; |
254 | } | 254 | } |
255 | 255 | ||
256 | clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4); | 256 | clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4); |
257 | if (IS_ERR(clnt4)) { | 257 | if (IS_ERR(clnt4)) { |
258 | dprintk("RPC: failed to bind second program to " | 258 | dprintk("RPC: failed to bind second program to " |
259 | "rpcbind v4 client (errno %ld).\n", | 259 | "rpcbind v4 client (errno %ld).\n", |
260 | PTR_ERR(clnt4)); | 260 | PTR_ERR(clnt4)); |
261 | clnt4 = NULL; | 261 | clnt4 = NULL; |
262 | } | 262 | } |
263 | 263 | ||
264 | rpcb_set_local(net, clnt, clnt4); | 264 | rpcb_set_local(net, clnt, clnt4); |
265 | 265 | ||
266 | out: | 266 | out: |
267 | return result; | 267 | return result; |
268 | } | 268 | } |
269 | 269 | ||
270 | /* | 270 | /* |
271 | * Returns zero on success, otherwise a negative errno value | 271 | * Returns zero on success, otherwise a negative errno value |
272 | * is returned. | 272 | * is returned. |
273 | */ | 273 | */ |
274 | static int rpcb_create_local_net(struct net *net) | 274 | static int rpcb_create_local_net(struct net *net) |
275 | { | 275 | { |
276 | static const struct sockaddr_in rpcb_inaddr_loopback = { | 276 | static const struct sockaddr_in rpcb_inaddr_loopback = { |
277 | .sin_family = AF_INET, | 277 | .sin_family = AF_INET, |
278 | .sin_addr.s_addr = htonl(INADDR_LOOPBACK), | 278 | .sin_addr.s_addr = htonl(INADDR_LOOPBACK), |
279 | .sin_port = htons(RPCBIND_PORT), | 279 | .sin_port = htons(RPCBIND_PORT), |
280 | }; | 280 | }; |
281 | struct rpc_create_args args = { | 281 | struct rpc_create_args args = { |
282 | .net = net, | 282 | .net = net, |
283 | .protocol = XPRT_TRANSPORT_TCP, | 283 | .protocol = XPRT_TRANSPORT_TCP, |
284 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, | 284 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, |
285 | .addrsize = sizeof(rpcb_inaddr_loopback), | 285 | .addrsize = sizeof(rpcb_inaddr_loopback), |
286 | .servername = "localhost", | 286 | .servername = "localhost", |
287 | .program = &rpcb_program, | 287 | .program = &rpcb_program, |
288 | .version = RPCBVERS_2, | 288 | .version = RPCBVERS_2, |
289 | .authflavor = RPC_AUTH_UNIX, | 289 | .authflavor = RPC_AUTH_UNIX, |
290 | .flags = RPC_CLNT_CREATE_NOPING, | 290 | .flags = RPC_CLNT_CREATE_NOPING, |
291 | }; | 291 | }; |
292 | struct rpc_clnt *clnt, *clnt4; | 292 | struct rpc_clnt *clnt, *clnt4; |
293 | int result = 0; | 293 | int result = 0; |
294 | 294 | ||
295 | clnt = rpc_create(&args); | 295 | clnt = rpc_create(&args); |
296 | if (IS_ERR(clnt)) { | 296 | if (IS_ERR(clnt)) { |
297 | dprintk("RPC: failed to create local rpcbind " | 297 | dprintk("RPC: failed to create local rpcbind " |
298 | "client (errno %ld).\n", PTR_ERR(clnt)); | 298 | "client (errno %ld).\n", PTR_ERR(clnt)); |
299 | result = -PTR_ERR(clnt); | 299 | result = -PTR_ERR(clnt); |
300 | goto out; | 300 | goto out; |
301 | } | 301 | } |
302 | 302 | ||
303 | /* | 303 | /* |
304 | * This results in an RPC ping. On systems running portmapper, | 304 | * This results in an RPC ping. On systems running portmapper, |
305 | * the v4 ping will fail. Proceed anyway, but disallow rpcb | 305 | * the v4 ping will fail. Proceed anyway, but disallow rpcb |
306 | * v4 upcalls. | 306 | * v4 upcalls. |
307 | */ | 307 | */ |
308 | clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4); | 308 | clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4); |
309 | if (IS_ERR(clnt4)) { | 309 | if (IS_ERR(clnt4)) { |
310 | dprintk("RPC: failed to bind second program to " | 310 | dprintk("RPC: failed to bind second program to " |
311 | "rpcbind v4 client (errno %ld).\n", | 311 | "rpcbind v4 client (errno %ld).\n", |
312 | PTR_ERR(clnt4)); | 312 | PTR_ERR(clnt4)); |
313 | clnt4 = NULL; | 313 | clnt4 = NULL; |
314 | } | 314 | } |
315 | 315 | ||
316 | rpcb_set_local(net, clnt, clnt4); | 316 | rpcb_set_local(net, clnt, clnt4); |
317 | 317 | ||
318 | out: | 318 | out: |
319 | return result; | 319 | return result; |
320 | } | 320 | } |
321 | 321 | ||
322 | /* | 322 | /* |
323 | * Returns zero on success, otherwise a negative errno value | 323 | * Returns zero on success, otherwise a negative errno value |
324 | * is returned. | 324 | * is returned. |
325 | */ | 325 | */ |
326 | int rpcb_create_local(struct net *net) | 326 | int rpcb_create_local(struct net *net) |
327 | { | 327 | { |
328 | static DEFINE_MUTEX(rpcb_create_local_mutex); | 328 | static DEFINE_MUTEX(rpcb_create_local_mutex); |
329 | int result = 0; | 329 | int result = 0; |
330 | 330 | ||
331 | if (rpcb_get_local(net)) | 331 | if (rpcb_get_local(net)) |
332 | return result; | 332 | return result; |
333 | 333 | ||
334 | mutex_lock(&rpcb_create_local_mutex); | 334 | mutex_lock(&rpcb_create_local_mutex); |
335 | if (rpcb_get_local(net)) | 335 | if (rpcb_get_local(net)) |
336 | goto out; | 336 | goto out; |
337 | 337 | ||
338 | if (rpcb_create_local_unix(net) != 0) | 338 | if (rpcb_create_local_unix(net) != 0) |
339 | result = rpcb_create_local_net(net); | 339 | result = rpcb_create_local_net(net); |
340 | 340 | ||
341 | out: | 341 | out: |
342 | mutex_unlock(&rpcb_create_local_mutex); | 342 | mutex_unlock(&rpcb_create_local_mutex); |
343 | return result; | 343 | return result; |
344 | } | 344 | } |
345 | 345 | ||
346 | static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, | 346 | static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, |
347 | struct sockaddr *srvaddr, size_t salen, | 347 | struct sockaddr *srvaddr, size_t salen, |
348 | int proto, u32 version) | 348 | int proto, u32 version) |
349 | { | 349 | { |
350 | struct rpc_create_args args = { | 350 | struct rpc_create_args args = { |
351 | .net = net, | 351 | .net = net, |
352 | .protocol = proto, | 352 | .protocol = proto, |
353 | .address = srvaddr, | 353 | .address = srvaddr, |
354 | .addrsize = salen, | 354 | .addrsize = salen, |
355 | .servername = hostname, | 355 | .servername = hostname, |
356 | .program = &rpcb_program, | 356 | .program = &rpcb_program, |
357 | .version = version, | 357 | .version = version, |
358 | .authflavor = RPC_AUTH_UNIX, | 358 | .authflavor = RPC_AUTH_UNIX, |
359 | .flags = (RPC_CLNT_CREATE_NOPING | | 359 | .flags = (RPC_CLNT_CREATE_NOPING | |
360 | RPC_CLNT_CREATE_NONPRIVPORT), | 360 | RPC_CLNT_CREATE_NONPRIVPORT), |
361 | }; | 361 | }; |
362 | 362 | ||
363 | switch (srvaddr->sa_family) { | 363 | switch (srvaddr->sa_family) { |
364 | case AF_INET: | 364 | case AF_INET: |
365 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); | 365 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); |
366 | break; | 366 | break; |
367 | case AF_INET6: | 367 | case AF_INET6: |
368 | ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT); | 368 | ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT); |
369 | break; | 369 | break; |
370 | default: | 370 | default: |
371 | return ERR_PTR(-EAFNOSUPPORT); | 371 | return ERR_PTR(-EAFNOSUPPORT); |
372 | } | 372 | } |
373 | 373 | ||
374 | return rpc_create(&args); | 374 | return rpc_create(&args); |
375 | } | 375 | } |
376 | 376 | ||
377 | static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) | 377 | static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) |
378 | { | 378 | { |
379 | int result, error = 0; | 379 | int result, error = 0; |
380 | 380 | ||
381 | msg->rpc_resp = &result; | 381 | msg->rpc_resp = &result; |
382 | 382 | ||
383 | error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN); | 383 | error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN); |
384 | if (error < 0) { | 384 | if (error < 0) { |
385 | dprintk("RPC: failed to contact local rpcbind " | 385 | dprintk("RPC: failed to contact local rpcbind " |
386 | "server (errno %d).\n", -error); | 386 | "server (errno %d).\n", -error); |
387 | return error; | 387 | return error; |
388 | } | 388 | } |
389 | 389 | ||
390 | if (!result) | 390 | if (!result) |
391 | return -EACCES; | 391 | return -EACCES; |
392 | return 0; | 392 | return 0; |
393 | } | 393 | } |
394 | 394 | ||
395 | /** | 395 | /** |
396 | * rpcb_register - set or unset a port registration with the local rpcbind svc | 396 | * rpcb_register - set or unset a port registration with the local rpcbind svc |
397 | * @prog: RPC program number to bind | 397 | * @prog: RPC program number to bind |
398 | * @vers: RPC version number to bind | 398 | * @vers: RPC version number to bind |
399 | * @prot: transport protocol to register | 399 | * @prot: transport protocol to register |
400 | * @port: port value to register | 400 | * @port: port value to register |
401 | * | 401 | * |
402 | * Returns zero if the registration request was dispatched successfully | 402 | * Returns zero if the registration request was dispatched successfully |
403 | * and the rpcbind daemon returned success. Otherwise, returns an errno | 403 | * and the rpcbind daemon returned success. Otherwise, returns an errno |
404 | * value that reflects the nature of the error (request could not be | 404 | * value that reflects the nature of the error (request could not be |
405 | * dispatched, timed out, or rpcbind returned an error). | 405 | * dispatched, timed out, or rpcbind returned an error). |
406 | * | 406 | * |
407 | * RPC services invoke this function to advertise their contact | 407 | * RPC services invoke this function to advertise their contact |
408 | * information via the system's rpcbind daemon. RPC services | 408 | * information via the system's rpcbind daemon. RPC services |
409 | * invoke this function once for each [program, version, transport] | 409 | * invoke this function once for each [program, version, transport] |
410 | * tuple they wish to advertise. | 410 | * tuple they wish to advertise. |
411 | * | 411 | * |
412 | * Callers may also unregister RPC services that are no longer | 412 | * Callers may also unregister RPC services that are no longer |
413 | * available by setting the passed-in port to zero. This removes | 413 | * available by setting the passed-in port to zero. This removes |
414 | * all registered transports for [program, version] from the local | 414 | * all registered transports for [program, version] from the local |
415 | * rpcbind database. | 415 | * rpcbind database. |
416 | * | 416 | * |
417 | * This function uses rpcbind protocol version 2 to contact the | 417 | * This function uses rpcbind protocol version 2 to contact the |
418 | * local rpcbind daemon. | 418 | * local rpcbind daemon. |
419 | * | 419 | * |
420 | * Registration works over both AF_INET and AF_INET6, and services | 420 | * Registration works over both AF_INET and AF_INET6, and services |
421 | * registered via this function are advertised as available for any | 421 | * registered via this function are advertised as available for any |
422 | * address. If the local rpcbind daemon is listening on AF_INET6, | 422 | * address. If the local rpcbind daemon is listening on AF_INET6, |
423 | * services registered via this function will be advertised on | 423 | * services registered via this function will be advertised on |
424 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 | 424 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 |
425 | * addresses). | 425 | * addresses). |
426 | */ | 426 | */ |
427 | int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short port) | 427 | int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short port) |
428 | { | 428 | { |
429 | struct rpcbind_args map = { | 429 | struct rpcbind_args map = { |
430 | .r_prog = prog, | 430 | .r_prog = prog, |
431 | .r_vers = vers, | 431 | .r_vers = vers, |
432 | .r_prot = prot, | 432 | .r_prot = prot, |
433 | .r_port = port, | 433 | .r_port = port, |
434 | }; | 434 | }; |
435 | struct rpc_message msg = { | 435 | struct rpc_message msg = { |
436 | .rpc_argp = &map, | 436 | .rpc_argp = &map, |
437 | }; | 437 | }; |
438 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 438 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
439 | 439 | ||
440 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 440 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
441 | "rpcbind\n", (port ? "" : "un"), | 441 | "rpcbind\n", (port ? "" : "un"), |
442 | prog, vers, prot, port); | 442 | prog, vers, prot, port); |
443 | 443 | ||
444 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; | 444 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; |
445 | if (port) | 445 | if (port) |
446 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 446 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
447 | 447 | ||
448 | return rpcb_register_call(sn->rpcb_local_clnt, &msg); | 448 | return rpcb_register_call(sn->rpcb_local_clnt, &msg); |
449 | } | 449 | } |
450 | 450 | ||
451 | /* | 451 | /* |
452 | * Fill in AF_INET family-specific arguments to register | 452 | * Fill in AF_INET family-specific arguments to register |
453 | */ | 453 | */ |
454 | static int rpcb_register_inet4(struct sunrpc_net *sn, | 454 | static int rpcb_register_inet4(struct sunrpc_net *sn, |
455 | const struct sockaddr *sap, | 455 | const struct sockaddr *sap, |
456 | struct rpc_message *msg) | 456 | struct rpc_message *msg) |
457 | { | 457 | { |
458 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | 458 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; |
459 | struct rpcbind_args *map = msg->rpc_argp; | 459 | struct rpcbind_args *map = msg->rpc_argp; |
460 | unsigned short port = ntohs(sin->sin_port); | 460 | unsigned short port = ntohs(sin->sin_port); |
461 | int result; | 461 | int result; |
462 | 462 | ||
463 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 463 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
464 | 464 | ||
465 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 465 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
466 | "local rpcbind\n", (port ? "" : "un"), | 466 | "local rpcbind\n", (port ? "" : "un"), |
467 | map->r_prog, map->r_vers, | 467 | map->r_prog, map->r_vers, |
468 | map->r_addr, map->r_netid); | 468 | map->r_addr, map->r_netid); |
469 | 469 | ||
470 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 470 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
471 | if (port) | 471 | if (port) |
472 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 472 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
473 | 473 | ||
474 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | 474 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); |
475 | kfree(map->r_addr); | 475 | kfree(map->r_addr); |
476 | return result; | 476 | return result; |
477 | } | 477 | } |
478 | 478 | ||
479 | /* | 479 | /* |
480 | * Fill in AF_INET6 family-specific arguments to register | 480 | * Fill in AF_INET6 family-specific arguments to register |
481 | */ | 481 | */ |
482 | static int rpcb_register_inet6(struct sunrpc_net *sn, | 482 | static int rpcb_register_inet6(struct sunrpc_net *sn, |
483 | const struct sockaddr *sap, | 483 | const struct sockaddr *sap, |
484 | struct rpc_message *msg) | 484 | struct rpc_message *msg) |
485 | { | 485 | { |
486 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; | 486 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; |
487 | struct rpcbind_args *map = msg->rpc_argp; | 487 | struct rpcbind_args *map = msg->rpc_argp; |
488 | unsigned short port = ntohs(sin6->sin6_port); | 488 | unsigned short port = ntohs(sin6->sin6_port); |
489 | int result; | 489 | int result; |
490 | 490 | ||
491 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 491 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
492 | 492 | ||
493 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 493 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
494 | "local rpcbind\n", (port ? "" : "un"), | 494 | "local rpcbind\n", (port ? "" : "un"), |
495 | map->r_prog, map->r_vers, | 495 | map->r_prog, map->r_vers, |
496 | map->r_addr, map->r_netid); | 496 | map->r_addr, map->r_netid); |
497 | 497 | ||
498 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 498 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
499 | if (port) | 499 | if (port) |
500 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 500 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
501 | 501 | ||
502 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | 502 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); |
503 | kfree(map->r_addr); | 503 | kfree(map->r_addr); |
504 | return result; | 504 | return result; |
505 | } | 505 | } |
506 | 506 | ||
507 | static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, | 507 | static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, |
508 | struct rpc_message *msg) | 508 | struct rpc_message *msg) |
509 | { | 509 | { |
510 | struct rpcbind_args *map = msg->rpc_argp; | 510 | struct rpcbind_args *map = msg->rpc_argp; |
511 | 511 | ||
512 | dprintk("RPC: unregistering [%u, %u, '%s'] with " | 512 | dprintk("RPC: unregistering [%u, %u, '%s'] with " |
513 | "local rpcbind\n", | 513 | "local rpcbind\n", |
514 | map->r_prog, map->r_vers, map->r_netid); | 514 | map->r_prog, map->r_vers, map->r_netid); |
515 | 515 | ||
516 | map->r_addr = ""; | 516 | map->r_addr = ""; |
517 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 517 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
518 | 518 | ||
519 | return rpcb_register_call(sn->rpcb_local_clnt4, msg); | 519 | return rpcb_register_call(sn->rpcb_local_clnt4, msg); |
520 | } | 520 | } |
521 | 521 | ||
522 | /** | 522 | /** |
523 | * rpcb_v4_register - set or unset a port registration with the local rpcbind | 523 | * rpcb_v4_register - set or unset a port registration with the local rpcbind |
524 | * @program: RPC program number of service to (un)register | 524 | * @program: RPC program number of service to (un)register |
525 | * @version: RPC version number of service to (un)register | 525 | * @version: RPC version number of service to (un)register |
526 | * @address: address family, IP address, and port to (un)register | 526 | * @address: address family, IP address, and port to (un)register |
527 | * @netid: netid of transport protocol to (un)register | 527 | * @netid: netid of transport protocol to (un)register |
528 | * | 528 | * |
529 | * Returns zero if the registration request was dispatched successfully | 529 | * Returns zero if the registration request was dispatched successfully |
530 | * and the rpcbind daemon returned success. Otherwise, returns an errno | 530 | * and the rpcbind daemon returned success. Otherwise, returns an errno |
531 | * value that reflects the nature of the error (request could not be | 531 | * value that reflects the nature of the error (request could not be |
532 | * dispatched, timed out, or rpcbind returned an error). | 532 | * dispatched, timed out, or rpcbind returned an error). |
533 | * | 533 | * |
534 | * RPC services invoke this function to advertise their contact | 534 | * RPC services invoke this function to advertise their contact |
535 | * information via the system's rpcbind daemon. RPC services | 535 | * information via the system's rpcbind daemon. RPC services |
536 | * invoke this function once for each [program, version, address, | 536 | * invoke this function once for each [program, version, address, |
537 | * netid] tuple they wish to advertise. | 537 | * netid] tuple they wish to advertise. |
538 | * | 538 | * |
539 | * Callers may also unregister RPC services that are registered at a | 539 | * Callers may also unregister RPC services that are registered at a |
540 | * specific address by setting the port number in @address to zero. | 540 | * specific address by setting the port number in @address to zero. |
541 | * They may unregister all registered protocol families at once for | 541 | * They may unregister all registered protocol families at once for |
542 | * a service by passing a NULL @address argument. If @netid is "" | 542 | * a service by passing a NULL @address argument. If @netid is "" |
543 | * then all netids for [program, version, address] are unregistered. | 543 | * then all netids for [program, version, address] are unregistered. |
544 | * | 544 | * |
545 | * This function uses rpcbind protocol version 4 to contact the | 545 | * This function uses rpcbind protocol version 4 to contact the |
546 | * local rpcbind daemon. The local rpcbind daemon must support | 546 | * local rpcbind daemon. The local rpcbind daemon must support |
547 | * version 4 of the rpcbind protocol in order for these functions | 547 | * version 4 of the rpcbind protocol in order for these functions |
548 | * to register a service successfully. | 548 | * to register a service successfully. |
549 | * | 549 | * |
550 | * Supported netids include "udp" and "tcp" for UDP and TCP over | 550 | * Supported netids include "udp" and "tcp" for UDP and TCP over |
551 | * IPv4, and "udp6" and "tcp6" for UDP and TCP over IPv6, | 551 | * IPv4, and "udp6" and "tcp6" for UDP and TCP over IPv6, |
552 | * respectively. | 552 | * respectively. |
553 | * | 553 | * |
554 | * The contents of @address determine the address family and the | 554 | * The contents of @address determine the address family and the |
555 | * port to be registered. The usual practice is to pass INADDR_ANY | 555 | * port to be registered. The usual practice is to pass INADDR_ANY |
556 | * as the raw address, but specifying a non-zero address is also | 556 | * as the raw address, but specifying a non-zero address is also |
557 | * supported by this API if the caller wishes to advertise an RPC | 557 | * supported by this API if the caller wishes to advertise an RPC |
558 | * service on a specific network interface. | 558 | * service on a specific network interface. |
559 | * | 559 | * |
560 | * Note that passing in INADDR_ANY does not create the same service | 560 | * Note that passing in INADDR_ANY does not create the same service |
561 | * registration as IN6ADDR_ANY. The former advertises an RPC | 561 | * registration as IN6ADDR_ANY. The former advertises an RPC |
562 | * service on any IPv4 address, but not on IPv6. The latter | 562 | * service on any IPv4 address, but not on IPv6. The latter |
563 | * advertises the service on all IPv4 and IPv6 addresses. | 563 | * advertises the service on all IPv4 and IPv6 addresses. |
564 | */ | 564 | */ |
565 | int rpcb_v4_register(struct net *net, const u32 program, const u32 version, | 565 | int rpcb_v4_register(struct net *net, const u32 program, const u32 version, |
566 | const struct sockaddr *address, const char *netid) | 566 | const struct sockaddr *address, const char *netid) |
567 | { | 567 | { |
568 | struct rpcbind_args map = { | 568 | struct rpcbind_args map = { |
569 | .r_prog = program, | 569 | .r_prog = program, |
570 | .r_vers = version, | 570 | .r_vers = version, |
571 | .r_netid = netid, | 571 | .r_netid = netid, |
572 | .r_owner = RPCB_OWNER_STRING, | 572 | .r_owner = RPCB_OWNER_STRING, |
573 | }; | 573 | }; |
574 | struct rpc_message msg = { | 574 | struct rpc_message msg = { |
575 | .rpc_argp = &map, | 575 | .rpc_argp = &map, |
576 | }; | 576 | }; |
577 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 577 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
578 | 578 | ||
579 | if (sn->rpcb_local_clnt4 == NULL) | 579 | if (sn->rpcb_local_clnt4 == NULL) |
580 | return -EPROTONOSUPPORT; | 580 | return -EPROTONOSUPPORT; |
581 | 581 | ||
582 | if (address == NULL) | 582 | if (address == NULL) |
583 | return rpcb_unregister_all_protofamilies(sn, &msg); | 583 | return rpcb_unregister_all_protofamilies(sn, &msg); |
584 | 584 | ||
585 | switch (address->sa_family) { | 585 | switch (address->sa_family) { |
586 | case AF_INET: | 586 | case AF_INET: |
587 | return rpcb_register_inet4(sn, address, &msg); | 587 | return rpcb_register_inet4(sn, address, &msg); |
588 | case AF_INET6: | 588 | case AF_INET6: |
589 | return rpcb_register_inet6(sn, address, &msg); | 589 | return rpcb_register_inet6(sn, address, &msg); |
590 | } | 590 | } |
591 | 591 | ||
592 | return -EAFNOSUPPORT; | 592 | return -EAFNOSUPPORT; |
593 | } | 593 | } |
594 | 594 | ||
595 | static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc) | 595 | static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc) |
596 | { | 596 | { |
597 | struct rpc_message msg = { | 597 | struct rpc_message msg = { |
598 | .rpc_proc = proc, | 598 | .rpc_proc = proc, |
599 | .rpc_argp = map, | 599 | .rpc_argp = map, |
600 | .rpc_resp = map, | 600 | .rpc_resp = map, |
601 | }; | 601 | }; |
602 | struct rpc_task_setup task_setup_data = { | 602 | struct rpc_task_setup task_setup_data = { |
603 | .rpc_client = rpcb_clnt, | 603 | .rpc_client = rpcb_clnt, |
604 | .rpc_message = &msg, | 604 | .rpc_message = &msg, |
605 | .callback_ops = &rpcb_getport_ops, | 605 | .callback_ops = &rpcb_getport_ops, |
606 | .callback_data = map, | 606 | .callback_data = map, |
607 | .flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN, | 607 | .flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN, |
608 | }; | 608 | }; |
609 | 609 | ||
610 | return rpc_run_task(&task_setup_data); | 610 | return rpc_run_task(&task_setup_data); |
611 | } | 611 | } |
612 | 612 | ||
613 | /* | 613 | /* |
614 | * In the case where rpc clients have been cloned, we want to make | 614 | * In the case where rpc clients have been cloned, we want to make |
615 | * sure that we use the program number/version etc of the actual | 615 | * sure that we use the program number/version etc of the actual |
616 | * owner of the xprt. To do so, we walk back up the tree of parents | 616 | * owner of the xprt. To do so, we walk back up the tree of parents |
617 | * to find whoever created the transport and/or whoever has the | 617 | * to find whoever created the transport and/or whoever has the |
618 | * autobind flag set. | 618 | * autobind flag set. |
619 | */ | 619 | */ |
620 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) | 620 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) |
621 | { | 621 | { |
622 | struct rpc_clnt *parent = clnt->cl_parent; | 622 | struct rpc_clnt *parent = clnt->cl_parent; |
623 | 623 | ||
624 | while (parent != clnt) { | 624 | while (parent != clnt) { |
625 | if (parent->cl_xprt != clnt->cl_xprt) | 625 | if (parent->cl_xprt != clnt->cl_xprt) |
626 | break; | 626 | break; |
627 | if (clnt->cl_autobind) | 627 | if (clnt->cl_autobind) |
628 | break; | 628 | break; |
629 | clnt = parent; | 629 | clnt = parent; |
630 | parent = parent->cl_parent; | 630 | parent = parent->cl_parent; |
631 | } | 631 | } |
632 | return clnt; | 632 | return clnt; |
633 | } | 633 | } |
634 | 634 | ||
635 | /** | 635 | /** |
636 | * rpcb_getport_async - obtain the port for a given RPC service on a given host | 636 | * rpcb_getport_async - obtain the port for a given RPC service on a given host |
637 | * @task: task that is waiting for portmapper request | 637 | * @task: task that is waiting for portmapper request |
638 | * | 638 | * |
639 | * This one can be called for an ongoing RPC request, and can be used in | 639 | * This one can be called for an ongoing RPC request, and can be used in |
640 | * an async (rpciod) context. | 640 | * an async (rpciod) context. |
641 | */ | 641 | */ |
642 | void rpcb_getport_async(struct rpc_task *task) | 642 | void rpcb_getport_async(struct rpc_task *task) |
643 | { | 643 | { |
644 | struct rpc_clnt *clnt; | 644 | struct rpc_clnt *clnt; |
645 | struct rpc_procinfo *proc; | 645 | struct rpc_procinfo *proc; |
646 | u32 bind_version; | 646 | u32 bind_version; |
647 | struct rpc_xprt *xprt; | 647 | struct rpc_xprt *xprt; |
648 | struct rpc_clnt *rpcb_clnt; | 648 | struct rpc_clnt *rpcb_clnt; |
649 | struct rpcbind_args *map; | 649 | struct rpcbind_args *map; |
650 | struct rpc_task *child; | 650 | struct rpc_task *child; |
651 | struct sockaddr_storage addr; | 651 | struct sockaddr_storage addr; |
652 | struct sockaddr *sap = (struct sockaddr *)&addr; | 652 | struct sockaddr *sap = (struct sockaddr *)&addr; |
653 | size_t salen; | 653 | size_t salen; |
654 | int status; | 654 | int status; |
655 | 655 | ||
656 | clnt = rpcb_find_transport_owner(task->tk_client); | 656 | clnt = rpcb_find_transport_owner(task->tk_client); |
657 | xprt = clnt->cl_xprt; | 657 | xprt = clnt->cl_xprt; |
658 | 658 | ||
659 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", | 659 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
660 | task->tk_pid, __func__, | 660 | task->tk_pid, __func__, |
661 | clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); | 661 | clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); |
662 | 662 | ||
663 | /* Put self on the wait queue to ensure we get notified if | 663 | /* Put self on the wait queue to ensure we get notified if |
664 | * some other task is already attempting to bind the port */ | 664 | * some other task is already attempting to bind the port */ |
665 | rpc_sleep_on(&xprt->binding, task, NULL); | 665 | rpc_sleep_on(&xprt->binding, task, NULL); |
666 | 666 | ||
667 | if (xprt_test_and_set_binding(xprt)) { | 667 | if (xprt_test_and_set_binding(xprt)) { |
668 | dprintk("RPC: %5u %s: waiting for another binder\n", | 668 | dprintk("RPC: %5u %s: waiting for another binder\n", |
669 | task->tk_pid, __func__); | 669 | task->tk_pid, __func__); |
670 | return; | 670 | return; |
671 | } | 671 | } |
672 | 672 | ||
673 | /* Someone else may have bound if we slept */ | 673 | /* Someone else may have bound if we slept */ |
674 | if (xprt_bound(xprt)) { | 674 | if (xprt_bound(xprt)) { |
675 | status = 0; | 675 | status = 0; |
676 | dprintk("RPC: %5u %s: already bound\n", | 676 | dprintk("RPC: %5u %s: already bound\n", |
677 | task->tk_pid, __func__); | 677 | task->tk_pid, __func__); |
678 | goto bailout_nofree; | 678 | goto bailout_nofree; |
679 | } | 679 | } |
680 | 680 | ||
681 | /* Parent transport's destination address */ | 681 | /* Parent transport's destination address */ |
682 | salen = rpc_peeraddr(clnt, sap, sizeof(addr)); | 682 | salen = rpc_peeraddr(clnt, sap, sizeof(addr)); |
683 | 683 | ||
684 | /* Don't ever use rpcbind v2 for AF_INET6 requests */ | 684 | /* Don't ever use rpcbind v2 for AF_INET6 requests */ |
685 | switch (sap->sa_family) { | 685 | switch (sap->sa_family) { |
686 | case AF_INET: | 686 | case AF_INET: |
687 | proc = rpcb_next_version[xprt->bind_index].rpc_proc; | 687 | proc = rpcb_next_version[xprt->bind_index].rpc_proc; |
688 | bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; | 688 | bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; |
689 | break; | 689 | break; |
690 | case AF_INET6: | 690 | case AF_INET6: |
691 | proc = rpcb_next_version6[xprt->bind_index].rpc_proc; | 691 | proc = rpcb_next_version6[xprt->bind_index].rpc_proc; |
692 | bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers; | 692 | bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers; |
693 | break; | 693 | break; |
694 | default: | 694 | default: |
695 | status = -EAFNOSUPPORT; | 695 | status = -EAFNOSUPPORT; |
696 | dprintk("RPC: %5u %s: bad address family\n", | 696 | dprintk("RPC: %5u %s: bad address family\n", |
697 | task->tk_pid, __func__); | 697 | task->tk_pid, __func__); |
698 | goto bailout_nofree; | 698 | goto bailout_nofree; |
699 | } | 699 | } |
700 | if (proc == NULL) { | 700 | if (proc == NULL) { |
701 | xprt->bind_index = 0; | 701 | xprt->bind_index = 0; |
702 | status = -EPFNOSUPPORT; | 702 | status = -EPFNOSUPPORT; |
703 | dprintk("RPC: %5u %s: no more getport versions available\n", | 703 | dprintk("RPC: %5u %s: no more getport versions available\n", |
704 | task->tk_pid, __func__); | 704 | task->tk_pid, __func__); |
705 | goto bailout_nofree; | 705 | goto bailout_nofree; |
706 | } | 706 | } |
707 | 707 | ||
708 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 708 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
709 | task->tk_pid, __func__, bind_version); | 709 | task->tk_pid, __func__, bind_version); |
710 | 710 | ||
711 | rpcb_clnt = rpcb_create(xprt->xprt_net, clnt->cl_server, sap, salen, | 711 | rpcb_clnt = rpcb_create(xprt->xprt_net, clnt->cl_server, sap, salen, |
712 | xprt->prot, bind_version); | 712 | xprt->prot, bind_version); |
713 | if (IS_ERR(rpcb_clnt)) { | 713 | if (IS_ERR(rpcb_clnt)) { |
714 | status = PTR_ERR(rpcb_clnt); | 714 | status = PTR_ERR(rpcb_clnt); |
715 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | 715 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", |
716 | task->tk_pid, __func__, PTR_ERR(rpcb_clnt)); | 716 | task->tk_pid, __func__, PTR_ERR(rpcb_clnt)); |
717 | goto bailout_nofree; | 717 | goto bailout_nofree; |
718 | } | 718 | } |
719 | 719 | ||
720 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); | 720 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); |
721 | if (!map) { | 721 | if (!map) { |
722 | status = -ENOMEM; | 722 | status = -ENOMEM; |
723 | dprintk("RPC: %5u %s: no memory available\n", | 723 | dprintk("RPC: %5u %s: no memory available\n", |
724 | task->tk_pid, __func__); | 724 | task->tk_pid, __func__); |
725 | goto bailout_release_client; | 725 | goto bailout_release_client; |
726 | } | 726 | } |
727 | map->r_prog = clnt->cl_prog; | 727 | map->r_prog = clnt->cl_prog; |
728 | map->r_vers = clnt->cl_vers; | 728 | map->r_vers = clnt->cl_vers; |
729 | map->r_prot = xprt->prot; | 729 | map->r_prot = xprt->prot; |
730 | map->r_port = 0; | 730 | map->r_port = 0; |
731 | map->r_xprt = xprt_get(xprt); | 731 | map->r_xprt = xprt_get(xprt); |
732 | map->r_status = -EIO; | 732 | map->r_status = -EIO; |
733 | 733 | ||
734 | switch (bind_version) { | 734 | switch (bind_version) { |
735 | case RPCBVERS_4: | 735 | case RPCBVERS_4: |
736 | case RPCBVERS_3: | 736 | case RPCBVERS_3: |
737 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 737 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
738 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); | 738 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); |
739 | map->r_owner = ""; | 739 | map->r_owner = ""; |
740 | break; | 740 | break; |
741 | case RPCBVERS_2: | 741 | case RPCBVERS_2: |
742 | map->r_addr = NULL; | 742 | map->r_addr = NULL; |
743 | break; | 743 | break; |
744 | default: | 744 | default: |
745 | BUG(); | 745 | BUG(); |
746 | } | 746 | } |
747 | 747 | ||
748 | child = rpcb_call_async(rpcb_clnt, map, proc); | 748 | child = rpcb_call_async(rpcb_clnt, map, proc); |
749 | rpc_release_client(rpcb_clnt); | 749 | rpc_release_client(rpcb_clnt); |
750 | if (IS_ERR(child)) { | 750 | if (IS_ERR(child)) { |
751 | /* rpcb_map_release() has freed the arguments */ | 751 | /* rpcb_map_release() has freed the arguments */ |
752 | dprintk("RPC: %5u %s: rpc_run_task failed\n", | 752 | dprintk("RPC: %5u %s: rpc_run_task failed\n", |
753 | task->tk_pid, __func__); | 753 | task->tk_pid, __func__); |
754 | return; | 754 | return; |
755 | } | 755 | } |
756 | 756 | ||
757 | xprt->stat.bind_count++; | 757 | xprt->stat.bind_count++; |
758 | rpc_put_task(child); | 758 | rpc_put_task(child); |
759 | return; | 759 | return; |
760 | 760 | ||
761 | bailout_release_client: | 761 | bailout_release_client: |
762 | rpc_release_client(rpcb_clnt); | 762 | rpc_release_client(rpcb_clnt); |
763 | bailout_nofree: | 763 | bailout_nofree: |
764 | rpcb_wake_rpcbind_waiters(xprt, status); | 764 | rpcb_wake_rpcbind_waiters(xprt, status); |
765 | task->tk_status = status; | 765 | task->tk_status = status; |
766 | } | 766 | } |
767 | EXPORT_SYMBOL_GPL(rpcb_getport_async); | 767 | EXPORT_SYMBOL_GPL(rpcb_getport_async); |
768 | 768 | ||
769 | /* | 769 | /* |
770 | * Rpcbind child task calls this callback via tk_exit. | 770 | * Rpcbind child task calls this callback via tk_exit. |
771 | */ | 771 | */ |
772 | static void rpcb_getport_done(struct rpc_task *child, void *data) | 772 | static void rpcb_getport_done(struct rpc_task *child, void *data) |
773 | { | 773 | { |
774 | struct rpcbind_args *map = data; | 774 | struct rpcbind_args *map = data; |
775 | struct rpc_xprt *xprt = map->r_xprt; | 775 | struct rpc_xprt *xprt = map->r_xprt; |
776 | int status = child->tk_status; | 776 | int status = child->tk_status; |
777 | 777 | ||
778 | /* Garbage reply: retry with a lesser rpcbind version */ | 778 | /* Garbage reply: retry with a lesser rpcbind version */ |
779 | if (status == -EIO) | 779 | if (status == -EIO) |
780 | status = -EPROTONOSUPPORT; | 780 | status = -EPROTONOSUPPORT; |
781 | 781 | ||
782 | /* rpcbind server doesn't support this rpcbind protocol version */ | 782 | /* rpcbind server doesn't support this rpcbind protocol version */ |
783 | if (status == -EPROTONOSUPPORT) | 783 | if (status == -EPROTONOSUPPORT) |
784 | xprt->bind_index++; | 784 | xprt->bind_index++; |
785 | 785 | ||
786 | if (status < 0) { | 786 | if (status < 0) { |
787 | /* rpcbind server not available on remote host? */ | 787 | /* rpcbind server not available on remote host? */ |
788 | xprt->ops->set_port(xprt, 0); | 788 | xprt->ops->set_port(xprt, 0); |
789 | } else if (map->r_port == 0) { | 789 | } else if (map->r_port == 0) { |
790 | /* Requested RPC service wasn't registered on remote host */ | 790 | /* Requested RPC service wasn't registered on remote host */ |
791 | xprt->ops->set_port(xprt, 0); | 791 | xprt->ops->set_port(xprt, 0); |
792 | status = -EACCES; | 792 | status = -EACCES; |
793 | } else { | 793 | } else { |
794 | /* Succeeded */ | 794 | /* Succeeded */ |
795 | xprt->ops->set_port(xprt, map->r_port); | 795 | xprt->ops->set_port(xprt, map->r_port); |
796 | xprt_set_bound(xprt); | 796 | xprt_set_bound(xprt); |
797 | status = 0; | 797 | status = 0; |
798 | } | 798 | } |
799 | 799 | ||
800 | dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n", | 800 | dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n", |
801 | child->tk_pid, status, map->r_port); | 801 | child->tk_pid, status, map->r_port); |
802 | 802 | ||
803 | map->r_status = status; | 803 | map->r_status = status; |
804 | } | 804 | } |
805 | 805 | ||
806 | /* | 806 | /* |
807 | * XDR functions for rpcbind | 807 | * XDR functions for rpcbind |
808 | */ | 808 | */ |
809 | 809 | ||
810 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, | 810 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, |
811 | const struct rpcbind_args *rpcb) | 811 | const struct rpcbind_args *rpcb) |
812 | { | 812 | { |
813 | struct rpc_task *task = req->rq_task; | 813 | struct rpc_task *task = req->rq_task; |
814 | __be32 *p; | 814 | __be32 *p; |
815 | 815 | ||
816 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", | 816 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", |
817 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 817 | task->tk_pid, task->tk_msg.rpc_proc->p_name, |
818 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); | 818 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); |
819 | 819 | ||
820 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); | 820 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); |
821 | *p++ = cpu_to_be32(rpcb->r_prog); | 821 | *p++ = cpu_to_be32(rpcb->r_prog); |
822 | *p++ = cpu_to_be32(rpcb->r_vers); | 822 | *p++ = cpu_to_be32(rpcb->r_vers); |
823 | *p++ = cpu_to_be32(rpcb->r_prot); | 823 | *p++ = cpu_to_be32(rpcb->r_prot); |
824 | *p = cpu_to_be32(rpcb->r_port); | 824 | *p = cpu_to_be32(rpcb->r_port); |
825 | } | 825 | } |
826 | 826 | ||
827 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | 827 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, |
828 | struct rpcbind_args *rpcb) | 828 | struct rpcbind_args *rpcb) |
829 | { | 829 | { |
830 | struct rpc_task *task = req->rq_task; | 830 | struct rpc_task *task = req->rq_task; |
831 | unsigned long port; | 831 | unsigned long port; |
832 | __be32 *p; | 832 | __be32 *p; |
833 | 833 | ||
834 | rpcb->r_port = 0; | 834 | rpcb->r_port = 0; |
835 | 835 | ||
836 | p = xdr_inline_decode(xdr, 4); | 836 | p = xdr_inline_decode(xdr, 4); |
837 | if (unlikely(p == NULL)) | 837 | if (unlikely(p == NULL)) |
838 | return -EIO; | 838 | return -EIO; |
839 | 839 | ||
840 | port = be32_to_cpup(p); | 840 | port = be32_to_cpup(p); |
841 | dprintk("RPC: %5u PMAP_%s result: %lu\n", task->tk_pid, | 841 | dprintk("RPC: %5u PMAP_%s result: %lu\n", task->tk_pid, |
842 | task->tk_msg.rpc_proc->p_name, port); | 842 | task->tk_msg.rpc_proc->p_name, port); |
843 | if (unlikely(port > USHRT_MAX)) | 843 | if (unlikely(port > USHRT_MAX)) |
844 | return -EIO; | 844 | return -EIO; |
845 | 845 | ||
846 | rpcb->r_port = port; | 846 | rpcb->r_port = port; |
847 | return 0; | 847 | return 0; |
848 | } | 848 | } |
849 | 849 | ||
850 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, | 850 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, |
851 | unsigned int *boolp) | 851 | unsigned int *boolp) |
852 | { | 852 | { |
853 | struct rpc_task *task = req->rq_task; | 853 | struct rpc_task *task = req->rq_task; |
854 | __be32 *p; | 854 | __be32 *p; |
855 | 855 | ||
856 | p = xdr_inline_decode(xdr, 4); | 856 | p = xdr_inline_decode(xdr, 4); |
857 | if (unlikely(p == NULL)) | 857 | if (unlikely(p == NULL)) |
858 | return -EIO; | 858 | return -EIO; |
859 | 859 | ||
860 | *boolp = 0; | 860 | *boolp = 0; |
861 | if (*p != xdr_zero) | 861 | if (*p != xdr_zero) |
862 | *boolp = 1; | 862 | *boolp = 1; |
863 | 863 | ||
864 | dprintk("RPC: %5u RPCB_%s call %s\n", | 864 | dprintk("RPC: %5u RPCB_%s call %s\n", |
865 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 865 | task->tk_pid, task->tk_msg.rpc_proc->p_name, |
866 | (*boolp ? "succeeded" : "failed")); | 866 | (*boolp ? "succeeded" : "failed")); |
867 | return 0; | 867 | return 0; |
868 | } | 868 | } |
869 | 869 | ||
870 | static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, | 870 | static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, |
871 | const u32 maxstrlen) | 871 | const u32 maxstrlen) |
872 | { | 872 | { |
873 | __be32 *p; | 873 | __be32 *p; |
874 | u32 len; | 874 | u32 len; |
875 | 875 | ||
876 | len = strlen(string); | 876 | len = strlen(string); |
877 | BUG_ON(len > maxstrlen); | 877 | BUG_ON(len > maxstrlen); |
878 | p = xdr_reserve_space(xdr, 4 + len); | 878 | p = xdr_reserve_space(xdr, 4 + len); |
879 | xdr_encode_opaque(p, string, len); | 879 | xdr_encode_opaque(p, string, len); |
880 | } | 880 | } |
881 | 881 | ||
882 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | 882 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, |
883 | const struct rpcbind_args *rpcb) | 883 | const struct rpcbind_args *rpcb) |
884 | { | 884 | { |
885 | struct rpc_task *task = req->rq_task; | 885 | struct rpc_task *task = req->rq_task; |
886 | __be32 *p; | 886 | __be32 *p; |
887 | 887 | ||
888 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", | 888 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", |
889 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 889 | task->tk_pid, task->tk_msg.rpc_proc->p_name, |
890 | rpcb->r_prog, rpcb->r_vers, | 890 | rpcb->r_prog, rpcb->r_vers, |
891 | rpcb->r_netid, rpcb->r_addr); | 891 | rpcb->r_netid, rpcb->r_addr); |
892 | 892 | ||
893 | p = xdr_reserve_space(xdr, (RPCB_program_sz + RPCB_version_sz) << 2); | 893 | p = xdr_reserve_space(xdr, (RPCB_program_sz + RPCB_version_sz) << 2); |
894 | *p++ = cpu_to_be32(rpcb->r_prog); | 894 | *p++ = cpu_to_be32(rpcb->r_prog); |
895 | *p = cpu_to_be32(rpcb->r_vers); | 895 | *p = cpu_to_be32(rpcb->r_vers); |
896 | 896 | ||
897 | encode_rpcb_string(xdr, rpcb->r_netid, RPCBIND_MAXNETIDLEN); | 897 | encode_rpcb_string(xdr, rpcb->r_netid, RPCBIND_MAXNETIDLEN); |
898 | encode_rpcb_string(xdr, rpcb->r_addr, RPCBIND_MAXUADDRLEN); | 898 | encode_rpcb_string(xdr, rpcb->r_addr, RPCBIND_MAXUADDRLEN); |
899 | encode_rpcb_string(xdr, rpcb->r_owner, RPCB_MAXOWNERLEN); | 899 | encode_rpcb_string(xdr, rpcb->r_owner, RPCB_MAXOWNERLEN); |
900 | } | 900 | } |
901 | 901 | ||
902 | static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | 902 | static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, |
903 | struct rpcbind_args *rpcb) | 903 | struct rpcbind_args *rpcb) |
904 | { | 904 | { |
905 | struct sockaddr_storage address; | 905 | struct sockaddr_storage address; |
906 | struct sockaddr *sap = (struct sockaddr *)&address; | 906 | struct sockaddr *sap = (struct sockaddr *)&address; |
907 | struct rpc_task *task = req->rq_task; | 907 | struct rpc_task *task = req->rq_task; |
908 | __be32 *p; | 908 | __be32 *p; |
909 | u32 len; | 909 | u32 len; |
910 | 910 | ||
911 | rpcb->r_port = 0; | 911 | rpcb->r_port = 0; |
912 | 912 | ||
913 | p = xdr_inline_decode(xdr, 4); | 913 | p = xdr_inline_decode(xdr, 4); |
914 | if (unlikely(p == NULL)) | 914 | if (unlikely(p == NULL)) |
915 | goto out_fail; | 915 | goto out_fail; |
916 | len = be32_to_cpup(p); | 916 | len = be32_to_cpup(p); |
917 | 917 | ||
918 | /* | 918 | /* |
919 | * If the returned universal address is a null string, | 919 | * If the returned universal address is a null string, |
920 | * the requested RPC service was not registered. | 920 | * the requested RPC service was not registered. |
921 | */ | 921 | */ |
922 | if (len == 0) { | 922 | if (len == 0) { |
923 | dprintk("RPC: %5u RPCB reply: program not registered\n", | 923 | dprintk("RPC: %5u RPCB reply: program not registered\n", |
924 | task->tk_pid); | 924 | task->tk_pid); |
925 | return 0; | 925 | return 0; |
926 | } | 926 | } |
927 | 927 | ||
928 | if (unlikely(len > RPCBIND_MAXUADDRLEN)) | 928 | if (unlikely(len > RPCBIND_MAXUADDRLEN)) |
929 | goto out_fail; | 929 | goto out_fail; |
930 | 930 | ||
931 | p = xdr_inline_decode(xdr, len); | 931 | p = xdr_inline_decode(xdr, len); |
932 | if (unlikely(p == NULL)) | 932 | if (unlikely(p == NULL)) |
933 | goto out_fail; | 933 | goto out_fail; |
934 | dprintk("RPC: %5u RPCB_%s reply: %s\n", task->tk_pid, | 934 | dprintk("RPC: %5u RPCB_%s reply: %s\n", task->tk_pid, |
935 | task->tk_msg.rpc_proc->p_name, (char *)p); | 935 | task->tk_msg.rpc_proc->p_name, (char *)p); |
936 | 936 | ||
937 | if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len, | 937 | if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len, |
938 | sap, sizeof(address)) == 0) | 938 | sap, sizeof(address)) == 0) |
939 | goto out_fail; | 939 | goto out_fail; |
940 | rpcb->r_port = rpc_get_port(sap); | 940 | rpcb->r_port = rpc_get_port(sap); |
941 | 941 | ||
942 | return 0; | 942 | return 0; |
943 | 943 | ||
944 | out_fail: | 944 | out_fail: |
945 | dprintk("RPC: %5u malformed RPCB_%s reply\n", | 945 | dprintk("RPC: %5u malformed RPCB_%s reply\n", |
946 | task->tk_pid, task->tk_msg.rpc_proc->p_name); | 946 | task->tk_pid, task->tk_msg.rpc_proc->p_name); |
947 | return -EIO; | 947 | return -EIO; |
948 | } | 948 | } |
949 | 949 | ||
950 | /* | 950 | /* |
951 | * Not all rpcbind procedures described in RFC 1833 are implemented | 951 | * Not all rpcbind procedures described in RFC 1833 are implemented |
952 | * since the Linux kernel RPC code requires only these. | 952 | * since the Linux kernel RPC code requires only these. |
953 | */ | 953 | */ |
954 | 954 | ||
955 | static struct rpc_procinfo rpcb_procedures2[] = { | 955 | static struct rpc_procinfo rpcb_procedures2[] = { |
956 | [RPCBPROC_SET] = { | 956 | [RPCBPROC_SET] = { |
957 | .p_proc = RPCBPROC_SET, | 957 | .p_proc = RPCBPROC_SET, |
958 | .p_encode = (kxdreproc_t)rpcb_enc_mapping, | 958 | .p_encode = (kxdreproc_t)rpcb_enc_mapping, |
959 | .p_decode = (kxdrdproc_t)rpcb_dec_set, | 959 | .p_decode = (kxdrdproc_t)rpcb_dec_set, |
960 | .p_arglen = RPCB_mappingargs_sz, | 960 | .p_arglen = RPCB_mappingargs_sz, |
961 | .p_replen = RPCB_setres_sz, | 961 | .p_replen = RPCB_setres_sz, |
962 | .p_statidx = RPCBPROC_SET, | 962 | .p_statidx = RPCBPROC_SET, |
963 | .p_timer = 0, | 963 | .p_timer = 0, |
964 | .p_name = "SET", | 964 | .p_name = "SET", |
965 | }, | 965 | }, |
966 | [RPCBPROC_UNSET] = { | 966 | [RPCBPROC_UNSET] = { |
967 | .p_proc = RPCBPROC_UNSET, | 967 | .p_proc = RPCBPROC_UNSET, |
968 | .p_encode = (kxdreproc_t)rpcb_enc_mapping, | 968 | .p_encode = (kxdreproc_t)rpcb_enc_mapping, |
969 | .p_decode = (kxdrdproc_t)rpcb_dec_set, | 969 | .p_decode = (kxdrdproc_t)rpcb_dec_set, |
970 | .p_arglen = RPCB_mappingargs_sz, | 970 | .p_arglen = RPCB_mappingargs_sz, |
971 | .p_replen = RPCB_setres_sz, | 971 | .p_replen = RPCB_setres_sz, |
972 | .p_statidx = RPCBPROC_UNSET, | 972 | .p_statidx = RPCBPROC_UNSET, |
973 | .p_timer = 0, | 973 | .p_timer = 0, |
974 | .p_name = "UNSET", | 974 | .p_name = "UNSET", |
975 | }, | 975 | }, |
976 | [RPCBPROC_GETPORT] = { | 976 | [RPCBPROC_GETPORT] = { |
977 | .p_proc = RPCBPROC_GETPORT, | 977 | .p_proc = RPCBPROC_GETPORT, |
978 | .p_encode = (kxdreproc_t)rpcb_enc_mapping, | 978 | .p_encode = (kxdreproc_t)rpcb_enc_mapping, |
979 | .p_decode = (kxdrdproc_t)rpcb_dec_getport, | 979 | .p_decode = (kxdrdproc_t)rpcb_dec_getport, |
980 | .p_arglen = RPCB_mappingargs_sz, | 980 | .p_arglen = RPCB_mappingargs_sz, |
981 | .p_replen = RPCB_getportres_sz, | 981 | .p_replen = RPCB_getportres_sz, |
982 | .p_statidx = RPCBPROC_GETPORT, | 982 | .p_statidx = RPCBPROC_GETPORT, |
983 | .p_timer = 0, | 983 | .p_timer = 0, |
984 | .p_name = "GETPORT", | 984 | .p_name = "GETPORT", |
985 | }, | 985 | }, |
986 | }; | 986 | }; |
987 | 987 | ||
988 | static struct rpc_procinfo rpcb_procedures3[] = { | 988 | static struct rpc_procinfo rpcb_procedures3[] = { |
989 | [RPCBPROC_SET] = { | 989 | [RPCBPROC_SET] = { |
990 | .p_proc = RPCBPROC_SET, | 990 | .p_proc = RPCBPROC_SET, |
991 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, | 991 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, |
992 | .p_decode = (kxdrdproc_t)rpcb_dec_set, | 992 | .p_decode = (kxdrdproc_t)rpcb_dec_set, |
993 | .p_arglen = RPCB_getaddrargs_sz, | 993 | .p_arglen = RPCB_getaddrargs_sz, |
994 | .p_replen = RPCB_setres_sz, | 994 | .p_replen = RPCB_setres_sz, |
995 | .p_statidx = RPCBPROC_SET, | 995 | .p_statidx = RPCBPROC_SET, |
996 | .p_timer = 0, | 996 | .p_timer = 0, |
997 | .p_name = "SET", | 997 | .p_name = "SET", |
998 | }, | 998 | }, |
999 | [RPCBPROC_UNSET] = { | 999 | [RPCBPROC_UNSET] = { |
1000 | .p_proc = RPCBPROC_UNSET, | 1000 | .p_proc = RPCBPROC_UNSET, |
1001 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, | 1001 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, |
1002 | .p_decode = (kxdrdproc_t)rpcb_dec_set, | 1002 | .p_decode = (kxdrdproc_t)rpcb_dec_set, |
1003 | .p_arglen = RPCB_getaddrargs_sz, | 1003 | .p_arglen = RPCB_getaddrargs_sz, |
1004 | .p_replen = RPCB_setres_sz, | 1004 | .p_replen = RPCB_setres_sz, |
1005 | .p_statidx = RPCBPROC_UNSET, | 1005 | .p_statidx = RPCBPROC_UNSET, |
1006 | .p_timer = 0, | 1006 | .p_timer = 0, |
1007 | .p_name = "UNSET", | 1007 | .p_name = "UNSET", |
1008 | }, | 1008 | }, |
1009 | [RPCBPROC_GETADDR] = { | 1009 | [RPCBPROC_GETADDR] = { |
1010 | .p_proc = RPCBPROC_GETADDR, | 1010 | .p_proc = RPCBPROC_GETADDR, |
1011 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, | 1011 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, |
1012 | .p_decode = (kxdrdproc_t)rpcb_dec_getaddr, | 1012 | .p_decode = (kxdrdproc_t)rpcb_dec_getaddr, |
1013 | .p_arglen = RPCB_getaddrargs_sz, | 1013 | .p_arglen = RPCB_getaddrargs_sz, |
1014 | .p_replen = RPCB_getaddrres_sz, | 1014 | .p_replen = RPCB_getaddrres_sz, |
1015 | .p_statidx = RPCBPROC_GETADDR, | 1015 | .p_statidx = RPCBPROC_GETADDR, |
1016 | .p_timer = 0, | 1016 | .p_timer = 0, |
1017 | .p_name = "GETADDR", | 1017 | .p_name = "GETADDR", |
1018 | }, | 1018 | }, |
1019 | }; | 1019 | }; |
1020 | 1020 | ||
1021 | static struct rpc_procinfo rpcb_procedures4[] = { | 1021 | static struct rpc_procinfo rpcb_procedures4[] = { |
1022 | [RPCBPROC_SET] = { | 1022 | [RPCBPROC_SET] = { |
1023 | .p_proc = RPCBPROC_SET, | 1023 | .p_proc = RPCBPROC_SET, |
1024 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, | 1024 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, |
1025 | .p_decode = (kxdrdproc_t)rpcb_dec_set, | 1025 | .p_decode = (kxdrdproc_t)rpcb_dec_set, |
1026 | .p_arglen = RPCB_getaddrargs_sz, | 1026 | .p_arglen = RPCB_getaddrargs_sz, |
1027 | .p_replen = RPCB_setres_sz, | 1027 | .p_replen = RPCB_setres_sz, |
1028 | .p_statidx = RPCBPROC_SET, | 1028 | .p_statidx = RPCBPROC_SET, |
1029 | .p_timer = 0, | 1029 | .p_timer = 0, |
1030 | .p_name = "SET", | 1030 | .p_name = "SET", |
1031 | }, | 1031 | }, |
1032 | [RPCBPROC_UNSET] = { | 1032 | [RPCBPROC_UNSET] = { |
1033 | .p_proc = RPCBPROC_UNSET, | 1033 | .p_proc = RPCBPROC_UNSET, |
1034 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, | 1034 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, |
1035 | .p_decode = (kxdrdproc_t)rpcb_dec_set, | 1035 | .p_decode = (kxdrdproc_t)rpcb_dec_set, |
1036 | .p_arglen = RPCB_getaddrargs_sz, | 1036 | .p_arglen = RPCB_getaddrargs_sz, |
1037 | .p_replen = RPCB_setres_sz, | 1037 | .p_replen = RPCB_setres_sz, |
1038 | .p_statidx = RPCBPROC_UNSET, | 1038 | .p_statidx = RPCBPROC_UNSET, |
1039 | .p_timer = 0, | 1039 | .p_timer = 0, |
1040 | .p_name = "UNSET", | 1040 | .p_name = "UNSET", |
1041 | }, | 1041 | }, |
1042 | [RPCBPROC_GETADDR] = { | 1042 | [RPCBPROC_GETADDR] = { |
1043 | .p_proc = RPCBPROC_GETADDR, | 1043 | .p_proc = RPCBPROC_GETADDR, |
1044 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, | 1044 | .p_encode = (kxdreproc_t)rpcb_enc_getaddr, |
1045 | .p_decode = (kxdrdproc_t)rpcb_dec_getaddr, | 1045 | .p_decode = (kxdrdproc_t)rpcb_dec_getaddr, |
1046 | .p_arglen = RPCB_getaddrargs_sz, | 1046 | .p_arglen = RPCB_getaddrargs_sz, |
1047 | .p_replen = RPCB_getaddrres_sz, | 1047 | .p_replen = RPCB_getaddrres_sz, |
1048 | .p_statidx = RPCBPROC_GETADDR, | 1048 | .p_statidx = RPCBPROC_GETADDR, |
1049 | .p_timer = 0, | 1049 | .p_timer = 0, |
1050 | .p_name = "GETADDR", | 1050 | .p_name = "GETADDR", |
1051 | }, | 1051 | }, |
1052 | }; | 1052 | }; |
1053 | 1053 | ||
1054 | static struct rpcb_info rpcb_next_version[] = { | 1054 | static const struct rpcb_info rpcb_next_version[] = { |
1055 | { | 1055 | { |
1056 | .rpc_vers = RPCBVERS_2, | 1056 | .rpc_vers = RPCBVERS_2, |
1057 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], | 1057 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], |
1058 | }, | 1058 | }, |
1059 | { | 1059 | { |
1060 | .rpc_proc = NULL, | 1060 | .rpc_proc = NULL, |
1061 | }, | 1061 | }, |
1062 | }; | 1062 | }; |
1063 | 1063 | ||
1064 | static struct rpcb_info rpcb_next_version6[] = { | 1064 | static const struct rpcb_info rpcb_next_version6[] = { |
1065 | { | 1065 | { |
1066 | .rpc_vers = RPCBVERS_4, | 1066 | .rpc_vers = RPCBVERS_4, |
1067 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], | 1067 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], |
1068 | }, | 1068 | }, |
1069 | { | 1069 | { |
1070 | .rpc_vers = RPCBVERS_3, | 1070 | .rpc_vers = RPCBVERS_3, |
1071 | .rpc_proc = &rpcb_procedures3[RPCBPROC_GETADDR], | 1071 | .rpc_proc = &rpcb_procedures3[RPCBPROC_GETADDR], |
1072 | }, | 1072 | }, |
1073 | { | 1073 | { |
1074 | .rpc_proc = NULL, | 1074 | .rpc_proc = NULL, |
1075 | }, | 1075 | }, |
1076 | }; | 1076 | }; |
1077 | 1077 | ||
1078 | static struct rpc_version rpcb_version2 = { | 1078 | static const struct rpc_version rpcb_version2 = { |
1079 | .number = RPCBVERS_2, | 1079 | .number = RPCBVERS_2, |
1080 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), | 1080 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), |
1081 | .procs = rpcb_procedures2 | 1081 | .procs = rpcb_procedures2 |
1082 | }; | 1082 | }; |
1083 | 1083 | ||
1084 | static struct rpc_version rpcb_version3 = { | 1084 | static const struct rpc_version rpcb_version3 = { |
1085 | .number = RPCBVERS_3, | 1085 | .number = RPCBVERS_3, |
1086 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), | 1086 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), |
1087 | .procs = rpcb_procedures3 | 1087 | .procs = rpcb_procedures3 |
1088 | }; | 1088 | }; |
1089 | 1089 | ||
1090 | static struct rpc_version rpcb_version4 = { | 1090 | static const struct rpc_version rpcb_version4 = { |
1091 | .number = RPCBVERS_4, | 1091 | .number = RPCBVERS_4, |
1092 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), | 1092 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), |
1093 | .procs = rpcb_procedures4 | 1093 | .procs = rpcb_procedures4 |
1094 | }; | 1094 | }; |
1095 | 1095 | ||
1096 | static struct rpc_version *rpcb_version[] = { | 1096 | static const struct rpc_version *rpcb_version[] = { |
1097 | NULL, | 1097 | NULL, |
1098 | NULL, | 1098 | NULL, |
1099 | &rpcb_version2, | 1099 | &rpcb_version2, |
1100 | &rpcb_version3, | 1100 | &rpcb_version3, |
1101 | &rpcb_version4 | 1101 | &rpcb_version4 |
1102 | }; | 1102 | }; |
1103 | 1103 | ||
1104 | static struct rpc_stat rpcb_stats; | 1104 | static struct rpc_stat rpcb_stats; |
1105 | 1105 | ||
1106 | static struct rpc_program rpcb_program = { | 1106 | static const struct rpc_program rpcb_program = { |
1107 | .name = "rpcbind", | 1107 | .name = "rpcbind", |
1108 | .number = RPCBIND_PROGRAM, | 1108 | .number = RPCBIND_PROGRAM, |
1109 | .nrvers = ARRAY_SIZE(rpcb_version), | 1109 | .nrvers = ARRAY_SIZE(rpcb_version), |
1110 | .version = rpcb_version, | 1110 | .version = rpcb_version, |
1111 | .stats = &rpcb_stats, | 1111 | .stats = &rpcb_stats, |
1112 | }; | 1112 | }; |
1113 | 1113 |