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

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