162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/lockd/clnt4xdr.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * XDR functions to encode/decode NLM version 4 RPC arguments and results. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * NLM client-side only. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Copyright (C) 2010, Oracle. All rights reserved. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/types.h> 1362306a36Sopenharmony_ci#include <linux/sunrpc/xdr.h> 1462306a36Sopenharmony_ci#include <linux/sunrpc/clnt.h> 1562306a36Sopenharmony_ci#include <linux/sunrpc/stats.h> 1662306a36Sopenharmony_ci#include <linux/lockd/lockd.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <uapi/linux/nfs3.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define NLMDBG_FACILITY NLMDBG_XDR 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) 2362306a36Sopenharmony_ci# error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" 2462306a36Sopenharmony_ci#endif 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) 2762306a36Sopenharmony_ci# error "NLM host name cannot be larger than NLM's maximum string length!" 2862306a36Sopenharmony_ci#endif 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * Declare the space requirements for NLM arguments and replies as 3262306a36Sopenharmony_ci * number of 32bit-words 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci#define NLM4_void_sz (0) 3562306a36Sopenharmony_ci#define NLM4_cookie_sz (1+(NLM_MAXCOOKIELEN>>2)) 3662306a36Sopenharmony_ci#define NLM4_caller_sz (1+(NLMCLNT_OHSIZE>>2)) 3762306a36Sopenharmony_ci#define NLM4_owner_sz (1+(NLMCLNT_OHSIZE>>2)) 3862306a36Sopenharmony_ci#define NLM4_fhandle_sz (1+(NFS3_FHSIZE>>2)) 3962306a36Sopenharmony_ci#define NLM4_lock_sz (5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz) 4062306a36Sopenharmony_ci#define NLM4_holder_sz (6+NLM4_owner_sz) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define NLM4_testargs_sz (NLM4_cookie_sz+1+NLM4_lock_sz) 4362306a36Sopenharmony_ci#define NLM4_lockargs_sz (NLM4_cookie_sz+4+NLM4_lock_sz) 4462306a36Sopenharmony_ci#define NLM4_cancargs_sz (NLM4_cookie_sz+2+NLM4_lock_sz) 4562306a36Sopenharmony_ci#define NLM4_unlockargs_sz (NLM4_cookie_sz+NLM4_lock_sz) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define NLM4_testres_sz (NLM4_cookie_sz+1+NLM4_holder_sz) 4862306a36Sopenharmony_ci#define NLM4_res_sz (NLM4_cookie_sz+1) 4962306a36Sopenharmony_ci#define NLM4_norep_sz (0) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic s64 loff_t_to_s64(loff_t offset) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci s64 res; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (offset >= NLM4_OFFSET_MAX) 5762306a36Sopenharmony_ci res = NLM4_OFFSET_MAX; 5862306a36Sopenharmony_ci else if (offset <= -NLM4_OFFSET_MAX) 5962306a36Sopenharmony_ci res = -NLM4_OFFSET_MAX; 6062306a36Sopenharmony_ci else 6162306a36Sopenharmony_ci res = offset; 6262306a36Sopenharmony_ci return res; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic void nlm4_compute_offsets(const struct nlm_lock *lock, 6662306a36Sopenharmony_ci u64 *l_offset, u64 *l_len) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci const struct file_lock *fl = &lock->fl; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci *l_offset = loff_t_to_s64(fl->fl_start); 7162306a36Sopenharmony_ci if (fl->fl_end == OFFSET_MAX) 7262306a36Sopenharmony_ci *l_len = 0; 7362306a36Sopenharmony_ci else 7462306a36Sopenharmony_ci *l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* 7862306a36Sopenharmony_ci * Encode/decode NLMv4 basic data types 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci * Basic NLMv4 data types are defined in Appendix II, section 6.1.4 8162306a36Sopenharmony_ci * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter 8262306a36Sopenharmony_ci * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W". 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * Not all basic data types have their own encoding and decoding 8562306a36Sopenharmony_ci * functions. For run-time efficiency, some data types are encoded 8662306a36Sopenharmony_ci * or decoded inline. 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void encode_bool(struct xdr_stream *xdr, const int value) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci __be32 *p; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 9462306a36Sopenharmony_ci *p = value ? xdr_one : xdr_zero; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void encode_int32(struct xdr_stream *xdr, const s32 value) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci __be32 *p; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 10262306a36Sopenharmony_ci *p = cpu_to_be32(value); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* 10662306a36Sopenharmony_ci * typedef opaque netobj<MAXNETOBJ_SZ> 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_cistatic void encode_netobj(struct xdr_stream *xdr, 10962306a36Sopenharmony_ci const u8 *data, const unsigned int length) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci __be32 *p; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci p = xdr_reserve_space(xdr, 4 + length); 11462306a36Sopenharmony_ci xdr_encode_opaque(p, data, length); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic int decode_netobj(struct xdr_stream *xdr, 11862306a36Sopenharmony_ci struct xdr_netobj *obj) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci ssize_t ret; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data, 12362306a36Sopenharmony_ci XDR_MAX_NETOBJ); 12462306a36Sopenharmony_ci if (unlikely(ret < 0)) 12562306a36Sopenharmony_ci return -EIO; 12662306a36Sopenharmony_ci obj->len = ret; 12762306a36Sopenharmony_ci return 0; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* 13162306a36Sopenharmony_ci * netobj cookie; 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_cistatic void encode_cookie(struct xdr_stream *xdr, 13462306a36Sopenharmony_ci const struct nlm_cookie *cookie) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic int decode_cookie(struct xdr_stream *xdr, 14062306a36Sopenharmony_ci struct nlm_cookie *cookie) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci u32 length; 14362306a36Sopenharmony_ci __be32 *p; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 14662306a36Sopenharmony_ci if (unlikely(p == NULL)) 14762306a36Sopenharmony_ci goto out_overflow; 14862306a36Sopenharmony_ci length = be32_to_cpup(p++); 14962306a36Sopenharmony_ci /* apparently HPUX can return empty cookies */ 15062306a36Sopenharmony_ci if (length == 0) 15162306a36Sopenharmony_ci goto out_hpux; 15262306a36Sopenharmony_ci if (length > NLM_MAXCOOKIELEN) 15362306a36Sopenharmony_ci goto out_size; 15462306a36Sopenharmony_ci p = xdr_inline_decode(xdr, length); 15562306a36Sopenharmony_ci if (unlikely(p == NULL)) 15662306a36Sopenharmony_ci goto out_overflow; 15762306a36Sopenharmony_ci cookie->len = length; 15862306a36Sopenharmony_ci memcpy(cookie->data, p, length); 15962306a36Sopenharmony_ci return 0; 16062306a36Sopenharmony_ciout_hpux: 16162306a36Sopenharmony_ci cookie->len = 4; 16262306a36Sopenharmony_ci memset(cookie->data, 0, 4); 16362306a36Sopenharmony_ci return 0; 16462306a36Sopenharmony_ciout_size: 16562306a36Sopenharmony_ci dprintk("NFS: returned cookie was too long: %u\n", length); 16662306a36Sopenharmony_ci return -EIO; 16762306a36Sopenharmony_ciout_overflow: 16862306a36Sopenharmony_ci return -EIO; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci/* 17262306a36Sopenharmony_ci * netobj fh; 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_cistatic void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci encode_netobj(xdr, (u8 *)&fh->data, fh->size); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* 18062306a36Sopenharmony_ci * enum nlm4_stats { 18162306a36Sopenharmony_ci * NLM4_GRANTED = 0, 18262306a36Sopenharmony_ci * NLM4_DENIED = 1, 18362306a36Sopenharmony_ci * NLM4_DENIED_NOLOCKS = 2, 18462306a36Sopenharmony_ci * NLM4_BLOCKED = 3, 18562306a36Sopenharmony_ci * NLM4_DENIED_GRACE_PERIOD = 4, 18662306a36Sopenharmony_ci * NLM4_DEADLCK = 5, 18762306a36Sopenharmony_ci * NLM4_ROFS = 6, 18862306a36Sopenharmony_ci * NLM4_STALE_FH = 7, 18962306a36Sopenharmony_ci * NLM4_FBIG = 8, 19062306a36Sopenharmony_ci * NLM4_FAILED = 9 19162306a36Sopenharmony_ci * }; 19262306a36Sopenharmony_ci * 19362306a36Sopenharmony_ci * struct nlm4_stat { 19462306a36Sopenharmony_ci * nlm4_stats stat; 19562306a36Sopenharmony_ci * }; 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * NB: we don't swap bytes for the NLM status values. The upper 19862306a36Sopenharmony_ci * layers deal directly with the status value in network byte 19962306a36Sopenharmony_ci * order. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_cistatic void encode_nlm4_stat(struct xdr_stream *xdr, 20262306a36Sopenharmony_ci const __be32 stat) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci __be32 *p; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci BUG_ON(be32_to_cpu(stat) > NLM_FAILED); 20762306a36Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 20862306a36Sopenharmony_ci *p = stat; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci __be32 *p; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 21662306a36Sopenharmony_ci if (unlikely(p == NULL)) 21762306a36Sopenharmony_ci goto out_overflow; 21862306a36Sopenharmony_ci if (unlikely(ntohl(*p) > ntohl(nlm4_failed))) 21962306a36Sopenharmony_ci goto out_bad_xdr; 22062306a36Sopenharmony_ci *stat = *p; 22162306a36Sopenharmony_ci return 0; 22262306a36Sopenharmony_ciout_bad_xdr: 22362306a36Sopenharmony_ci dprintk("%s: server returned invalid nlm4_stats value: %u\n", 22462306a36Sopenharmony_ci __func__, be32_to_cpup(p)); 22562306a36Sopenharmony_ci return -EIO; 22662306a36Sopenharmony_ciout_overflow: 22762306a36Sopenharmony_ci return -EIO; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* 23162306a36Sopenharmony_ci * struct nlm4_holder { 23262306a36Sopenharmony_ci * bool exclusive; 23362306a36Sopenharmony_ci * int32 svid; 23462306a36Sopenharmony_ci * netobj oh; 23562306a36Sopenharmony_ci * uint64 l_offset; 23662306a36Sopenharmony_ci * uint64 l_len; 23762306a36Sopenharmony_ci * }; 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_cistatic void encode_nlm4_holder(struct xdr_stream *xdr, 24062306a36Sopenharmony_ci const struct nlm_res *result) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci const struct nlm_lock *lock = &result->lock; 24362306a36Sopenharmony_ci u64 l_offset, l_len; 24462306a36Sopenharmony_ci __be32 *p; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci encode_bool(xdr, lock->fl.fl_type == F_RDLCK); 24762306a36Sopenharmony_ci encode_int32(xdr, lock->svid); 24862306a36Sopenharmony_ci encode_netobj(xdr, lock->oh.data, lock->oh.len); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci p = xdr_reserve_space(xdr, 4 + 4); 25162306a36Sopenharmony_ci nlm4_compute_offsets(lock, &l_offset, &l_len); 25262306a36Sopenharmony_ci p = xdr_encode_hyper(p, l_offset); 25362306a36Sopenharmony_ci xdr_encode_hyper(p, l_len); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct nlm_lock *lock = &result->lock; 25962306a36Sopenharmony_ci struct file_lock *fl = &lock->fl; 26062306a36Sopenharmony_ci u64 l_offset, l_len; 26162306a36Sopenharmony_ci u32 exclusive; 26262306a36Sopenharmony_ci int error; 26362306a36Sopenharmony_ci __be32 *p; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci memset(lock, 0, sizeof(*lock)); 26662306a36Sopenharmony_ci locks_init_lock(fl); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci p = xdr_inline_decode(xdr, 4 + 4); 26962306a36Sopenharmony_ci if (unlikely(p == NULL)) 27062306a36Sopenharmony_ci goto out_overflow; 27162306a36Sopenharmony_ci exclusive = be32_to_cpup(p++); 27262306a36Sopenharmony_ci lock->svid = be32_to_cpup(p); 27362306a36Sopenharmony_ci fl->fl_pid = (pid_t)lock->svid; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci error = decode_netobj(xdr, &lock->oh); 27662306a36Sopenharmony_ci if (unlikely(error)) 27762306a36Sopenharmony_ci goto out; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci p = xdr_inline_decode(xdr, 8 + 8); 28062306a36Sopenharmony_ci if (unlikely(p == NULL)) 28162306a36Sopenharmony_ci goto out_overflow; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci fl->fl_flags = FL_POSIX; 28462306a36Sopenharmony_ci fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; 28562306a36Sopenharmony_ci p = xdr_decode_hyper(p, &l_offset); 28662306a36Sopenharmony_ci xdr_decode_hyper(p, &l_len); 28762306a36Sopenharmony_ci nlm4svc_set_file_lock_range(fl, l_offset, l_len); 28862306a36Sopenharmony_ci error = 0; 28962306a36Sopenharmony_ciout: 29062306a36Sopenharmony_ci return error; 29162306a36Sopenharmony_ciout_overflow: 29262306a36Sopenharmony_ci return -EIO; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci/* 29662306a36Sopenharmony_ci * string caller_name<LM_MAXSTRLEN>; 29762306a36Sopenharmony_ci */ 29862306a36Sopenharmony_cistatic void encode_caller_name(struct xdr_stream *xdr, const char *name) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci /* NB: client-side does not set lock->len */ 30162306a36Sopenharmony_ci u32 length = strlen(name); 30262306a36Sopenharmony_ci __be32 *p; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci p = xdr_reserve_space(xdr, 4 + length); 30562306a36Sopenharmony_ci xdr_encode_opaque(p, name, length); 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/* 30962306a36Sopenharmony_ci * struct nlm4_lock { 31062306a36Sopenharmony_ci * string caller_name<LM_MAXSTRLEN>; 31162306a36Sopenharmony_ci * netobj fh; 31262306a36Sopenharmony_ci * netobj oh; 31362306a36Sopenharmony_ci * int32 svid; 31462306a36Sopenharmony_ci * uint64 l_offset; 31562306a36Sopenharmony_ci * uint64 l_len; 31662306a36Sopenharmony_ci * }; 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_cistatic void encode_nlm4_lock(struct xdr_stream *xdr, 31962306a36Sopenharmony_ci const struct nlm_lock *lock) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci u64 l_offset, l_len; 32262306a36Sopenharmony_ci __be32 *p; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci encode_caller_name(xdr, lock->caller); 32562306a36Sopenharmony_ci encode_fh(xdr, &lock->fh); 32662306a36Sopenharmony_ci encode_netobj(xdr, lock->oh.data, lock->oh.len); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci p = xdr_reserve_space(xdr, 4 + 8 + 8); 32962306a36Sopenharmony_ci *p++ = cpu_to_be32(lock->svid); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci nlm4_compute_offsets(lock, &l_offset, &l_len); 33262306a36Sopenharmony_ci p = xdr_encode_hyper(p, l_offset); 33362306a36Sopenharmony_ci xdr_encode_hyper(p, l_len); 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/* 33862306a36Sopenharmony_ci * NLMv4 XDR encode functions 33962306a36Sopenharmony_ci * 34062306a36Sopenharmony_ci * NLMv4 argument types are defined in Appendix II of RFC 1813: 34162306a36Sopenharmony_ci * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's 34262306a36Sopenharmony_ci * "Protocols for Interworking: XNFS, Version 3W". 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci/* 34662306a36Sopenharmony_ci * struct nlm4_testargs { 34762306a36Sopenharmony_ci * netobj cookie; 34862306a36Sopenharmony_ci * bool exclusive; 34962306a36Sopenharmony_ci * struct nlm4_lock alock; 35062306a36Sopenharmony_ci * }; 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_cistatic void nlm4_xdr_enc_testargs(struct rpc_rqst *req, 35362306a36Sopenharmony_ci struct xdr_stream *xdr, 35462306a36Sopenharmony_ci const void *data) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci const struct nlm_args *args = data; 35762306a36Sopenharmony_ci const struct nlm_lock *lock = &args->lock; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci encode_cookie(xdr, &args->cookie); 36062306a36Sopenharmony_ci encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 36162306a36Sopenharmony_ci encode_nlm4_lock(xdr, lock); 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci/* 36562306a36Sopenharmony_ci * struct nlm4_lockargs { 36662306a36Sopenharmony_ci * netobj cookie; 36762306a36Sopenharmony_ci * bool block; 36862306a36Sopenharmony_ci * bool exclusive; 36962306a36Sopenharmony_ci * struct nlm4_lock alock; 37062306a36Sopenharmony_ci * bool reclaim; 37162306a36Sopenharmony_ci * int state; 37262306a36Sopenharmony_ci * }; 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_cistatic void nlm4_xdr_enc_lockargs(struct rpc_rqst *req, 37562306a36Sopenharmony_ci struct xdr_stream *xdr, 37662306a36Sopenharmony_ci const void *data) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci const struct nlm_args *args = data; 37962306a36Sopenharmony_ci const struct nlm_lock *lock = &args->lock; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci encode_cookie(xdr, &args->cookie); 38262306a36Sopenharmony_ci encode_bool(xdr, args->block); 38362306a36Sopenharmony_ci encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 38462306a36Sopenharmony_ci encode_nlm4_lock(xdr, lock); 38562306a36Sopenharmony_ci encode_bool(xdr, args->reclaim); 38662306a36Sopenharmony_ci encode_int32(xdr, args->state); 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci/* 39062306a36Sopenharmony_ci * struct nlm4_cancargs { 39162306a36Sopenharmony_ci * netobj cookie; 39262306a36Sopenharmony_ci * bool block; 39362306a36Sopenharmony_ci * bool exclusive; 39462306a36Sopenharmony_ci * struct nlm4_lock alock; 39562306a36Sopenharmony_ci * }; 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_cistatic void nlm4_xdr_enc_cancargs(struct rpc_rqst *req, 39862306a36Sopenharmony_ci struct xdr_stream *xdr, 39962306a36Sopenharmony_ci const void *data) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci const struct nlm_args *args = data; 40262306a36Sopenharmony_ci const struct nlm_lock *lock = &args->lock; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci encode_cookie(xdr, &args->cookie); 40562306a36Sopenharmony_ci encode_bool(xdr, args->block); 40662306a36Sopenharmony_ci encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 40762306a36Sopenharmony_ci encode_nlm4_lock(xdr, lock); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci/* 41162306a36Sopenharmony_ci * struct nlm4_unlockargs { 41262306a36Sopenharmony_ci * netobj cookie; 41362306a36Sopenharmony_ci * struct nlm4_lock alock; 41462306a36Sopenharmony_ci * }; 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_cistatic void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req, 41762306a36Sopenharmony_ci struct xdr_stream *xdr, 41862306a36Sopenharmony_ci const void *data) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci const struct nlm_args *args = data; 42162306a36Sopenharmony_ci const struct nlm_lock *lock = &args->lock; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci encode_cookie(xdr, &args->cookie); 42462306a36Sopenharmony_ci encode_nlm4_lock(xdr, lock); 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/* 42862306a36Sopenharmony_ci * struct nlm4_res { 42962306a36Sopenharmony_ci * netobj cookie; 43062306a36Sopenharmony_ci * nlm4_stat stat; 43162306a36Sopenharmony_ci * }; 43262306a36Sopenharmony_ci */ 43362306a36Sopenharmony_cistatic void nlm4_xdr_enc_res(struct rpc_rqst *req, 43462306a36Sopenharmony_ci struct xdr_stream *xdr, 43562306a36Sopenharmony_ci const void *data) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci const struct nlm_res *result = data; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci encode_cookie(xdr, &result->cookie); 44062306a36Sopenharmony_ci encode_nlm4_stat(xdr, result->status); 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci/* 44462306a36Sopenharmony_ci * union nlm4_testrply switch (nlm4_stats stat) { 44562306a36Sopenharmony_ci * case NLM4_DENIED: 44662306a36Sopenharmony_ci * struct nlm4_holder holder; 44762306a36Sopenharmony_ci * default: 44862306a36Sopenharmony_ci * void; 44962306a36Sopenharmony_ci * }; 45062306a36Sopenharmony_ci * 45162306a36Sopenharmony_ci * struct nlm4_testres { 45262306a36Sopenharmony_ci * netobj cookie; 45362306a36Sopenharmony_ci * nlm4_testrply test_stat; 45462306a36Sopenharmony_ci * }; 45562306a36Sopenharmony_ci */ 45662306a36Sopenharmony_cistatic void nlm4_xdr_enc_testres(struct rpc_rqst *req, 45762306a36Sopenharmony_ci struct xdr_stream *xdr, 45862306a36Sopenharmony_ci const void *data) 45962306a36Sopenharmony_ci{ 46062306a36Sopenharmony_ci const struct nlm_res *result = data; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci encode_cookie(xdr, &result->cookie); 46362306a36Sopenharmony_ci encode_nlm4_stat(xdr, result->status); 46462306a36Sopenharmony_ci if (result->status == nlm_lck_denied) 46562306a36Sopenharmony_ci encode_nlm4_holder(xdr, result); 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/* 47062306a36Sopenharmony_ci * NLMv4 XDR decode functions 47162306a36Sopenharmony_ci * 47262306a36Sopenharmony_ci * NLMv4 argument types are defined in Appendix II of RFC 1813: 47362306a36Sopenharmony_ci * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's 47462306a36Sopenharmony_ci * "Protocols for Interworking: XNFS, Version 3W". 47562306a36Sopenharmony_ci */ 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci/* 47862306a36Sopenharmony_ci * union nlm4_testrply switch (nlm4_stats stat) { 47962306a36Sopenharmony_ci * case NLM4_DENIED: 48062306a36Sopenharmony_ci * struct nlm4_holder holder; 48162306a36Sopenharmony_ci * default: 48262306a36Sopenharmony_ci * void; 48362306a36Sopenharmony_ci * }; 48462306a36Sopenharmony_ci * 48562306a36Sopenharmony_ci * struct nlm4_testres { 48662306a36Sopenharmony_ci * netobj cookie; 48762306a36Sopenharmony_ci * nlm4_testrply test_stat; 48862306a36Sopenharmony_ci * }; 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_cistatic int decode_nlm4_testrply(struct xdr_stream *xdr, 49162306a36Sopenharmony_ci struct nlm_res *result) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci int error; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci error = decode_nlm4_stat(xdr, &result->status); 49662306a36Sopenharmony_ci if (unlikely(error)) 49762306a36Sopenharmony_ci goto out; 49862306a36Sopenharmony_ci if (result->status == nlm_lck_denied) 49962306a36Sopenharmony_ci error = decode_nlm4_holder(xdr, result); 50062306a36Sopenharmony_ciout: 50162306a36Sopenharmony_ci return error; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic int nlm4_xdr_dec_testres(struct rpc_rqst *req, 50562306a36Sopenharmony_ci struct xdr_stream *xdr, 50662306a36Sopenharmony_ci void *data) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci struct nlm_res *result = data; 50962306a36Sopenharmony_ci int error; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci error = decode_cookie(xdr, &result->cookie); 51262306a36Sopenharmony_ci if (unlikely(error)) 51362306a36Sopenharmony_ci goto out; 51462306a36Sopenharmony_ci error = decode_nlm4_testrply(xdr, result); 51562306a36Sopenharmony_ciout: 51662306a36Sopenharmony_ci return error; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci/* 52062306a36Sopenharmony_ci * struct nlm4_res { 52162306a36Sopenharmony_ci * netobj cookie; 52262306a36Sopenharmony_ci * nlm4_stat stat; 52362306a36Sopenharmony_ci * }; 52462306a36Sopenharmony_ci */ 52562306a36Sopenharmony_cistatic int nlm4_xdr_dec_res(struct rpc_rqst *req, 52662306a36Sopenharmony_ci struct xdr_stream *xdr, 52762306a36Sopenharmony_ci void *data) 52862306a36Sopenharmony_ci{ 52962306a36Sopenharmony_ci struct nlm_res *result = data; 53062306a36Sopenharmony_ci int error; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci error = decode_cookie(xdr, &result->cookie); 53362306a36Sopenharmony_ci if (unlikely(error)) 53462306a36Sopenharmony_ci goto out; 53562306a36Sopenharmony_ci error = decode_nlm4_stat(xdr, &result->status); 53662306a36Sopenharmony_ciout: 53762306a36Sopenharmony_ci return error; 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci/* 54262306a36Sopenharmony_ci * For NLM, a void procedure really returns nothing 54362306a36Sopenharmony_ci */ 54462306a36Sopenharmony_ci#define nlm4_xdr_dec_norep NULL 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci#define PROC(proc, argtype, restype) \ 54762306a36Sopenharmony_ci[NLMPROC_##proc] = { \ 54862306a36Sopenharmony_ci .p_proc = NLMPROC_##proc, \ 54962306a36Sopenharmony_ci .p_encode = nlm4_xdr_enc_##argtype, \ 55062306a36Sopenharmony_ci .p_decode = nlm4_xdr_dec_##restype, \ 55162306a36Sopenharmony_ci .p_arglen = NLM4_##argtype##_sz, \ 55262306a36Sopenharmony_ci .p_replen = NLM4_##restype##_sz, \ 55362306a36Sopenharmony_ci .p_statidx = NLMPROC_##proc, \ 55462306a36Sopenharmony_ci .p_name = #proc, \ 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic const struct rpc_procinfo nlm4_procedures[] = { 55862306a36Sopenharmony_ci PROC(TEST, testargs, testres), 55962306a36Sopenharmony_ci PROC(LOCK, lockargs, res), 56062306a36Sopenharmony_ci PROC(CANCEL, cancargs, res), 56162306a36Sopenharmony_ci PROC(UNLOCK, unlockargs, res), 56262306a36Sopenharmony_ci PROC(GRANTED, testargs, res), 56362306a36Sopenharmony_ci PROC(TEST_MSG, testargs, norep), 56462306a36Sopenharmony_ci PROC(LOCK_MSG, lockargs, norep), 56562306a36Sopenharmony_ci PROC(CANCEL_MSG, cancargs, norep), 56662306a36Sopenharmony_ci PROC(UNLOCK_MSG, unlockargs, norep), 56762306a36Sopenharmony_ci PROC(GRANTED_MSG, testargs, norep), 56862306a36Sopenharmony_ci PROC(TEST_RES, testres, norep), 56962306a36Sopenharmony_ci PROC(LOCK_RES, res, norep), 57062306a36Sopenharmony_ci PROC(CANCEL_RES, res, norep), 57162306a36Sopenharmony_ci PROC(UNLOCK_RES, res, norep), 57262306a36Sopenharmony_ci PROC(GRANTED_RES, res, norep), 57362306a36Sopenharmony_ci}; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic unsigned int nlm_version4_counts[ARRAY_SIZE(nlm4_procedures)]; 57662306a36Sopenharmony_ciconst struct rpc_version nlm_version4 = { 57762306a36Sopenharmony_ci .number = 4, 57862306a36Sopenharmony_ci .nrprocs = ARRAY_SIZE(nlm4_procedures), 57962306a36Sopenharmony_ci .procs = nlm4_procedures, 58062306a36Sopenharmony_ci .counts = nlm_version4_counts, 58162306a36Sopenharmony_ci}; 582