| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/fs/nfs/callback_xdr.c | |||
| 3 | * | |||
| 4 | * Copyright (C) 2004 Trond Myklebust | |||
| 5 | * | |||
| 6 | * NFSv4 callback encode/decode procedures | |||
| 7 | */ | |||
| 8 | #include <linux/config.h> | |||
| 9 | #include <linux/kernel.h> | |||
| 10 | #include <linux/sunrpc/svc.h> | |||
| 11 | #include <linux/nfs4.h> | |||
| 12 | #include <linux/nfs_fs.h> | |||
| 13 | #include "nfs4_fs.h" | |||
| 14 | #include "callback.h" | |||
| 15 | ||||
| 16 | #define CB_OP_TAGLEN_MAXSZ (512) | |||
| 17 | #define CB_OP_HDR_RES_MAXSZ (2 + CB_OP_TAGLEN_MAXSZ) | |||
| 18 | #define CB_OP_GETATTR_BITMAP_MAXSZ (4) | |||
| 19 | #define CB_OP_GETATTR_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ | |||
| 20 | CB_OP_GETATTR_BITMAP_MAXSZ + \ | |||
| 21 | 2 + 2 + 3 + 3) | |||
| 22 | #define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) | |||
| 23 | ||||
| 24 | #define NFSDBG_FACILITY NFSDBG_CALLBACK | |||
| 25 | ||||
| 26 | typedef unsigned (*callback_process_op_t)(void *, void *); | |||
| 27 | typedef unsigned (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *); | |||
| 28 | typedef unsigned (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *); | |||
| 29 | ||||
| 30 | ||||
| 31 | struct callback_op { | |||
| 32 | callback_process_op_t process_op; | |||
| 33 | callback_decode_arg_t decode_args; | |||
| 34 | callback_encode_res_t encode_res; | |||
| 35 | long res_maxsize; | |||
| 36 | }; | |||
| 37 | ||||
| 38 | static struct callback_op callback_ops[]; | |||
| 39 | ||||
| 0 | 0 | - | 40 | static int nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp) |
| 41 | { | |||
| 42 | return htonl(NFS4_OK); | |||
| 0 | 0 | - | 42 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 0 | - | 42 | return ( ( __be32 ) ( __builtin_constant_p ( (.. | |
| 43 | } | |||
| 44 | ||||
| 0 | 0 | - | 45 | static int nfs4_decode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy) |
| 46 | { | |||
| 0 | - | 47 | return xdr_argsize_check(rqstp, p); | |
| 48 | } | |||
| 49 | ||||
| 0 | 0 | - | 50 | static int nfs4_encode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy) |
| 51 | { | |||
| 0 | - | 52 | return xdr_ressize_check(rqstp, p); | |
| 53 | } | |||
| 54 | ||||
| 0 | 0 | - | 55 | static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes) |
| 56 | { | |||
| 57 | uint32_t *p; | |||
| 58 | ||||
| 59 | p = xdr_inline_decode(xdr, nbytes); | |||
| 0 | 0 | - | 60 | if (unlikely(p == NULL)) |
| 61 | printk(KERN_WARNING "NFSv4 callback reply buffer overflowed!\n"); | |||
| 0 | - | 62 | return p; | |
| 63 | } | |||
| 64 | ||||
| 0 | 0 | - | 65 | static unsigned decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str) |
| 66 | { | |||
| 67 | uint32_t *p; | |||
| 68 | ||||
| 69 | p = read_buf(xdr, 4); | |||
| 0 | 0 | - | 70 | if (unlikely(p == NULL)) |
| 71 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 71 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 71 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 72 | *len = ntohl(*p); | |||
| 0 | 0 | - | 72 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 73 | ||||
| 0 | 0 | - | 74 | if (*len != 0) { |
| 75 | p = read_buf(xdr, *len); | |||
| 0 | 0 | - | 76 | if (unlikely(p == NULL)) |
| 77 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 77 | ternary-?: __builtin_constant_p ( ( __u32 .. |
| 0 | - | 77 | return ( ( __be32 ) ( __builtin_constant_p.. | |
| 78 | *str = (const char *)p; | |||
| 79 | } else | |||
| 80 | *str = NULL; | |||
| 81 | ||||
| 0 | - | 82 | return 0; | |
| 83 | } | |||
| 84 | ||||
| 0 | 0 | - | 85 | static unsigned decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh) |
| 86 | { | |||
| 87 | uint32_t *p; | |||
| 88 | ||||
| 89 | p = read_buf(xdr, 4); | |||
| 0 | 0 | - | 90 | if (unlikely(p == NULL)) |
| 91 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 91 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 91 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 92 | fh->size = ntohl(*p); | |||
| 0 | 0 | - | 92 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 0 | 0 | - | 93 | if (fh->size > NFS4_FHSIZE) |
| 94 | return htonl(NFS4ERR_BADHANDLE); | |||
| 0 | 0 | - | 94 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 94 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 95 | p = read_buf(xdr, fh->size); | |||
| 0 | 0 | - | 96 | if (unlikely(p == NULL)) |
| 97 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 97 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 97 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 98 | memcpy(&fh->data[0], p, fh->size); | |||
| 99 | memset(&fh->data[fh->size], 0, sizeof(fh->data) - fh->size); | |||
| 0 | - | 100 | return 0; | |
| 101 | } | |||
| 102 | ||||
| 0 | 0 | - | 103 | static unsigned decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) |
| 104 | { | |||
| 105 | uint32_t *p; | |||
| 106 | unsigned int attrlen; | |||
| 107 | ||||
| 108 | p = read_buf(xdr, 4); | |||
| 0 | 0 | - | 109 | if (unlikely(p == NULL)) |
| 110 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 110 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 110 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 111 | attrlen = ntohl(*p); | |||
| 0 | 0 | - | 111 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 112 | p = read_buf(xdr, attrlen << 2); | |||
| 0 | 0 | - | 113 | if (unlikely(p == NULL)) |
| 114 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 114 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 114 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 0 | 0 | - | 115 | if (likely(attrlen > 0)) |
| 116 | bitmap[0] = ntohl(*p++); | |||
| 0 | 0 | - | 116 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | 0 | - | 117 | if (attrlen > 1) |
| 118 | bitmap[1] = ntohl(*p); | |||
| 0 | 0 | - | 118 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 119 | return 0; | |
| 120 | } | |||
| 121 | ||||
| 0 | 0 | - | 122 | static unsigned decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) |
| 123 | { | |||
| 124 | uint32_t *p; | |||
| 125 | ||||
| 126 | p = read_buf(xdr, 16); | |||
| 0 | 0 | - | 127 | if (unlikely(p == NULL)) |
| 128 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 128 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 128 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 129 | memcpy(stateid->data, p, 16); | |||
| 0 | - | 130 | return 0; | |
| 131 | } | |||
| 132 | ||||
| 0 | 0 | - | 133 | static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr) |
| 134 | { | |||
| 135 | uint32_t *p; | |||
| 136 | unsigned int minor_version; | |||
| 137 | unsigned status; | |||
| 138 | ||||
| 139 | status = decode_string(xdr, &hdr->taglen, &hdr->tag); | |||
| 0 | 0 | - | 140 | if (unlikely(status != 0)) |
| 0 | - | 141 | return status; | |
| 142 | /* We do not like overly long tags! */ | |||
| 0 | 0 | - | 143 | if (hdr->taglen > CB_OP_TAGLEN_MAXSZ-12 || hdr->taglen < 0) { |
| 0 | - | 143 | T || _ | |
| 0 | - | 143 | F || T | |
| 0 | - | 143 | F || F | |
| 144 | printk("NFSv4 CALLBACK %s: client sent tag of length %u\n", | |||
| 145 | __FUNCTION__, hdr->taglen); | |||
| 146 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 146 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 146 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 147 | } | |||
| 148 | p = read_buf(xdr, 12); | |||
| 0 | 0 | - | 149 | if (unlikely(p == NULL)) |
| 150 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 150 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 150 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 151 | minor_version = ntohl(*p++); | |||
| 0 | 0 | - | 151 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 152 | /* Check minor version is zero. */ | |||
| 0 | 0 | - | 153 | if (minor_version != 0) { |
| 154 | printk(KERN_WARNING "%s: NFSv4 server callback with illegal minor version %u!\n", | |||
| 155 | __FUNCTION__, minor_version); | |||
| 156 | return htonl(NFS4ERR_MINOR_VERS_MISMATCH); | |||
| 0 | 0 | - | 156 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 156 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 157 | } | |||
| 158 | hdr->callback_ident = ntohl(*p++); | |||
| 0 | 0 | - | 158 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 159 | hdr->nops = ntohl(*p); | |||
| 0 | 0 | - | 159 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 0 | - | 160 | return 0; | |
| 161 | } | |||
| 162 | ||||
| 0 | 0 | - | 163 | static unsigned decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) |
| 164 | { | |||
| 165 | uint32_t *p; | |||
| 166 | p = read_buf(xdr, 4); | |||
| 0 | 0 | - | 167 | if (unlikely(p == NULL)) |
| 168 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 168 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 168 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 169 | *op = ntohl(*p); | |||
| 0 | 0 | - | 169 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 0 | - | 170 | return 0; | |
| 171 | } | |||
| 172 | ||||
| 0 | 0 | - | 173 | static unsigned decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_getattrargs *args) |
| 174 | { | |||
| 175 | unsigned status; | |||
| 176 | ||||
| 177 | status = decode_fh(xdr, &args->fh); | |||
| 0 | 0 | - | 178 | if (unlikely(status != 0)) |
| 0 | - | 179 | goto out; | |
| 180 | args->addr = &rqstp->rq_addr; | |||
| 181 | status = decode_bitmap(xdr, args->bitmap); | |||
| 182 | out: | |||
| 183 | dprintk("%s: exit with status = %d\n", __FUNCTION__, status); | |||
| 0 | 0 | - | 183 | if (__builtin_expect ( ! ! ( nfs_debug & 0x0.. |
| 0 | 0 | - | 183 | do-while (0) |
| 0 | - | 184 | return status; | |
| 185 | } | |||
| 186 | ||||
| 0 | 0 | - | 187 | static unsigned decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args) |
| 188 | { | |||
| 189 | uint32_t *p; | |||
| 190 | unsigned status; | |||
| 191 | ||||
| 192 | args->addr = &rqstp->rq_addr; | |||
| 193 | status = decode_stateid(xdr, &args->stateid); | |||
| 0 | 0 | - | 194 | if (unlikely(status != 0)) |
| 0 | - | 195 | goto out; | |
| 196 | p = read_buf(xdr, 4); | |||
| 0 | 0 | - | 197 | if (unlikely(p == NULL)) { |
| 198 | status = htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 198 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 199 | goto out; | |
| 200 | } | |||
| 201 | args->truncate = ntohl(*p); | |||
| 0 | 0 | - | 201 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 202 | status = decode_fh(xdr, &args->fh); | |||
| 203 | out: | |||
| 204 | dprintk("%s: exit with status = %d\n", __FUNCTION__, status); | |||
| 0 | 0 | - | 204 | if (__builtin_expect ( ! ! ( nfs_debug & 0x0.. |
| 0 | 0 | - | 204 | do-while (0) |
| 0 | - | 205 | return 0; | |
| 206 | } | |||
| 207 | ||||
| 0 | 0 | - | 208 | static unsigned encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) |
| 209 | { | |||
| 210 | uint32_t *p; | |||
| 211 | ||||
| 212 | p = xdr_reserve_space(xdr, 4 + len); | |||
| 0 | 0 | - | 213 | if (unlikely(p == NULL)) |
| 214 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 214 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 214 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 215 | xdr_encode_opaque(p, str, len); | |||
| 0 | - | 216 | return 0; | |
| 217 | } | |||
| 218 | ||||
| 219 | #define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) | |||
| 220 | #define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) | |||
| 0 | 0 | - | 221 | static unsigned encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, uint32_t **savep) |
| 222 | { | |||
| 223 | uint32_t bm[2]; | |||
| 224 | uint32_t *p; | |||
| 225 | ||||
| 226 | bm[0] = htonl(bitmap[0] & CB_SUPPORTED_ATTR0); | |||
| 0 | 0 | - | 226 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 227 | bm[1] = htonl(bitmap[1] & CB_SUPPORTED_ATTR1); | |||
| 0 | 0 | - | 227 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 0 | 0 | - | 228 | if (bm[1] != 0) { |
| 229 | p = xdr_reserve_space(xdr, 16); | |||
| 0 | 0 | - | 230 | if (unlikely(p == NULL)) |
| 231 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 231 | ternary-?: __builtin_constant_p ( ( __u32 .. |
| 0 | - | 231 | return ( ( __be32 ) ( __builtin_constant_p.. | |
| 232 | *p++ = htonl(2); | |||
| 0 | 0 | - | 232 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 233 | *p++ = bm[0]; | |||
| 234 | *p++ = bm[1]; | |||
| 0 | 0 | - | 235 | } else if (bm[0] != 0) { |
| 236 | p = xdr_reserve_space(xdr, 12); | |||
| 0 | 0 | - | 237 | if (unlikely(p == NULL)) |
| 238 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 238 | ternary-?: __builtin_constant_p ( ( __u32 .. |
| 0 | - | 238 | return ( ( __be32 ) ( __builtin_constant_p.. | |
| 239 | *p++ = htonl(1); | |||
| 0 | 0 | - | 239 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 240 | *p++ = bm[0]; | |||
| 241 | } else { | |||
| 242 | p = xdr_reserve_space(xdr, 8); | |||
| 0 | 0 | - | 243 | if (unlikely(p == NULL)) |
| 244 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 244 | ternary-?: __builtin_constant_p ( ( __u32 .. |
| 0 | - | 244 | return ( ( __be32 ) ( __builtin_constant_p.. | |
| 245 | *p++ = htonl(0); | |||
| 0 | 0 | - | 245 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 246 | } | |||
| 247 | *savep = p; | |||
| 0 | - | 248 | return 0; | |
| 249 | } | |||
| 250 | ||||
| 0 | 0 | - | 251 | static unsigned encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change) |
| 252 | { | |||
| 253 | uint32_t *p; | |||
| 254 | ||||
| 0 | 0 | - | 255 | if (!(bitmap[0] & FATTR4_WORD0_CHANGE)) |
| 0 | - | 256 | return 0; | |
| 257 | p = xdr_reserve_space(xdr, 8); | |||
| 0 | 0 | - | 258 | if (unlikely(p == 0)) |
| 259 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 259 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 259 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 260 | p = xdr_encode_hyper(p, change); | |||
| 0 | - | 261 | return 0; | |
| 262 | } | |||
| 263 | ||||
| 0 | 0 | - | 264 | static unsigned encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size) |
| 265 | { | |||
| 266 | uint32_t *p; | |||
| 267 | ||||
| 0 | 0 | - | 268 | if (!(bitmap[0] & FATTR4_WORD0_SIZE)) |
| 0 | - | 269 | return 0; | |
| 270 | p = xdr_reserve_space(xdr, 8); | |||
| 0 | 0 | - | 271 | if (unlikely(p == 0)) |
| 272 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 272 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 272 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 273 | p = xdr_encode_hyper(p, size); | |||
| 0 | - | 274 | return 0; | |
| 275 | } | |||
| 276 | ||||
| 0 | 0 | - | 277 | static unsigned encode_attr_time(struct xdr_stream *xdr, const struct timespec *time) |
| 278 | { | |||
| 279 | uint32_t *p; | |||
| 280 | ||||
| 281 | p = xdr_reserve_space(xdr, 12); | |||
| 0 | 0 | - | 282 | if (unlikely(p == 0)) |
| 283 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 283 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 283 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 284 | p = xdr_encode_hyper(p, time->tv_sec); | |||
| 285 | *p = htonl(time->tv_nsec); | |||
| 0 | 0 | - | 285 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 0 | - | 286 | return 0; | |
| 287 | } | |||
| 288 | ||||
| 0 | 0 | - | 289 | static unsigned encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) |
| 290 | { | |||
| 0 | 0 | - | 291 | if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) |
| 0 | - | 292 | return 0; | |
| 0 | - | 293 | return encode_attr_time(xdr,time); | |
| 294 | } | |||
| 295 | ||||
| 0 | 0 | - | 296 | static unsigned encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) |
| 297 | { | |||
| 0 | 0 | - | 298 | if (!(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) |
| 0 | - | 299 | return 0; | |
| 0 | - | 300 | return encode_attr_time(xdr,time); | |
| 301 | } | |||
| 302 | ||||
| 0 | 0 | - | 303 | static unsigned encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr) |
| 304 | { | |||
| 305 | unsigned status; | |||
| 306 | ||||
| 307 | hdr->status = xdr_reserve_space(xdr, 4); | |||
| 0 | 0 | - | 308 | if (unlikely(hdr->status == NULL)) |
| 309 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 309 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 309 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 310 | status = encode_string(xdr, hdr->taglen, hdr->tag); | |||
| 0 | 0 | - | 311 | if (unlikely(status != 0)) |
| 0 | - | 312 | return status; | |
| 313 | hdr->nops = xdr_reserve_space(xdr, 4); | |||
| 0 | 0 | - | 314 | if (unlikely(hdr->nops == NULL)) |
| 315 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 315 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 315 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 0 | - | 316 | return 0; | |
| 317 | } | |||
| 318 | ||||
| 0 | 0 | - | 319 | static unsigned encode_op_hdr(struct xdr_stream *xdr, uint32_t op, uint32_t res) |
| 320 | { | |||
| 321 | uint32_t *p; | |||
| 322 | ||||
| 323 | p = xdr_reserve_space(xdr, 8); | |||
| 0 | 0 | - | 324 | if (unlikely(p == NULL)) |
| 325 | return htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 325 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 0 | - | 325 | return ( ( __be32 ) ( __builtin_constant_p (.. | |
| 326 | *p++ = htonl(op); | |||
| 0 | 0 | - | 326 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 327 | *p = res; | |||
| 0 | - | 328 | return 0; | |
| 329 | } | |||
| 330 | ||||
| 0 | 0 | - | 331 | static unsigned encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res) |
| 332 | { | |||
| 333 | uint32_t *savep; | |||
| 334 | unsigned status = res->status; | |||
| 335 | ||||
| 0 | 0 | - | 336 | if (unlikely(status != 0)) |
| 0 | - | 337 | goto out; | |
| 338 | status = encode_attr_bitmap(xdr, res->bitmap, &savep); | |||
| 0 | 0 | - | 339 | if (unlikely(status != 0)) |
| 0 | - | 340 | goto out; | |
| 341 | status = encode_attr_change(xdr, res->bitmap, res->change_attr); | |||
| 0 | 0 | - | 342 | if (unlikely(status != 0)) |
| 0 | - | 343 | goto out; | |
| 344 | status = encode_attr_size(xdr, res->bitmap, res->size); | |||
| 0 | 0 | - | 345 | if (unlikely(status != 0)) |
| 0 | - | 346 | goto out; | |
| 347 | status = encode_attr_ctime(xdr, res->bitmap, &res->ctime); | |||
| 0 | 0 | - | 348 | if (unlikely(status != 0)) |
| 0 | - | 349 | goto out; | |
| 350 | status = encode_attr_mtime(xdr, res->bitmap, &res->mtime); | |||
| 351 | *savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1))); | |||
| 0 | 0 | - | 351 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 352 | out: | |||
| 353 | dprintk("%s: exit with status = %d\n", __FUNCTION__, status); | |||
| 0 | 0 | - | 353 | if (__builtin_expect ( ! ! ( nfs_debug & 0x0.. |
| 0 | 0 | - | 353 | do-while (0) |
| 0 | - | 354 | return status; | |
| 355 | } | |||
| 356 | ||||
| 0 | 0 | - | 357 | static unsigned process_op(struct svc_rqst *rqstp, |
| 358 | struct xdr_stream *xdr_in, void *argp, | |||
| 359 | struct xdr_stream *xdr_out, void *resp) | |||
| 360 | { | |||
| 361 | struct callback_op *op; | |||
| 362 | unsigned int op_nr; | |||
| 363 | unsigned int status = 0; | |||
| 364 | long maxlen; | |||
| 365 | unsigned res; | |||
| 366 | ||||
| 367 | dprintk("%s: start\n", __FUNCTION__); | |||
| 0 | 0 | - | 367 | if (__builtin_expect ( ! ! ( nfs_debug & 0x0.. |
| 0 | 0 | - | 367 | do-while (0) |
| 368 | status = decode_op_hdr(xdr_in, &op_nr); | |||
| 0 | 0 | - | 369 | if (unlikely(status != 0)) { |
| 370 | op_nr = OP_CB_ILLEGAL; | |||
| 371 | op = &callback_ops[0]; | |||
| 0 | 0 | - | 372 | } else if (unlikely(op_nr != OP_CB_GETATTR && op_nr != OP_CB_RECALL)) { |
| 373 | op_nr = OP_CB_ILLEGAL; | |||
| 374 | op = &callback_ops[0]; | |||
| 375 | status = htonl(NFS4ERR_OP_ILLEGAL); | |||
| 0 | 0 | - | 375 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 376 | } else | |||
| 377 | op = &callback_ops[op_nr]; | |||
| 378 | ||||
| 379 | maxlen = xdr_out->end - xdr_out->p; | |||
| 0 | 0 | - | 380 | if (maxlen > 0 && maxlen < PAGE_SIZE) { |
| 0 | - | 380 | T && T | |
| 0 | - | 380 | T && F | |
| 0 | - | 380 | F && _ | |
| 0 | 0 | - | 381 | if (likely(status == 0 && op->decode_args != NULL)) |
| 382 | status = op->decode_args(rqstp, xdr_in, argp); | |||
| 0 | 0 | - | 383 | if (likely(status == 0 && op->process_op != NULL)) |
| 384 | status = op->process_op(argp, resp); | |||
| 385 | } else | |||
| 386 | status = htonl(NFS4ERR_RESOURCE); | |||
| 0 | 0 | - | 386 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 387 | ||||
| 388 | res = encode_op_hdr(xdr_out, op_nr, status); | |||
| 0 | 0 | |||