1 /* 2 * linux/fs/nfs/nfs2xdr.c 3 * 4 * XDR functions to encode/decode NFS RPC arguments and results. 5 * 6 * Copyright (C) 1992, 1993, 1994 Rick Sladkey 7 * Copyright (C) 1996 Olaf Kirch 8 * 04 Aug 1998 Ion Badulescu <ionut@cs.columbia.edu> 9 * FIFO's need special handling in NFSv2 10 */ 11 12 #include <linux/param.h> 13 #include <linux/time.h> 14 #include <linux/mm.h> 15 #include <linux/slab.h> 16 #include <linux/utsname.h> 17 #include <linux/errno.h> 18 #include <linux/string.h> 19 #include <linux/in.h> 20 #include <linux/pagemap.h> 21 #include <linux/proc_fs.h> 22 #include <linux/sunrpc/clnt.h> 23 #include <linux/nfs.h> 24 #include <linux/nfs2.h> 25 #include <linux/nfs_fs.h> 26 #include "internal.h" 27 28 #define NFSDBG_FACILITY NFSDBG_XDR 29 30 /* Mapping from NFS error code to "errno" error code. */ 31 #define errno_NFSERR_IO EIO 32 33 /* 34 * Declare the space requirements for NFS arguments and replies as 35 * number of 32bit-words 36 */ 37 #define NFS_fhandle_sz (8) 38 #define NFS_sattr_sz (8) 39 #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2)) 40 #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2)) 41 #define NFS_fattr_sz (17) 42 #define NFS_info_sz (5) 43 #define NFS_entry_sz (NFS_filename_sz+3) 44 45 #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz) 46 #define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz) 47 #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz) 48 #define NFS_readlinkargs_sz (NFS_fhandle_sz) 49 #define NFS_readargs_sz (NFS_fhandle_sz+3) 50 #define NFS_writeargs_sz (NFS_fhandle_sz+4) 51 #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz) 52 #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz) 53 #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz) 54 #define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz) 55 #define NFS_readdirargs_sz (NFS_fhandle_sz+2) 56 57 #define NFS_attrstat_sz (1+NFS_fattr_sz) 58 #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz) 59 #define NFS_readlinkres_sz (2) 60 #define NFS_readres_sz (1+NFS_fattr_sz+1) 61 #define NFS_writeres_sz (NFS_attrstat_sz) 62 #define NFS_stat_sz (1) 63 #define NFS_readdirres_sz (1) 64 #define NFS_statfsres_sz (1+NFS_info_sz) 65 66 /* 67 * Common NFS XDR functions as inlines 68 */ 69 static inline __be32 * 70 xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fhandle) 71 { 72 memcpy(p, fhandle->data, NFS2_FHSIZE); 73 return p + XDR_QUADLEN(NFS2_FHSIZE); 74 } 75 76 static inline __be32 * 77 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle) 78 { 79 /* NFSv2 handles have a fixed length */ 80 fhandle->size = NFS2_FHSIZE; 81 memcpy(fhandle->data, p, NFS2_FHSIZE); 82 return p + XDR_QUADLEN(NFS2_FHSIZE); 83 } 84 85 static inline __be32* 86 xdr_encode_time(__be32 *p, struct timespec *timep) 87 { 88 *p++ = htonl(timep->tv_sec); 89 /* Convert nanoseconds into microseconds */ 90 *p++ = htonl(timep->tv_nsec ? timep->tv_nsec / 1000 : 0); 91 return p; 92 } 93 94 static inline __be32* 95 xdr_encode_current_server_time(__be32 *p, struct timespec *timep) 96 { 97 /* 98 * Passing the invalid value useconds=1000000 is a 99 * Sun convention for "set to current server time". 100 * It's needed to make permissions checks for the 101 * "touch" program across v2 mounts to Solaris and 102 * Irix boxes work correctly. See description of 103 * sattr in section 6.1 of "NFS Illustrated" by 104 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5 105 */ 106 *p++ = htonl(timep->tv_sec); 107 *p++ = htonl(1000000); 108 return p; 109 } 110 111 static inline __be32* 112 xdr_decode_time(__be32 *p, struct timespec *timep) 113 { 114 timep->tv_sec = ntohl(*p++); 115 /* Convert microseconds into nanoseconds */ 116 timep->tv_nsec = ntohl(*p++) * 1000; 117 return p; 118 } 119 120 static __be32 * 121 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) 122 { 123 u32 rdev; 124 fattr->type = (enum nfs_ftype) ntohl(*p++); 125 fattr->mode = ntohl(*p++); 126 fattr->nlink = ntohl(*p++); 127 fattr->uid = ntohl(*p++); 128 fattr->gid = ntohl(*p++); 129 fattr->size = ntohl(*p++); 130 fattr->du.nfs2.blocksize = ntohl(*p++); 131 rdev = ntohl(*p++); 132 fattr->du.nfs2.blocks = ntohl(*p++); 133 fattr->fsid.major = ntohl(*p++); 134 fattr->fsid.minor = 0; 135 fattr->fileid = ntohl(*p++); 136 p = xdr_decode_time(p, &fattr->atime); 137 p = xdr_decode_time(p, &fattr->mtime); 138 p = xdr_decode_time(p, &fattr->ctime); 139 fattr->valid |= NFS_ATTR_FATTR; 140 fattr->rdev = new_decode_dev(rdev); 141 if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) { 142 fattr->type = NFFIFO; 143 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; 144 fattr->rdev = 0; 145 } 146 return p; 147 } 148 149 static inline __be32 * 150 xdr_encode_sattr(__be32 *p, struct iattr *attr) 151 { 152 const __be32 not_set = __constant_htonl(0xFFFFFFFF); 153 154 *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set; 155 *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set; 156 *p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set; 157 *p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set; 158 159 if (attr->ia_valid & ATTR_ATIME_SET) { 160 p = xdr_encode_time(p, &attr->ia_atime); 161 } else if (attr->ia_valid & ATTR_ATIME) { 162 p = xdr_encode_current_server_time(p, &attr->ia_atime); 163 } else { 164 *p++ = not_set; 165 *p++ = not_set; 166 } 167 168 if (attr->ia_valid & ATTR_MTIME_SET) { 169 p = xdr_encode_time(p, &attr->ia_mtime); 170 } else if (attr->ia_valid & ATTR_MTIME) { 171 p = xdr_encode_current_server_time(p, &attr->ia_mtime); 172 } else { 173 *p++ = not_set; 174 *p++ = not_set; 175 } 176 return p; 177 } 178 179 /* 180 * NFS encode functions 181 */ 182 /* 183 * Encode file handle argument 184 * GETATTR, READLINK, STATFS 185 */ 186 static int 187 nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh) 188 { 189 p = xdr_encode_fhandle(p, fh); 190 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 191 return 0; 192 } 193 194 /* 195 * Encode SETATTR arguments 196 */ 197 static int 198 nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args) 199 { 200 p = xdr_encode_fhandle(p, args->fh); 201 p = xdr_encode_sattr(p, args->sattr); 202 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 203 return 0; 204 } 205 206 /* 207 * Encode directory ops argument 208 * LOOKUP, RMDIR 209 */ 210 static int 211 nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args) 212 { 213 p = xdr_encode_fhandle(p, args->fh); 214 p = xdr_encode_array(p, args->name, args->len); 215 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 216 return 0; 217 } 218 219 /* 220 * Encode REMOVE argument 221 */ 222 static int 223 nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args) 224 { 225 p = xdr_encode_fhandle(p, args->fh); 226 p = xdr_encode_array(p, args->name.name, args->name.len); 227 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 228 return 0; 229 } 230 231 /* 232 * Arguments to a READ call. Since we read data directly into the page 233 * cache, we also set up the reply iovec here so that iov[1] points 234 * exactly to the page we want to fetch. 235 */ 236 static int 237 nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) 238 { 239 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 240 unsigned int replen; 241 u32 offset = (u32)args->offset; 242 u32 count = args->count; 243 244 p = xdr_encode_fhandle(p, args->fh); 245 *p++ = htonl(offset); 246 *p++ = htonl(count); 247 *p++ = htonl(count); 248 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 249 250 /* Inline the page array */ 251 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; 252 xdr_inline_pages(&req->rq_rcv_buf, replen, 253 args->pages, args->pgbase, count); 254 req->rq_rcv_buf.flags |= XDRBUF_READ; 255 return 0; 256 } 257 258 /* 259 * Decode READ reply 260 */ 261 static int 262 nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) 263 { 264 struct kvec *iov = req->rq_rcv_buf.head; 265 size_t hdrlen; 266 u32 count, recvd; 267 int status; 268 269 if ((status = ntohl(*p++))) 270 return nfs_stat_to_errno(status); 271 p = xdr_decode_fattr(p, res->fattr); 272 273 count = ntohl(*p++); 274 res->eof = 0; 275 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 276 if (iov->iov_len < hdrlen) { 277 dprintk("NFS: READ reply header overflowed:" 278 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 279 return -errno_NFSERR_IO; 280 } else if (iov->iov_len != hdrlen) { 281 dprintk("NFS: READ header is short. iovec will be shifted.\n"); 282 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen); 283 } 284 285 recvd = req->rq_rcv_buf.len - hdrlen; 286 if (count > recvd) { 287 dprintk("NFS: server cheating in read reply: " 288 "count %u > recvd %u\n", count, recvd); 289 count = recvd; 290 } 291 292 dprintk("RPC: readres OK count %u\n", count); 293 if (count < res->count) 294 res->count = count; 295 296 return count; 297 } 298 299 300 /* 301 * Write arguments. Splice the buffer to be written into the iovec. 302 */ 303 static int 304 nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 305 { 306 struct xdr_buf *sndbuf = &req->rq_snd_buf; 307 u32 offset = (u32)args->offset; 308 u32 count = args->count; 309 310 p = xdr_encode_fhandle(p, args->fh); 311 *p++ = htonl(offset); 312 *p++ = htonl(offset); 313 *p++ = htonl(count); 314 *p++ = htonl(count); 315 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 316 317 /* Copy the page array */ 318 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); 319 sndbuf->flags |= XDRBUF_WRITE; 320 return 0; 321 } 322 323 /* 324 * Encode create arguments 325 * CREATE, MKDIR 326 */ 327 static int 328 nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args) 329 { 330 p = xdr_encode_fhandle(p, args->fh); 331 p = xdr_encode_array(p, args->name, args->len); 332 p = xdr_encode_sattr(p, args->sattr); 333 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 334 return 0; 335 } 336 337 /* 338 * Encode RENAME arguments 339 */ 340 static int 341 nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args) 342 { 343 p = xdr_encode_fhandle(p, args->fromfh); 344 p = xdr_encode_array(p, args->fromname, args->fromlen); 345 p = xdr_encode_fhandle(p, args->tofh); 346 p = xdr_encode_array(p, args->toname, args->tolen); 347 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 348 return 0; 349 } 350 351 /* 352 * Encode LINK arguments 353 */ 354 static int 355 nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args) 356 { 357 p = xdr_encode_fhandle(p, args->fromfh); 358 p = xdr_encode_fhandle(p, args->tofh); 359 p = xdr_encode_array(p, args->toname, args->tolen); 360 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 361 return 0; 362 } 363 364 /* 365 * Encode SYMLINK arguments 366 */ 367 static int 368 nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args) 369 { 370 struct xdr_buf *sndbuf = &req->rq_snd_buf; 371 size_t pad; 372 373 p = xdr_encode_fhandle(p, args->fromfh); 374 p = xdr_encode_array(p, args->fromname, args->fromlen); 375 *p++ = htonl(args->pathlen); 376 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 377 378 xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen); 379 380 /* 381 * xdr_encode_pages may have added a few bytes to ensure the 382 * pathname ends on a 4-byte boundary. Start encoding the 383 * attributes after the pad bytes. 384 */ 385 pad = sndbuf->tail->iov_len; 386 if (pad > 0) 387 p++; 388 p = xdr_encode_sattr(p, args->sattr); 389 sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad; 390 return 0; 391 } 392 393 /* 394 * Encode arguments to readdir call 395 */ 396 static int 397 nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args) 398 { 399 struct rpc_task *task = req->rq_task; 400 struct rpc_auth *auth = task->tk_msg.rpc_cred->cr_auth; 401 unsigned int replen; 402 u32 count = args->count; 403 404 p = xdr_encode_fhandle(p, args->fh); 405 *p++ = htonl(args->cookie); 406 *p++ = htonl(count); /* see above */ 407 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 408 409 /* Inline the page array */ 410 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2; 411 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count); 412 return 0; 413 } 414 415 /* 416 * Decode the result of a readdir call. 417 * We're not really decoding anymore, we just leave the buffer untouched 418 * and only check that it is syntactically correct. 419 * The real decoding happens in nfs_decode_entry below, called directly 420 * from nfs_readdir for each entry. 421 */ 422 static int 423 nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) 424 { 425 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 426 struct kvec *iov = rcvbuf->head; 427 struct page **page; 428 size_t hdrlen; 429 unsigned int pglen, recvd; 430 u32 len; 431 int status, nr = 0; 432 __be32 *end, *entry, *kaddr; 433 434 if ((status = ntohl(*p++))) 435 return nfs_stat_to_errno(status); 436 437 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 438 if (iov->iov_len < hdrlen) { 439 dprintk("NFS: READDIR reply header overflowed:" 440 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 441 return -errno_NFSERR_IO; 442 } else if (iov->iov_len != hdrlen) { 443 dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); 444 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 445 } 446 447 pglen = rcvbuf->page_len; 448 recvd = rcvbuf->len - hdrlen; 449 if (pglen > recvd) 450 pglen = recvd; 451 page = rcvbuf->pages; 452 kaddr = p = kmap_atomic(*page, KM_USER0); 453 end = (__be32 *)((char *)p + pglen); 454 entry = p; 455 456 /* Make sure the packet actually has a value_follows and EOF entry */ 457 if ((entry + 1) > end) 458 goto short_pkt; 459 460 for (; *p++; nr++) { 461 if (p + 2 > end) 462 goto short_pkt; 463 p++; /* fileid */ 464 len = ntohl(*p++); 465 p += XDR_QUADLEN(len) + 1; /* name plus cookie */ 466 if (len > NFS2_MAXNAMLEN) { 467 dprintk("NFS: giant filename in readdir (len 0x%x)!\n", 468 len); 469 goto err_unmap; 470 } 471 if (p + 2 > end) 472 goto short_pkt; 473 entry = p; 474 } 475 476 /* 477 * Apparently some server sends responses that are a valid size, but 478 * contain no entries, and have value_follows==0 and EOF==0. For 479 * those, just set the EOF marker. 480 */ 481 if (!nr && entry[1] == 0) { 482 dprintk("NFS: readdir reply truncated!\n"); 483 entry[1] = 1; 484 } 485 out: 486 kunmap_atomic(kaddr, KM_USER0); 487 return nr; 488 short_pkt: 489 /* 490 * When we get a short packet there are 2 possibilities. We can 491 * return an error, or fix up the response to look like a valid 492 * response and return what we have so far. If there are no 493 * entries and the packet was short, then return -EIO. If there 494 * are valid entries in the response, return them and pretend that 495 * the call was successful, but incomplete. The caller can retry the 496 * readdir starting at the last cookie. 497 */ 498 entry[0] = entry[1] = 0; 499 if (!nr) 500 nr = -errno_NFSERR_IO; 501 goto out; 502 err_unmap: 503 nr = -errno_NFSERR_IO; 504 goto out; 505 } 506 507 __be32 * 508 nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 509 { 510 if (!*p++) { 511 if (!*p) 512 return ERR_PTR(-EAGAIN); 513 entry->eof = 1; 514 return ERR_PTR(-EBADCOOKIE); 515 } 516 517 entry->ino = ntohl(*p++); 518 entry->len = ntohl(*p++); 519 entry->name = (const char *) p; 520 p += XDR_QUADLEN(entry->len); 521 entry->prev_cookie = entry->cookie; 522 entry->cookie = ntohl(*p++); 523 entry->eof = !p[0] && p[1]; 524 525 return p; 526 } 527 528 /* 529 * NFS XDR decode functions 530 */ 531 /* 532 * Decode simple status reply 533 */ 534 static int 535 nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy) 536 { 537 int status; 538 539 if ((status = ntohl(*p++)) != 0) 540 status = nfs_stat_to_errno(status); 541 return status; 542 } 543 544 /* 545 * Decode attrstat reply 546 * GETATTR, SETATTR, WRITE 547 */ 548 static int 549 nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 550 { 551 int status; 552 553 if ((status = ntohl(*p++))) 554 return nfs_stat_to_errno(status); 555 xdr_decode_fattr(p, fattr); 556 return 0; 557 } 558 559 /* 560 * Decode diropres reply 561 * LOOKUP, CREATE, MKDIR 562 */ 563 static int 564 nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res) 565 { 566 int status; 567 568 if ((status = ntohl(*p++))) 569 return nfs_stat_to_errno(status); 570 p = xdr_decode_fhandle(p, res->fh); 571 xdr_decode_fattr(p, res->fattr); 572 return 0; 573 } 574 575 /* 576 * Encode READLINK args 577 */ 578 static int 579 nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args) 580 { 581 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 582 unsigned int replen; 583 584 p = xdr_encode_fhandle(p, args->fh); 585 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 586 587 /* Inline the page array */ 588 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2; 589 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen); 590 return 0; 591 } 592 593 /* 594 * Decode READLINK reply 595 */ 596 static int 597 nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) 598 { 599 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 600 struct kvec *iov = rcvbuf->head; 601 size_t hdrlen; 602 u32 len, recvd; 603 char *kaddr; 604 int status; 605 606 if ((status = ntohl(*p++))) 607 return nfs_stat_to_errno(status); 608 /* Convert length of symlink */ 609 len = ntohl(*p++); 610 if (len >= rcvbuf->page_len) { 611 dprintk("nfs: server returned giant symlink!\n"); 612 return -ENAMETOOLONG; 613 } 614 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 615 if (iov->iov_len < hdrlen) { 616 dprintk("NFS: READLINK reply header overflowed:" 617 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 618 return -errno_NFSERR_IO; 619 } else if (iov->iov_len != hdrlen) { 620 dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); 621 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 622 } 623 recvd = req->rq_rcv_buf.len - hdrlen; 624 if (recvd < len) { 625 dprintk("NFS: server cheating in readlink reply: " 626 "count %u > recvd %u\n", len, recvd); 627 return -EIO; 628 } 629 630 /* NULL terminate the string we got */ 631 kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0); 632 kaddr[len+rcvbuf->page_base] = '\0'; 633 kunmap_atomic(kaddr, KM_USER0); 634 return 0; 635 } 636 637 /* 638 * Decode WRITE reply 639 */ 640 static int 641 nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 642 { 643 res->verf->committed = NFS_FILE_SYNC; 644 return nfs_xdr_attrstat(req, p, res->fattr); 645 } 646 647 /* 648 * Decode STATFS reply 649 */ 650 static int 651 nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res) 652 { 653 int status; 654 655 if ((status = ntohl(*p++))) 656 return nfs_stat_to_errno(status); 657 658 res->tsize = ntohl(*p++); 659 res->bsize = ntohl(*p++); 660 res->blocks = ntohl(*p++); 661 res->bfree = ntohl(*p++); 662 res->bavail = ntohl(*p++); 663 return 0; 664 } 665 666 /* 667 * We need to translate between nfs status return values and 668 * the local errno values which may not be the same. 669 */ 670 static struct { 671 int stat; 672 int errno; 673 } nfs_errtbl[] = { 674 { NFS_OK, 0 }, 675 { NFSERR_PERM, -EPERM }, 676 { NFSERR_NOENT, -ENOENT }, 677 { NFSERR_IO, -errno_NFSERR_IO}, 678 { NFSERR_NXIO, -ENXIO }, 679 /* { NFSERR_EAGAIN, -EAGAIN }, */ 680 { NFSERR_ACCES, -EACCES }, 681 { NFSERR_EXIST, -EEXIST }, 682 { NFSERR_XDEV, -EXDEV }, 683 { NFSERR_NODEV, -ENODEV }, 684 { NFSERR_NOTDIR, -ENOTDIR }, 685 { NFSERR_ISDIR, -EISDIR }, 686 { NFSERR_INVAL, -EINVAL }, 687 { NFSERR_FBIG, -EFBIG }, 688 { NFSERR_NOSPC, -ENOSPC }, 689 { NFSERR_ROFS, -EROFS }, 690 { NFSERR_MLINK, -EMLINK }, 691 { NFSERR_NAMETOOLONG, -ENAMETOOLONG }, 692 { NFSERR_NOTEMPTY, -ENOTEMPTY }, 693 { NFSERR_DQUOT, -EDQUOT }, 694 { NFSERR_STALE, -ESTALE }, 695 { NFSERR_REMOTE, -EREMOTE }, 696 #ifdef EWFLUSH 697 { NFSERR_WFLUSH, -EWFLUSH }, 698 #endif 699 { NFSERR_BADHANDLE, -EBADHANDLE }, 700 { NFSERR_NOT_SYNC, -ENOTSYNC }, 701 { NFSERR_BAD_COOKIE, -EBADCOOKIE }, 702 { NFSERR_NOTSUPP, -ENOTSUPP }, 703 { NFSERR_TOOSMALL, -ETOOSMALL }, 704 { NFSERR_SERVERFAULT, -ESERVERFAULT }, 705 { NFSERR_BADTYPE, -EBADTYPE }, 706 { NFSERR_JUKEBOX, -EJUKEBOX }, 707 { -1, -EIO } 708 }; 709 710 /* 711 * Convert an NFS error code to a local one. 712 * This one is used jointly by NFSv2 and NFSv3. 713 */ 714 int 715 nfs_stat_to_errno(int stat) 716 { 717 int i; 718 719 for (i = 0; nfs_errtbl[i].stat != -1; i++) { 720 if (nfs_errtbl[i].stat == stat) 721 return nfs_errtbl[i].errno; 722 } 723 dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat); 724 return nfs_errtbl[i].errno; 725 } 726 727 #define PROC(proc, argtype, restype, timer) \ 728 [NFSPROC_##proc] = { \ 729 .p_proc = NFSPROC_##proc, \ 730 .p_encode = (kxdrproc_t) nfs_xdr_##argtype, \ 731 .p_decode = (kxdrproc_t) nfs_xdr_##restype, \ 732 .p_arglen = NFS_##argtype##_sz, \ 733 .p_replen = NFS_##restype##_sz, \ 734 .p_timer = timer, \ 735 .p_statidx = NFSPROC_##proc, \ 736 .p_name = #proc, \ 737 } 738 struct rpc_procinfo nfs_procedures[] = { 739 PROC(GETATTR, fhandle, attrstat, 1), 740 PROC(SETATTR, sattrargs, attrstat, 0), 741 PROC(LOOKUP, diropargs, diropres, 2), 742 PROC(READLINK, readlinkargs, readlinkres, 3), 743 PROC(READ, readargs, readres, 3), 744 PROC(WRITE, writeargs, writeres, 4), 745 PROC(CREATE, createargs, diropres, 0), 746 PROC(REMOVE, removeargs, stat, 0), 747 PROC(RENAME, renameargs, stat, 0), 748 PROC(LINK, linkargs, stat, 0), 749 PROC(SYMLINK, symlinkargs, stat, 0), 750 PROC(MKDIR, createargs, diropres, 0), 751 PROC(RMDIR, diropargs, stat, 0), 752 PROC(READDIR, readdirargs, readdirres, 3), 753 PROC(STATFS, fhandle, statfsres, 0), 754 }; 755 756 struct rpc_version nfs_version2 = { 757 .number = 2, 758 .nrprocs = ARRAY_SIZE(nfs_procedures), 759 .procs = nfs_procedures 760 }; 761