root/fs/nfs/proc.c

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

DEFINITIONS

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

   1 /*
   2  *  linux/fs/nfs/proc.c
   3  *
   4  *  Copyright (C) 1992  Rick Sladkey
   5  *
   6  *  OS-independent nfs remote procedure call functions
   7  */
   8 
   9 /*
  10  * Defining NFS_PROC_DEBUG causes a lookup of a file named
  11  * "xyzzy" to toggle debugging.  Just cd to an NFS-mounted
  12  * filesystem and type 'ls xyzzy' to turn on debugging.
  13  */
  14 
  15 #if 0
  16 #define NFS_PROC_DEBUG
  17 #endif
  18 
  19 #include <linux/param.h>
  20 #include <linux/sched.h>
  21 #include <linux/mm.h>
  22 #include <linux/nfs_fs.h>
  23 #include <linux/utsname.h>
  24 #include <linux/errno.h>
  25 #include <linux/string.h>
  26 
  27 #include <netinet/in.h>
  28 
  29 static int proc_debug = 0;
  30 
  31 #ifdef NFS_PROC_DEBUG
  32 #define PRINTK if (proc_debug) printk
  33 #else
  34 #define PRINTK if (0) printk
  35 #endif
  36 
  37 static int *nfs_rpc_header(int *p, int procedure);
  38 static int *nfs_rpc_verify(int *p);
  39 static int nfs_stat_to_errno(int stat);
  40 
  41 /*
  42  * Here are a bunch of xdr encode/decode functions that convert
  43  * between machine dependent and xdr data formats.
  44  */
  45 
  46 static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         *((struct nfs_fh *) p) = *fhandle;
  49         p += (sizeof (*fhandle) + 3) >> 2;
  50         return p;
  51 }
  52 
  53 static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55         *fhandle = *((struct nfs_fh *) p);
  56         p += (sizeof (*fhandle) + 3) >> 2;
  57         return p;
  58 }
  59 
  60 static inline int *xdr_encode_string(int *p, char *string)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62         int len, quadlen;
  63         
  64         len = strlen(string);
  65         quadlen = (len + 3) >> 2;
  66         *p++ = htonl(len);
  67         memcpy((char *) p, string, len);
  68         memset(((char *) p) + len, '\0', (quadlen << 2) - len);
  69         p += quadlen;
  70         return p;
  71 }
  72 
  73 static inline int *xdr_decode_string(int *p, char *string)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75         int len;
  76 
  77         len = ntohl(*p++);
  78         memcpy(string, (char *) p, len);
  79         string[len] = '\0';
  80         p += (len + 3) >> 2;
  81         return p;
  82 }
  83 
  84 static inline int *xdr_encode_data(int *p, char *data, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         int quadlen;
  87         
  88         quadlen = (len + 3) >> 2;
  89         *p++ = htonl(len);
  90         memcpy((char *) p, data, len);
  91         memset(((char *) p) + len, '\0', (quadlen << 2) - len);
  92         p += quadlen;
  93         return p;
  94 }
  95 
  96 static inline int *xdr_decode_data(int *p, char *data, int *lenp)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98         int len;
  99 
 100         len = *lenp = ntohl(*p++);
 101         memcpy(data, (char *) p, len);
 102         data[len] = '\0';
 103         p += (len + 3) >> 2;
 104         return p;
 105 }
 106 
 107 static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         fattr->type = ntohl(*p++);
 110         fattr->mode = ntohl(*p++);
 111         fattr->nlink = ntohl(*p++);
 112         fattr->uid = ntohl(*p++);
 113         fattr->gid = ntohl(*p++);
 114         fattr->size = ntohl(*p++);
 115         fattr->blocksize = ntohl(*p++);
 116         fattr->rdev = ntohl(*p++);
 117         fattr->blocks = ntohl(*p++);
 118         fattr->fsid = ntohl(*p++);
 119         fattr->fileid = ntohl(*p++);
 120         fattr->atime.seconds = ntohl(*p++);
 121         fattr->atime.useconds = ntohl(*p++);
 122         fattr->mtime.seconds = ntohl(*p++);
 123         fattr->mtime.useconds = ntohl(*p++);
 124         fattr->ctime.seconds = ntohl(*p++);
 125         fattr->ctime.useconds = ntohl(*p++);
 126         return p;
 127 }
 128 
 129 static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         *p++ = htonl(sattr->mode);
 132         *p++ = htonl(sattr->uid);
 133         *p++ = htonl(sattr->gid);
 134         *p++ = htonl(sattr->size);
 135         *p++ = htonl(sattr->atime.seconds);
 136         *p++ = htonl(sattr->atime.useconds);
 137         *p++ = htonl(sattr->mtime.seconds);
 138         *p++ = htonl(sattr->mtime.useconds);
 139         return p;
 140 }
 141 
 142 static int *xdr_decode_entry(int *p, struct nfs_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         entry->fileid = ntohl(*p++);
 145         p = xdr_decode_string(p, entry->name);
 146         entry->cookie = ntohl(*p++);
 147         entry->eof = 0;
 148         return p;
 149 }
 150 
 151 static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153         res->tsize = ntohl(*p++);
 154         res->bsize = ntohl(*p++);
 155         res->blocks = ntohl(*p++);
 156         res->bfree = ntohl(*p++);
 157         res->bavail = ntohl(*p++);
 158         return p;
 159 }
 160 
 161 int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 162                      struct nfs_fattr *fattr)
 163 {
 164         int *p, *p0;
 165         int status;
 166 
 167         PRINTK("NFS call  getattr\n");
 168         p = p0 = (int *) get_free_page(GFP_KERNEL);
 169         p = nfs_rpc_header(p, NFSPROC_GETATTR);
 170         p = xdr_encode_fhandle(p, fhandle);
 171         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 172                 free_page((long) p0);
 173                 return status;
 174         }
 175         if (!(p = nfs_rpc_verify(p0)))
 176                 status = NFSERR_IO;
 177         else if ((status = ntohl(*p++)) == NFS_OK) {
 178                 p = xdr_decode_fattr(p, fattr);
 179                 PRINTK("NFS reply getattr\n");
 180         }
 181         free_page((long) p0);
 182         return -nfs_stat_to_errno(status);
 183 }
 184 
 185 int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 186                      struct nfs_sattr *sattr, struct nfs_fattr *fattr)
 187 {
 188         int *p, *p0;
 189         int status;
 190 
 191         PRINTK("NFS call  setattr\n");
 192         p = p0 = (int *) get_free_page(GFP_KERNEL);
 193         p = nfs_rpc_header(p, NFSPROC_SETATTR);
 194         p = xdr_encode_fhandle(p, fhandle);
 195         p = xdr_encode_sattr(p, sattr);
 196         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 197                 free_page((long) p0);
 198                 return status;
 199         }
 200         if (!(p = nfs_rpc_verify(p0)))
 201                 status = NFSERR_IO;
 202         else if ((status = ntohl(*p++)) == NFS_OK) {
 203                 p = xdr_decode_fattr(p, fattr);
 204                 PRINTK("NFS reply setattr\n");
 205         }
 206         free_page((long) p0);
 207         return -nfs_stat_to_errno(status);
 208 }
 209 
 210 int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, char *name,
     /* [previous][next][first][last][top][bottom][index][help] */
 211                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 212 {
 213         int *p, *p0;
 214         int status;
 215 
 216         PRINTK("NFS call  lookup %s\n", name);
 217 #ifdef NFS_PROC_DEBUG
 218         if (!strcmp(name, "xyzzy"))
 219                 proc_debug = 1 - proc_debug;
 220 #endif
 221         p = p0 = (int *) get_free_page(GFP_KERNEL);
 222         p = nfs_rpc_header(p, NFSPROC_LOOKUP);
 223         p = xdr_encode_fhandle(p, dir);
 224         p = xdr_encode_string(p, name);
 225         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 226                 free_page((long) p0);
 227                 return status;
 228         }
 229         if (!(p = nfs_rpc_verify(p0)))
 230                 status = NFSERR_IO;
 231         else if ((status = ntohl(*p++)) == NFS_OK) {
 232                 p = xdr_decode_fhandle(p, fhandle);
 233                 p = xdr_decode_fattr(p, fattr);
 234                 PRINTK("NFS reply lookup\n");
 235         }
 236         free_page((long) p0);
 237         return -nfs_stat_to_errno(status);
 238 }
 239 
 240 int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 241                       char *res)
 242 {
 243         int *p, *p0;
 244         int status;
 245 
 246         PRINTK("NFS call  readlink\n");
 247         p = p0 = (int *) get_free_page(GFP_KERNEL);
 248         p = nfs_rpc_header(p, NFSPROC_READLINK);
 249         p = xdr_encode_fhandle(p, fhandle);
 250         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 251                 free_page((long) p0);
 252                 return status;
 253         }
 254         if (!(p = nfs_rpc_verify(p0)))
 255                 status = NFSERR_IO;
 256         else if ((status = ntohl(*p++)) == NFS_OK) {
 257                 p = xdr_decode_string(p, res);
 258                 PRINTK("NFS reply readlink %s\n", res);
 259         }
 260         free_page((long) p0);
 261         return -nfs_stat_to_errno(status);
 262 }
 263 
 264 int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 265                   int offset, int count, char *data, struct nfs_fattr *fattr)
 266 {
 267         int *p, *p0;
 268         int status;
 269         int len = 0; /* = 0 is for gcc */
 270 
 271         PRINTK("NFS call  read %d @ %d\n", count, offset);
 272         p = p0 = (int *) get_free_page(GFP_KERNEL);
 273         p = nfs_rpc_header(p, NFSPROC_READ);
 274         p = xdr_encode_fhandle(p, fhandle);
 275         *p++ = htonl(offset);
 276         *p++ = htonl(count);
 277         *p++ = htonl(count); /* traditional, could be any value */
 278         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 279                 free_page((long) p0);
 280                 return status;
 281         }
 282         if (!(p = nfs_rpc_verify(p0)))
 283                 status = NFSERR_IO;
 284         else if ((status = ntohl(*p++)) == NFS_OK) {
 285                 p = xdr_decode_fattr(p, fattr);
 286                 p = xdr_decode_data(p, data, &len);
 287                 PRINTK("NFS reply read %d\n", len);
 288         }
 289         free_page((long) p0);
 290         return (status == NFS_OK) ? len : -nfs_stat_to_errno(status);
 291 }
 292 
 293 int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 294                    int offset, int count, char *data, struct nfs_fattr *fattr)
 295 {
 296         int *p, *p0;
 297         int status;
 298 
 299         PRINTK("NFS call  write %d @ %d\n", count, offset);
 300         p = p0 = (int *) get_free_page(GFP_KERNEL);
 301         p = nfs_rpc_header(p, NFSPROC_WRITE);
 302         p = xdr_encode_fhandle(p, fhandle);
 303         *p++ = htonl(offset); /* traditional, could be any value */
 304         *p++ = htonl(offset);
 305         *p++ = htonl(count); /* traditional, could be any value */
 306         p = xdr_encode_data(p, data, count);
 307         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 308                 free_page((long) p0);
 309                 return status;
 310         }
 311         if (!(p = nfs_rpc_verify(p0)))
 312                 status = NFSERR_IO;
 313         else if ((status = ntohl(*p++)) == NFS_OK) {
 314                 p = xdr_decode_fattr(p, fattr);
 315                 PRINTK("NFS reply write\n");
 316         }
 317         free_page((long) p0);
 318         return -nfs_stat_to_errno(status);
 319 }
 320 
 321 int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 322                     char *name, struct nfs_sattr *sattr,
 323                     struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 324 {
 325         int *p, *p0;
 326         int status;
 327 
 328         PRINTK("NFS call  create %s\n", name);
 329         p = p0 = (int *) get_free_page(GFP_KERNEL);
 330         p = nfs_rpc_header(p, NFSPROC_CREATE);
 331         p = xdr_encode_fhandle(p, dir);
 332         p = xdr_encode_string(p, name);
 333         p = xdr_encode_sattr(p, sattr);
 334         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 335                 free_page((long) p0);
 336                 return status;
 337         }
 338         if (!(p = nfs_rpc_verify(p0)))
 339                 status = NFSERR_IO;
 340         else if ((status = ntohl(*p++)) == NFS_OK) {
 341                 p = xdr_decode_fhandle(p, fhandle);
 342                 p = xdr_decode_fattr(p, fattr);
 343                 PRINTK("NFS reply create\n");
 344         }
 345         free_page((long) p0);
 346         return -nfs_stat_to_errno(status);
 347 }
 348 
 349 int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351         int *p, *p0;
 352         int status;
 353 
 354         PRINTK("NFS call  remove %s\n", name);
 355         p = p0 = (int *) get_free_page(GFP_KERNEL);
 356         p = nfs_rpc_header(p, NFSPROC_REMOVE);
 357         p = xdr_encode_fhandle(p, dir);
 358         p = xdr_encode_string(p, name);
 359         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 360                 free_page((long) p0);
 361                 return status;
 362         }
 363         if (!(p = nfs_rpc_verify(p0)))
 364                 status = NFSERR_IO;
 365         else if ((status = ntohl(*p++)) == NFS_OK) {
 366                 PRINTK("NFS reply remove\n");
 367         }
 368         free_page((long) p0);
 369         return -nfs_stat_to_errno(status);
 370 }
 371 
 372 int nfs_proc_rename(struct nfs_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 373                     struct nfs_fh *old_dir, char *old_name,
 374                     struct nfs_fh *new_dir, char *new_name)
 375 {
 376         int *p, *p0;
 377         int status;
 378 
 379         PRINTK("NFS call  rename %s -> %s\n", old_name, new_name);
 380         p = p0 = (int *) get_free_page(GFP_KERNEL);
 381         p = nfs_rpc_header(p, NFSPROC_RENAME);
 382         p = xdr_encode_fhandle(p, old_dir);
 383         p = xdr_encode_string(p, old_name);
 384         p = xdr_encode_fhandle(p, new_dir);
 385         p = xdr_encode_string(p, new_name);
 386         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 387                 free_page((long) p0);
 388                 return status;
 389         }
 390         if (!(p = nfs_rpc_verify(p0)))
 391                 status = NFSERR_IO;
 392         else if ((status = ntohl(*p++)) == NFS_OK) {
 393                 PRINTK("NFS reply rename\n");
 394         }
 395         free_page((long) p0);
 396         return -nfs_stat_to_errno(status);
 397 }
 398 
 399 int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 400                   struct nfs_fh *dir, char *name)
 401 {
 402         int *p, *p0;
 403         int status;
 404 
 405         PRINTK("NFS call  link %s\n", name);
 406         p = p0 = (int *) get_free_page(GFP_KERNEL);
 407         p = nfs_rpc_header(p, NFSPROC_LINK);
 408         p = xdr_encode_fhandle(p, fhandle);
 409         p = xdr_encode_fhandle(p, dir);
 410         p = xdr_encode_string(p, name);
 411         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 412                 free_page((long) p0);
 413                 return status;
 414         }
 415         if (!(p = nfs_rpc_verify(p0)))
 416                 status = NFSERR_IO;
 417         else if ((status = ntohl(*p++)) == NFS_OK) {
 418                 PRINTK("NFS reply link\n");
 419         }
 420         free_page((long) p0);
 421         return -nfs_stat_to_errno(status);
 422 }
 423 
 424 int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 425                      char *name, char *path, struct nfs_sattr *sattr)
 426 {
 427         int *p, *p0;
 428         int status;
 429 
 430         PRINTK("NFS call  symlink %s -> %s\n", name, path);
 431         p = p0 = (int *) get_free_page(GFP_KERNEL);
 432         p = nfs_rpc_header(p, NFSPROC_SYMLINK);
 433         p = xdr_encode_fhandle(p, dir);
 434         p = xdr_encode_string(p, name);
 435         p = xdr_encode_string(p, path);
 436         p = xdr_encode_sattr(p, sattr);
 437         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 438                 free_page((long) p0);
 439                 return status;
 440         }
 441         if (!(p = nfs_rpc_verify(p0)))
 442                 status = NFSERR_IO;
 443         else if ((status = ntohl(*p++)) == NFS_OK) {
 444                 PRINTK("NFS reply symlink\n");
 445         }
 446         free_page((long) p0);
 447         return -nfs_stat_to_errno(status);
 448 }
 449 
 450 int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 451                    char *name, struct nfs_sattr *sattr,
 452                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 453 {
 454         int *p, *p0;
 455         int status;
 456 
 457         PRINTK("NFS call  mkdir %s\n", name);
 458         p = p0 = (int *) get_free_page(GFP_KERNEL);
 459         p = nfs_rpc_header(p, NFSPROC_MKDIR);
 460         p = xdr_encode_fhandle(p, dir);
 461         p = xdr_encode_string(p, name);
 462         p = xdr_encode_sattr(p, sattr);
 463         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 464                 free_page((long) p0);
 465                 return status;
 466         }
 467         if (!(p = nfs_rpc_verify(p0)))
 468                 status = NFSERR_IO;
 469         else if ((status = ntohl(*p++)) == NFS_OK) {
 470                 p = xdr_decode_fhandle(p, fhandle);
 471                 p = xdr_decode_fattr(p, fattr);
 472                 PRINTK("NFS reply mkdir\n");
 473         }
 474         free_page((long) p0);
 475         return -nfs_stat_to_errno(status);
 476 }
 477 
 478 int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480         int *p, *p0;
 481         int status;
 482 
 483         PRINTK("NFS call  rmdir %s\n", name);
 484         p = p0 = (int *) get_free_page(GFP_KERNEL);
 485         p = nfs_rpc_header(p, NFSPROC_RMDIR);
 486         p = xdr_encode_fhandle(p, dir);
 487         p = xdr_encode_string(p, name);
 488         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 489                 free_page((long) p0);
 490                 return status;
 491         }
 492         if (!(p = nfs_rpc_verify(p0)))
 493                 status = NFSERR_IO;
 494         else if ((status = ntohl(*p++)) == NFS_OK) {
 495                 PRINTK("NFS reply rmdir\n");
 496         }
 497         free_page((long) p0);
 498         return -nfs_stat_to_errno(status);
 499 }
 500 
 501 int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 502                      int cookie, int count, struct nfs_entry *entry)
 503 {
 504         int *p, *p0;
 505         int status;
 506         int i = 0; /* = 0 is for gcc */
 507         int size;
 508         int eof;
 509 
 510         PRINTK("NFS call  readdir %d @ %d\n", count, cookie);
 511         size = server->rsize;
 512         p = p0 = (int *) get_free_page(GFP_KERNEL);
 513         p = nfs_rpc_header(p, NFSPROC_READDIR);
 514         p = xdr_encode_fhandle(p, fhandle);
 515         *p++ = htonl(cookie);
 516         *p++ = htonl(size);
 517         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 518                 free_page((long) p0);
 519                 return status;
 520         }
 521         if (!(p = nfs_rpc_verify(p0)))
 522                 status = NFSERR_IO;
 523         else if ((status = ntohl(*p++)) == NFS_OK) {
 524                 for (i = 0; i < count && *p++; i++)
 525                         p = xdr_decode_entry(p, entry++);
 526                 eof = (i == count && !*p++ && *p++) || (i < count && *p++);
 527                 if (eof && i)
 528                         entry[-1].eof = 1;
 529                 PRINTK("NFS reply readdir %d %s\n", i, eof ? "eof" : "");
 530         }
 531         free_page((long) p0);
 532         return (status == NFS_OK) ? i : -nfs_stat_to_errno(status);
 533 }
 534 
 535 int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 536                     struct nfs_fsinfo *res)
 537 {
 538         int *p, *p0;
 539         int status;
 540 
 541         PRINTK("NFS call  statfs\n");
 542         p = p0 = (int *) get_free_page(GFP_KERNEL);
 543         p = nfs_rpc_header(p, NFSPROC_STATFS);
 544         p = xdr_encode_fhandle(p, fhandle);
 545         if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 546                 free_page((long) p0);
 547                 return status;
 548         }
 549         if (!(p = nfs_rpc_verify(p0)))
 550                 status = NFSERR_IO;
 551         else if ((status = ntohl(*p++)) == NFS_OK) {
 552                 p = xdr_decode_fsinfo(p, res);
 553                 PRINTK("NFS reply statfs\n");
 554         }
 555         free_page((long) p0);
 556         return -nfs_stat_to_errno(status);
 557 }
 558 
 559 /*
 560  * Here are a few RPC-assist functions.
 561  */
 562 
 563 static int *nfs_rpc_header(int *p, int procedure)
     /* [previous][next][first][last][top][bottom][index][help] */
 564 {
 565         int *p1, *p2;
 566         int i;
 567         static int xid = 0;
 568         unsigned char *sys = system_utsname.nodename;
 569 
 570         if (xid == 0) {
 571                 xid = CURRENT_TIME;
 572                 xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0];
 573         }
 574         *p++ = htonl(++xid);
 575         *p++ = htonl(RPC_CALL);
 576         *p++ = htonl(RPC_VERSION);
 577         *p++ = htonl(NFS_PROGRAM);
 578         *p++ = htonl(NFS_VERSION);
 579         *p++ = htonl(procedure);
 580         *p++ = htonl(RPC_AUTH_UNIX);
 581         p1 = p++;
 582         *p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
 583         p = xdr_encode_string(p, sys);
 584         *p++ = htonl(current->euid);
 585         *p++ = htonl(current->egid);
 586         p2 = p++;
 587         for (i = 0; i < 16 && i < NGROUPS && current->groups[i] != NOGROUP; i++)
 588                 *p++ = htonl(current->groups[i]);
 589         *p2 = htonl(i);
 590         *p1 = htonl((p - (p1 + 1)) << 2);
 591         *p++ = htonl(RPC_AUTH_NULL);
 592         *p++ = htonl(0);
 593         return p;
 594 }
 595 
 596 static int *nfs_rpc_verify(int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 597 {
 598         int n;
 599 
 600         p++;
 601         if ((n = ntohl(*p++)) != RPC_REPLY) {
 602                 printk("nfs_rpc_verify: not an RPC reply: %d\n", n);
 603                 return 0;
 604         }
 605         if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
 606                 printk("nfs_rpc_verify: RPC call rejected: %d\n", n);
 607                 return 0;
 608         }
 609         if ((n = ntohl(*p++)) != RPC_AUTH_NULL && n != RPC_AUTH_UNIX) {
 610                 printk("nfs_rpc_verify: bad RPC authentication type: %d\n",
 611                         n);
 612                 return 0;
 613         }
 614         n = ntohl(*p++);
 615         p += (n + 3) >> 2;
 616         if ((n = ntohl(*p++)) != RPC_SUCCESS) {
 617                 printk("nfs_rpc_verify: RPC call failed: %d\n", n);
 618                 return 0;
 619         }
 620         return p;
 621 }
 622         
 623 /*
 624  * We need to translate between nfs status return values and
 625  * the local errno values which may not be the same.
 626  */
 627 
 628 #ifndef EDQUOT
 629 #define EDQUOT  ENOSPC
 630 #endif
 631 
 632 static struct {
 633         enum nfs_stat stat;
 634         int errno;
 635 } nfs_errtbl[] = {
 636         { NFS_OK,               0               },
 637         { NFSERR_PERM,          EPERM           },
 638         { NFSERR_NOENT,         ENOENT          },
 639         { NFSERR_IO,            EIO             },
 640         { NFSERR_NXIO,          ENXIO           },
 641         { NFSERR_ACCES,         EACCES          },
 642         { NFSERR_EXIST,         EEXIST          },
 643         { NFSERR_NODEV,         ENODEV          },
 644         { NFSERR_NOTDIR,        ENOTDIR         },
 645         { NFSERR_ISDIR,         EISDIR          },
 646         { NFSERR_FBIG,          EFBIG           },
 647         { NFSERR_NOSPC,         ENOSPC          },
 648         { NFSERR_ROFS,          EROFS           },
 649         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
 650         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
 651         { NFSERR_DQUOT,         EDQUOT          },
 652         { NFSERR_STALE,         ESTALE          },
 653 #ifdef EWFLUSH
 654         { NFSERR_WFLUSH,        EWFLUSH         },
 655 #endif
 656         { -1,                   EIO             }
 657 };
 658 
 659 static int nfs_stat_to_errno(int stat)
     /* [previous][next][first][last][top][bottom][index][help] */
 660 {
 661         int i;
 662 
 663         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
 664                 if (nfs_errtbl[i].stat == stat)
 665                         return nfs_errtbl[i].errno;
 666         }
 667         printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
 668         return nfs_errtbl[i].errno;
 669 }
 670 

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