Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSD: Update XDR encoders in NFSv4 callback client

Clean up.

Remove old-style NFSv4 XDR macros in favor of the style now used in
fs/nfs/nfs4xdr.c. These were forgotten during the recent nfs4xdr.c
rewrite.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

authored by

Chuck Lever and committed by
Trond Myklebust
a033db48 3460f29a

+177 -76
+177 -76
fs/nfsd/nfs4callback.c
··· 50 50 NFSPROC4_CLNT_CB_SEQUENCE, 51 51 }; 52 52 53 - enum nfs_cb_opnum4 { 54 - OP_CB_RECALL = 4, 55 - OP_CB_SEQUENCE = 11, 56 - }; 57 - 58 53 #define NFS4_MAXTAGLEN 20 59 54 60 55 #define NFS4_enc_cb_null_sz 0 ··· 73 78 #define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \ 74 79 cb_sequence_dec_sz + \ 75 80 op_dec_sz) 76 - 77 - /* 78 - * Generic encode routines from fs/nfs/nfs4xdr.c 79 - */ 80 - static inline __be32 * 81 - xdr_writemem(__be32 *p, const void *ptr, int nbytes) 82 - { 83 - int tmp = XDR_QUADLEN(nbytes); 84 - if (!tmp) 85 - return p; 86 - p[tmp-1] = 0; 87 - memcpy(p, ptr, nbytes); 88 - return p + tmp; 89 - } 90 - 91 - #define WRITE32(n) *p++ = htonl(n) 92 - #define WRITEMEM(ptr,nbytes) do { \ 93 - p = xdr_writemem(p, ptr, nbytes); \ 94 - } while (0) 95 - #define RESERVE_SPACE(nbytes) do { \ 96 - p = xdr_reserve_space(xdr, nbytes); \ 97 - if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __func__); \ 98 - BUG_ON(!p); \ 99 - } while (0) 100 81 101 82 /* 102 83 * Generic decode routines from fs/nfs/nfs4xdr.c ··· 168 197 return stat; 169 198 } 170 199 200 + static __be32 *xdr_encode_empty_array(__be32 *p) 201 + { 202 + *p++ = xdr_zero; 203 + return p; 204 + } 205 + 171 206 /* 172 - * XDR encode 207 + * Encode/decode NFSv4 CB basic data types 208 + * 209 + * Basic NFSv4 callback data types are defined in section 15 of RFC 210 + * 3530: "Network File System (NFS) version 4 Protocol" and section 211 + * 20 of RFC 5661: "Network File System (NFS) Version 4 Minor Version 212 + * 1 Protocol" 173 213 */ 174 214 175 - static void 176 - encode_stateid(struct xdr_stream *xdr, stateid_t *sid) 215 + /* 216 + * nfs_cb_opnum4 217 + * 218 + * enum nfs_cb_opnum4 { 219 + * OP_CB_GETATTR = 3, 220 + * ... 221 + * }; 222 + */ 223 + enum nfs_cb_opnum4 { 224 + OP_CB_GETATTR = 3, 225 + OP_CB_RECALL = 4, 226 + OP_CB_LAYOUTRECALL = 5, 227 + OP_CB_NOTIFY = 6, 228 + OP_CB_PUSH_DELEG = 7, 229 + OP_CB_RECALL_ANY = 8, 230 + OP_CB_RECALLABLE_OBJ_AVAIL = 9, 231 + OP_CB_RECALL_SLOT = 10, 232 + OP_CB_SEQUENCE = 11, 233 + OP_CB_WANTS_CANCELLED = 12, 234 + OP_CB_NOTIFY_LOCK = 13, 235 + OP_CB_NOTIFY_DEVICEID = 14, 236 + OP_CB_ILLEGAL = 10044 237 + }; 238 + 239 + static void encode_nfs_cb_opnum4(struct xdr_stream *xdr, enum nfs_cb_opnum4 op) 177 240 { 178 241 __be32 *p; 179 242 180 - RESERVE_SPACE(sizeof(stateid_t)); 181 - WRITE32(sid->si_generation); 182 - WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); 243 + p = xdr_reserve_space(xdr, 4); 244 + *p = cpu_to_be32(op); 183 245 } 184 246 185 - static void 186 - encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) 247 + /* 248 + * nfs_fh4 249 + * 250 + * typedef opaque nfs_fh4<NFS4_FHSIZE>; 251 + */ 252 + static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh) 253 + { 254 + u32 length = fh->fh_size; 255 + __be32 *p; 256 + 257 + BUG_ON(length > NFS4_FHSIZE); 258 + p = xdr_reserve_space(xdr, 4 + length); 259 + xdr_encode_opaque(p, &fh->fh_base, length); 260 + } 261 + 262 + /* 263 + * stateid4 264 + * 265 + * struct stateid4 { 266 + * uint32_t seqid; 267 + * opaque other[12]; 268 + * }; 269 + */ 270 + static void encode_stateid4(struct xdr_stream *xdr, const stateid_t *sid) 271 + { 272 + __be32 *p; 273 + 274 + p = xdr_reserve_space(xdr, NFS4_STATEID_SIZE); 275 + *p++ = cpu_to_be32(sid->si_generation); 276 + xdr_encode_opaque_fixed(p, &sid->si_opaque, NFS4_STATEID_OTHER_SIZE); 277 + } 278 + 279 + /* 280 + * sessionid4 281 + * 282 + * typedef opaque sessionid4[NFS4_SESSIONID_SIZE]; 283 + */ 284 + static void encode_sessionid4(struct xdr_stream *xdr, 285 + const struct nfsd4_session *session) 286 + { 287 + __be32 *p; 288 + 289 + p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN); 290 + xdr_encode_opaque_fixed(p, session->se_sessionid.data, 291 + NFS4_MAX_SESSIONID_LEN); 292 + } 293 + 294 + /* 295 + * CB_COMPOUND4args 296 + * 297 + * struct CB_COMPOUND4args { 298 + * utf8str_cs tag; 299 + * uint32_t minorversion; 300 + * uint32_t callback_ident; 301 + * nfs_cb_argop4 argarray<>; 302 + * }; 303 + */ 304 + static void encode_cb_compound4args(struct xdr_stream *xdr, 305 + struct nfs4_cb_compound_hdr *hdr) 187 306 { 188 307 __be32 * p; 189 308 190 - RESERVE_SPACE(16); 191 - WRITE32(0); /* tag length is always 0 */ 192 - WRITE32(hdr->minorversion); 193 - WRITE32(hdr->ident); 309 + p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4); 310 + p = xdr_encode_empty_array(p); /* empty tag */ 311 + *p++ = cpu_to_be32(hdr->minorversion); 312 + *p++ = cpu_to_be32(hdr->ident); 313 + 194 314 hdr->nops_p = p; 195 - WRITE32(hdr->nops); 315 + *p = cpu_to_be32(hdr->nops); /* argarray element count */ 196 316 } 197 317 318 + /* 319 + * Update argarray element count 320 + */ 198 321 static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr) 199 322 { 200 - *hdr->nops_p = htonl(hdr->nops); 323 + BUG_ON(hdr->nops > NFS4_MAX_BACK_CHANNEL_OPS); 324 + *hdr->nops_p = cpu_to_be32(hdr->nops); 201 325 } 202 326 203 - static void 204 - encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp, 205 - struct nfs4_cb_compound_hdr *hdr) 327 + /* 328 + * CB_RECALL4args 329 + * 330 + * struct CB_RECALL4args { 331 + * stateid4 stateid; 332 + * bool truncate; 333 + * nfs_fh4 fh; 334 + * }; 335 + */ 336 + static void encode_cb_recall4args(struct xdr_stream *xdr, 337 + const struct nfs4_delegation *dp, 338 + struct nfs4_cb_compound_hdr *hdr) 206 339 { 207 340 __be32 *p; 208 - int len = dp->dl_fh.fh_size; 209 341 210 - RESERVE_SPACE(4); 211 - WRITE32(OP_CB_RECALL); 212 - encode_stateid(xdr, &dp->dl_stateid); 213 - RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2)); 214 - WRITE32(0); /* truncate optimization not implemented */ 215 - WRITE32(len); 216 - WRITEMEM(&dp->dl_fh.fh_base, len); 342 + encode_nfs_cb_opnum4(xdr, OP_CB_RECALL); 343 + encode_stateid4(xdr, &dp->dl_stateid); 344 + 345 + p = xdr_reserve_space(xdr, 4); 346 + *p++ = xdr_zero; /* truncate */ 347 + 348 + encode_nfs_fh4(xdr, &dp->dl_fh); 349 + 217 350 hdr->nops++; 218 351 } 219 352 220 - static void 221 - encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb, 222 - struct nfs4_cb_compound_hdr *hdr) 353 + /* 354 + * CB_SEQUENCE4args 355 + * 356 + * struct CB_SEQUENCE4args { 357 + * sessionid4 csa_sessionid; 358 + * sequenceid4 csa_sequenceid; 359 + * slotid4 csa_slotid; 360 + * slotid4 csa_highest_slotid; 361 + * bool csa_cachethis; 362 + * referring_call_list4 csa_referring_call_lists<>; 363 + * }; 364 + */ 365 + static void encode_cb_sequence4args(struct xdr_stream *xdr, 366 + const struct nfsd4_callback *cb, 367 + struct nfs4_cb_compound_hdr *hdr) 223 368 { 369 + struct nfsd4_session *session = cb->cb_clp->cl_cb_session; 224 370 __be32 *p; 225 - struct nfsd4_session *ses = cb->cb_clp->cl_cb_session; 226 371 227 372 if (hdr->minorversion == 0) 228 373 return; 229 374 230 - RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20); 375 + encode_nfs_cb_opnum4(xdr, OP_CB_SEQUENCE); 376 + encode_sessionid4(xdr, session); 231 377 232 - WRITE32(OP_CB_SEQUENCE); 233 - WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN); 234 - WRITE32(ses->se_cb_seq_nr); 235 - WRITE32(0); /* slotid, always 0 */ 236 - WRITE32(0); /* highest slotid always 0 */ 237 - WRITE32(0); /* cachethis always 0 */ 238 - WRITE32(0); /* FIXME: support referring_call_lists */ 378 + p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4 + 4); 379 + *p++ = cpu_to_be32(session->se_cb_seq_nr); /* csa_sequenceid */ 380 + *p++ = xdr_zero; /* csa_slotid */ 381 + *p++ = xdr_zero; /* csa_highest_slotid */ 382 + *p++ = xdr_zero; /* csa_cachethis */ 383 + xdr_encode_empty_array(p); /* csa_referring_call_lists */ 384 + 239 385 hdr->nops++; 240 386 } 241 387 242 - static int 243 - nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p) 388 + /* 389 + * NFSv4.0 and NFSv4.1 XDR encode functions 390 + * 391 + * NFSv4.0 callback argument types are defined in section 15 of RFC 392 + * 3530: "Network File System (NFS) version 4 Protocol" and section 20 393 + * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1 394 + * Protocol". 395 + */ 396 + 397 + /* 398 + * NB: Without this zero space reservation, callbacks over krb5p fail 399 + */ 400 + static int nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p, void *__unused) 244 401 { 245 402 struct xdr_stream xdrs, *xdr = &xdrs; 246 403 247 404 xdr_init_encode(&xdrs, &req->rq_snd_buf, p); 248 - RESERVE_SPACE(0); 405 + xdr_reserve_space(xdr, 0); 249 406 return 0; 250 407 } 251 408 252 - static int 253 - nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, 254 - struct nfsd4_callback *cb) 409 + /* 410 + * 20.2. Operation 4: CB_RECALL - Recall a Delegation 411 + */ 412 + static int nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, 413 + const struct nfsd4_callback *cb) 255 414 { 256 415 struct xdr_stream xdr; 257 - struct nfs4_delegation *args = cb->cb_op; 416 + const struct nfs4_delegation *args = cb->cb_op; 258 417 struct nfs4_cb_compound_hdr hdr = { 259 418 .ident = cb->cb_clp->cl_cb_ident, 260 419 .minorversion = cb->cb_minorversion, 261 420 }; 262 421 263 422 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 264 - encode_cb_compound_hdr(&xdr, &hdr); 265 - encode_cb_sequence(&xdr, cb, &hdr); 266 - encode_cb_recall(&xdr, args, &hdr); 423 + encode_cb_compound4args(&xdr, &hdr); 424 + encode_cb_sequence4args(&xdr, cb, &hdr); 425 + encode_cb_recall4args(&xdr, args, &hdr); 267 426 encode_cb_nops(&hdr); 268 427 return 0; 269 428 }