root/fs/nfs/dir.c

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

DEFINITIONS

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

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