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

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