root/fs/nfs/dir.c

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

DEFINITIONS

This source file includes following definitions.
  1. nfs_dir_read
  2. nfs_readdir
  3. nfs_kfree_cache
  4. nfs_lookup_cache_index
  5. nfs_lookup_cache_lookup
  6. nfs_lookup_cache_add
  7. nfs_lookup_cache_remove
  8. nfs_lookup_cache_refresh
  9. nfs_lookup
  10. nfs_create
  11. nfs_mknod
  12. nfs_mkdir
  13. nfs_rmdir
  14. nfs_unlink
  15. nfs_symlink
  16. nfs_link
  17. nfs_rename
  18. nfs_refresh_inode

   1 /*
   2  *  linux/fs/nfs/dir.c
   3  *
   4  *  Copyright (C) 1992  Rick Sladkey
   5  *
   6  *  nfs directory handling functions
   7  */
   8 
   9 #include <linux/sched.h>
  10 #include <linux/errno.h>
  11 #include <linux/stat.h>
  12 #include <linux/nfs_fs.h>
  13 #include <linux/fcntl.h>
  14 #include <linux/string.h>
  15 #include <linux/kernel.h>
  16 #include <linux/malloc.h>
  17 #include <linux/mm.h>
  18 
  19 #include <asm/segment.h>        /* for fs functions */
  20 
  21 static int nfs_dir_read(struct inode *, struct file *filp, char *buf,
  22                         int count);
  23 static int nfs_readdir(struct inode *, struct file *, void *, filldir_t);
  24 static int nfs_lookup(struct inode *dir, const char *name, int len,
  25                       struct inode **result);
  26 static int nfs_create(struct inode *dir, const char *name, int len, int mode,
  27                       struct inode **result);
  28 static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode);
  29 static int nfs_rmdir(struct inode *dir, const char *name, int len);
  30 static int nfs_unlink(struct inode *dir, const char *name, int len);
  31 static int nfs_symlink(struct inode *inode, const char *name, int len,
  32                        const char *symname);
  33 static int nfs_link(struct inode *oldinode, struct inode *dir,
  34                     const char *name, int len);
  35 static int nfs_mknod(struct inode *dir, const char *name, int len, int mode,
  36                      int rdev);
  37 static int nfs_rename(struct inode *old_dir, const char *old_name,
  38                       int old_len, struct inode *new_dir, const char *new_name,
  39                       int new_len);
  40 
  41 static struct file_operations nfs_dir_operations = {
  42         NULL,                   /* lseek - default */
  43         nfs_dir_read,           /* read - bad */
  44         NULL,                   /* write - bad */
  45         nfs_readdir,            /* readdir */
  46         NULL,                   /* select - default */
  47         NULL,                   /* ioctl - default */
  48         NULL,                   /* mmap */
  49         NULL,                   /* no special open code */
  50         NULL,                   /* no special release code */
  51         NULL                    /* fsync */
  52 };
  53 
  54 struct inode_operations nfs_dir_inode_operations = {
  55         &nfs_dir_operations,    /* default directory file-ops */
  56         nfs_create,             /* create */
  57         nfs_lookup,             /* lookup */
  58         nfs_link,               /* link */
  59         nfs_unlink,             /* unlink */
  60         nfs_symlink,            /* symlink */
  61         nfs_mkdir,              /* mkdir */
  62         nfs_rmdir,              /* rmdir */
  63         nfs_mknod,              /* mknod */
  64         nfs_rename,             /* rename */
  65         NULL,                   /* readlink */
  66         NULL,                   /* follow_link */
  67         NULL,                   /* bmap */
  68         NULL,                   /* truncate */
  69         NULL                    /* permission */
  70 };
  71 
  72 static int nfs_dir_read(struct inode *inode, struct file *filp, char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
  73                         int count)
  74 {
  75         return -EISDIR;
  76 }
  77 
  78 static struct nfs_entry *c_entry = NULL;
  79 
  80 /*
  81  * We need to do caching of directory entries to prevent an
  82  * incredible amount of RPC traffic.  Only the most recent open
  83  * directory is cached.  This seems sufficient for most purposes.
  84  * Technically, we ought to flush the cache on close but this is
  85  * not a problem in practice.
  86  */
  87 
  88 static int nfs_readdir(struct inode *inode, struct file *filp,
     /* [previous][next][first][last][top][bottom][index][help] */
  89                        void *dirent, filldir_t filldir)
  90 {
  91         static kdev_t c_dev = 0;
  92         static int c_ino;
  93         static int c_size;
  94 
  95         int result;
  96         int i, index = 0;
  97         struct nfs_entry *entry;
  98 
  99         if (!inode || !S_ISDIR(inode->i_mode)) {
 100                 printk("nfs_readdir: inode is NULL or not a directory\n");
 101                 return -EBADF;
 102         }
 103 
 104         /* initialize cache memory if it hasn't been used before */
 105 
 106         if (c_entry == NULL) {
 107                 i = sizeof (struct nfs_entry)*NFS_READDIR_CACHE_SIZE;
 108                 c_entry = (struct nfs_entry *) kmalloc(i, GFP_KERNEL);
 109                 if (c_entry == NULL) {
 110                         printk("nfs_readdir: no MEMORY for cache\n");
 111                         return -ENOMEM;
 112                 }
 113                 for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++) {
 114                         c_entry[i].name = (char *) kmalloc(NFS_MAXNAMLEN + 1,
 115                                 GFP_KERNEL);
 116                         if (c_entry[i].name == NULL) {
 117                                 printk("nfs_readdir: no MEMORY for cache\n");
 118                                 while (--i>=0)
 119                                         kfree(c_entry[i].name);
 120                                 kfree(c_entry);
 121                                 c_entry = NULL;
 122                                 return -ENOMEM;
 123                         }
 124                 }
 125         }
 126         entry = NULL;
 127 
 128         /* try to find it in the cache */
 129 
 130         if (inode->i_dev == c_dev && inode->i_ino == c_ino) {
 131                 for (i = 0; i < c_size; i++) {
 132                         if (filp->f_pos == c_entry[i].cookie) {
 133                                 if (i == c_size - 1) {
 134                                         if (c_entry[i].eof)
 135                                                 return 0;
 136                                 }
 137                                 else
 138                                         entry = c_entry + (index = i + 1);
 139                                 break;
 140                         }
 141                 }
 142         }
 143 
 144         /* if we didn't find it in the cache, revert to an nfs call */
 145 
 146         if (!entry) {
 147                 result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(inode),
 148                         filp->f_pos, NFS_READDIR_CACHE_SIZE, c_entry);
 149                 if (result < 0) {
 150                         c_dev = 0;
 151                         return result;
 152                 }
 153                 if (result > 0) {
 154                         c_dev = inode->i_dev;
 155                         c_ino = inode->i_ino;
 156                         c_size = result;
 157                         entry = c_entry + (index = 0);
 158                 }
 159         }
 160 
 161         /* if we found it in the cache or from an nfs call, return results */
 162         if (!entry)
 163                 return 0;
 164         while (index < c_size) {
 165                 int nextpos = entry->cookie;
 166                 if (filldir(dirent, entry->name, strlen(entry->name), filp->f_pos, entry->fileid) < 0)
 167                         break;
 168                 filp->f_pos = nextpos;
 169                 /* revalidate the cache if we slept in filldir() */
 170                 if (inode->i_dev != c_dev)
 171                         break;
 172                 if (inode->i_ino != c_ino)
 173                         break;
 174                 if (nextpos != entry->cookie)
 175                         break;
 176                 index++;
 177                 entry++;
 178         }
 179         return 0;
 180 }
 181 
 182 /*
 183  * free cache memory
 184  * called from cleanup_module
 185  */
 186 
 187 void nfs_kfree_cache(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 188 {
 189         int i;
 190 
 191         if (c_entry == NULL)
 192                 return;
 193         for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++)
 194                 kfree(c_entry[i].name);
 195         kfree(c_entry);
 196         c_entry = NULL;
 197 }
 198  
 199 
 200 /*
 201  * Lookup caching is a big win for performance but this is just
 202  * a trial to see how well it works on a small scale.
 203  * For example, bash does a lookup on ".." 13 times for each path
 204  * element when running pwd.  Yes, hard to believe but true.
 205  * Try pwd in a filesystem mounted with noac.
 206  *
 207  * It trades a little cpu time and memory for a lot of network bandwidth.
 208  * Since the cache is not hashed yet, it is a good idea not to make it too
 209  * large because every lookup looks through the entire cache even
 210  * though most of them will fail.
 211  */
 212 
 213 static struct nfs_lookup_cache_entry {
 214         kdev_t dev;
 215         int inode;
 216         char filename[NFS_MAXNAMLEN + 1];
 217         struct nfs_fh fhandle;
 218         struct nfs_fattr fattr;
 219         int expiration_date;
 220 } nfs_lookup_cache[NFS_LOOKUP_CACHE_SIZE];
 221 
 222 static struct nfs_lookup_cache_entry *nfs_lookup_cache_index(struct inode *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 223                                                              const char *filename)
 224 {
 225         struct nfs_lookup_cache_entry *entry;
 226         int i;
 227 
 228         for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
 229                 entry = nfs_lookup_cache + i;
 230                 if (entry->dev == dir->i_dev
 231                     && entry->inode == dir->i_ino
 232                     && !strncmp(filename, entry->filename, NFS_MAXNAMLEN))
 233                         return entry;
 234         }
 235         return NULL;
 236 }
 237 
 238 static int nfs_lookup_cache_lookup(struct inode *dir, const char *filename,
     /* [previous][next][first][last][top][bottom][index][help] */
 239                                    struct nfs_fh *fhandle,
 240                                    struct nfs_fattr *fattr)
 241 {
 242         static int nfs_lookup_cache_in_use = 0;
 243 
 244         struct nfs_lookup_cache_entry *entry;
 245 
 246         if (!nfs_lookup_cache_in_use) {
 247                 memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache));
 248                 nfs_lookup_cache_in_use = 1;
 249         }
 250         if ((entry = nfs_lookup_cache_index(dir, filename))) {
 251                 if (jiffies > entry->expiration_date) {
 252                         entry->dev = 0;
 253                         return 0;
 254                 }
 255                 *fhandle = entry->fhandle;
 256                 *fattr = entry->fattr;
 257                 return 1;
 258         }
 259         return 0;
 260 }
 261 
 262 static void nfs_lookup_cache_add(struct inode *dir, const char *filename,
     /* [previous][next][first][last][top][bottom][index][help] */
 263                                  struct nfs_fh *fhandle,
 264                                  struct nfs_fattr *fattr)
 265 {
 266         static int nfs_lookup_cache_pos = 0;
 267         struct nfs_lookup_cache_entry *entry;
 268 
 269         /* compensate for bug in SGI NFS server */
 270         if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1
 271             || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1)
 272                 return;
 273         if (!(entry = nfs_lookup_cache_index(dir, filename))) {
 274                 entry = nfs_lookup_cache + nfs_lookup_cache_pos++;
 275                 if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE)
 276                         nfs_lookup_cache_pos = 0;
 277         }
 278         entry->dev = dir->i_dev;
 279         entry->inode = dir->i_ino;
 280         strcpy(entry->filename, filename);
 281         entry->fhandle = *fhandle;
 282         entry->fattr = *fattr;
 283         entry->expiration_date = jiffies + (S_ISDIR(fattr->mode)
 284                 ? NFS_SERVER(dir)->acdirmin : NFS_SERVER(dir)->acregmin);
 285 }
 286 
 287 static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
 288                                     const char *filename)
 289 {
 290         struct nfs_lookup_cache_entry *entry;
 291         kdev_t dev;
 292         int fileid;
 293         int i;
 294 
 295         if (inode) {
 296                 dev = inode->i_dev;
 297                 fileid = inode->i_ino;
 298         }
 299         else if ((entry = nfs_lookup_cache_index(dir, filename))) {
 300                 dev = entry->dev;
 301                 fileid = entry->fattr.fileid;
 302         }
 303         else
 304                 return;
 305         for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
 306                 entry = nfs_lookup_cache + i;
 307                 if (entry->dev == dev && entry->fattr.fileid == fileid)
 308                         entry->dev = 0;
 309         }
 310 }
 311 
 312 static void nfs_lookup_cache_refresh(struct inode *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 313                                      struct nfs_fattr *fattr)
 314 {
 315         struct nfs_lookup_cache_entry *entry;
 316         kdev_t dev = file->i_dev;
 317         int fileid = file->i_ino;
 318         int i;
 319 
 320         for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
 321                 entry = nfs_lookup_cache + i;
 322                 if (entry->dev == dev && entry->fattr.fileid == fileid)
 323                         entry->fattr = *fattr;
 324         }
 325 }
 326 
 327 static int nfs_lookup(struct inode *dir, const char *__name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 328                       struct inode **result)
 329 {
 330         struct nfs_fh fhandle;
 331         struct nfs_fattr fattr;
 332         char name[len > NFS_MAXNAMLEN? 1 : len+1];
 333         int error;
 334 
 335         *result = NULL;
 336         if (!dir || !S_ISDIR(dir->i_mode)) {
 337                 printk("nfs_lookup: inode is NULL or not a directory\n");
 338                 iput(dir);
 339                 return -ENOENT;
 340         }
 341         if (len > NFS_MAXNAMLEN) {
 342                 iput(dir);
 343                 return -ENAMETOOLONG;
 344         }
 345         memcpy(name,__name,len);
 346         name[len] = '\0';
 347         if (len == 1 && name[0] == '.') { /* cheat for "." */
 348                 *result = dir;
 349                 return 0;
 350         }
 351         if ((NFS_SERVER(dir)->flags & NFS_MOUNT_NOAC)
 352             || !nfs_lookup_cache_lookup(dir, name, &fhandle, &fattr)) {
 353                 if ((error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
 354                     name, &fhandle, &fattr))) {
 355                         iput(dir);
 356                         return error;
 357                 }
 358                 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
 359         }
 360         if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
 361                 iput(dir);
 362                 return -EACCES;
 363         }
 364         iput(dir);
 365         return 0;
 366 }
 367 
 368 static int nfs_create(struct inode *dir, const char *name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 369                       struct inode **result)
 370 {
 371         struct nfs_sattr sattr;
 372         struct nfs_fattr fattr;
 373         struct nfs_fh fhandle;
 374         int error;
 375 
 376         *result = NULL;
 377         if (!dir || !S_ISDIR(dir->i_mode)) {
 378                 printk("nfs_create: inode is NULL or not a directory\n");
 379                 iput(dir);
 380                 return -ENOENT;
 381         }
 382         if (len > NFS_MAXNAMLEN) {
 383                 iput(dir);
 384                 return -ENAMETOOLONG;
 385         }
 386         sattr.mode = mode;
 387         sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 388         sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 389         if ((error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
 390                 name, &sattr, &fhandle, &fattr))) {
 391                 iput(dir);
 392                 return error;
 393         }
 394         if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
 395                 iput(dir);
 396                 return -EACCES;
 397         }
 398         nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
 399         iput(dir);
 400         return 0;
 401 }
 402 
 403 static int nfs_mknod(struct inode *dir, const char *name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 404                      int mode, int rdev)
 405 {
 406         struct nfs_sattr sattr;
 407         struct nfs_fattr fattr;
 408         struct nfs_fh fhandle;
 409         int error;
 410 
 411         if (!dir || !S_ISDIR(dir->i_mode)) {
 412                 printk("nfs_mknod: inode is NULL or not a directory\n");
 413                 iput(dir);
 414                 return -ENOENT;
 415         }
 416         if (len > NFS_MAXNAMLEN) {
 417                 iput(dir);
 418                 return -ENAMETOOLONG;
 419         }
 420         sattr.mode = mode;
 421         sattr.uid = sattr.gid = (unsigned) -1;
 422         if (S_ISCHR(mode) || S_ISBLK(mode))
 423                 sattr.size = rdev; /* get out your barf bag */
 424         else
 425                 sattr.size = (unsigned) -1;
 426         sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 427         error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
 428                 name, &sattr, &fhandle, &fattr);
 429         if (!error)
 430                 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
 431         iput(dir);
 432         return error;
 433 }
 434 
 435 static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 436 {
 437         struct nfs_sattr sattr;
 438         struct nfs_fattr fattr;
 439         struct nfs_fh fhandle;
 440         int error;
 441 
 442         if (!dir || !S_ISDIR(dir->i_mode)) {
 443                 printk("nfs_mkdir: inode is NULL or not a directory\n");
 444                 iput(dir);
 445                 return -ENOENT;
 446         }
 447         if (len > NFS_MAXNAMLEN) {
 448                 iput(dir);
 449                 return -ENAMETOOLONG;
 450         }
 451         sattr.mode = mode;
 452         sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 453         sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 454         error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
 455                 name, &sattr, &fhandle, &fattr);
 456         if (!error)
 457                 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
 458         iput(dir);
 459         return error;
 460 }
 461 
 462 static int nfs_rmdir(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 463 {
 464         int error;
 465 
 466         if (!dir || !S_ISDIR(dir->i_mode)) {
 467                 printk("nfs_rmdir: inode is NULL or not a directory\n");
 468                 iput(dir);
 469                 return -ENOENT;
 470         }
 471         if (len > NFS_MAXNAMLEN) {
 472                 iput(dir);
 473                 return -ENAMETOOLONG;
 474         }
 475         error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), name);
 476         if (!error)
 477                 nfs_lookup_cache_remove(dir, NULL, name);
 478         iput(dir);
 479         return error;
 480 }
 481 
 482 static int nfs_unlink(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 483 {
 484         int error;
 485 
 486         if (!dir || !S_ISDIR(dir->i_mode)) {
 487                 printk("nfs_unlink: inode is NULL or not a directory\n");
 488                 iput(dir);
 489                 return -ENOENT;
 490         }
 491         if (len > NFS_MAXNAMLEN) {
 492                 iput(dir);
 493                 return -ENAMETOOLONG;
 494         }
 495         error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), name);
 496         if (!error)
 497                 nfs_lookup_cache_remove(dir, NULL, name);
 498         iput(dir);
 499         return error;
 500 }
 501 
 502 static int nfs_symlink(struct inode *dir, const char *name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 503                        const char *symname)
 504 {
 505         struct nfs_sattr sattr;
 506         int error;
 507 
 508         if (!dir || !S_ISDIR(dir->i_mode)) {
 509                 printk("nfs_symlink: inode is NULL or not a directory\n");
 510                 iput(dir);
 511                 return -ENOENT;
 512         }
 513         if (len > NFS_MAXNAMLEN) {
 514                 iput(dir);
 515                 return -ENAMETOOLONG;
 516         }
 517         if (strlen(symname) > NFS_MAXPATHLEN) {
 518                 iput(dir);
 519                 return -ENAMETOOLONG;
 520         }
 521         sattr.mode = S_IFLNK | S_IRWXUGO; /* SunOS 4.1.2 crashes without this! */
 522         sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 523         sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 524         error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
 525                 name, symname, &sattr);
 526         iput(dir);
 527         return error;
 528 }
 529 
 530 static int nfs_link(struct inode *oldinode, struct inode *dir,
     /* [previous][next][first][last][top][bottom][index][help] */
 531                     const char *name, int len)
 532 {
 533         int error;
 534 
 535         if (!oldinode) {
 536                 printk("nfs_link: old inode is NULL\n");
 537                 iput(oldinode);
 538                 iput(dir);
 539                 return -ENOENT;
 540         }
 541         if (!dir || !S_ISDIR(dir->i_mode)) {
 542                 printk("nfs_link: dir is NULL or not a directory\n");
 543                 iput(oldinode);
 544                 iput(dir);
 545                 return -ENOENT;
 546         }
 547         if (len > NFS_MAXNAMLEN) {
 548                 iput(oldinode);
 549                 iput(dir);
 550                 return -ENAMETOOLONG;
 551         }
 552         error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode),
 553                 NFS_FH(dir), name);
 554         if (!error)
 555                 nfs_lookup_cache_remove(dir, oldinode, NULL);
 556         iput(oldinode);
 557         iput(dir);
 558         return error;
 559 }
 560 
 561 static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 562                       struct inode *new_dir, const char *new_name, int new_len)
 563 {
 564         int error;
 565 
 566         if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
 567                 printk("nfs_rename: old inode is NULL or not a directory\n");
 568                 iput(old_dir);
 569                 iput(new_dir);
 570                 return -ENOENT;
 571         }
 572         if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
 573                 printk("nfs_rename: new inode is NULL or not a directory\n");
 574                 iput(old_dir);
 575                 iput(new_dir);
 576                 return -ENOENT;
 577         }
 578         if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) {
 579                 iput(old_dir);
 580                 iput(new_dir);
 581                 return -ENAMETOOLONG;
 582         }
 583         error = nfs_proc_rename(NFS_SERVER(old_dir),
 584                 NFS_FH(old_dir), old_name,
 585                 NFS_FH(new_dir), new_name);
 586         if (!error) {
 587                 nfs_lookup_cache_remove(old_dir, NULL, old_name);
 588                 nfs_lookup_cache_remove(new_dir, NULL, new_name);
 589         }
 590         iput(old_dir);
 591         iput(new_dir);
 592         return error;
 593 }
 594 
 595 /*
 596  * Many nfs protocol calls return the new file attributes after
 597  * an operation.  Here we update the inode to reflect the state
 598  * of the server's inode.
 599  */
 600 
 601 void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
     /* [previous][next][first][last][top][bottom][index][help] */
 602 {
 603         int was_empty;
 604 
 605         if (!inode || !fattr) {
 606                 printk("nfs_refresh_inode: inode or fattr is NULL\n");
 607                 return;
 608         }
 609         if (inode->i_ino != fattr->fileid) {
 610                 printk("nfs_refresh_inode: inode number mismatch\n");
 611                 return;
 612         }
 613         was_empty = inode->i_mode == 0;
 614         inode->i_mode = fattr->mode;
 615         inode->i_nlink = fattr->nlink;
 616         inode->i_uid = fattr->uid;
 617         inode->i_gid = fattr->gid;
 618         inode->i_size = fattr->size;
 619         inode->i_blksize = fattr->blocksize;
 620         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 621                 inode->i_rdev = to_kdev_t(fattr->rdev);
 622         else
 623                 inode->i_rdev = 0;
 624         inode->i_blocks = fattr->blocks;
 625         inode->i_atime = fattr->atime.seconds;
 626         inode->i_mtime = fattr->mtime.seconds;
 627         inode->i_ctime = fattr->ctime.seconds;
 628         if (was_empty) {
 629                 if (S_ISREG(inode->i_mode))
 630                         inode->i_op = &nfs_file_inode_operations;
 631                 else if (S_ISDIR(inode->i_mode))
 632                         inode->i_op = &nfs_dir_inode_operations;
 633                 else if (S_ISLNK(inode->i_mode))
 634                         inode->i_op = &nfs_symlink_inode_operations;
 635                 else if (S_ISCHR(inode->i_mode))
 636                         inode->i_op = &chrdev_inode_operations;
 637                 else if (S_ISBLK(inode->i_mode))
 638                         inode->i_op = &blkdev_inode_operations;
 639                 else if (S_ISFIFO(inode->i_mode))
 640                         init_fifo(inode);
 641                 else
 642                         inode->i_op = NULL;
 643         }
 644         nfs_lookup_cache_refresh(inode, fattr);
 645 }
 646 

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