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_write
  20. nfs_proc_create
  21. nfs_proc_remove
  22. nfs_proc_rename
  23. nfs_proc_link
  24. nfs_proc_symlink
  25. nfs_proc_mkdir
  26. nfs_proc_rmdir
  27. nfs_proc_readdir
  28. nfs_proc_statfs
  29. rpc_header
  30. nfs_rpc_header
  31. rpc_verify
  32. nfs_rpc_verify
  33. 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 0
  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 nfs_proc_write(struct inode * inode, int offset,
     /* [previous][next][first][last][top][bottom][index][help] */
 420                    int count, const char *data, struct nfs_fattr *fattr)
 421 {
 422         int *p, *p0;
 423         int status;
 424         int ruid = 0;
 425         void * kdata;   /* address of kernel copy */
 426         struct nfs_server * server = NFS_SERVER(inode);
 427         struct nfs_fh *fhandle = NFS_FH(inode);
 428 
 429         PRINTK("NFS call  write %d @ %d\n", count, offset);
 430         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 431                 return -EIO;
 432 retry:
 433         p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
 434         p = xdr_encode_fhandle(p, fhandle);
 435         *p++ = htonl(offset); /* traditional, could be any value */
 436         *p++ = htonl(offset);
 437         *p++ = htonl(count); /* traditional, could be any value */
 438         kdata = (void *) (p+1); /* start of data in RPC buffer */
 439         p = xdr_encode_data(p, data, count);
 440         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 441                 nfs_rpc_free(p0);
 442                 return status;
 443         }
 444         if (!(p = nfs_rpc_verify(p0)))
 445                 status = -errno_NFSERR_IO;
 446         else if ((status = ntohl(*p++)) == NFS_OK) {
 447                 update_vm_cache(inode, offset, kdata, count);
 448                 p = xdr_decode_fattr(p, fattr);
 449                 PRINTK("NFS reply write\n");
 450                 /* status = 0; */
 451         }
 452         else {
 453                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 454                         ruid = 1;
 455                         goto retry;
 456                 }
 457                 PRINTK("NFS reply write failed = %d\n", status);
 458                 status = -nfs_stat_to_errno(status);
 459         }
 460         nfs_rpc_free(p0);
 461         return status;
 462 }
 463 
 464 int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 465                     const char *name, struct nfs_sattr *sattr,
 466                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 467 {
 468         int *p, *p0;
 469         int status;
 470         int ruid = 0;
 471 
 472         PRINTK("NFS call  create %s\n", name);
 473         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 474                 return -EIO;
 475 retry:
 476         p = nfs_rpc_header(p0, NFSPROC_CREATE, ruid);
 477         p = xdr_encode_fhandle(p, dir);
 478         p = xdr_encode_string(p, name);
 479         p = xdr_encode_sattr(p, sattr);
 480         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 481                 nfs_rpc_free(p0);
 482                 return status;
 483         }
 484         if (!(p = nfs_rpc_verify(p0)))
 485                 status = -errno_NFSERR_IO;
 486         else if ((status = ntohl(*p++)) == NFS_OK) {
 487                 p = xdr_decode_fhandle(p, fhandle);
 488                 p = xdr_decode_fattr(p, fattr);
 489                 PRINTK("NFS reply create\n");
 490                 /* status = 0; */
 491         }
 492         else {
 493                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 494                         ruid = 1;
 495                         goto retry;
 496                 }
 497                 PRINTK("NFS reply create failed = %d\n", status);
 498                 status = -nfs_stat_to_errno(status);
 499         }
 500         nfs_rpc_free(p0);
 501         return status;
 502 }
 503 
 504 int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 505 {
 506         int *p, *p0;
 507         int status;
 508         int ruid = 0;
 509 
 510         PRINTK("NFS call  remove %s\n", name);
 511         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 512                 return -EIO;
 513 retry:
 514         p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
 515         p = xdr_encode_fhandle(p, dir);
 516         p = xdr_encode_string(p, name);
 517         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 518                 nfs_rpc_free(p0);
 519                 return status;
 520         }
 521         if (!(p = nfs_rpc_verify(p0)))
 522                 status = -errno_NFSERR_IO;
 523         else if ((status = ntohl(*p++)) == NFS_OK) {
 524                 PRINTK("NFS reply remove\n");
 525                 /* status = 0; */
 526         }
 527         else {
 528                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 529                         ruid = 1;
 530                         goto retry;
 531                 }
 532                 PRINTK("NFS reply remove failed = %d\n", status);
 533                 status = -nfs_stat_to_errno(status);
 534         }
 535         nfs_rpc_free(p0);
 536         return status;
 537 }
 538 
 539 int nfs_proc_rename(struct nfs_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 540                     struct nfs_fh *old_dir, const char *old_name,
 541                     struct nfs_fh *new_dir, const char *new_name)
 542 {
 543         int *p, *p0;
 544         int status;
 545         int ruid = 0;
 546 
 547         PRINTK("NFS call  rename %s -> %s\n", old_name, new_name);
 548         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 549                 return -EIO;
 550 retry:
 551         p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid);
 552         p = xdr_encode_fhandle(p, old_dir);
 553         p = xdr_encode_string(p, old_name);
 554         p = xdr_encode_fhandle(p, new_dir);
 555         p = xdr_encode_string(p, new_name);
 556         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 557                 nfs_rpc_free(p0);
 558                 return status;
 559         }
 560         if (!(p = nfs_rpc_verify(p0)))
 561                 status = -errno_NFSERR_IO;
 562         else if ((status = ntohl(*p++)) == NFS_OK) {
 563                 PRINTK("NFS reply rename\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 rename 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_link(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 579                   struct nfs_fh *dir, const char *name)
 580 {
 581         int *p, *p0;
 582         int status;
 583         int ruid = 0;
 584 
 585         PRINTK("NFS call  link %s\n", name);
 586         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 587                 return -EIO;
 588 retry:
 589         p = nfs_rpc_header(p0, NFSPROC_LINK, ruid);
 590         p = xdr_encode_fhandle(p, fhandle);
 591         p = xdr_encode_fhandle(p, dir);
 592         p = xdr_encode_string(p, name);
 593         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 594                 nfs_rpc_free(p0);
 595                 return status;
 596         }
 597         if (!(p = nfs_rpc_verify(p0)))
 598                 status = -errno_NFSERR_IO;
 599         else if ((status = ntohl(*p++)) == NFS_OK) {
 600                 PRINTK("NFS reply link\n");
 601                 /* status = 0; */
 602         }
 603         else {
 604                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 605                         ruid = 1;
 606                         goto retry;
 607                 }
 608                 PRINTK("NFS reply link failed = %d\n", status);
 609                 status = -nfs_stat_to_errno(status);
 610         }
 611         nfs_rpc_free(p0);
 612         return status;
 613 }
 614 
 615 int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 616                      const char *name, const char *path, struct nfs_sattr *sattr)
 617 {
 618         int *p, *p0;
 619         int status;
 620         int ruid = 0;
 621 
 622         PRINTK("NFS call  symlink %s -> %s\n", name, path);
 623         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 624                 return -EIO;
 625 retry:
 626         p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid);
 627         p = xdr_encode_fhandle(p, dir);
 628         p = xdr_encode_string(p, name);
 629         p = xdr_encode_string(p, path);
 630         p = xdr_encode_sattr(p, sattr);
 631         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 632                 nfs_rpc_free(p0);
 633                 return status;
 634         }
 635         if (!(p = nfs_rpc_verify(p0)))
 636                 status = -errno_NFSERR_IO;
 637         else if ((status = ntohl(*p++)) == NFS_OK) {
 638                 PRINTK("NFS reply symlink\n");
 639                 /* status = 0; */
 640         }
 641         else {
 642                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 643                         ruid = 1;
 644                         goto retry;
 645                 }
 646                 PRINTK("NFS reply symlink failed = %d\n", status);
 647                 status = -nfs_stat_to_errno(status);
 648         }
 649         nfs_rpc_free(p0);
 650         return status;
 651 }
 652 
 653 int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 654                    const char *name, struct nfs_sattr *sattr,
 655                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 656 {
 657         int *p, *p0;
 658         int status;
 659         int ruid = 0;
 660 
 661         PRINTK("NFS call  mkdir %s\n", name);
 662         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 663                 return -EIO;
 664 retry:
 665         p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid);
 666         p = xdr_encode_fhandle(p, dir);
 667         p = xdr_encode_string(p, name);
 668         p = xdr_encode_sattr(p, sattr);
 669         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 670                 nfs_rpc_free(p0);
 671                 return status;
 672         }
 673         if (!(p = nfs_rpc_verify(p0)))
 674                 status = -errno_NFSERR_IO;
 675         else if ((status = ntohl(*p++)) == NFS_OK) {
 676                 p = xdr_decode_fhandle(p, fhandle);
 677                 p = xdr_decode_fattr(p, fattr);
 678                 PRINTK("NFS reply mkdir\n");
 679                 /* status = 0; */
 680         }
 681         else {
 682                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 683                         ruid = 1;
 684                         goto retry;
 685                 }
 686                 PRINTK("NFS reply mkdir failed = %d\n", status);
 687                 status = -nfs_stat_to_errno(status);
 688         }
 689         nfs_rpc_free(p0);
 690         return status;
 691 }
 692 
 693 int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 694 {
 695         int *p, *p0;
 696         int status;
 697         int ruid = 0;
 698 
 699         PRINTK("NFS call  rmdir %s\n", name);
 700         if (!(p0 = nfs_rpc_alloc(server->wsize)))
 701                 return -EIO;
 702 retry:
 703         p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
 704         p = xdr_encode_fhandle(p, dir);
 705         p = xdr_encode_string(p, name);
 706         if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
 707                 nfs_rpc_free(p0);
 708                 return status;
 709         }
 710         if (!(p = nfs_rpc_verify(p0)))
 711                 status = -errno_NFSERR_IO;
 712         else if ((status = ntohl(*p++)) == NFS_OK) {
 713                 PRINTK("NFS reply rmdir\n");
 714                 /* status = 0; */
 715         }
 716         else {
 717                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 718                         ruid = 1;
 719                         goto retry;
 720                 }
 721                 PRINTK("NFS reply rmdir failed = %d\n", status);
 722                 status = -nfs_stat_to_errno(status);
 723         }
 724         nfs_rpc_free(p0);
 725         return status;
 726 }
 727 
 728 int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 729                      int cookie, int count, struct nfs_entry *entry)
 730 {
 731         int *p, *p0;
 732         int status;
 733         int ruid = 0;
 734         int i;
 735         int size;
 736         int eof;
 737 
 738         PRINTK("NFS call  readdir %d @ %d\n", count, cookie);
 739         size = server->rsize;
 740         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 741                 return -EIO;
 742 retry:
 743         p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid);
 744         p = xdr_encode_fhandle(p, fhandle);
 745         *p++ = htonl(cookie);
 746         *p++ = htonl(size);
 747         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 748                 nfs_rpc_free(p0);
 749                 return status;
 750         }
 751         if (!(p = nfs_rpc_verify(p0)))
 752                 status = -errno_NFSERR_IO;
 753         else if ((status = ntohl(*p++)) == NFS_OK) {
 754                 for (i = 0; i < count && *p++; i++) {
 755                         if (!(p = xdr_decode_entry(p, entry++)))
 756                                 break;
 757                 }
 758                 if (!p) {
 759                         printk("nfs_proc_readdir: giant filename\n");
 760                         status = -errno_NFSERR_IO;
 761                 }
 762                 else {
 763                         eof = (i == count && !*p++ && *p++)
 764                               || (i < count && *p++);
 765                         if (eof && i)
 766                                 entry[-1].eof = 1;
 767                         PRINTK("NFS reply readdir %d %s\n", i,
 768                                eof ? "eof" : "");
 769                         status = i;
 770                 }
 771         }
 772         else {
 773                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 774                         ruid = 1;
 775                         goto retry;
 776                 }
 777                 PRINTK("NFS reply readdir failed = %d\n", status);
 778                 status = -nfs_stat_to_errno(status);
 779         }
 780         nfs_rpc_free(p0);
 781         return status;
 782 }
 783 
 784 int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 785                     struct nfs_fsinfo *res)
 786 {
 787         int *p, *p0;
 788         int status;
 789         int ruid = 0;
 790 
 791         PRINTK("NFS call  statfs\n");
 792         if (!(p0 = nfs_rpc_alloc(server->rsize)))
 793                 return -EIO;
 794 retry:
 795         p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
 796         p = xdr_encode_fhandle(p, fhandle);
 797         if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
 798                 nfs_rpc_free(p0);
 799                 return status;
 800         }
 801         if (!(p = nfs_rpc_verify(p0)))
 802                 status = -errno_NFSERR_IO;
 803         else if ((status = ntohl(*p++)) == NFS_OK) {
 804                 p = xdr_decode_fsinfo(p, res);
 805                 PRINTK("NFS reply statfs\n");
 806                 /* status = 0; */
 807         }
 808         else {
 809                 if (!ruid && current->fsuid == 0 && current->uid != 0) {
 810                         ruid = 1;
 811                         goto retry;
 812                 }
 813                 PRINTK("NFS reply statfs failed = %d\n", status);
 814                 status = -nfs_stat_to_errno(status);
 815         }
 816         nfs_rpc_free(p0);
 817         return status;
 818 }
 819 
 820 /*
 821  * Here are a few RPC-assist functions.
 822  */
 823 
 824 int *rpc_header(int *p, int procedure, int program, int version,
     /* [previous][next][first][last][top][bottom][index][help] */
 825                                         int uid, int gid, int *groups)
 826 {
 827         int *p1, *p2;
 828         int i;
 829         static int xid = 0;
 830         unsigned char *sys = (unsigned char *) system_utsname.nodename;
 831 
 832         if (xid == 0) {
 833                 xid = CURRENT_TIME;
 834                 xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0];
 835         }
 836         *p++ = htonl(++xid);
 837         *p++ = htonl(RPC_CALL);
 838         *p++ = htonl(RPC_VERSION);
 839         *p++ = htonl(program);
 840         *p++ = htonl(version);
 841         *p++ = htonl(procedure);
 842         *p++ = htonl(RPC_AUTH_UNIX);
 843         p1 = p++;
 844         *p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
 845         p = xdr_encode_string(p, (char *) sys);
 846         *p++ = htonl(uid);
 847         *p++ = htonl(gid);
 848         p2 = p++;
 849         for (i = 0; i < 16 && i < NGROUPS && groups[i] != NOGROUP; i++)
 850                 *p++ = htonl(groups[i]);
 851         *p2 = htonl(i);
 852         *p1 = htonl((p - (p1 + 1)) << 2);
 853         *p++ = htonl(RPC_AUTH_NULL);
 854         *p++ = htonl(0);
 855         return p;
 856 }
 857 
 858 
 859 static int *nfs_rpc_header(int *p, int procedure, int ruid)
     /* [previous][next][first][last][top][bottom][index][help] */
 860 {
 861         return rpc_header(p, procedure, NFS_PROGRAM, NFS_VERSION,
 862                         (ruid ? current->uid : current->fsuid),
 863                         current->egid, current->groups);
 864 }
 865 
 866 
 867 int *rpc_verify(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 868 {
 869         unsigned int n;
 870 
 871         p++;
 872         if ((n = ntohl(*p++)) != RPC_REPLY) {
 873                 printk("nfs_rpc_verify: not an RPC reply: %d\n", n);
 874                 return NULL;
 875         }
 876         if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
 877                 printk("nfs_rpc_verify: RPC call rejected: %d\n", n);
 878                 return NULL;
 879         }
 880         switch (n = ntohl(*p++)) {
 881         case RPC_AUTH_NULL: case RPC_AUTH_UNIX: case RPC_AUTH_SHORT:
 882                 break;
 883         default:
 884                 printk("nfs_rpc_verify: bad RPC authentication type: %d\n", n);
 885                 return NULL;
 886         }
 887         if ((n = ntohl(*p++)) > 400) {
 888                 printk("nfs_rpc_verify: giant auth size\n");
 889                 return NULL;
 890         }
 891         p += QUADLEN(n);
 892         if ((n = ntohl(*p++)) != RPC_SUCCESS) {
 893                 printk("nfs_rpc_verify: RPC call failed: %d\n", n);
 894                 return NULL;
 895         }
 896         return p;
 897 }
 898 
 899 
 900 static int *nfs_rpc_verify(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 901 {
 902         return rpc_verify(p);
 903 }
 904 
 905 
 906 /*
 907  * We need to translate between nfs status return values and
 908  * the local errno values which may not be the same.
 909  */
 910 
 911 static struct {
 912         int stat;
 913         int errno;
 914 } nfs_errtbl[] = {
 915         { NFS_OK,               0               },
 916         { NFSERR_PERM,          EPERM           },
 917         { NFSERR_NOENT,         ENOENT          },
 918         { NFSERR_IO,            errno_NFSERR_IO },
 919         { NFSERR_NXIO,          ENXIO           },
 920         { NFSERR_EAGAIN,        EAGAIN          },
 921         { NFSERR_ACCES,         EACCES          },
 922         { NFSERR_EXIST,         EEXIST          },
 923         { NFSERR_NODEV,         ENODEV          },
 924         { NFSERR_NOTDIR,        ENOTDIR         },
 925         { NFSERR_ISDIR,         EISDIR          },
 926         { NFSERR_INVAL,         EINVAL          },
 927         { NFSERR_FBIG,          EFBIG           },
 928         { NFSERR_NOSPC,         ENOSPC          },
 929         { NFSERR_ROFS,          EROFS           },
 930         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
 931         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
 932         { NFSERR_DQUOT,         EDQUOT          },
 933         { NFSERR_STALE,         ESTALE          },
 934 #ifdef EWFLUSH
 935         { NFSERR_WFLUSH,        EWFLUSH         },
 936 #endif
 937         { -1,                   EIO             }
 938 };
 939 
 940 static int nfs_stat_to_errno(int stat)
     /* [previous][next][first][last][top][bottom][index][help] */
 941 {
 942         int i;
 943 
 944         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
 945                 if (nfs_errtbl[i].stat == stat)
 946                         return nfs_errtbl[i].errno;
 947         }
 948         printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
 949         return nfs_errtbl[i].errno;
 950 }
 951 

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