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

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