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

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