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 /* #define NFS_PARANOIA 1 */ 30 31 /* Mapping from NFS error code to "errno" error code. */ 32 #define errno_NFSERR_IO EIO 33 34 /* 35 * Declare the space requirements for NFS arguments and replies as 36 * number of 32bit-words 37 */ 38 #define NFS_fhandle_sz (8) 39 #define NFS_sattr_sz (8) 40 #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2)) 41 #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2)) 42 #define NFS_fattr_sz (17) 43 #define NFS_info_sz (5) 44 #define NFS_entry_sz (NFS_filename_sz+3) 45 46 #define NFS_diropargs_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, 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, REMOVE, 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 * Arguments to a READ call. Since we read data directly into the page 221 * cache, we also set up the reply iovec here so that iov[1] points 222 * exactly to the page we want to fetch. 223 */ 224 static int 225 nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) 226 { 227 struct rpc_auth *auth = req->rq_task->tk_auth; 228 unsigned int replen; 229 u32 offset = (u32)args->offset; 230 u32 count = args->count; 231 232 p = xdr_encode_fhandle(p, args->fh); 233 *p++ = htonl(offset); 234 *p++ = htonl(count); 235 *p++ = htonl(count); 236 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 237 238 /* Inline the page array */ 239 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; 240 xdr_inline_pages(&req->rq_rcv_buf, replen, 241 args->pages, args->pgbase, count); 242 return 0; 243 } 244 245 /* 246 * Decode READ reply 247 */ 248 static int 249 nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) 250 { 251 struct kvec *iov = req->rq_rcv_buf.head; 252 int status, count, recvd, hdrlen; 253 254 if ((status = ntohl(*p++))) 255 return -nfs_stat_to_errno(status); 256 p = xdr_decode_fattr(p, res->fattr); 257 258 count = ntohl(*p++); 259 res->eof = 0; 260 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 261 if (iov->iov_len < hdrlen) { 262 printk(KERN_WARNING "NFS: READ reply header overflowed:" 263 "length %d > %Zu\n", hdrlen, iov->iov_len); 264 return -errno_NFSERR_IO; 265 } else if (iov->iov_len != hdrlen) { 266 dprintk("NFS: READ header is short. iovec will be shifted.\n"); 267 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen); 268 } 269 270 recvd = req->rq_rcv_buf.len - hdrlen; 271 if (count > recvd) { 272 printk(KERN_WARNING "NFS: server cheating in read reply: " 273 "count %d > recvd %d\n", count, recvd); 274 count = recvd; 275 } 276 277 dprintk("RPC: readres OK count %d\n", count); 278 if (count < res->count) 279 res->count = count; 280 281 return count; 282 } 283 284 285 /* 286 * Write arguments. Splice the buffer to be written into the iovec. 287 */ 288 static int 289 nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 290 { 291 struct xdr_buf *sndbuf = &req->rq_snd_buf; 292 u32 offset = (u32)args->offset; 293 u32 count = args->count; 294 295 p = xdr_encode_fhandle(p, args->fh); 296 *p++ = htonl(offset); 297 *p++ = htonl(offset); 298 *p++ = htonl(count); 299 *p++ = htonl(count); 300 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 301 302 /* Copy the page array */ 303 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); 304 return 0; 305 } 306 307 /* 308 * Encode create arguments 309 * CREATE, MKDIR 310 */ 311 static int 312 nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args) 313 { 314 p = xdr_encode_fhandle(p, args->fh); 315 p = xdr_encode_array(p, args->name, args->len); 316 p = xdr_encode_sattr(p, args->sattr); 317 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 318 return 0; 319 } 320 321 /* 322 * Encode RENAME arguments 323 */ 324 static int 325 nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args) 326 { 327 p = xdr_encode_fhandle(p, args->fromfh); 328 p = xdr_encode_array(p, args->fromname, args->fromlen); 329 p = xdr_encode_fhandle(p, args->tofh); 330 p = xdr_encode_array(p, args->toname, args->tolen); 331 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 332 return 0; 333 } 334 335 /* 336 * Encode LINK arguments 337 */ 338 static int 339 nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args) 340 { 341 p = xdr_encode_fhandle(p, args->fromfh); 342 p = xdr_encode_fhandle(p, args->tofh); 343 p = xdr_encode_array(p, args->toname, args->tolen); 344 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 345 return 0; 346 } 347 348 /* 349 * Encode SYMLINK arguments 350 */ 351 static int 352 nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args) 353 { 354 struct xdr_buf *sndbuf = &req->rq_snd_buf; 355 size_t pad; 356 357 p = xdr_encode_fhandle(p, args->fromfh); 358 p = xdr_encode_array(p, args->fromname, args->fromlen); 359 *p++ = htonl(args->pathlen); 360 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 361 362 xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen); 363 364 /* 365 * xdr_encode_pages may have added a few bytes to ensure the 366 * pathname ends on a 4-byte boundary. Start encoding the 367 * attributes after the pad bytes. 368 */ 369 pad = sndbuf->tail->iov_len; 370 if (pad > 0) 371 p++; 372 p = xdr_encode_sattr(p, args->sattr); 373 sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad; 374 return 0; 375 } 376 377 /* 378 * Encode arguments to readdir call 379 */ 380 static int 381 nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args) 382 { 383 struct rpc_task *task = req->rq_task; 384 struct rpc_auth *auth = task->tk_auth; 385 unsigned int replen; 386 u32 count = args->count; 387 388 p = xdr_encode_fhandle(p, args->fh); 389 *p++ = htonl(args->cookie); 390 *p++ = htonl(count); /* see above */ 391 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 392 393 /* Inline the page array */ 394 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2; 395 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count); 396 return 0; 397 } 398 399 /* 400 * Decode the result of a readdir call. 401 * We're not really decoding anymore, we just leave the buffer untouched 402 * and only check that it is syntactically correct. 403 * The real decoding happens in nfs_decode_entry below, called directly 404 * from nfs_readdir for each entry. 405 */ 406 static int 407 nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) 408 { 409 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 410 struct kvec *iov = rcvbuf->head; 411 struct page **page; 412 int hdrlen, recvd; 413 int status, nr; 414 unsigned int len, pglen; 415 __be32 *end, *entry, *kaddr; 416 417 if ((status = ntohl(*p++))) 418 return -nfs_stat_to_errno(status); 419 420 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 421 if (iov->iov_len < hdrlen) { 422 printk(KERN_WARNING "NFS: READDIR reply header overflowed:" 423 "length %d > %Zu\n", hdrlen, iov->iov_len); 424 return -errno_NFSERR_IO; 425 } else if (iov->iov_len != hdrlen) { 426 dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); 427 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 428 } 429 430 pglen = rcvbuf->page_len; 431 recvd = rcvbuf->len - hdrlen; 432 if (pglen > recvd) 433 pglen = recvd; 434 page = rcvbuf->pages; 435 kaddr = p = kmap_atomic(*page, KM_USER0); 436 end = (__be32 *)((char *)p + pglen); 437 entry = p; 438 for (nr = 0; *p++; nr++) { 439 if (p + 2 > end) 440 goto short_pkt; 441 p++; /* fileid */ 442 len = ntohl(*p++); 443 p += XDR_QUADLEN(len) + 1; /* name plus cookie */ 444 if (len > NFS2_MAXNAMLEN) { 445 printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n", 446 len); 447 goto err_unmap; 448 } 449 if (p + 2 > end) 450 goto short_pkt; 451 entry = p; 452 } 453 if (!nr && (entry[0] != 0 || entry[1] == 0)) 454 goto short_pkt; 455 out: 456 kunmap_atomic(kaddr, KM_USER0); 457 return nr; 458 short_pkt: 459 entry[0] = entry[1] = 0; 460 /* truncate listing ? */ 461 if (!nr) { 462 printk(KERN_NOTICE "NFS: readdir reply truncated!\n"); 463 entry[1] = 1; 464 } 465 goto out; 466 err_unmap: 467 nr = -errno_NFSERR_IO; 468 goto out; 469 } 470 471 __be32 * 472 nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 473 { 474 if (!*p++) { 475 if (!*p) 476 return ERR_PTR(-EAGAIN); 477 entry->eof = 1; 478 return ERR_PTR(-EBADCOOKIE); 479 } 480 481 entry->ino = ntohl(*p++); 482 entry->len = ntohl(*p++); 483 entry->name = (const char *) p; 484 p += XDR_QUADLEN(entry->len); 485 entry->prev_cookie = entry->cookie; 486 entry->cookie = ntohl(*p++); 487 entry->eof = !p[0] && p[1]; 488 489 return p; 490 } 491 492 /* 493 * NFS XDR decode functions 494 */ 495 /* 496 * Decode simple status reply 497 */ 498 static int 499 nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy) 500 { 501 int status; 502 503 if ((status = ntohl(*p++)) != 0) 504 status = -nfs_stat_to_errno(status); 505 return status; 506 } 507 508 /* 509 * Decode attrstat reply 510 * GETATTR, SETATTR, WRITE 511 */ 512 static int 513 nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 514 { 515 int status; 516 517 if ((status = ntohl(*p++))) 518 return -nfs_stat_to_errno(status); 519 xdr_decode_fattr(p, fattr); 520 return 0; 521 } 522 523 /* 524 * Decode diropres reply 525 * LOOKUP, CREATE, MKDIR 526 */ 527 static int 528 nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res) 529 { 530 int status; 531 532 if ((status = ntohl(*p++))) 533 return -nfs_stat_to_errno(status); 534 p = xdr_decode_fhandle(p, res->fh); 535 xdr_decode_fattr(p, res->fattr); 536 return 0; 537 } 538 539 /* 540 * Encode READLINK args 541 */ 542 static int 543 nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args) 544 { 545 struct rpc_auth *auth = req->rq_task->tk_auth; 546 unsigned int replen; 547 548 p = xdr_encode_fhandle(p, args->fh); 549 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 550 551 /* Inline the page array */ 552 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2; 553 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen); 554 return 0; 555 } 556 557 /* 558 * Decode READLINK reply 559 */ 560 static int 561 nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) 562 { 563 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 564 struct kvec *iov = rcvbuf->head; 565 int hdrlen, len, recvd; 566 char *kaddr; 567 int status; 568 569 if ((status = ntohl(*p++))) 570 return -nfs_stat_to_errno(status); 571 /* Convert length of symlink */ 572 len = ntohl(*p++); 573 if (len >= rcvbuf->page_len || len <= 0) { 574 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n"); 575 return -ENAMETOOLONG; 576 } 577 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 578 if (iov->iov_len < hdrlen) { 579 printk(KERN_WARNING "NFS: READLINK reply header overflowed:" 580 "length %d > %Zu\n", hdrlen, iov->iov_len); 581 return -errno_NFSERR_IO; 582 } else if (iov->iov_len != hdrlen) { 583 dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); 584 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 585 } 586 recvd = req->rq_rcv_buf.len - hdrlen; 587 if (recvd < len) { 588 printk(KERN_WARNING "NFS: server cheating in readlink reply: " 589 "count %u > recvd %u\n", len, recvd); 590 return -EIO; 591 } 592 593 /* NULL terminate the string we got */ 594 kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0); 595 kaddr[len+rcvbuf->page_base] = '\0'; 596 kunmap_atomic(kaddr, KM_USER0); 597 return 0; 598 } 599 600 /* 601 * Decode WRITE reply 602 */ 603 static int 604 nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 605 { 606 res->verf->committed = NFS_FILE_SYNC; 607 return nfs_xdr_attrstat(req, p, res->fattr); 608 } 609 610 /* 611 * Decode STATFS reply 612 */ 613 static int 614 nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res) 615 { 616 int status; 617 618 if ((status = ntohl(*p++))) 619 return -nfs_stat_to_errno(status); 620 621 res->tsize = ntohl(*p++); 622 res->bsize = ntohl(*p++); 623 res->blocks = ntohl(*p++); 624 res->bfree = ntohl(*p++); 625 res->bavail = ntohl(*p++); 626 return 0; 627 } 628 629 /* 630 * We need to translate between nfs status return values and 631 * the local errno values which may not be the same. 632 */ 633 static struct { 634 int stat; 635 int errno; 636 } nfs_errtbl[] = { 637 { NFS_OK, 0 }, 638 { NFSERR_PERM, EPERM }, 639 { NFSERR_NOENT, ENOENT }, 640 { NFSERR_IO, errno_NFSERR_IO }, 641 { NFSERR_NXIO, ENXIO }, 642 /* { NFSERR_EAGAIN, EAGAIN }, */ 643 { NFSERR_ACCES, EACCES }, 644 { NFSERR_EXIST, EEXIST }, 645 { NFSERR_XDEV, EXDEV }, 646 { NFSERR_NODEV, ENODEV }, 647 { NFSERR_NOTDIR, ENOTDIR }, 648 { NFSERR_ISDIR, EISDIR }, 649 { NFSERR_INVAL, EINVAL }, 650 { NFSERR_FBIG, EFBIG }, 651 { NFSERR_NOSPC, ENOSPC }, 652 { NFSERR_ROFS, EROFS }, 653 { NFSERR_MLINK, EMLINK }, 654 { NFSERR_NAMETOOLONG, ENAMETOOLONG }, 655 { NFSERR_NOTEMPTY, ENOTEMPTY }, 656 { NFSERR_DQUOT, EDQUOT }, 657 { NFSERR_STALE, ESTALE }, 658 { NFSERR_REMOTE, EREMOTE }, 659 #ifdef EWFLUSH 660 { NFSERR_WFLUSH, EWFLUSH }, 661 #endif 662 { NFSERR_BADHANDLE, EBADHANDLE }, 663 { NFSERR_NOT_SYNC, ENOTSYNC }, 664 { NFSERR_BAD_COOKIE, EBADCOOKIE }, 665 { NFSERR_NOTSUPP, ENOTSUPP }, 666 { NFSERR_TOOSMALL, ETOOSMALL }, 667 { NFSERR_SERVERFAULT, ESERVERFAULT }, 668 { NFSERR_BADTYPE, EBADTYPE }, 669 { NFSERR_JUKEBOX, EJUKEBOX }, 670 { -1, EIO } 671 }; 672 673 /* 674 * Convert an NFS error code to a local one. 675 * This one is used jointly by NFSv2 and NFSv3. 676 */ 677 int 678 nfs_stat_to_errno(int stat) 679 { 680 int i; 681 682 for (i = 0; nfs_errtbl[i].stat != -1; i++) { 683 if (nfs_errtbl[i].stat == stat) 684 return nfs_errtbl[i].errno; 685 } 686 printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat); 687 return nfs_errtbl[i].errno; 688 } 689 690 #ifndef MAX 691 # define MAX(a, b) (((a) > (b))? (a) : (b)) 692 #endif 693 694 #define PROC(proc, argtype, restype, timer) \ 695 [NFSPROC_##proc] = { \ 696 .p_proc = NFSPROC_##proc, \ 697 .p_encode = (kxdrproc_t) nfs_xdr_##argtype, \ 698 .p_decode = (kxdrproc_t) nfs_xdr_##restype, \ 699 .p_bufsiz = MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \ 700 .p_timer = timer, \ 701 .p_statidx = NFSPROC_##proc, \ 702 .p_name = #proc, \ 703 } 704 struct rpc_procinfo nfs_procedures[] = { 705 PROC(GETATTR, fhandle, attrstat, 1), 706 PROC(SETATTR, sattrargs, attrstat, 0), 707 PROC(LOOKUP, diropargs, diropres, 2), 708 PROC(READLINK, readlinkargs, readlinkres, 3), 709 PROC(READ, readargs, readres, 3), 710 PROC(WRITE, writeargs, writeres, 4), 711 PROC(CREATE, createargs, diropres, 0), 712 PROC(REMOVE, diropargs, stat, 0), 713 PROC(RENAME, renameargs, stat, 0), 714 PROC(LINK, linkargs, stat, 0), 715 PROC(SYMLINK, symlinkargs, stat, 0), 716 PROC(MKDIR, createargs, diropres, 0), 717 PROC(RMDIR, diropargs, stat, 0), 718 PROC(READDIR, readdirargs, readdirres, 3), 719 PROC(STATFS, fhandle, statfsres, 0), 720 }; 721 722 struct rpc_version nfs_version2 = { 723 .number = 2, 724 .nrprocs = ARRAY_SIZE(nfs_procedures), 725 .procs = nfs_procedures 726 }; 727