diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-07-20 14:56:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-07-20 14:56:40 +0000 |
commit | e308faf24f68e262d92d294a01ddca7a17e76762 (patch) | |
tree | 22c47cb315811834861f013067878ff664e95abd /fs/nfs | |
parent | 30c6397ce63178fcb3e7963ac247f0a03132aca9 (diff) |
Sync with Linux 2.1.46.
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 546 | ||||
-rw-r--r-- | fs/nfs/file.c | 7 | ||||
-rw-r--r-- | fs/nfs/inode.c | 31 | ||||
-rw-r--r-- | fs/nfs/nfsroot.c | 15 | ||||
-rw-r--r-- | fs/nfs/read.c | 2 | ||||
-rw-r--r-- | fs/nfs/symlink.c | 36 | ||||
-rw-r--r-- | fs/nfs/write.c | 5 |
7 files changed, 218 insertions, 424 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 71835c255..b10331c6a 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -42,16 +42,15 @@ struct nfs_dirent { static int nfs_dir_open(struct inode * inode, struct file * file); static long nfs_dir_read(struct inode *, struct file *, char *, unsigned long); static int nfs_readdir(struct inode *, struct file *, void *, filldir_t); -static int nfs_lookup(struct inode *, const char *, int, struct inode **); -static int nfs_create(struct inode *, const char *, int, int, struct inode **); -static int nfs_mkdir(struct inode *, const char *, int, int); -static int nfs_rmdir(struct inode *, const char *, int); -static int nfs_unlink(struct inode *, const char *, int); -static int nfs_symlink(struct inode *, const char *, int, const char *); -static int nfs_link(struct inode *, struct inode *, const char *, int); -static int nfs_mknod(struct inode *, const char *, int, int, int); -static int nfs_rename(struct inode *, const char *, int, - struct inode *, const char *, int); +static int nfs_lookup(struct inode *, struct dentry *); +static int nfs_create(struct inode *, struct dentry *, int); +static int nfs_mkdir(struct inode *, struct dentry *, int); +static int nfs_rmdir(struct inode *, struct dentry *); +static int nfs_unlink(struct inode *, struct dentry *); +static int nfs_symlink(struct inode *, struct dentry *, const char *); +static int nfs_link(struct inode *, struct inode *, struct dentry *); +static int nfs_mknod(struct inode *, struct dentry *, int, int); +static int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); static struct file_operations nfs_dir_operations = { NULL, /* lseek - default */ @@ -78,6 +77,7 @@ struct inode_operations nfs_dir_inode_operations = { nfs_mknod, /* mknod */ nfs_rename, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -328,488 +328,267 @@ nfs_free_dircache(void) } -/* - * Lookup caching is a big win for performance but this is just - * a trial to see how well it works on a small scale. - * For example, bash does a lookup on ".." 13 times for each path - * element when running pwd. Yes, hard to believe but true. - * Try pwd in a filesystem mounted with noac. - * - * It trades a little cpu time and memory for a lot of network bandwidth. - * Since the cache is not hashed yet, it is a good idea not to make it too - * large because every lookup looks through the entire cache even - * though most of them will fail. - * - * FIXME: The lookup cache should also cache failed lookups. This can - * be a considerable win on diskless clients. - */ - -static struct nfs_lookup_cache_entry { - kdev_t dev; - ino_t inode; - char filename[NFS_MAXNAMLEN + 1]; - struct nfs_fh fhandle; - struct nfs_fattr fattr; - unsigned long expiration_date; -} nfs_lookup_cache[NFS_LOOKUP_CACHE_SIZE]; - -static struct nfs_lookup_cache_entry *nfs_lookup_cache_index(struct inode *dir, - const char *filename) -{ - struct nfs_lookup_cache_entry *entry; - int i; - - for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) { - entry = nfs_lookup_cache + i; - if (entry->dev == dir->i_dev - && entry->inode == dir->i_ino - && !strncmp(filename, entry->filename, NFS_MAXNAMLEN)) - return entry; - } - return NULL; -} - -static int nfs_lookup_cache_lookup(struct inode *dir, const char *filename, - struct nfs_fh *fhandle, - struct nfs_fattr *fattr) -{ - static int nfs_lookup_cache_in_use = 0; - - struct nfs_lookup_cache_entry *entry; - - dfprintk(LOOKUPCACHE, "NFS: lookup_cache_lookup(%x/%ld, %s)\n", - dir->i_dev, dir->i_ino, filename); - if (!nfs_lookup_cache_in_use) { - memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache)); - nfs_lookup_cache_in_use = 1; - } - if ((entry = nfs_lookup_cache_index(dir, filename))) { - if (jiffies > entry->expiration_date) { - entry->dev = 0; - return 0; - } - *fhandle = entry->fhandle; - *fattr = entry->fattr; - return 1; - } - return 0; -} - -static void nfs_lookup_cache_add(struct inode *dir, const char *filename, - struct nfs_fh *fhandle, - struct nfs_fattr *fattr) -{ - static int nfs_lookup_cache_pos = 0; - struct nfs_lookup_cache_entry *entry; - - dfprintk(LOOKUPCACHE, "NFS: lookup_cache_add(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, filename); - - /* compensate for bug in SGI NFS server */ - if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1 - || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1) - return; - if (!(entry = nfs_lookup_cache_index(dir, filename))) { - entry = nfs_lookup_cache + nfs_lookup_cache_pos++; - if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE) - nfs_lookup_cache_pos = 0; - } - - entry->dev = dir->i_dev; - entry->inode = dir->i_ino; - strcpy(entry->filename, filename); - entry->fhandle = *fhandle; - entry->fattr = *fattr; - entry->expiration_date = jiffies + (S_ISDIR(fattr->mode) - ? NFS_SERVER(dir)->acdirmin : NFS_SERVER(dir)->acregmin); -} - -static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode, - const char *filename) -{ - struct nfs_lookup_cache_entry *entry; - kdev_t dev; - ino_t fileid; - int i; - - if (inode) { - dev = inode->i_dev; - fileid = inode->i_ino; - } - else if ((entry = nfs_lookup_cache_index(dir, filename))) { - dev = entry->dev; - fileid = entry->fattr.fileid; - } - else - return; - - dfprintk(LOOKUPCACHE, "NFS: lookup_cache_remove(%x/%ld)\n", - dev, (long)fileid); - - for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) { - entry = nfs_lookup_cache + i; - if (entry->dev == dev && entry->fattr.fileid == fileid) - entry->dev = 0; - } -} - -static void nfs_lookup_cache_refresh(struct inode *file, - struct nfs_fattr *fattr) -{ - struct nfs_lookup_cache_entry *entry; - kdev_t dev = file->i_dev; - int fileid = file->i_ino; - int i; - - for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) { - entry = nfs_lookup_cache + i; - if (entry->dev == dev && entry->fattr.fileid == fileid) - entry->fattr = *fattr; - } -} - -static int nfs_lookup(struct inode *dir, const char *__name, int len, - struct inode **result) +static int nfs_lookup(struct inode *dir, struct dentry * dentry) { + struct inode *inode; struct nfs_fh fhandle; struct nfs_fattr fattr; - char name[len > NFS_MAXNAMLEN? 1 : len+1]; + int len = dentry->d_name.len; int error; dfprintk(VFS, "NFS: lookup(%x/%ld, %.*s)\n", - dir->i_dev, dir->i_ino, len, __name); + dir->i_dev, dir->i_ino, len, dentry->d_name.name); - *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_lookup: inode is NULL or not a directory\n"); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(dir); + + if (len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } - memcpy(name,__name,len); - name[len] = '\0'; - if (len == 0 || (len == 1 && name[0] == '.')) { /* cheat for "" and "." */ - *result = dir; - return 0; - } - if ((NFS_SERVER(dir)->flags & NFS_MOUNT_NOAC) - || !nfs_lookup_cache_lookup(dir, name, &fhandle, &fattr)) { - if ((error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir), - name, &fhandle, &fattr))) { - iput(dir); - return error; - } - nfs_lookup_cache_add(dir, name, &fhandle, &fattr); - } - if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) { - iput(dir); - return -EACCES; - } - iput(dir); + + error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name, &fhandle, &fattr); + + inode = NULL; + if (!error) { + error = -ENOENT; + inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); + if (!inode) + return -EACCES; + } else if (error != -ENOENT) + return error; + + d_add(dentry, inode); return 0; } -static int nfs_create(struct inode *dir, const char *name, int len, int mode, - struct inode **result) +static int nfs_create(struct inode *dir, struct dentry * dentry, int mode) { struct nfs_sattr sattr; struct nfs_fattr fattr; struct nfs_fh fhandle; + struct inode *inode; int error; dfprintk(VFS, "NFS: create(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, name); + dir->i_dev, dir->i_ino, dentry->d_name.name); - *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_create: inode is NULL or not a directory\n"); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(dir); + + if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } + sattr.mode = mode; sattr.uid = sattr.gid = sattr.size = (unsigned) -1; sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1; - if ((error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir), - name, &sattr, &fhandle, &fattr))) { - iput(dir); + error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir), + dentry->d_name.name, &sattr, &fhandle, &fattr); + + if (error) return error; - } - if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) { - iput(dir); + + inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); + if (!inode) return -EACCES; - } - nfs_lookup_cache_add(dir, name, &fhandle, &fattr); - nfs_invalidate_dircache(dir); - iput(dir); + + d_instantiate(dentry, inode); return 0; } -static int nfs_mknod(struct inode *dir, const char *name, int len, - int mode, int rdev) +static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) { struct nfs_sattr sattr; struct nfs_fattr fattr; struct nfs_fh fhandle; + struct inode *inode; int error; dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, name); + dir->i_dev, dir->i_ino, dentry->d_name.name); if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_mknod: inode is NULL or not a directory\n"); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(dir); + + if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } + sattr.mode = mode; - sattr.uid = sattr.gid = (unsigned) -1; + sattr.uid = sattr.gid = sattr.size = (unsigned) -1; if (S_ISCHR(mode) || S_ISBLK(mode)) sattr.size = rdev; /* get out your barf bag */ - else - sattr.size = (unsigned) -1; + sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1; error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir), - name, &sattr, &fhandle, &fattr); - if (!error) - nfs_lookup_cache_add(dir, name, &fhandle, &fattr); - nfs_invalidate_dircache(dir); - iput(dir); - return error; + dentry->d_name.name, &sattr, &fhandle, &fattr); + + if (error) + return error; + + inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); + if (!inode) + return -EACCES; + + d_instantiate(dentry, inode); + return 0; } -static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode) +static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { struct nfs_sattr sattr; struct nfs_fattr fattr; struct nfs_fh fhandle; + struct inode * inode; int error; dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, name); + dir->i_dev, dir->i_ino, dentry->d_name.name); if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_mkdir: inode is NULL or not a directory\n"); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(dir); + + if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } + sattr.mode = mode; sattr.uid = sattr.gid = sattr.size = (unsigned) -1; sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1; + error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir), - name, &sattr, &fhandle, &fattr); - if (!error) - nfs_lookup_cache_add(dir, name, &fhandle, &fattr); - nfs_invalidate_dircache(dir); - iput(dir); - return error; + dentry->d_name.name, &sattr, &fhandle, &fattr); + + if (error) + return error; + + inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); + if (!inode) + return -EACCES; + + d_instantiate(dentry, inode); + return 0; } -static int nfs_rmdir(struct inode *dir, const char *name, int len) +static int nfs_rmdir(struct inode *dir, struct dentry *dentry) { int error; dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, name); + dir->i_dev, dir->i_ino, dentry->d_name.name); if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_rmdir: inode is NULL or not a directory\n"); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(dir); - return -ENAMETOOLONG; - } - error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), name); - if (!error) - nfs_lookup_cache_remove(dir, NULL, name); - nfs_invalidate_dircache(dir); - iput(dir); - return error; -} - -static int nfs_sillyrename(struct inode *dir, const char *name, int len) -{ - struct inode *inode; - char silly[16]; - int slen, ret; - - atomic_inc(&dir->i_count); - if (nfs_lookup(dir, name, len, &inode) < 0) - return -EIO; /* arbitrary */ - - if (atomic_read(&inode->i_count) == 1) { - iput(inode); - return -EIO; - } - if (NFS_RENAMED_DIR(inode)) { - iput(NFS_RENAMED_DIR(inode)); - NFS_RENAMED_DIR(inode) = NULL; - iput(inode); - return -EIO; - } - slen = sprintf(silly, ".nfs%ld", inode->i_ino); - if (len == slen && !strncmp(name, silly, len)) { - iput(inode); - return -EIO; /* DWIM */ - } + if (dentry->d_name.len > NFS_MAXNAMLEN) + return -ENAMETOOLONG; - dfprintk(VFS, "NFS: sillyrename(%x/%ld, %s)\n", - dir->i_dev, dir->i_ino, name); + error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name); + if (error) + return error; - ret = nfs_proc_rename(NFS_SERVER(dir), NFS_FH(dir), name, - NFS_FH(dir), silly); - if (ret >= 0) { - nfs_lookup_cache_remove(dir, NULL, name); - nfs_lookup_cache_remove(dir, NULL, silly); - NFS_RENAMED_DIR(inode) = dir; - atomic_inc(&dir->i_count); - } - nfs_invalidate_dircache(dir); - iput(inode); - return ret; + d_delete(dentry); + return 0; } /* - * When releasing the inode, finally remove any unlinked but open files. - * Note that we have to clear the set of pending signals temporarily; - * otherwise the RPC call will fail. + * We should do silly-rename here, but I'm too lazy to fix + * up the directory entry implications of it.. */ -void nfs_sillyrename_cleanup(struct inode *inode) -{ - unsigned long oldsig; - struct inode *dir = NFS_RENAMED_DIR(inode); - char silly[14]; - int error, slen; - - dfprintk(VFS, "NFS: sillyrename cleanup(%x/%ld)\n", - inode->i_dev, inode->i_ino); - - oldsig = current->signal; - current->signal = 0; - - slen = sprintf(silly, ".nfs%ld", inode->i_ino); - error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), silly); - if (error < 0) - printk("NFS: silly_rename cleanup failed (err %d)\n", -error); - - nfs_lookup_cache_remove(dir, NULL, silly); - nfs_invalidate_dircache(dir); - NFS_RENAMED_DIR(inode) = NULL; - iput(dir); - - current->signal |= oldsig; -} - -static int nfs_unlink(struct inode *dir, const char *name, int len) +static int nfs_unlink(struct inode *dir, struct dentry *dentry) { int error; dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n", - dir->i_dev, dir->i_ino, name); + dir->i_dev, dir->i_ino, dentry->d_name.name); if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_unlink: inode is NULL or not a directory\n"); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(dir); + + if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } - if ((error = nfs_sillyrename(dir, name, len)) < 0) { - error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), name); - if (!error) - nfs_lookup_cache_remove(dir, NULL, name); - } - nfs_invalidate_dircache(dir); - iput(dir); - return error; + + error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name); + if (error) + return error; + + d_delete(dentry); + return 0; } -static int nfs_symlink(struct inode *dir, const char *name, int len, - const char *symname) +static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct nfs_sattr sattr; + struct nfs_fattr fattr; + struct nfs_fh fhandle; + struct inode * inode; int error; dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n", - dir->i_dev, dir->i_ino, name, symname); + dir->i_dev, dir->i_ino, dentry->d_name.name, symname); if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_symlink: inode is NULL or not a directory\n"); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(dir); + + if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } - if (strlen(symname) > NFS_MAXPATHLEN) { - iput(dir); + + if (strlen(symname) > NFS_MAXPATHLEN) return -ENAMETOOLONG; - } + sattr.mode = S_IFLNK | S_IRWXUGO; /* SunOS 4.1.2 crashes without this! */ sattr.uid = sattr.gid = sattr.size = (unsigned) -1; sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1; + error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir), - name, symname, &sattr); - nfs_invalidate_dircache(dir); - iput(dir); - return error; + dentry->d_name.name, symname, &sattr); + + if (error) + return error; + + inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); + if (!inode) + return -EACCES; + + d_instantiate(dentry, inode); + return 0; } -static int nfs_link(struct inode *oldinode, struct inode *dir, - const char *name, int len) +static int nfs_link(struct inode *inode, struct inode *dir, struct dentry *dentry) { int error; dfprintk(VFS, "NFS: link(%x/%ld -> %x/%ld, %s)\n", - oldinode->i_dev, oldinode->i_ino, - dir->i_dev, dir->i_ino, name); + inode->i_dev, inode->i_ino, + dir->i_dev, dir->i_ino, dentry->d_name.name); - if (!oldinode) { - printk("nfs_link: old inode is NULL\n"); - iput(oldinode); - iput(dir); - return -ENOENT; - } if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_link: dir is NULL or not a directory\n"); - iput(oldinode); - iput(dir); return -ENOENT; } - if (len > NFS_MAXNAMLEN) { - iput(oldinode); - iput(dir); + + if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } - error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode), - NFS_FH(dir), name); - if (!error) { - nfs_lookup_cache_remove(dir, oldinode, NULL); - NFS_READTIME(oldinode) = 0; /* force getattr */ - } - nfs_invalidate_dircache(dir); - iput(oldinode); - iput(dir); - return error; + + error = nfs_proc_link(NFS_SERVER(inode), NFS_FH(inode), + NFS_FH(dir), dentry->d_name.name); + + if (error) + return error; + + inode->i_count++; + d_instantiate(dentry, inode); + return 0; } /* @@ -821,45 +600,39 @@ static int nfs_link(struct inode *oldinode, struct inode *dir, * rename the old file using the silly_rename stuff. This way, the original * file in old_dir will go away when the last process iput()s the inode. */ -static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len, - struct inode *new_dir, const char *new_name, int new_len) +static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) { int error; dfprintk(VFS, "NFS: rename(%x/%ld, %s -> %x/%ld, %s)\n", - old_dir->i_dev, old_dir->i_ino, old_name, - new_dir->i_dev, new_dir->i_ino, new_name); + old_dir->i_dev, old_dir->i_ino, old_dentry->d_name.name, + new_dir->i_dev, new_dir->i_ino, new_dentry->d_name.name); if (!old_dir || !S_ISDIR(old_dir->i_mode)) { printk("nfs_rename: old inode is NULL or not a directory\n"); - iput(old_dir); - iput(new_dir); return -ENOENT; } + if (!new_dir || !S_ISDIR(new_dir->i_mode)) { printk("nfs_rename: new inode is NULL or not a directory\n"); - iput(old_dir); - iput(new_dir); return -ENOENT; } - if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) { - iput(old_dir); - iput(new_dir); + + if (old_dentry->d_name.len > NFS_MAXNAMLEN || new_dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - } error = nfs_proc_rename(NFS_SERVER(old_dir), - NFS_FH(old_dir), old_name, - NFS_FH(new_dir), new_name); - if (!error) { - nfs_lookup_cache_remove(old_dir, NULL, old_name); - nfs_lookup_cache_remove(new_dir, NULL, new_name); - } - nfs_invalidate_dircache(old_dir); - nfs_invalidate_dircache(new_dir); - iput(old_dir); - iput(new_dir); - return error; + NFS_FH(old_dir), old_dentry->d_name.name, + NFS_FH(new_dir), new_dentry->d_name.name); + + if (error) + return error; + + /* Update the dcache */ + d_move(old_dentry, new_dentry->d_parent, &new_dentry->d_name); + d_delete(new_dentry); + return 0; } /* @@ -873,8 +646,7 @@ void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) int was_empty; dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d)\n", - inode->i_dev, inode->i_ino, - atomic_read(&inode->i_count)); + inode->i_dev, inode->i_ino, inode->i_count); if (!inode || !fattr) { printk("nfs_refresh_inode: inode or fattr is NULL\n"); @@ -925,6 +697,4 @@ void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) init_fifo(inode); } else inode->i_op = NULL; - nfs_lookup_cache_refresh(inode, fattr); } - diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 56540bbdc..eb4735a6d 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -69,6 +69,7 @@ struct inode_operations nfs_file_inode_operations = { NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ nfs_readpage, /* readpage */ nfs_writepage, /* writepage */ NULL, /* bmap */ @@ -142,7 +143,7 @@ nfs_file_write(struct inode *inode, struct file *file, int result; dfprintk(VFS, "nfs: write(%x/%ld (%d), %lu@%lu)\n", - inode->i_dev, inode->i_ino, atomic_read(&inode->i_count), + inode->i_dev, inode->i_ino, inode->i_count, count, (unsigned long) file->f_pos); if (!inode) { @@ -179,11 +180,11 @@ nfs_lock(struct inode *inode, struct file *filp, int cmd, struct file_lock *fl) int status; dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%ld:%ld)\n", - filp->f_inode->i_dev, filp->f_inode->i_ino, + filp->f_dentry->d_inode->i_dev, filp->f_dentry->d_inode->i_ino, fl->fl_type, fl->fl_flags, fl->fl_start, fl->fl_end); - if (!(inode = filp->f_inode)) + if (!(inode = filp->f_dentry->d_inode)) return -EINVAL; /* No mandatory locks over NFS */ diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 5ab9600e9..cf52a0d56 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -36,15 +36,17 @@ static int nfs_notify_change(struct inode *, struct iattr *); static void nfs_put_inode(struct inode *); +static void nfs_delete_inode(struct inode *); static void nfs_put_super(struct super_block *); static void nfs_read_inode(struct inode *); -static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz); +static int nfs_statfs(struct super_block *, struct statfs *, int bufsiz); static struct super_operations nfs_sops = { nfs_read_inode, /* read inode */ - nfs_notify_change, /* notify change */ NULL, /* write inode */ nfs_put_inode, /* put inode */ + nfs_delete_inode, /* delete inode */ + nfs_notify_change, /* notify change */ nfs_put_super, /* put superblock */ NULL, /* write superblock */ nfs_statfs, /* stat filesystem */ @@ -73,11 +75,16 @@ static void nfs_put_inode(struct inode * inode) { dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino); +} - if (NFS_RENAMED_DIR(inode)) - nfs_sillyrename_cleanup(inode); - if (inode->i_pipe) - clear_inode(inode); +/* + * This should do any silly-rename cleanups once we + * get silly-renaming working again.. + */ +static void +nfs_delete_inode(struct inode * inode) +{ + dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino); } void @@ -230,7 +237,8 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) /* Unlock super block and try to get root fh attributes */ unlock_super(sb); - if ((sb->s_mounted = nfs_fhget(sb, &data->root, NULL)) != NULL) { + sb->s_root = d_alloc_root(nfs_fhget(sb, &data->root, NULL), NULL); + if (sb->s_root != NULL) { /* We're airborne */ if (!(server->flags & NFS_MOUNT_NONLM)) lockd_up(); @@ -250,7 +258,7 @@ failure: return NULL; } -static void +static int nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { int error; @@ -271,7 +279,7 @@ nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) tmp.f_files = 0; tmp.f_ffree = 0; tmp.f_namelen = NAME_MAX; - copy_to_user(buf, &tmp, bufsiz); + return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; } /* @@ -317,7 +325,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle, } dprintk("NFS: fhget(%x/%ld ct=%d)\n", inode->i_dev, inode->i_ino, - atomic_read(&inode->i_count)); + inode->i_count); return inode; } @@ -364,7 +372,6 @@ nfs_notify_change(struct inode *inode, struct iattr *attr) nfs_truncate_dirty_pages(inode, sattr.size); nfs_refresh_inode(inode, &fattr); } - inode->i_dirt = 0; return error; } @@ -435,7 +442,7 @@ done: */ static struct file_system_type nfs_fs_type = { "nfs", - FS_NO_DCACHE, + 0 /* FS_NO_DCACHE - this doesn't work right now*/, nfs_read_super, NULL }; diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index add3309f3..51cca7c48 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -1,5 +1,5 @@ /* - * $Id: nfsroot.c,v 1.37 1997/06/04 08:28:10 davem Exp $ + * $Id: nfsroot.c,v 1.3 1997/06/17 13:26:56 ralf Exp $ * * Copyright (C) 1995, 1996 Gero Kuhlmann <gero@gkminix.han.de> * @@ -78,7 +78,6 @@ #include <asm/param.h> #include <linux/utsname.h> -#include <linux/nametrans.h> #include <linux/in.h> #include <linux/if.h> #include <linux/inet.h> @@ -833,9 +832,6 @@ __initfunc(static void root_do_bootp_ext(u8 *ext)) root_bootp_string(nfs_path, ext+1, *ext, NFS_MAXPATHLEN); break; } -#ifdef CONFIG_TRANS_NAMES - translations_dirty = 1; -#endif } @@ -1258,9 +1254,6 @@ __initfunc(static void root_nfs_addrs(char *addrs)) system_utsname.domainname[0] = '\0'; user_dev_name[0] = '\0'; bootp_flag = rarp_flag = 1; -#ifdef CONFIG_TRANS_NAMES - translations_dirty = 1; -#endif /* The following is just a shortcut for automatic IP configuration */ if (!strcmp(addrs, "bootp")) { @@ -1306,9 +1299,6 @@ __initfunc(static void root_nfs_addrs(char *addrs)) } strncpy(system_utsname.nodename, ip, __NEW_UTS_LEN); system_utsname.nodename[__NEW_UTS_LEN] = '\0'; -#ifdef CONFIG_TRANS_NAMES - translations_dirty = 1; -#endif break; case 5: strncpy(user_dev_name, ip, IFNAMSIZ); @@ -1342,9 +1332,6 @@ __initfunc(static int root_nfs_setup(void)) if (!system_utsname.nodename[0]) { strncpy(system_utsname.nodename, in_ntoa(myaddr), __NEW_UTS_LEN); system_utsname.nodename[__NEW_UTS_LEN] = '\0'; -#ifdef CONFIG_TRANS_NAMES - translations_dirty = 1; -#endif } /* Set the correct netmask */ diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 2c3b59036..4ce61f731 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -150,7 +150,6 @@ nfs_readpage_result(struct rpc_task *task) fail++; dprintk("NFS: %d successful reads, %d failures\n", succ, fail); } - iput(req->ra_inode); clear_bit(PG_locked, &page->flags); wake_up(&page->wait); @@ -188,7 +187,6 @@ nfs_readpage_async(struct inode *inode, struct page *page) nfs_readpage_result, req); if (result >= 0) { - atomic_inc(&inode->i_count); atomic_inc(&page->count); return 0; } diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index a22f96239..3d545f7d8 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -19,6 +19,7 @@ #include <asm/uaccess.h> static int nfs_readlink(struct inode *, char *, int); +static struct dentry *nfs_follow_link(struct inode *, struct dentry *); /* * symlinks can't do much... @@ -35,6 +36,7 @@ struct inode_operations nfs_symlink_inode_operations = { NULL, /* mknod */ NULL, /* rename */ nfs_readlink, /* readlink */ + nfs_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -55,7 +57,6 @@ static int nfs_readlink(struct inode *inode, char *buffer, int buflen) buflen = NFS_MAXPATHLEN; error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem, &res, &len, buflen); - iput(inode); if (! error) { copy_to_user(buffer, res, len); put_user('\0', buffer + len); @@ -64,3 +65,36 @@ static int nfs_readlink(struct inode *inode, char *buffer, int buflen) kfree(mem); return error; } + +static struct dentry * nfs_follow_link(struct inode * inode, struct dentry *base) +{ + int error; + unsigned int len; + char *res; + void *mem; + char *path; + + dfprintk(VFS, "nfs: follow_link(%x/%ld)\n", inode->i_dev, inode->i_ino); + + error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem, + &res, &len, NFS_MAXPATHLEN); + + if (error) { + dput(base); + kfree(mem); + return ERR_PTR(error); + } + path = kmalloc(len + 1, GFP_KERNEL); + if (!path) { + dput(base); + kfree(mem); + return ERR_PTR(-ENOMEM); + } + memcpy(path, res, len); + path[len] = 0; + kfree(mem); + + base = lookup_dentry(path, base, 1); + kfree(path); + return base; +} diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f27d083e4..9241c679e 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -338,7 +338,7 @@ create_write_request(struct inode *inode, struct page *page, wreq->wb_page = page; wreq->wb_offset = offset; wreq->wb_bytes = bytes; - atomic_inc(&inode->i_count); + atomic_inc(&page->count); append_write_request(&NFS_WRITEBACK(inode), wreq); @@ -695,7 +695,6 @@ nfs_check_error(struct inode *inode) status = req->wb_task.tk_status; remove_write_request(&nfs_failed_requests, req); - iput(req->wb_inode); kfree(req); return status; } @@ -788,7 +787,6 @@ nfs_wback_result(struct rpc_task *task) dprintk("NFS: %4d saving write failure code\n", task->tk_pid); append_write_request(&nfs_failed_requests, req); - atomic_inc(&inode->i_count); } clear_bit(PG_uptodate, &page->flags); } else if (!WB_CANCELLED(req)) { @@ -818,6 +816,5 @@ nfs_wback_result(struct rpc_task *task) kfree(req); free_page(page_address(page)); - iput(inode); nr_write_requests--; } |