root/fs/nfs/proc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfs_rpc_alloc
  2. nfs_rpc_free
  3. xdr_encode_fhandle
  4. xdr_decode_fhandle
  5. xdr_encode_string
  6. xdr_decode_string
  7. xdr_decode_string2
  8. xdr_encode_data
  9. xdr_decode_data
  10. xdr_decode_fattr
  11. xdr_encode_sattr
  12. xdr_decode_entry
  13. xdr_decode_fsinfo
  14. nfs_proc_getattr
  15. nfs_proc_setattr
  16. nfs_proc_lookup
  17. nfs_proc_readlink
  18. nfs_proc_read
  19. nfs_proc_read_request
  20. nfs_proc_read_reply
  21. nfs_proc_write
  22. nfs_proc_create
  23. nfs_proc_remove
  24. nfs_proc_rename
  25. nfs_proc_link
  26. nfs_proc_symlink
  27. nfs_proc_mkdir
  28. nfs_proc_rmdir
  29. nfs_proc_readdir
  30. nfs_proc_statfs
  31. rpc_header
  32. nfs_rpc_header
  33. rpc_verify
  34. nfs_rpc_verify
  35. nfs_stat_to_errno

   1 /*
   2  *  linux/fs/nfs/proc.c
   3  *
   4  *  Copyright (C) 1992, 1993, 1994  Rick Sladkey
   5  *
   6  *  OS-independent nfs remote procedure call functions
   7  *
   8  *  Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers
   9  *  so at last we can have decent(ish) throughput off a 
  10  *  Sun server.
  11  *
  12  *  Coding optimized and cleaned up by Florian La Roche.
  13  *  Note: Error returns are optimized for NFS_OK, which isn't translated via
  14  *  nfs_stat_to_errno(), but happens to be already the right return code.
  15  *
  16  *  FixMe: We ought to define a sensible small max size for
  17  *  things like getattr that are tiny packets and use the
  18  *  old get_free_page stuff with it.
  19  *
  20  *  Also, the code currently doesn't check the size of the packet, when
  21  *  it decodes the packet.
  22  *
  23  *  Feel free to fix it and mail me the diffs if it worries you.
  24  */
  25 
  26 /*
  27  * Defining NFS_PROC_DEBUG causes a lookup of a file named
  28  * "xyzzy" to toggle debugging.  Just cd to an NFS-mounted
  29  * filesystem and type 'ls xyzzy' to turn on debugging.
  30  */
  31 
  32 #if 1
  33 #define NFS_PROC_DEBUG
  34 #endif
  35 
  36 #include <linux/param.h>
  37 #include <linux/sched.h>
  38 #include <linux/mm.h>
  39 #include <linux/malloc.h>
  40 #include <linux/nfs_fs.h>
  41 #include <linux/utsname.h>
  42 #include <linux/errno.h>
  43 #include <linux/string.h>
  44 #include <linux/in.h>
  45 #include <linux/pagemap.h>
  46 
  47 #include <asm/segment.h>
  48 
  49 #ifdef NFS_PROC_DEBUG
  50 
  51 static int proc_debug = 0;
  52 #define PRINTK(format, args...) \
  53         do {                                            \
  54                 if (proc_debug)                         \
  55                         printk(format , ## args);       \
  56         } while (0)
  57 
  58 #else /* !NFS_PROC_DEBUG */
  59 
  60 #define PRINTK(format, args...) do ; while (0)
  61 
  62 #endif /* !NFS_PROC_DEBUG */
  63 
  64 /* Mapping from NFS error code to "errno" error code. */
  65 #define errno_NFSERR_IO EIO
  66 
  67 static int *nfs_rpc_header(int *p, int procedure, int ruid);
  68 static int *nfs_rpc_verify(int *p);
  69 static int nfs_stat_to_errno(int stat);
  70 
  71 /*
  72  * Our memory allocation and release functions.
  73  */
  74  
  75 #define NFS_SLACK_SPACE         1024    /* Total overkill */ 
  76 /* !!! Be careful, this constant is now also used in sock.c...
  77    We should easily convert to not using it anymore for most cases... */
  78 
  79 static inline int *nfs_rpc_alloc(int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81         int *i;
  82 
  83         while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_NFS))) {
  84                 schedule();
  85         }
  86         return i;
  87 }
  88 
  89 static inline void nfs_rpc_free(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         kfree((void *)p);
  92 }
  93 
  94 /*
  95  * Here are a bunch of xdr encode/decode functions that convert
  96  * between machine dependent and xdr data formats.
  97  */
  98 
  99 #define QUADLEN(len) (((len) + 3) >> 2)
 100 
 101 static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         *((struct nfs_fh *) p) = *fhandle;
 104         return p + QUADLEN(sizeof(*fhandle));
 105 }
 106 
 107 static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         *fhandle = *((struct nfs_fh *) p);
 110         return p + QUADLEN(sizeof(*fhandle));
 111 }
 112 
 113 static inline int *xdr_encode_string(int *p, const char *string)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         int len = strlen(string);
 116         int quadlen = QUADLEN(len);
 117 
 118         p[quadlen] = 0;
 119         *p++ = htonl(len);
 120         memcpy(p, string, len);
 121         return p + quadlen;
 122 }
 123 
 124 static inline int *xdr_decode_string(int *p, char *string, unsigned int maxlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         unsigned int len = ntohl(*p++);
 127         if (len > maxlen)
 128                 return NULL;
 129         memcpy(string, p, len);
 130         string[len] = '\0';
 131         return p + QUADLEN(len);
 132 }
 133 
 134 static inline int *xdr_decode_string2(int *p, char **string, unsigned int *len,
     /* [previous][next][first][last][top][bottom][index][help] */
 135                         unsigned int maxlen)
 136 {
 137         *len = ntohl(*p++);
 138         if (*len > maxlen)
 139                 return NULL;
 140         *string = (char *) p;
 141         return p + QUADLEN(*len);
 142 }
 143 
 144 
 145 static inline int *xdr_encode_data(int *p, const char *data, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147         int quadlen = QUADLEN(len);
 148         
 149         p[quadlen] = 0;
 150         *p++ = htonl(len);
 151         memcpy_fromfs(p, data, len);
 152         return p + quadlen;
 153 }
 154 
 155 static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         unsigned len = *lenp = ntohl(*p++);
 158         if (len > maxlen)
 159                 return NULL;
 160         memcpy(data, p, len);
 161         return p + QUADLEN(len);
 162 }
 163 
 164 static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166         fattr->type = (enum nfs_ftype) ntohl(*p++);
 167         fattr->mode = ntohl(*p++);
 168         fattr->nlink = ntohl(*p++);
 169         fattr->uid = ntohl(*p++);
 170         fattr->gid = ntohl(*p++);
 171         fattr->size = ntohl(*p++);
 172         fattr->blocksize = ntohl(*p++);
 173         fattr->rdev = ntohl(*p++);
 174         fattr->blocks = ntohl(*p++);
 175         fattr->fsid = ntohl(*p++);
 176         fattr->fileid = ntohl(*p++);
 177         fattr->atime.seconds = ntohl(*p++);
 178         fattr->atime.useconds = ntohl(*p++);
 179         fattr->mtime.seconds = ntohl(*p++);
 180         fattr->mtime.useconds = ntohl(*p++);
 181         fattr->ctime.seconds = ntohl(*p++);
 182         fattr->ctime.useconds = ntohl(*p++);
 183         return p;
 184 }
 185 
 186 static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         *p++ = htonl(sattr->mode);
 189         *p++ = htonl(sattr->uid);
 190         *p++ = htonl(sattr->gid);
 191         *p++ = htonl(sattr->size);
 192         *p++ = htonl(sattr->atime.seconds);
 193         *p++ = htonl(sattr->atime.useconds);
 194         *p++ = htonl(sattr->mtime.seconds);
 195         *p++ = htonl(sattr->mtime.useconds);
 196         return p;
 197 }
 198 
 199 static int *xdr_decode_entry(int *p, struct nfs_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201         entry->fileid = ntohl(*p++);
 202         if (!(p = xdr_decode_string(p, entry->name, NFS_MAXNAMLEN)))
 203                 return NULL;
 204         entry->cookie = ntohl(*p++);
 205         entry->eof = 0;
 206         return p;
 207 }
 208 
 209 static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211         res->tsize = ntohl(*p++);
 212         res->bsize = ntohl(*p++);
 213         res->blocks = ntohl(*p++);
 214         res->bfree = ntohl(*p++);
 215         res->bavail = ntohl(*p++);
 216         return p;
 217 }
 218 
 219 /*
 220  * One function for each procedure in the NFS protocol.
 221  */
 222 
 223 int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 224                      struct nfs_fattr *fattr)
 225 {
 226         int *p, *p0;
 227         int status;
 228         int ruid = 0;
 229 
 230         PRINTK("NFS call  getattr\n");
 231         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 232                 return -EIO;
 233 retry:
 234         p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid);
 235         p = xdr_encode_fhandle(p, fhandle);
 236         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 237                 nfs_rpc_free(p0);
 238                 return status;
 239         }
 240         if (!(p = nfs_rpc_verify(p0)))
 241                 status = -errno_NFSERR_IO;
 242         else if ((status = ntohl(*p++)) == NFS_OK) {
 243                 p = xdr_decode_fattr(p, fattr);
 244                 PRINTK("NFS reply getattr\n");
 245                 /* status = 0; */
 246         }
 247         else {
 248                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 249                         ruid = 1;
 250                         goto retry;
 251                 }
 252                 PRINTK("NFS reply getattr failed = %d\n", status);
 253                 status = -nfs_stat_to_errno(status);
 254         }
 255         nfs_rpc_free(p0);
 256         return status;
 257 }
 258 
 259 int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 260                      struct nfs_sattr *sattr, struct nfs_fattr *fattr)
 261 {
 262         int *p, *p0;
 263         int status;
 264         int ruid = 0;
 265 
 266         PRINTK("NFS call  setattr\n");
 267         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 268                 return -EIO;
 269 retry:
 270         p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);
 271         p = xdr_encode_fhandle(p, fhandle);
 272         p = xdr_encode_sattr(p, sattr);
 273         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 274                 nfs_rpc_free(p0);
 275                 return status;
 276         }
 277         if (!(p = nfs_rpc_verify(p0)))
 278                 status = -errno_NFSERR_IO;
 279         else if ((status = ntohl(*p++)) == NFS_OK) {
 280                 p = xdr_decode_fattr(p, fattr);
 281                 PRINTK("NFS reply setattr\n");
 282                 /* status = 0; */
 283         }
 284         else {
 285                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 286                         ruid = 1;
 287                         goto retry;
 288                 }
 289                 PRINTK("NFS reply setattr failed = %d\n", status);
 290                 status = -nfs_stat_to_errno(status);
 291         }
 292         nfs_rpc_free(p0);
 293         return status;
 294 }
 295 
 296 int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
     /* [previous][next][first][last][top][bottom][index][help] */
 297                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 298 {
 299         int *p, *p0;
 300         int status;
 301         int ruid = 0;
 302 
 303         PRINTK("NFS call  lookup %s\n", name);
 304 #ifdef NFS_PROC_DEBUG
 305         if (!strcmp(name, "xyzzy"))
 306                 proc_debug = 1 - proc_debug;
 307 #endif
 308         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 309                 return -EIO;
 310 retry:
 311         p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);
 312         p = xdr_encode_fhandle(p, dir);
 313         p = xdr_encode_string(p, name);
 314         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 315                 nfs_rpc_free(p0);
 316                 return status;
 317         }
 318         if (!(p = nfs_rpc_verify(p0)))
 319                 status = -errno_NFSERR_IO;
 320         else if ((status = ntohl(*p++)) == NFS_OK) {
 321                 p = xdr_decode_fhandle(p, fhandle);
 322                 p = xdr_decode_fattr(p, fattr);
 323                 PRINTK("NFS reply lookup\n");
 324                 /* status = 0; */
 325         }
 326         else {
 327                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 328                         ruid = 1;
 329                         goto retry;
 330                 }
 331                 PRINTK("NFS reply lookup failed = %d\n", status);
 332                 status = -nfs_stat_to_errno(status);
 333         }
 334         nfs_rpc_free(p0);
 335         return status;
 336 }
 337 
 338 int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 339                 int **p0, char **string, unsigned int *len, unsigned int maxlen)
 340 {
 341         int *p;
 342         int status, ruid = 0;
 343 
 344         PRINTK("NFS call  readlink\n");
 345         if (!(*p0 = nfs_rpc_alloc(server->rsize)))
 346                 return -EIO;
 347 retry:
 348         p = nfs_rpc_header(*p0, NFSPROC_READLINK, ruid);
 349         p = xdr_encode_fhandle(p, fhandle);
 350         if ((status = nfs_rpc_call(server, *p0, p, server->rsize)) < 0)
 351                 return status;
 352         if (!(p = nfs_rpc_verify(*p0)))
 353                 status = -errno_NFSERR_IO;
 354         else if ((status = ntohl(*p++)) == NFS_OK) {
 355                 if (!(p = xdr_decode_string2(p, string, len, maxlen))) {
 356                         printk("nfs_proc_readlink: giant pathname\n");
 357                         status = -errno_NFSERR_IO;
 358                 }
 359                 else    /* status = 0, */
 360                         PRINTK("NFS reply readlink\n");
 361         }
 362         else {
 363                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 364                         ruid = 1;
 365                         goto retry;
 366                 }
 367                 PRINTK("NFS reply readlink failed = %d\n", status);
 368                 status = -nfs_stat_to_errno(status);
 369         }
 370         return status;
 371 }
 372 
 373 int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 374           int offset, int count, char *data, struct nfs_fattr *fattr)
 375 {
 376         int *p, *p0;
 377         int status;
 378         int ruid = 0;
 379         int len;
 380 
 381         PRINTK("NFS call  read %d @ %d\n", count, offset);
 382         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 383                 return -EIO;
 384 retry:
 385         p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
 386         p = xdr_encode_fhandle(p, fhandle);
 387         *p++ = htonl(offset);
 388         *p++ = htonl(count);
 389         *p++ = htonl(count); /* traditional, could be any value */
 390         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 391                 nfs_rpc_free(p0);
 392                 return status;
 393         }
 394         if (!(p = nfs_rpc_verify(p0)))
 395                 status = -errno_NFSERR_IO;
 396         else if ((status = ntohl(*p++)) == NFS_OK) {
 397                 p = xdr_decode_fattr(p, fattr);
 398                 if (!(p = xdr_decode_data(p, data, &len, count))) {
 399                         printk("nfs_proc_read: giant data size\n"); 
 400                         status = -errno_NFSERR_IO;
 401                 }
 402                 else {
 403                         status = len;
 404                         PRINTK("NFS reply read %d\n", len);
 405                 }
 406         }
 407         else {
 408                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 409                         ruid = 1;
 410                         goto retry;
 411                 }
 412                 PRINTK("NFS reply read failed = %d\n", status);
 413                 status = -nfs_stat_to_errno(status);
 414         }
 415         nfs_rpc_free(p0);
 416         return status;
 417 }
 418 
 419 int
 420 nfs_proc_read_request(struct rpc_ioreq *req, struct nfs_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 421                         struct nfs_fh *fh, unsigned long offset,
 422                         unsigned long count, __u32 *buf)
 423 {
 424         __u32   *p, *p0;
 425         int     len;
 426 
 427         PRINTK("NFS reqst read %ld @ %ld\n", count, offset);
 428         if (!(p0 = nfs_rpc_alloc(NFS_SLACK_SPACE)))
 429                 return -EIO;
 430 
 431         p = nfs_rpc_header(p0, NFSPROC_READ, 0);
 432         p = xdr_encode_fhandle(p, fh);
 433         *p++ = htonl(offset);
 434         *p++ = htonl(count);
 435         *p++ = htonl(count); /* traditional, could be any value */
 436         req->rq_svec[0].iov_base = p0;
 437         req->rq_svec[0].iov_len  = (p - p0) << 2;
 438         req->rq_slen = (p - p0) << 2;
 439         req->rq_snr = 1;
 440 
 441         len = (6 + 1 + 17 + 1);         /* standard READ reply header */
 442         req->rq_rvec[0].iov_base = p0;
 443         req->rq_rvec[0].iov_len  = len << 2;
 444         req->rq_rvec[1].iov_base = buf;
 445         req->rq_rvec[1].iov_len  = count;
 446         req->rq_rvec[2].iov_base = p0 + len;            /* spill buffer */
 447         req->rq_rvec[2].iov_len  = (NFS_SLACK_SPACE - len) << 2;
 448         req->rq_rlen = count + NFS_SLACK_SPACE;
 449         req->rq_rnr = 3;
 450 
 451         req->rq_addr = &server->toaddr;
 452         req->rq_alen = sizeof(server->toaddr);
 453 
 454         return 0;
 455 }
 456 
 457 int
 458 nfs_proc_read_reply(struct rpc_ioreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 459 {
 460         struct nfs_fattr fattr;
 461         int             status;
 462         __u32           *p0, *p;
 463         int             count;
 464 
 465         p0 = (__u32 *) req->rq_rvec[0].iov_base;
 466 
 467         if (!(p = nfs_rpc_verify(p0))) {
 468                 status = -errno_NFSERR_IO;
 469         } else if ((status = ntohl(*p++)) == NFS_OK) {
 470                 p = xdr_decode_fattr(p, &fattr);
 471                 count = ntohl(*p++);
 472                 if (p != req->rq_rvec[2].iov_base) {
 473                         /* unexpected RPC reply header size. punt.
 474                          * fixme: move iovec contents to align data
 475                          * on page boundary and adjust RPC header size
 476                          * guess. */
 477                         status = -errno_NFSERR_IO;
 478                         PRINTK("NFS reply read odd header size %d\n",
 479                                         (p - p0) << 2);
 480                 } else {
 481                         status = count;
 482                         PRINTK("NFS reply read %d\n", count);
 483                 }
 484         }
 485         else {
 486                 PRINTK("NFS reply read failed = %d\n", status);
 487                 status = -nfs_stat_to_errno(status);
 488         }
 489         nfs_rpc_free(p0);
 490         return status;
 491 }
 492 
 493 int nfs_proc_write(struct inode * inode, int offset,
     /* [previous][next][first][last][top][bottom][index][help] */
 494                    int count, const char *data, struct nfs_fattr *fattr)
 495 {
 496         int *p, *p0;
 497         int status;
 498         int ruid = 0;
 499         void * kdata;   /* address of kernel copy */
 500         struct nfs_server * server = NFS_SERVER(inode);
 501         struct nfs_fh *fhandle = NFS_FH(inode);
 502 
 503         PRINTK("NFS call  write %d @ %d\n", count, offset);
 504         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 505                 return -EIO;
 506 retry:
 507         p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
 508         p = xdr_encode_fhandle(p, fhandle);
 509         *p++ = htonl(offset); /* traditional, could be any value */
 510         *p++ = htonl(offset);
 511         *p++ = htonl(count); /* traditional, could be any value */
 512         kdata = (void *) (p+1); /* start of data in RPC buffer */
 513         p = xdr_encode_data(p, data, count);
 514         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 515                 nfs_rpc_free(p0);
 516                 return status;
 517         }
 518         if (!(p = nfs_rpc_verify(p0)))
 519                 status = -errno_NFSERR_IO;
 520         else if ((status = ntohl(*p++)) == NFS_OK) {
 521                 update_vm_cache(inode, offset, kdata, count);
 522                 p = xdr_decode_fattr(p, fattr);
 523                 PRINTK("NFS reply write\n");
 524                 /* status = 0; */
 525         }
 526         else {
 527                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 528                         ruid = 1;
 529                         goto retry;
 530                 }
 531                 PRINTK("NFS reply write failed = %d\n", status);
 532                 status = -nfs_stat_to_errno(status);
 533         }
 534         nfs_rpc_free(p0);
 535         return status;
 536 }
 537 
 538 int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 539                     const char *name, struct nfs_sattr *sattr,
 540                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 541 {
 542         int *p, *p0;
 543         int status;
 544         int ruid = 0;
 545 
 546         PRINTK("NFS call  create %s\n", name);
 547         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 548                 return -EIO;
 549 retry:
 550         p = nfs_rpc_header(p0, NFSPROC_CREATE, ruid);
 551         p = xdr_encode_fhandle(p, dir);
 552         p = xdr_encode_string(p, name);
 553         p = xdr_encode_sattr(p, sattr);
 554         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 555                 nfs_rpc_free(p0);
 556                 return status;
 557         }
 558         if (!(p = nfs_rpc_verify(p0)))
 559                 status = -errno_NFSERR_IO;
 560         else if ((status = ntohl(*p++)) == NFS_OK) {
 561                 p = xdr_decode_fhandle(p, fhandle);
 562                 p = xdr_decode_fattr(p, fattr);
 563                 PRINTK("NFS reply create\n");
 564                 /* status = 0; */
 565         }
 566         else {
 567                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 568                         ruid = 1;
 569                         goto retry;
 570                 }
 571                 PRINTK("NFS reply create failed = %d\n", status);
 572                 status = -nfs_stat_to_errno(status);
 573         }
 574         nfs_rpc_free(p0);
 575         return status;
 576 }
 577 
 578 int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 579 {
 580         int *p, *p0;
 581         int status;
 582         int ruid = 0;
 583 
 584         PRINTK("NFS call  remove %s\n", name);
 585         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 586                 return -EIO;
 587 retry:
 588         p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
 589         p = xdr_encode_fhandle(p, dir);
 590         p = xdr_encode_string(p, name);
 591         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 592                 nfs_rpc_free(p0);
 593                 return status;
 594         }
 595         if (!(p = nfs_rpc_verify(p0)))
 596                 status = -errno_NFSERR_IO;
 597         else if ((status = ntohl(*p++)) == NFS_OK) {
 598                 PRINTK("NFS reply remove\n");
 599                 /* status = 0; */
 600         }
 601         else {
 602                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 603                         ruid = 1;
 604                         goto retry;
 605                 }
 606                 PRINTK("NFS reply remove failed = %d\n", status);
 607                 status = -nfs_stat_to_errno(status);
 608         }
 609         nfs_rpc_free(p0);
 610         return status;
 611 }
 612 
 613 int nfs_proc_rename(struct nfs_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 614                     struct nfs_fh *old_dir, const char *old_name,
 615                     struct nfs_fh *new_dir, const char *new_name)
 616 {
 617         int *p, *p0;
 618         int status;
 619         int ruid = 0;
 620 
 621         PRINTK("NFS call  rename %s -> %s\n", old_name, new_name);
 622         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 623                 return -EIO;
 624 retry:
 625         p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid);
 626         p = xdr_encode_fhandle(p, old_dir);
 627         p = xdr_encode_string(p, old_name);
 628         p = xdr_encode_fhandle(p, new_dir);
 629         p = xdr_encode_string(p, new_name);
 630         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 631                 nfs_rpc_free(p0);
 632                 return status;
 633         }
 634         if (!(p = nfs_rpc_verify(p0)))
 635                 status = -errno_NFSERR_IO;
 636         else if ((status = ntohl(*p++)) == NFS_OK) {
 637                 PRINTK("NFS reply rename\n");
 638                 /* status = 0; */
 639         }
 640         else {
 641                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 642                         ruid = 1;
 643                         goto retry;
 644                 }
 645                 PRINTK("NFS reply rename failed = %d\n", status);
 646                 status = -nfs_stat_to_errno(status);
 647         }
 648         nfs_rpc_free(p0);
 649         return status;
 650 }
 651 
 652 int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 653                   struct nfs_fh *dir, const char *name)
 654 {
 655         int *p, *p0;
 656         int status;
 657         int ruid = 0;
 658 
 659         PRINTK("NFS call  link %s\n", name);
 660         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 661                 return -EIO;
 662 retry:
 663         p = nfs_rpc_header(p0, NFSPROC_LINK, ruid);
 664         p = xdr_encode_fhandle(p, fhandle);
 665         p = xdr_encode_fhandle(p, dir);
 666         p = xdr_encode_string(p, name);
 667         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 668                 nfs_rpc_free(p0);
 669                 return status;
 670         }
 671         if (!(p = nfs_rpc_verify(p0)))
 672                 status = -errno_NFSERR_IO;
 673         else if ((status = ntohl(*p++)) == NFS_OK) {
 674                 PRINTK("NFS reply link\n");
 675                 /* status = 0; */
 676         }
 677         else {
 678                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 679                         ruid = 1;
 680                         goto retry;
 681                 }
 682                 PRINTK("NFS reply link failed = %d\n", status);
 683                 status = -nfs_stat_to_errno(status);
 684         }
 685         nfs_rpc_free(p0);
 686         return status;
 687 }
 688 
 689 int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 690                      const char *name, const char *path, struct nfs_sattr *sattr)
 691 {
 692         int *p, *p0;
 693         int status;
 694         int ruid = 0;
 695 
 696         PRINTK("NFS call  symlink %s -> %s\n", name, path);
 697         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 698                 return -EIO;
 699 retry:
 700         p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid);
 701         p = xdr_encode_fhandle(p, dir);
 702         p = xdr_encode_string(p, name);
 703         p = xdr_encode_string(p, path);
 704         p = xdr_encode_sattr(p, sattr);
 705         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 706                 nfs_rpc_free(p0);
 707                 return status;
 708         }
 709         if (!(p = nfs_rpc_verify(p0)))
 710                 status = -errno_NFSERR_IO;
 711         else if ((status = ntohl(*p++)) == NFS_OK) {
 712                 PRINTK("NFS reply symlink\n");
 713                 /* status = 0; */
 714         }
 715         else {
 716                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 717                         ruid = 1;
 718                         goto retry;
 719                 }
 720                 PRINTK("NFS reply symlink failed = %d\n", status);
 721                 status = -nfs_stat_to_errno(status);
 722         }
 723         nfs_rpc_free(p0);
 724         return status;
 725 }
 726 
 727 int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 728                    const char *name, struct nfs_sattr *sattr,
 729                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 730 {
 731         int *p, *p0;
 732         int status;
 733         int ruid = 0;
 734 
 735         PRINTK("NFS call  mkdir %s\n", name);
 736         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 737                 return -EIO;
 738 retry:
 739         p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid);
 740         p = xdr_encode_fhandle(p, dir);
 741         p = xdr_encode_string(p, name);
 742         p = xdr_encode_sattr(p, sattr);
 743         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 744                 nfs_rpc_free(p0);
 745                 return status;
 746         }
 747         if (!(p = nfs_rpc_verify(p0)))
 748                 status = -errno_NFSERR_IO;
 749         else if ((status = ntohl(*p++)) == NFS_OK) {
 750                 p = xdr_decode_fhandle(p, fhandle);
 751                 p = xdr_decode_fattr(p, fattr);
 752                 PRINTK("NFS reply mkdir\n");
 753                 /* status = 0; */
 754         }
 755         else {
 756                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 757                         ruid = 1;
 758                         goto retry;
 759                 }
 760                 PRINTK("NFS reply mkdir failed = %d\n", status);
 761                 status = -nfs_stat_to_errno(status);
 762         }
 763         nfs_rpc_free(p0);
 764         return status;
 765 }
 766 
 767 int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 768 {
 769         int *p, *p0;
 770         int status;
 771         int ruid = 0;
 772 
 773         PRINTK("NFS call  rmdir %s\n", name);
 774         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 775                 return -EIO;
 776 retry:
 777         p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
 778         p = xdr_encode_fhandle(p, dir);
 779         p = xdr_encode_string(p, name);
 780         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 781                 nfs_rpc_free(p0);
 782                 return status;
 783         }
 784         if (!(p = nfs_rpc_verify(p0)))
 785                 status = -errno_NFSERR_IO;
 786         else if ((status = ntohl(*p++)) == NFS_OK) {
 787                 PRINTK("NFS reply rmdir\n");
 788                 /* status = 0; */
 789         }
 790         else {
 791                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 792                         ruid = 1;
 793                         goto retry;
 794                 }
 795                 PRINTK("NFS reply rmdir failed = %d\n", status);
 796                 status = -nfs_stat_to_errno(status);
 797         }
 798         nfs_rpc_free(p0);
 799         return status;
 800 }
 801 
 802 int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 803                      int cookie, int count, struct nfs_entry *entry)
 804 {
 805         int *p, *p0;
 806         int status;
 807         int ruid = 0;
 808         int i;
 809         int size;
 810         int eof;
 811 
 812         PRINTK("NFS call  readdir %d @ %d\n", count, cookie);
 813         size = server->rsize;
 814         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 815                 return -EIO;
 816 retry:
 817         p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid);
 818         p = xdr_encode_fhandle(p, fhandle);
 819         *p++ = htonl(cookie);
 820         *p++ = htonl(size);
 821         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 822                 nfs_rpc_free(p0);
 823                 return status;
 824         }
 825         if (!(p = nfs_rpc_verify(p0)))
 826                 status = -errno_NFSERR_IO;
 827         else if ((status = ntohl(*p++)) == NFS_OK) {
 828                 for (i = 0; i < count && *p++; i++) {
 829                         if (!(p = xdr_decode_entry(p, entry++)))
 830                                 break;
 831                 }
 832                 if (!p) {
 833                         printk("nfs_proc_readdir: giant filename\n");
 834                         status = -errno_NFSERR_IO;
 835                 }
 836                 else {
 837                         eof = (i == count && !*p++ && *p++)
 838                               || (i < count && *p++);
 839                         if (eof && i)
 840                                 entry[-1].eof = 1;
 841                         PRINTK("NFS reply readdir %d %s\n", i,
 842                                eof ? "eof" : "");
 843                         status = i;
 844                 }
 845         }
 846         else {
 847                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 848                         ruid = 1;
 849                         goto retry;
 850                 }
 851                 PRINTK("NFS reply readdir failed = %d\n", status);
 852                 status = -nfs_stat_to_errno(status);
 853         }
 854         nfs_rpc_free(p0);
 855         return status;
 856 }
 857 
 858 int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 859                     struct nfs_fsinfo *res)
 860 {
 861         int *p, *p0;
 862         int status;
 863         int ruid = 0;
 864 
 865         PRINTK("NFS call  statfs\n");
 866         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 867                 return -EIO;
 868 retry:
 869         p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
 870         p = xdr_encode_fhandle(p, fhandle);
 871         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 872                 nfs_rpc_free(p0);
 873                 return status;
 874         }
 875         if (!(p = nfs_rpc_verify(p0)))
 876                 status = -errno_NFSERR_IO;
 877         else if ((status = ntohl(*p++)) == NFS_OK) {
 878                 p = xdr_decode_fsinfo(p, res);
 879                 PRINTK("NFS reply statfs\n");
 880                 /* status = 0; */
 881         }
 882         else {
 883                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 884                         ruid = 1;
 885                         goto retry;
 886                 }
 887                 PRINTK("NFS reply statfs failed = %d\n", status);
 888                 status = -nfs_stat_to_errno(status);
 889         }
 890         nfs_rpc_free(p0);
 891         return status;
 892 }
 893 
 894 /*
 895  * Here are a few RPC-assist functions.
 896  */
 897 
 898 int *rpc_header(int *p, int procedure, int program, int version,
     /* [previous][next][first][last][top][bottom][index][help] */
 899                                         int uid, int gid, int *groups)
 900 {
 901         int *p1, *p2;
 902         int i;
 903         static int xid = 0;
 904         unsigned char *sys = (unsigned char *) system_utsname.nodename;
 905 
 906         if (xid == 0) {
 907                 xid = CURRENT_TIME;
 908                 xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0];
 909         }
 910         *p++ = htonl(++xid);
 911         *p++ = htonl(RPC_CALL);
 912         *p++ = htonl(RPC_VERSION);
 913         *p++ = htonl(program);
 914         *p++ = htonl(version);
 915         *p++ = htonl(procedure);
 916         *p++ = htonl(RPC_AUTH_UNIX);
 917         p1 = p++;
 918         *p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
 919         p = xdr_encode_string(p, (char *) sys);
 920         *p++ = htonl(uid);
 921         *p++ = htonl(gid);
 922         p2 = p++;
 923         for (i = 0; i < 16 && i < NGROUPS && groups[i] != NOGROUP; i++)
 924                 *p++ = htonl(groups[i]);
 925         *p2 = htonl(i);
 926         *p1 = htonl((p - (p1 + 1)) << 2);
 927         *p++ = htonl(RPC_AUTH_NULL);
 928         *p++ = htonl(0);
 929         return p;
 930 }
 931 
 932 
 933 static int *nfs_rpc_header(int *p, int procedure, int ruid)
     /* [previous][next][first][last][top][bottom][index][help] */
 934 {
 935         return rpc_header(p, procedure, NFS_PROGRAM, NFS_VERSION,
 936                         (ruid ? current->uid : current->fsuid),
 937                         current->egid, current->groups);
 938 }
 939 
 940 
 941 int *rpc_verify(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 942 {
 943         unsigned int n;
 944 
 945         p++;
 946         if ((n = ntohl(*p++)) != RPC_REPLY) {
 947                 printk("nfs_rpc_verify: not an RPC reply: %x\n", n);
 948                 return NULL;
 949         }
 950         if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
 951                 printk("nfs_rpc_verify: RPC call rejected: %d\n", n);
 952                 return NULL;
 953         }
 954         switch (n = ntohl(*p++)) {
 955         case RPC_AUTH_NULL: case RPC_AUTH_UNIX: case RPC_AUTH_SHORT:
 956                 break;
 957         default:
 958                 printk("nfs_rpc_verify: bad RPC authentication type: %d\n", n);
 959                 return NULL;
 960         }
 961         if ((n = ntohl(*p++)) > 400) {
 962                 printk("nfs_rpc_verify: giant auth size\n");
 963                 return NULL;
 964         }
 965         p += QUADLEN(n);
 966         if ((n = ntohl(*p++)) != RPC_SUCCESS) {
 967                 printk("nfs_rpc_verify: RPC call failed: %d\n", n);
 968                 return NULL;
 969         }
 970         return p;
 971 }
 972 
 973 
 974 static int *nfs_rpc_verify(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 975 {
 976         return rpc_verify(p);
 977 }
 978 
 979 
 980 /*
 981  * We need to translate between nfs status return values and
 982  * the local errno values which may not be the same.
 983  */
 984 
 985 static struct {
 986         int stat;
 987         int errno;
 988 } nfs_errtbl[] = {
 989         { NFS_OK,               0               },
 990         { NFSERR_PERM,          EPERM           },
 991         { NFSERR_NOENT,         ENOENT          },
 992         { NFSERR_IO,            errno_NFSERR_IO },
 993         { NFSERR_NXIO,          ENXIO           },
 994         { NFSERR_EAGAIN,        EAGAIN          },
 995         { NFSERR_ACCES,         EACCES          },
 996         { NFSERR_EXIST,         EEXIST          },
 997         { NFSERR_NODEV,         ENODEV          },
 998         { NFSERR_NOTDIR,        ENOTDIR         },
 999         { NFSERR_ISDIR,         EISDIR          },
1000         { NFSERR_INVAL,         EINVAL          },
1001         { NFSERR_FBIG,          EFBIG           },
1002         { NFSERR_NOSPC,         ENOSPC          },
1003         { NFSERR_ROFS,          EROFS           },
1004         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
1005         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
1006         { NFSERR_DQUOT,         EDQUOT          },
1007         { NFSERR_STALE,         ESTALE          },
1008 #ifdef EWFLUSH
1009         { NFSERR_WFLUSH,        EWFLUSH         },
1010 #endif
1011         { -1,                   EIO             }
1012 };
1013 
1014 static int nfs_stat_to_errno(int stat)
     /* [previous][next][first][last][top][bottom][index][help] */
1015 {
1016         int i;
1017 
1018         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1019                 if (nfs_errtbl[i].stat == stat)
1020                         return nfs_errtbl[i].errno;
1021         }
1022         printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
1023         return nfs_errtbl[i].errno;
1024 }
1025 

/* [previous][next][first][last][top][bottom][index][help] */