summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/adfs/super.c52
-rw-r--r--fs/affs/namei.c5
-rw-r--r--fs/affs/super.c33
-rw-r--r--fs/autofs/init.c7
-rw-r--r--fs/autofs/inode.c39
-rw-r--r--fs/autofs/root.c2
-rw-r--r--fs/autofs4/init.c7
-rw-r--r--fs/autofs4/inode.c40
-rw-r--r--fs/autofs4/root.c2
-rw-r--r--fs/bfs/dir.c6
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/bfs/inode.c39
-rw-r--r--fs/buffer.c48
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/coda/inode.c46
-rw-r--r--fs/cramfs/inode.c30
-rw-r--r--fs/devfs/base.c35
-rw-r--r--fs/devpts/inode.c54
-rw-r--r--fs/efs/super.c40
-rw-r--r--fs/ext2/balloc.c3
-rw-r--r--fs/ext2/ialloc.c3
-rw-r--r--fs/ext2/super.c45
-rw-r--r--fs/fat/inode.c33
-rw-r--r--fs/filesystems.c9
-rw-r--r--fs/hfs/dir.c2
-rw-r--r--fs/hfs/super.c44
-rw-r--r--fs/hpfs/hpfs_fn.h2
-rw-r--r--fs/hpfs/namei.c2
-rw-r--r--fs/hpfs/super.c36
-rw-r--r--fs/inode.c1
-rw-r--r--fs/iobuf.c36
-rw-r--r--fs/isofs/inode.c40
-rw-r--r--fs/lockd/lockd_syms.c11
-rw-r--r--fs/lockd/svc.c1
-rw-r--r--fs/lockd/svcsubs.c37
-rw-r--r--fs/lockd/xdr.c37
-rw-r--r--fs/lockd/xdr4.c8
-rw-r--r--fs/minix/inode.c43
-rw-r--r--fs/minix/namei.c5
-rw-r--r--fs/msdos/msdosfs_syms.c7
-rw-r--r--fs/msdos/namei.c15
-rw-r--r--fs/namei.c147
-rw-r--r--fs/ncpfs/dir.c3
-rw-r--r--fs/ncpfs/inode.c37
-rw-r--r--fs/nfs/dir.c25
-rw-r--r--fs/nfs/inode.c43
-rw-r--r--fs/nfsd/export.c12
-rw-r--r--fs/nfsd/lockd.c17
-rw-r--r--fs/nfsd/nfs3proc.c182
-rw-r--r--fs/nfsd/nfs3xdr.c37
-rw-r--r--fs/nfsd/nfsctl.c66
-rw-r--r--fs/nfsd/nfsfh.c201
-rw-r--r--fs/nfsd/nfsproc.c148
-rw-r--r--fs/nfsd/nfsxdr.c65
-rw-r--r--fs/nfsd/vfs.c201
-rw-r--r--fs/ntfs/fs.c59
-rw-r--r--fs/open.c21
-rw-r--r--fs/openpromfs/inode.c36
-rw-r--r--fs/proc/array.c5
-rw-r--r--fs/proc/inode.c24
-rw-r--r--fs/proc/procfs_syms.c7
-rw-r--r--fs/qnx4/inode.c41
-rw-r--r--fs/qnx4/namei.c2
-rw-r--r--fs/romfs/inode.c32
-rw-r--r--fs/smbfs/dir.c2
-rw-r--r--fs/smbfs/inode.c35
-rw-r--r--fs/super.c489
-rw-r--r--fs/sysv/inode.c59
-rw-r--r--fs/sysv/namei.c5
-rw-r--r--fs/udf/namei.c3
-rw-r--r--fs/udf/super.c57
-rw-r--r--fs/ufs/super.c39
-rw-r--r--fs/umsdos/inode.c12
-rw-r--r--fs/umsdos/namei.c2
-rw-r--r--fs/umsdos/rdir.c2
-rw-r--r--fs/vfat/namei.c24
-rw-r--r--fs/vfat/vfatfs_syms.c7
77 files changed, 1308 insertions, 1748 deletions
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 7c80a6958..da2cc0788 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -158,7 +158,6 @@ static void adfs_put_super(struct super_block *sb)
for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
brelse(sb->u.adfs_sb.s_map[i].dm_bh);
kfree(sb->u.adfs_sb.s_map);
- MOD_DEC_USE_COUNT;
}
static int parse_options(struct super_block *sb, char *options)
@@ -213,21 +212,20 @@ static int adfs_remount(struct super_block *sb, int *flags, char *data)
return parse_options(sb, data);
}
-static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int adfs_statfs(struct super_block *sb, struct statfs *buf)
{
struct adfs_sb_info *asb = &sb->u.adfs_sb;
- struct statfs tmp;
-
- tmp.f_type = ADFS_SUPER_MAGIC;
- tmp.f_namelen = asb->s_namelen;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = asb->s_size;
- tmp.f_files = asb->s_ids_per_zone * asb->s_map_size;
- tmp.f_bavail =
- tmp.f_bfree = adfs_map_free(sb);
- tmp.f_ffree = tmp.f_bfree * tmp.f_files / tmp.f_blocks;
-
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+
+ buf->f_type = ADFS_SUPER_MAGIC;
+ buf->f_namelen = asb->s_namelen;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = asb->s_size;
+ buf->f_files = asb->s_ids_per_zone * asb->s_map_size;
+ buf->f_bavail =
+ buf->f_bfree = adfs_map_free(sb);
+ buf->f_ffree = buf->f_bfree * buf->f_files / buf->f_blocks;
+
+ return 0;
}
static struct super_operations adfs_sops = {
@@ -317,8 +315,6 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
if (parse_options(sb, data))
goto error;
- MOD_INC_USE_COUNT;
- lock_super(sb);
set_blocksize(dev, BLOCK_SIZE);
if (!(bh = bread(dev, ADFS_DISCRECORD / BLOCK_SIZE, BLOCK_SIZE))) {
adfs_error(sb, "unable to read superblock");
@@ -396,7 +392,6 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
* set up enough so that we can read an inode
*/
sb->s_op = &adfs_sops;
- unlock_super(sb);
dr = (struct adfs_discrecord *)(sb->u.adfs_sb.s_map[0].dm_bh->b_data + 4);
@@ -440,31 +435,24 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
error_free_bh:
brelse(bh);
error_unlock:
- unlock_super(sb);
error_dec_use:
- MOD_DEC_USE_COUNT;
error:
- sb->s_dev = 0;
return NULL;
}
-static struct file_system_type adfs_fs_type = {
- "adfs", FS_REQUIRES_DEV, adfs_read_super, NULL
-};
+static DECLARE_FSTYPE_DEV(adfs_fs_type, "adfs", adfs_read_super);
-int __init init_adfs_fs(void)
+static int __init init_adfs_fs(void)
{
return register_filesystem(&adfs_fs_type);
}
-#ifdef MODULE
-int init_module(void)
-{
- return init_adfs_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_adfs_fs(void)
{
unregister_filesystem(&adfs_fs_type);
}
-#endif
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_adfs_fs)
+module_exit(exit_adfs_fs)
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 38e5bccbe..c1a849a70 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -368,7 +368,7 @@ affs_rmdir(struct inode *dir, struct dentry *dentry)
if (!empty_dir(bh,AFFS_I2HSIZE(inode)))
goto rmdir_done;
retval = -EBUSY;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
goto rmdir_done;
if ((retval = affs_remove_header(bh,inode)) < 0)
@@ -557,6 +557,9 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
}
if (S_ISDIR(old_inode->i_mode)) {
if (new_inode) {
+ retval = -EBUSY;
+ if (!d_unhashed(new_dentry))
+ goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
goto end_rename;
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 9eed5c09e..5f2387bde 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -35,7 +35,7 @@ extern struct timezone sys_tz;
#define MIN(a,b) (((a)<(b))?(a):(b))
-static int affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int affs_statfs(struct super_block *sb, struct statfs *buf);
static int affs_remount (struct super_block *sb, int *flags, char *data);
static void
@@ -65,7 +65,6 @@ affs_put_super(struct super_block *sb)
*/
set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize);
- MOD_DEC_USE_COUNT;
return;
}
@@ -262,8 +261,6 @@ affs_read_super(struct super_block *s, void *data, int silent)
pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
- MOD_INC_USE_COUNT;
- lock_super(s);
s->s_magic = AFFS_SUPER_MAGIC;
s->s_op = &affs_sops;
s->u.affs_sb.s_bitmap = NULL;
@@ -547,7 +544,6 @@ nobitmap:
goto out_no_root;
s->s_root->d_op = &affs_dentry_operations;
- unlock_super(s);
/* Record date of last change if the bitmap was truncated and
* create data zones if the volume is writable.
*/
@@ -615,9 +611,6 @@ out_free_prefix:
if (s->u.affs_sb.s_prefix)
kfree(s->u.affs_sb.s_prefix);
out_fail:
- s->s_dev = 0;
- unlock_super(s);
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -661,31 +654,23 @@ affs_remount(struct super_block *sb, int *flags, char *data)
}
static int
-affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+affs_statfs(struct super_block *sb, struct statfs *buf)
{
int free;
- struct statfs tmp;
pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size,
sb->u.affs_sb.s_reserved);
free = affs_count_free_blocks(sb);
- tmp.f_type = AFFS_SUPER_MAGIC;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved;
- tmp.f_bfree = free;
- tmp.f_bavail = free;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- return copy_to_user(buf,&tmp,bufsiz) ? -EFAULT : 0;
+ buf->f_type = AFFS_SUPER_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved;
+ buf->f_bfree = free;
+ buf->f_bavail = free;
+ return 0;
}
-static struct file_system_type affs_fs_type = {
- "affs",
- FS_REQUIRES_DEV,
- affs_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);
int __init init_affs_fs(void)
{
diff --git a/fs/autofs/init.c b/fs/autofs/init.c
index 4c9e8fe76..0aaa8134a 100644
--- a/fs/autofs/init.c
+++ b/fs/autofs/init.c
@@ -14,12 +14,7 @@
#include <linux/init.h>
#include "autofs_i.h"
-static struct file_system_type autofs_fs_type = {
- "autofs",
- 0,
- autofs_read_super,
- NULL
-};
+static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs_read_super, 0);
static int __init init_autofs_fs(void)
{
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index a67ca9822..1aa665d1c 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -49,13 +49,9 @@ static void autofs_put_super(struct super_block *sb)
kfree(sb->u.generic_sbp);
DPRINTK(("autofs: shutting down\n"));
-
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
}
-static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int autofs_statfs(struct super_block *sb, struct statfs *buf);
static void autofs_read_inode(struct inode *inode);
static void autofs_write_inode(struct inode *inode);
@@ -141,9 +137,6 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
struct autofs_sb_info *sbi;
int minproto, maxproto;
- MOD_INC_USE_COUNT;
-
- lock_super(s);
/* Super block already completed? */
if (s->s_root)
goto out_unlock;
@@ -167,7 +160,6 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
s->s_magic = AUTOFS_SUPER_MAGIC;
s->s_op = &autofs_sops;
s->s_root = NULL;
- unlock_super(s); /* shouldn't we keep it locked a while longer? */
/*
* Get the root inode and dentry, but defer checking for errors.
@@ -224,7 +216,6 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
* Success ... somebody else completed the super block for us.
*/
out_unlock:
- unlock_super(s);
goto out_dec;
out_fput:
if (pipe)
@@ -235,7 +226,6 @@ out_dput:
else
iput(root_inode);
out_dec:
- MOD_DEC_USE_COUNT;
return s;
/*
@@ -246,14 +236,12 @@ fail_fput:
/*
* fput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
fput(pipe);
/* fall through */
fail_dput:
/*
* dput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
dput(root);
goto fail_free;
fail_iput:
@@ -261,32 +249,23 @@ fail_iput:
/*
* iput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
iput(root_inode);
fail_free:
kfree(sbi);
- goto fail_dec;
fail_unlock:
- unlock_super(s);
fail_dec:
- s->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
-static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int autofs_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = AUTOFS_SUPER_MAGIC;
- tmp.f_bsize = 1024;
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = AUTOFS_SUPER_MAGIC;
+ buf->f_bsize = 1024;
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_ffree = 0;
+ buf->f_namelen = NAME_MAX;
+ return 0;
}
static void autofs_read_inode(struct inode *inode)
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 35afe3cdc..1540ceda8 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -227,7 +227,7 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr
* doesn't do the right thing for all system calls, but it should
* be OK for the operations we permit from an autofs.
*/
- if ( dentry->d_inode && list_empty(&dentry->d_hash) )
+ if ( dentry->d_inode && d_unhashed(dentry) )
return ERR_PTR(-ENOENT);
return NULL;
diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c
index 48bf60b5f..baf12d913 100644
--- a/fs/autofs4/init.c
+++ b/fs/autofs4/init.c
@@ -14,12 +14,7 @@
#include <linux/init.h>
#include "autofs_i.h"
-static struct file_system_type autofs_fs_type = {
- "autofs",
- 0,
- autofs4_read_super,
- NULL
-};
+static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs4_read_super, 0);
static int __init init_autofs4_fs(void)
{
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 40d149272..b4ea73fdb 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -103,10 +103,6 @@ static void autofs4_put_super(struct super_block *sb)
kfree(sbi);
DPRINTK(("autofs: shutting down\n"));
-
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
}
static void autofs4_umount_begin(struct super_block *sb)
@@ -117,7 +113,7 @@ static void autofs4_umount_begin(struct super_block *sb)
autofs4_catatonic_mode(sbi);
}
-static int autofs4_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int autofs4_statfs(struct super_block *sb, struct statfs *buf);
static void autofs4_read_inode(struct inode *inode);
static void autofs4_write_inode(struct inode *inode);
@@ -219,9 +215,6 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
struct autofs_sb_info *sbi;
int minproto, maxproto;
- MOD_INC_USE_COUNT;
-
- lock_super(s);
/* Super block already completed? */
if (s->s_root)
goto out_unlock;
@@ -248,7 +241,6 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
s->s_magic = AUTOFS_SUPER_MAGIC;
s->s_op = &autofs4_sops;
s->s_root = NULL;
- unlock_super(s); /* shouldn't we keep it locked a while longer? */
/*
* Get the root inode and dentry, but defer checking for errors.
@@ -315,7 +307,6 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
* Success ... somebody else completed the super block for us.
*/
out_unlock:
- unlock_super(s);
goto out_dec;
out_fput:
if (pipe)
@@ -326,7 +317,6 @@ out_dput:
else
iput(root_inode);
out_dec:
- MOD_DEC_USE_COUNT;
return s;
/*
@@ -337,14 +327,12 @@ fail_fput:
/*
* fput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
fput(pipe);
/* fall through */
fail_dput:
/*
* dput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
dput(root);
goto fail_free;
fail_iput:
@@ -352,32 +340,22 @@ fail_iput:
/*
* iput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
iput(root_inode);
fail_free:
kfree(sbi);
- goto fail_dec;
fail_unlock:
- unlock_super(s);
-fail_dec:
- s->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
-static int autofs4_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int autofs4_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = AUTOFS_SUPER_MAGIC;
- tmp.f_bsize = 1024;
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = AUTOFS_SUPER_MAGIC;
+ buf->f_bsize = 1024;
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_ffree = 0;
+ buf->f_namelen = NAME_MAX;
+ return 0;
}
static void autofs4_read_inode(struct inode *inode)
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 05045d408..8ff33b344 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -353,7 +353,7 @@ static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dent
* doesn't do the right thing for all system calls, but it should
* be OK for the operations we permit from an autofs.
*/
- if ( dentry->d_inode && list_empty(&dentry->d_hash) )
+ if ( dentry->d_inode && d_unhashed(dentry) )
return ERR_PTR(-ENOENT);
return NULL;
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 44e96e101..38881a1b6 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -182,7 +182,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
}
de->ino = 0;
dir->i_version = ++event;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh, 0);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(dir);
inode->i_nlink--;
@@ -242,7 +242,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
new_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(new_inode);
}
- mark_buffer_dirty(old_bh, 1);
+ mark_buffer_dirty(old_bh, 0);
error = 0;
end_rename:
@@ -294,7 +294,7 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
de->ino = ino;
for (i=0; i<BFS_NAMELEN; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh, 0);
brelse(bh);
return 0;
}
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index aba9cefd1..f5ef5e652 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -33,7 +33,7 @@ static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
return -EIO;
new = getblk(dev, to, BFS_BSIZE);
memcpy(new->b_data, bh->b_data, bh->b_size);
- mark_buffer_dirty(new, 1);
+ mark_buffer_dirty(new, 0);
bforget(bh);
brelse(new);
return 0;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 79c7c6507..2c38ccafe 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -124,7 +124,7 @@ static void bfs_write_inode(struct inode * inode)
di->i_eblock = inode->iu_eblock;
di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh, 0);
brelse(bh);
}
@@ -165,7 +165,7 @@ static void bfs_delete_inode(struct inode * inode)
}
di->i_ino = 0;
di->i_sblock = 0;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh, 0);
brelse(bh);
/* if this was the last file, make the previous
@@ -182,22 +182,19 @@ static void bfs_put_super(struct super_block *s)
{
brelse(s->su_sbh);
kfree(s->su_imap);
- MOD_DEC_USE_COUNT;
}
-static int bfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz)
+static int bfs_statfs(struct super_block *s, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = BFS_MAGIC;
- tmp.f_bsize = s->s_blocksize;
- tmp.f_blocks = s->su_blocks;
- tmp.f_bfree = tmp.f_bavail = s->su_freeb;
- tmp.f_files = s->su_lasti + 1 - BFS_ROOT_INO;
- tmp.f_ffree = s->su_freei;
- tmp.f_fsid.val[0] = s->s_dev;
- tmp.f_namelen = BFS_NAMELEN;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = BFS_MAGIC;
+ buf->f_bsize = s->s_blocksize;
+ buf->f_blocks = s->su_blocks;
+ buf->f_bfree = buf->f_bavail = s->su_freeb;
+ buf->f_files = s->su_lasti + 1 - BFS_ROOT_INO;
+ buf->f_ffree = s->su_freei;
+ buf->f_fsid.val[0] = s->s_dev;
+ buf->f_namelen = BFS_NAMELEN;
+ return 0;
}
static void bfs_write_super(struct super_block *s)
@@ -245,8 +242,6 @@ static struct super_block * bfs_read_super(struct super_block * s,
struct inode * inode;
int i, imap_len;
- MOD_INC_USE_COUNT;
- lock_super(s);
dev = s->s_dev;
set_blocksize(dev, BFS_BSIZE);
s->s_blocksize = BFS_BSIZE;
@@ -318,22 +313,14 @@ static struct super_block * bfs_read_super(struct super_block * s,
s->s_dirt = 1;
}
dump_imap("read_super", s);
- unlock_super(s);
return s;
out:
brelse(bh);
- s->s_dev = 0;
- unlock_super(s);
- MOD_DEC_USE_COUNT;
return NULL;
}
-static struct file_system_type bfs_fs_type = {
- name: "bfs",
- fs_flags: FS_REQUIRES_DEV,
- read_super: bfs_read_super,
-};
+static DECLARE_FSTYPE_DEV( bfs_fs_type, "bfs", bfs_read_super);
#ifdef MODULE
#define init_bfs_fs init_module
diff --git a/fs/buffer.c b/fs/buffer.c
index 4e79483e4..dabf1d39c 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1754,10 +1754,10 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate)
mark_buffer_uptodate(bh, uptodate);
kiobuf = bh->b_kiobuf;
- if (!uptodate)
- kiobuf->errno = -EIO;
- if (atomic_dec_and_test(&kiobuf->io_count))
- kiobuf->end_io(kiobuf);
+ unlock_buffer(bh);
+
+ kiobuf = bh->b_kiobuf;
+ end_kio_request(kiobuf, uptodate);
}
@@ -1766,8 +1766,7 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate)
* for them to complete. Clean up the buffer_heads afterwards.
*/
-static int do_kio(struct kiobuf *kiobuf,
- int rw, int nr, struct buffer_head *bh[], int size)
+static int do_kio(int rw, int nr, struct buffer_head *bh[], int size)
{
int iosize;
int i;
@@ -1778,18 +1777,20 @@ static int do_kio(struct kiobuf *kiobuf,
if (rw == WRITE)
rw = WRITERAW;
- atomic_add(nr, &kiobuf->io_count);
- kiobuf->errno = 0;
ll_rw_block(rw, nr, bh);
- kiobuf_wait_for_io(kiobuf);
-
- spin_lock(&unused_list_lock);
-
iosize = 0;
+ spin_lock(&unused_list_lock);
+
for (i = nr; --i >= 0; ) {
iosize += size;
tmp = bh[i];
+ if (buffer_locked(tmp)) {
+ spin_unlock(&unused_list_lock);
+ wait_on_buffer(tmp);
+ spin_lock(&unused_list_lock);
+ }
+
if (!buffer_uptodate(tmp)) {
/* We are traversing bh'es in reverse order so
clearing iosize on error calculates the
@@ -1801,11 +1802,7 @@ static int do_kio(struct kiobuf *kiobuf,
spin_unlock(&unused_list_lock);
- if (iosize)
- return iosize;
- if (kiobuf->errno)
- return kiobuf->errno;
- return -EIO;
+ return iosize;
}
/*
@@ -1847,8 +1844,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
if ((iobuf->offset & (size-1)) ||
(iobuf->length & (size-1)))
return -EINVAL;
- if (!iobuf->locked)
- panic("brw_kiovec: iobuf not locked for I/O");
if (!iobuf->nr_pages)
panic("brw_kiovec: iobuf not initialised");
}
@@ -1861,10 +1856,15 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
iobuf = iovec[i];
offset = iobuf->offset;
length = iobuf->length;
-
+ iobuf->errno = 0;
+
for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
map = iobuf->maplist[pageind];
-
+ if (!map) {
+ err = -EFAULT;
+ goto error;
+ }
+
while (length > 0) {
blocknr = b[bufind++];
tmp = get_unused_buffer_head(0);
@@ -1893,11 +1893,13 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
length -= size;
offset += size;
+ atomic_inc(&iobuf->io_count);
+
/*
* Start the IO if we have got too much
*/
if (bhind >= KIO_MAX_SECTORS) {
- err = do_kio(iobuf, rw, bhind, bh, size);
+ err = do_kio(rw, bhind, bh, size);
if (err >= 0)
transferred += err;
else
@@ -1915,7 +1917,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
/* Is there any IO still left to submit? */
if (bhind) {
- err = do_kio(iobuf, rw, bhind, bh, size);
+ err = do_kio(rw, bhind, bh, size);
if (err >= 0)
transferred += err;
else
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 8e25fccd6..1e39811e6 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -451,7 +451,7 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
dircnp = ITOC(dir);
- if (!list_empty(&de->d_hash))
+ if (!d_unhashed(de))
return -EBUSY;
error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 1f82ef5bd..7f163acf9 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -37,8 +37,7 @@ static void coda_read_inode(struct inode *);
static void coda_put_inode(struct inode *);
static void coda_delete_inode(struct inode *);
static void coda_put_super(struct super_block *);
-static int coda_statfs(struct super_block *sb, struct statfs *buf,
- int bufsiz);
+static int coda_statfs(struct super_block *sb, struct statfs *buf);
/* exported operations */
struct super_operations coda_super_operations =
@@ -61,16 +60,13 @@ static struct super_block * coda_read_super(struct super_block *sb,
int error;
ENTRY;
- MOD_INC_USE_COUNT;
vc = &coda_upc_comm;
sbi = &coda_super_info;
if ( sbi->sbi_sb ) {
printk("Already mounted\n");
- unlock_super(sb);
EXIT;
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -80,7 +76,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
INIT_LIST_HEAD(&(sbi->sbi_cchead));
INIT_LIST_HEAD(&(sbi->sbi_volroothead));
- lock_super(sb);
sb->u.generic_sbp = sbi;
sb->s_blocksize = 1024; /* XXXXX what do we put here?? */
sb->s_blocksize_bits = 10;
@@ -93,7 +88,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
if ( error ) {
printk("coda_read_super: coda_get_rootfid failed with %d\n",
error);
- sb->s_dev = 0;
goto error;
}
printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
@@ -102,7 +96,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
error = coda_cnode_make(&root, &fid, sb);
if ( error || !root ) {
printk("Failure of coda_cnode_make for root: error %d\n", error);
- sb->s_dev = 0;
goto error;
}
@@ -110,14 +103,11 @@ static struct super_block * coda_read_super(struct super_block *sb,
root->i_ino, root->i_dev);
sbi->sbi_root = root;
sb->s_root = d_alloc_root(root);
- unlock_super(sb);
EXIT;
return sb;
error:
- unlock_super(sb);
EXIT;
- MOD_DEC_USE_COUNT;
if (sbi) {
sbi->sbi_vcomm = NULL;
sbi->sbi_root = NULL;
@@ -126,7 +116,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
if (root) {
iput(root);
}
- sb->s_dev = 0;
return NULL;
}
@@ -136,15 +125,12 @@ static void coda_put_super(struct super_block *sb)
ENTRY;
-
- sb->s_dev = 0;
coda_cache_clear_all(sb);
sb_info = coda_sbp(sb);
coda_super_info.sbi_sb = NULL;
printk("Coda: Bye bye.\n");
memset(sb_info, 0, sizeof(* sb_info));
- MOD_DEC_USE_COUNT;
EXIT;
}
@@ -235,31 +221,25 @@ int coda_notify_change(struct dentry *de, struct iattr *iattr)
return error;
}
-static int coda_statfs(struct super_block *sb, struct statfs *buf,
- int bufsiz)
+static int coda_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
int error;
- memset(&tmp, 0, sizeof(struct statfs));
-
- error = venus_statfs(sb, &tmp);
+ error = venus_statfs(sb, buf);
if (error) {
/* fake something like AFS does */
- tmp.f_blocks = 9000000;
- tmp.f_bfree = 9000000;
- tmp.f_bavail = 9000000;
- tmp.f_files = 9000000;
- tmp.f_ffree = 9000000;
+ buf->f_blocks = 9000000;
+ buf->f_bfree = 9000000;
+ buf->f_bavail = 9000000;
+ buf->f_files = 9000000;
+ buf->f_ffree = 9000000;
}
/* and fill in the rest */
- tmp.f_type = CODA_SUPER_MAGIC;
- tmp.f_bsize = 1024;
- tmp.f_namelen = CODA_MAXNAMLEN;
-
- copy_to_user(buf, &tmp, bufsiz);
+ buf->f_type = CODA_SUPER_MAGIC;
+ buf->f_bsize = 1024;
+ buf->f_namelen = CODA_MAXNAMLEN;
return 0;
}
@@ -267,9 +247,7 @@ static int coda_statfs(struct super_block *sb, struct statfs *buf,
/* init_coda: used by filesystems.c to register coda */
-struct file_system_type coda_fs_type = {
- "coda", 0, coda_read_super, NULL
-};
+DECLARE_FSTYPE( coda_fs_type, "coda", coda_read_super, 0);
int init_coda_fs(void)
{
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 89b9719f5..237c7d9aa 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -153,7 +153,6 @@ static struct super_block * cramfs_read_super(struct super_block *sb, void *data
unsigned long root_offset;
struct super_block * retval = NULL;
- lock_super(sb);
set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -198,7 +197,6 @@ static struct super_block * cramfs_read_super(struct super_block *sb, void *data
retval = sb;
out:
- unlock_super(sb);
return retval;
}
@@ -208,20 +206,15 @@ static void cramfs_put_super(struct super_block *sb)
return;
}
-static int cramfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+static int cramfs_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- /* Unsupported fields set to -1 as per man page. */
- memset(&tmp, 0xff, sizeof(tmp));
-
- tmp.f_type = CRAMFS_MAGIC;
- tmp.f_bsize = PAGE_CACHE_SIZE;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = 255;
- return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+ buf->f_type = CRAMFS_MAGIC;
+ buf->f_bsize = PAGE_CACHE_SIZE;
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_ffree = 0;
+ buf->f_namelen = 255;
+ return 0;
}
/*
@@ -372,12 +365,7 @@ static struct super_operations cramfs_ops = {
statfs: cramfs_statfs,
};
-static struct file_system_type cramfs_fs_type = {
- "cramfs",
- FS_REQUIRES_DEV,
- cramfs_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(cramfs_fs_type, "cramfs", cramfs_read_super);
static int __init init_cramfs_fs(void)
{
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index f2e09cd6e..ab1e9ee83 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -2305,27 +2305,21 @@ static void devfs_put_super (struct super_block *sb)
if (devfs_debug & DEBUG_S_PUT)
printk ("%s: put_super(): devfs ptr: %p\n", DEVFS_NAME, fs_info);
#endif
- sb->s_dev = 0;
#ifdef CONFIG_DEVFS_TUNNEL
dput (fs_info->table[0]->covered);
#endif
delete_fs (fs_info);
- MOD_DEC_USE_COUNT;
} /* End Function devfs_put_super */
-static int devfs_statfs (struct super_block *sb, struct statfs *buf,int bufsiz)
+static int devfs_statfs (struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = DEVFS_SUPER_MAGIC;
- tmp.f_bsize = PAGE_SIZE / sizeof (long);
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user (buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = DEVFS_SUPER_MAGIC;
+ buf->f_bsize = PAGE_SIZE / sizeof (long);
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_ffree = 0;
+ buf->f_namelen = NAME_MAX;
+ return 0;
} /* End Function devfs_statfs */
static struct super_operations devfs_sops =
@@ -3152,7 +3146,6 @@ static struct super_block *devfs_read_super (struct super_block *sb,
{
if (strcmp (aopt, "explicit") == 0) fs_info->require_explicit = TRUE;
}
- lock_super (sb);
sb->u.generic_sbp = fs_info;
sb->s_blocksize = 1024;
sb->s_blocksize_bits = 10;
@@ -3173,32 +3166,22 @@ static struct super_block *devfs_read_super (struct super_block *sb,
#ifdef CONFIG_DEVFS_TUNNEL
di->covered = dget (sb->s_root->d_covered);
#endif
- unlock_super (sb);
#ifdef CONFIG_DEVFS_DEBUG
if (devfs_debug & DEBUG_DISABLED)
printk ("%s: read super, made devfs ptr: %p\n",
DEVFS_NAME, sb->u.generic_sbp);
#endif
- MOD_INC_USE_COUNT;
return sb;
out_no_root:
printk ("devfs_read_super: get root inode failed\n");
delete_fs (fs_info);
if (root_inode) iput (root_inode);
- sb->s_dev = 0;
- unlock_super (sb);
return NULL;
} /* End Function devfs_read_super */
-static struct file_system_type devfs_fs_type =
-{
- DEVFS_NAME,
- 0,
- devfs_read_super,
- NULL,
-};
+static DECLARE_FSTYPE(devfs_fs_type, DEVFS_NAME, devfs_read_super, 0);
/* File operations for devfsd follow */
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index dab1864cb..67cc1c7b1 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -51,19 +51,13 @@ static void devpts_put_super(struct super_block *sb)
kfree(sbi->inodes);
kfree(sbi);
-
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
}
-static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int devpts_statfs(struct super_block *sb, struct statfs *buf);
static void devpts_read_inode(struct inode *inode);
-static void devpts_write_inode(struct inode *inode);
static struct super_operations devpts_sops = {
read_inode: devpts_read_inode,
- write_inode: devpts_write_inode,
put_super: devpts_put_super,
statfs: devpts_statfs,
};
@@ -125,9 +119,6 @@ struct super_block *devpts_read_super(struct super_block *s, void *data,
struct dentry * root;
struct devpts_sb_info *sbi;
- MOD_INC_USE_COUNT;
-
- lock_super(s);
/* Super block already completed? */
if (s->s_root)
goto out_unlock;
@@ -151,7 +142,6 @@ struct super_block *devpts_read_super(struct super_block *s, void *data,
s->s_magic = DEVPTS_SUPER_MAGIC;
s->s_op = &devpts_sops;
s->s_root = NULL;
- unlock_super(s); /* shouldn't we keep it locked a while longer? */
/*
* Get the root inode and dentry, but defer checking for errors.
@@ -183,7 +173,6 @@ struct super_block *devpts_read_super(struct super_block *s, void *data,
/*
* Success! Install the root dentry now to indicate completion.
*/
- lock_super(s);
s->s_root = root;
sbi->next = mounts;
@@ -192,14 +181,12 @@ struct super_block *devpts_read_super(struct super_block *s, void *data,
sbi->back = &mounts;
mounts = s;
- unlock_super(s);
return s;
/*
* Success ... somebody else completed the super block for us.
*/
out_unlock:
- unlock_super(s);
goto out_dec;
out_dput:
if (root)
@@ -207,7 +194,6 @@ out_dput:
else
iput(root_inode);
out_dec:
- MOD_DEC_USE_COUNT;
return s;
/*
@@ -217,7 +203,6 @@ fail_dput:
/*
* dput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
dput(root);
goto fail_free;
fail_iput:
@@ -225,32 +210,22 @@ fail_iput:
/*
* iput() can block, so we clear the super block first.
*/
- s->s_dev = 0;
iput(root_inode);
fail_free:
kfree(sbi);
- goto fail_dec;
fail_unlock:
- unlock_super(s);
-fail_dec:
- s->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
-static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int devpts_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = DEVPTS_SUPER_MAGIC;
- tmp.f_bsize = 1024;
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = DEVPTS_SUPER_MAGIC;
+ buf->f_bsize = 1024;
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_ffree = 0;
+ buf->f_namelen = NAME_MAX;
+ return 0;
}
static void devpts_read_inode(struct inode *inode)
@@ -284,16 +259,7 @@ static void devpts_read_inode(struct inode *inode)
return;
}
-static void devpts_write_inode(struct inode *inode)
-{
-}
-
-static struct file_system_type devpts_fs_type = {
- "devpts",
- 0,
- devpts_read_super,
- NULL
-};
+static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, 0);
void devpts_pty_new(int number, kdev_t device)
{
diff --git a/fs/efs/super.c b/fs/efs/super.c
index 4522b2cfe..092c2f0a7 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -13,12 +13,7 @@
#include <linux/efs_vh.h>
#include <linux/efs_fs_sb.h>
-static struct file_system_type efs_fs_type = {
- "efs", /* filesystem name */
- FS_REQUIRES_DEV, /* fs_flags */
- efs_read_super, /* entry function pointer */
- NULL /* next */
-};
+static DECLARE_FSTYPE_DEV(efs_fs_type, "efs", efs_read_super);
static struct super_operations efs_superblock_operations = {
read_inode: efs_read_inode,
@@ -145,9 +140,6 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
struct efs_sb_info *sb;
struct buffer_head *bh;
- MOD_INC_USE_COUNT;
- lock_super(s);
-
sb = SUPER_INFO(s);
set_blocksize(dev, EFS_BLOCKSIZE);
@@ -199,7 +191,6 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
s->s_op = &efs_superblock_operations;
s->s_dev = dev;
s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE));
- unlock_super(s);
if (!(s->s_root)) {
printk(KERN_ERR "EFS: get root inode failed\n");
@@ -214,35 +205,30 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
return(s);
out_no_fs_ul:
- unlock_super(s);
out_no_fs:
- s->s_dev = 0;
- MOD_DEC_USE_COUNT;
return(NULL);
}
void efs_put_super(struct super_block *s) {
- MOD_DEC_USE_COUNT;
}
-int efs_statfs(struct super_block *s, struct statfs *buf, int bufsiz) {
- struct statfs ret;
+int efs_statfs(struct super_block *s, struct statfs *buf) {
struct efs_sb_info *sb = SUPER_INFO(s);
- ret.f_type = EFS_SUPER_MAGIC; /* efs magic number */
- ret.f_bsize = EFS_BLOCKSIZE; /* blocksize */
- ret.f_blocks = sb->total_groups * /* total data blocks */
+ buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */
+ buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */
+ buf->f_blocks = sb->total_groups * /* total data blocks */
(sb->group_size - sb->inode_blocks);
- ret.f_bfree = sb->data_free; /* free data blocks */
- ret.f_bavail = sb->data_free; /* free blocks for non-root */
- ret.f_files = sb->total_groups * /* total inodes */
+ buf->f_bfree = sb->data_free; /* free data blocks */
+ buf->f_bavail = sb->data_free; /* free blocks for non-root */
+ buf->f_files = sb->total_groups * /* total inodes */
sb->inode_blocks *
(EFS_BLOCKSIZE / sizeof(struct efs_dinode));
- ret.f_ffree = sb->inode_free; /* free inodes */
- ret.f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
- ret.f_fsid.val[1] = sb->fs_magic & 0xffff; /* fs ID */
- ret.f_namelen = EFS_MAXNAMELEN; /* max filename length */
+ buf->f_ffree = sb->inode_free; /* free inodes */
+ buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
+ buf->f_fsid.val[1] = sb->fs_magic & 0xffff; /* fs ID */
+ buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */
- return copy_to_user(buf, &ret, bufsiz) ? -EFAULT : 0;
+ return 0;
}
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 43a425bbb..904f5cb8f 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -679,6 +679,7 @@ int ext2_group_sparse(int group)
test_root(group, 7));
}
+/* Called at mount-time, super-block is locked */
void ext2_check_blocks_bitmap (struct super_block * sb)
{
struct buffer_head * bh;
@@ -689,7 +690,6 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
struct ext2_group_desc * gdp;
int i, j;
- lock_super (sb);
es = sb->u.ext2_sb.s_es;
desc_count = 0;
bitmap_count = 0;
@@ -752,5 +752,4 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
"Wrong free blocks count in super block, "
"stored = %lu, counted = %lu",
(unsigned long) le32_to_cpu(es->s_free_blocks_count), bitmap_count);
- unlock_super (sb);
}
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 72437bb89..3a3e4a69c 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -527,6 +527,7 @@ unsigned long ext2_count_free_inodes (struct super_block * sb)
#endif
}
+/* Called at mount-time, super-block is locked */
void ext2_check_inodes_bitmap (struct super_block * sb)
{
struct ext2_super_block * es;
@@ -535,7 +536,6 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
struct ext2_group_desc * gdp;
int i;
- lock_super (sb);
es = sb->u.ext2_sb.s_es;
desc_count = 0;
bitmap_count = 0;
@@ -564,5 +564,4 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
"stored = %lu, counted = %lu",
(unsigned long) le32_to_cpu(es->s_free_inodes_count),
bitmap_count);
- unlock_super (sb);
}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index b4cdc5868..73be71e61 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -116,7 +116,6 @@ void ext2_put_super (struct super_block * sb)
brelse (sb->u.ext2_sb.s_block_bitmap[i]);
brelse (sb->u.ext2_sb.s_sbh);
- MOD_DEC_USE_COUNT;
return;
}
@@ -402,12 +401,9 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
&sb->u.ext2_sb.s_mount_opt)) {
- sb->s_dev = 0;
return NULL;
}
- MOD_INC_USE_COUNT;
- lock_super (sb);
set_blocksize (dev, blocksize);
/*
@@ -421,10 +417,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
}
if (!(bh = bread (dev, logic_sb_block, blocksize))) {
- sb->s_dev = 0;
- unlock_super (sb);
printk ("EXT2-fs: unable to read superblock\n");
- MOD_DEC_USE_COUNT;
return NULL;
}
/*
@@ -439,11 +432,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
printk ("VFS: Can't find an ext2 filesystem on dev "
"%s.\n", bdevname(dev));
failed_mount:
- sb->s_dev = 0;
- unlock_super (sb);
if (bh)
brelse(bh);
- MOD_DEC_USE_COUNT;
return NULL;
}
if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) {
@@ -616,7 +606,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
sb->u.ext2_sb.s_db_per_group = db_count;
- unlock_super (sb);
/*
* set up enough so that it can read an inode
*/
@@ -624,7 +613,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sb->s_op = &ext2_sops;
sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO));
if (!sb->s_root) {
- sb->s_dev = 0;
for (i = 0; i < db_count; i++)
if (sb->u.ext2_sb.s_group_desc[i])
brelse (sb->u.ext2_sb.s_group_desc[i]);
@@ -632,7 +620,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
db_count * sizeof (struct buffer_head *));
brelse (bh);
printk ("EXT2-fs: get root inode failed\n");
- MOD_DEC_USE_COUNT;
return NULL;
}
ext2_setup_super (sb, es);
@@ -725,10 +712,9 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
return 0;
}
-int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
+int ext2_statfs (struct super_block * sb, struct statfs * buf)
{
unsigned long overhead;
- struct statfs tmp;
int ngroups, i;
if (test_opt (sb, MINIX_DF))
@@ -768,25 +754,20 @@ int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
(2 + sb->u.ext2_sb.s_itb_per_group));
}
- tmp.f_type = EXT2_SUPER_MAGIC;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = le32_to_cpu(sb->u.ext2_sb.s_es->s_blocks_count) - overhead;
- tmp.f_bfree = ext2_count_free_blocks (sb);
- tmp.f_bavail = tmp.f_bfree - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count);
- if (tmp.f_bfree < le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count))
- tmp.f_bavail = 0;
- tmp.f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count);
- tmp.f_ffree = ext2_count_free_inodes (sb);
- tmp.f_namelen = EXT2_NAME_LEN;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = EXT2_SUPER_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = le32_to_cpu(sb->u.ext2_sb.s_es->s_blocks_count) - overhead;
+ buf->f_bfree = ext2_count_free_blocks (sb);
+ buf->f_bavail = buf->f_bfree - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count);
+ if (buf->f_bfree < le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count))
+ buf->f_bavail = 0;
+ buf->f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count);
+ buf->f_ffree = ext2_count_free_inodes (sb);
+ buf->f_namelen = EXT2_NAME_LEN;
+ return 0;
}
-static struct file_system_type ext2_fs_type = {
- "ext2",
- FS_REQUIRES_DEV /* | FS_IBASKET */, /* ibaskets have unresolved bugs */
- ext2_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(ext2_fs_type, "ext2", ext2_read_super);
static int __init init_ext2_fs(void)
{
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 63af738a3..f95adc0fd 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -194,11 +194,6 @@ void fat_put_super(struct super_block *sb)
kfree(MSDOS_SB(sb)->options.iocharset);
MSDOS_SB(sb)->options.iocharset = NULL;
}
-
- if (MSDOS_SB(sb)->put_super_callback)
- MSDOS_SB(sb)->put_super_callback(sb);
- MOD_DEC_USE_COUNT;
- return;
}
@@ -444,9 +439,7 @@ fat_read_super(struct super_block *sb, void *data, int silent,
sbi->cvf_format = NULL;
sbi->private_data = NULL;
- MOD_INC_USE_COUNT;
sbi->dir_ops = fs_dir_inode_ops;
- sbi->put_super_callback = NULL;
sb->s_op = &fat_sops;
if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)];
@@ -465,7 +458,6 @@ fat_read_super(struct super_block *sb, void *data, int silent,
memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options));
fat_cache_init();
- lock_super(sb);
if( blksize > 1024 )
{
/* Force the superblock to a larger size here. */
@@ -479,7 +471,6 @@ fat_read_super(struct super_block *sb, void *data, int silent,
set_blocksize(sb->s_dev, 1024);
}
bh = bread(sb->s_dev, 0, sb->s_blocksize);
- unlock_super(sb);
if (bh == NULL || !buffer_uptodate(bh)) {
brelse (bh);
goto out_no_bread;
@@ -693,23 +684,21 @@ out_fail:
printk("VFS: freeing iocharset=%s\n", opts.iocharset);
kfree(opts.iocharset);
}
- sb->s_dev = 0;
if(sbi->private_data)
kfree(sbi->private_data);
sbi->private_data=NULL;
- MOD_DEC_USE_COUNT;
return NULL;
}
-int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
+int fat_statfs(struct super_block *sb,struct statfs *buf)
{
int free,nr;
- struct statfs tmp;
if (MSDOS_SB(sb)->cvf_format &&
MSDOS_SB(sb)->cvf_format->cvf_statfs)
- return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz);
+ return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,
+ sizeof(struct statfs));
lock_fat(sb);
if (MSDOS_SB(sb)->free_clusters != -1)
@@ -721,15 +710,13 @@ int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
MSDOS_SB(sb)->free_clusters = free;
}
unlock_fat(sb);
- tmp.f_type = sb->s_magic;
- tmp.f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
- tmp.f_blocks = MSDOS_SB(sb)->clusters;
- tmp.f_bfree = free;
- tmp.f_bavail = free;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = sb->s_magic;
+ buf->f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
+ buf->f_blocks = MSDOS_SB(sb)->clusters;
+ buf->f_bfree = free;
+ buf->f_bavail = free;
+ buf->f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12;
+ return 0;
}
static int is_exec(char *extension)
diff --git a/fs/filesystems.c b/fs/filesystems.c
index d0a446c6e..807f8306d 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -32,7 +32,6 @@
#include <linux/hfs_fs.h>
#include <linux/devpts_fs.h>
#include <linux/bfs_fs.h>
-#include <linux/adfs_fs.h>
#include <linux/openprom_fs.h>
#include <linux/major.h>
#include <linux/smp.h>
@@ -89,10 +88,6 @@ void __init filesystem_setup(void)
init_devfs_fs(); /* Header file may make this empty */
-#ifdef CONFIG_LOCKD
- nlmxdr_init();
-#endif
-
#ifdef CONFIG_NFS_FS
init_nfs_fs();
#endif
@@ -141,10 +136,6 @@ void __init filesystem_setup(void)
init_efs_fs();
#endif
-#ifdef CONFIG_ADFS_FS
- init_adfs_fs();
-#endif
-
#ifdef CONFIG_DEVPTS_FS
init_devpts_fs();
#endif
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 40f8d2e5f..debe0a967 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -311,7 +311,7 @@ int hfs_rmdir(struct inode * parent, struct dentry *dentry)
goto hfs_rmdir_put;
error = -EBUSY;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
goto hfs_rmdir_put;
if (/* we only have to worry about 2 and 3 for mount points */
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 3ed8307a0..251690dc8 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -36,7 +36,7 @@
static void hfs_read_inode(struct inode *);
static void hfs_put_super(struct super_block *);
-static int hfs_statfs(struct super_block *, struct statfs *, int);
+static int hfs_statfs(struct super_block *, struct statfs *);
static void hfs_write_super(struct super_block *);
/*================ Global variables ================*/
@@ -51,11 +51,7 @@ static struct super_operations hfs_super_operations = {
/*================ File-local variables ================*/
-static struct file_system_type hfs_fs = {
- "hfs",
- FS_REQUIRES_DEV,
- hfs_read_super,
- NULL};
+static DECLARE_FSTYPE_DEV(hfs_fs, "hfs", hfs_read_super);
/*================ File-local functions ================*/
@@ -126,8 +122,6 @@ static void hfs_put_super(struct super_block *sb)
/* restore default blocksize for the device */
set_blocksize(sb->s_dev, BLOCK_SIZE);
-
- MOD_DEC_USE_COUNT;
}
/*
@@ -139,21 +133,20 @@ static void hfs_put_super(struct super_block *sb)
*
* changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
*/
-static int hfs_statfs(struct super_block *sb, struct statfs *buf, int len)
+static int hfs_statfs(struct super_block *sb, struct statfs *buf)
{
struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
- struct statfs tmp;
-
- tmp.f_type = HFS_SUPER_MAGIC;
- tmp.f_bsize = HFS_SECTOR_SIZE;
- tmp.f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
- tmp.f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
- tmp.f_bavail = tmp.f_bfree;
- tmp.f_files = mdb->fs_ablocks;
- tmp.f_ffree = mdb->free_ablocks;
- tmp.f_namelen = HFS_NAMELEN;
-
- return copy_to_user(buf, &tmp, len) ? -EFAULT : 0;
+
+ buf->f_type = HFS_SUPER_MAGIC;
+ buf->f_bsize = HFS_SECTOR_SIZE;
+ buf->f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
+ buf->f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
+ buf->f_bavail = buf->f_bfree;
+ buf->f_files = mdb->fs_ablocks;
+ buf->f_ffree = mdb->free_ablocks;
+ buf->f_namelen = HFS_NAMELEN;
+
+ return 0;
}
/*
@@ -407,11 +400,6 @@ struct super_block *hfs_read_super(struct super_block *s, void *data,
goto bail3;
}
- /* in case someone tries to unload the module while we wait on I/O */
- MOD_INC_USE_COUNT;
-
- lock_super(s);
-
/* set the device driver to 512-byte blocks */
set_blocksize(dev, HFS_SECTOR_SIZE);
@@ -471,7 +459,6 @@ struct super_block *hfs_read_super(struct super_block *s, void *data,
s->s_root->d_op = &hfs_dentry_operations;
/* everything's okay */
- unlock_super(s);
return s;
bail_no_root:
@@ -481,10 +468,7 @@ bail1:
hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
bail2:
set_blocksize(dev, BLOCK_SIZE);
- unlock_super(s);
- MOD_DEC_USE_COUNT;
bail3:
- s->s_dev = 0;
return NULL;
}
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 44d1037cf..677fda52c 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -311,7 +311,7 @@ int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *);
int hpfs_remount_fs(struct super_block *, int *, char *);
void hpfs_put_super(struct super_block *);
unsigned hpfs_count_one_bitmap(struct super_block *, secno);
-int hpfs_statfs(struct super_block *, struct statfs *, int);
+int hpfs_statfs(struct super_block *, struct statfs *);
struct super_block *hpfs_read_super(struct super_block *, void *, int);
extern struct address_space_operations hpfs_aops;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 663817085..f02239eae 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -375,7 +375,7 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
hpfs_unlock_2inodes(dir, inode);
return -ENOTDIR;
}
- if (!list_empty(&dentry->d_hash)) {
+ if (!d_unhashed(dentry)) {
hpfs_brelse4(&qbh);
hpfs_unlock_2inodes(dir, inode);
return -EBUSY;
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 8937bb90e..d29f6e574 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -102,8 +102,6 @@ void hpfs_put_super(struct super_block *s)
if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table);
if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir);
unmark_dirty(s);
- s->s_dev = 0;
- MOD_DEC_USE_COUNT;
}
unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
@@ -132,22 +130,21 @@ static unsigned count_bitmaps(struct super_block *s)
return count;
}
-int hpfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz)
+int hpfs_statfs(struct super_block *s, struct statfs *buf)
{
- struct statfs tmp;
/*if (s->s_hpfs_n_free == -1) {*/
s->s_hpfs_n_free = count_bitmaps(s);
s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap);
/*}*/
- tmp.f_type = s->s_magic;
- tmp.f_bsize = 512;
- tmp.f_blocks = s->s_hpfs_fs_size;
- tmp.f_bfree = s->s_hpfs_n_free;
- tmp.f_bavail = s->s_hpfs_n_free;
- tmp.f_files = s->s_hpfs_dirband_size / 4;
- tmp.f_ffree = s->s_hpfs_n_free_dnodes;
- tmp.f_namelen = 254;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = s->s_magic;
+ buf->f_bsize = 512;
+ buf->f_blocks = s->s_hpfs_fs_size;
+ buf->f_bfree = s->s_hpfs_n_free;
+ buf->f_bavail = s->s_hpfs_n_free;
+ buf->f_files = s->s_hpfs_dirband_size / 4;
+ buf->f_ffree = s->s_hpfs_n_free_dnodes;
+ buf->f_namelen = 254;
+ return 0;
}
/* Super operations */
@@ -369,8 +366,6 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options,
int o;
- MOD_INC_USE_COUNT;
-
s->s_hpfs_bmp_dir = NULL;
s->s_hpfs_cp_table = NULL;
@@ -400,7 +395,6 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options,
}
/*s->s_hpfs_mounting = 1;*/
- lock_super(s);
dev = s->s_dev;
set_blocksize(dev, 512);
s->s_hpfs_fs_size = -1;
@@ -524,7 +518,6 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options,
hpfs_lock_iget(s, 1);
s->s_root = d_alloc_root(iget(s, s->s_hpfs_root));
hpfs_unlock_iget(s);
- unlock_super(s);
if (!s->s_root || !s->s_root->d_inode) {
printk("HPFS: iget failed. Why???\n");
goto bail0;
@@ -555,17 +548,14 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options,
bail4: brelse(bh2);
bail3: brelse(bh1);
bail2: brelse(bh0);
-bail1: unlock_super(s);
-bail0: s->s_dev = 0;
+bail1:
+bail0:
if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir);
if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table);
- MOD_DEC_USE_COUNT;
return NULL;
}
-struct file_system_type hpfs_fs_type = {
- "hpfs", FS_REQUIRES_DEV, hpfs_read_super, NULL
-};
+DECLARE_FSTYPE_DEV(hpfs_fs_type, "hpfs", hpfs_read_super);
int init_hpfs_fs(void)
{
diff --git a/fs/inode.c b/fs/inode.c
index 9b216857d..c4915bba1 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -94,6 +94,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
INIT_LIST_HEAD(&inode->i_data.pages);
INIT_LIST_HEAD(&inode->i_dentry);
sema_init(&inode->i_sem, 1);
+ sema_init(&inode->i_zombie, 1);
spin_lock_init(&inode->i_data.i_shared_lock);
}
}
diff --git a/fs/iobuf.c b/fs/iobuf.c
index 4eaefe723..4be225870 100644
--- a/fs/iobuf.c
+++ b/fs/iobuf.c
@@ -12,18 +12,21 @@
static kmem_cache_t *kiobuf_cachep;
-/*
- * The default IO completion routine for kiobufs: just wake up
- * the kiobuf, nothing more.
- */
-void simple_wakeup_kiobuf(struct kiobuf *kiobuf)
+void end_kio_request(struct kiobuf *kiobuf, int uptodate)
{
- wake_up(&kiobuf->wait_queue);
+ if ((!uptodate) && !kiobuf->errno)
+ kiobuf->errno = -EIO;
+
+ if (atomic_dec_and_test(&kiobuf->io_count)) {
+ if (kiobuf->end_io)
+ kiobuf->end_io(kiobuf);
+ wake_up(&kiobuf->wait_queue);
+ }
}
-void __init kiobuf_init(void)
+void __init kiobuf_setup(void)
{
kiobuf_cachep = kmem_cache_create("kiobuf",
sizeof(struct kiobuf),
@@ -33,6 +36,13 @@ void __init kiobuf_init(void)
panic("Cannot create kernel iobuf cache\n");
}
+void kiobuf_init(struct kiobuf *iobuf)
+{
+ memset(iobuf, 0, sizeof(*iobuf));
+ init_waitqueue_head(&iobuf->wait_queue);
+ iobuf->array_len = KIO_STATIC_PAGES;
+ iobuf->maplist = iobuf->map_array;
+}
int alloc_kiovec(int nr, struct kiobuf **bufp)
{
@@ -45,12 +55,7 @@ int alloc_kiovec(int nr, struct kiobuf **bufp)
free_kiovec(i, bufp);
return -ENOMEM;
}
-
- memset(iobuf, 0, sizeof(*iobuf));
- init_waitqueue_head(&iobuf->wait_queue);
- iobuf->end_io = simple_wakeup_kiobuf;
- iobuf->array_len = KIO_STATIC_PAGES;
- iobuf->maplist = iobuf->map_array;
+ kiobuf_init(iobuf);
*bufp++ = iobuf;
}
@@ -64,6 +69,8 @@ void free_kiovec(int nr, struct kiobuf **bufp)
for (i = 0; i < nr; i++) {
iobuf = bufp[i];
+ if (iobuf->locked)
+ unlock_kiovec(1, &iobuf);
if (iobuf->array_len > KIO_STATIC_PAGES)
kfree (iobuf->maplist);
kmem_cache_free(kiobuf_cachep, bufp[i]);
@@ -104,6 +111,9 @@ void kiobuf_wait_for_io(struct kiobuf *kiobuf)
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
+ if (atomic_read(&kiobuf->io_count) == 0)
+ return;
+
add_wait_queue(&kiobuf->wait_queue, &wait);
repeat:
run_task_queue(&tq_disk);
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 996d5ba68..b13ee0285 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -69,12 +69,11 @@ static void isofs_put_super(struct super_block *sb)
check_malloc, check_bread);
#endif
- MOD_DEC_USE_COUNT;
return;
}
static void isofs_read_inode(struct inode *);
-static int isofs_statfs (struct super_block *, struct statfs *, int);
+static int isofs_statfs (struct super_block *, struct statfs *);
static struct super_operations isofs_sops = {
read_inode: isofs_read_inode,
@@ -487,10 +486,6 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
struct inode * inode;
struct iso9660_options opt;
- MOD_INC_USE_COUNT;
- /* lock before any blocking operations */
- lock_super(s);
-
if (!parse_options((char *) data, &opt))
goto out_unlock;
@@ -825,7 +820,6 @@ root_found:
if (opt.check == 'r') table++;
s->s_root->d_op = &isofs_dentry_ops[table];
- unlock_super(s);
return s;
/*
@@ -868,26 +862,21 @@ out_unknown_format:
out_freebh:
brelse(bh);
out_unlock:
- s->s_dev = 0;
- unlock_super(s);
- MOD_DEC_USE_COUNT;
return NULL;
}
-static int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
+static int isofs_statfs (struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = ISOFS_SUPER_MAGIC;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = (sb->u.isofs_sb.s_nzones
+ buf->f_type = ISOFS_SUPER_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = (sb->u.isofs_sb.s_nzones
<< (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = sb->u.isofs_sb.s_ninodes;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_files = sb->u.isofs_sb.s_ninodes;
+ buf->f_ffree = 0;
+ buf->f_namelen = NAME_MAX;
+ return 0;
}
/* Life is simpler than for other filesystem since we never
@@ -1440,12 +1429,7 @@ void leak_check_brelse(struct buffer_head * bh){
#endif
-static struct file_system_type iso9660_fs_type = {
- "iso9660",
- FS_REQUIRES_DEV,
- isofs_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);
int __init init_iso9660_fs(void)
{
diff --git a/fs/lockd/lockd_syms.c b/fs/lockd/lockd_syms.c
index db36300ba..b3990ed98 100644
--- a/fs/lockd/lockd_syms.c
+++ b/fs/lockd/lockd_syms.c
@@ -39,15 +39,4 @@ EXPORT_SYMBOL(nlmsvc_ops);
EXPORT_SYMBOL(nlmsvc_grace_period);
EXPORT_SYMBOL(nlmsvc_timeout);
-#ifdef CONFIG_LOCKD_V4
-
-/* NLM4 exported symbols */
-EXPORT_SYMBOL(nlm4_rofs);
-EXPORT_SYMBOL(nlm4_stale_fh);
-EXPORT_SYMBOL(nlm4_deadlock);
-EXPORT_SYMBOL(nlm4_failed);
-EXPORT_SYMBOL(nlm4_fbig);
-
-#endif
-
#endif /* CONFIG_MODULES */
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 62401adbd..264c19c2e 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -322,7 +322,6 @@ init_module(void)
init_MUTEX(&nlmsvc_sema);
nlmsvc_users = 0;
nlmsvc_pid = 0;
- nlmxdr_init();
return 0;
}
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index b3489a88d..c6395a54f 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -25,15 +25,17 @@
/*
* Global file hash table
*/
-#define FILE_NRHASH 32
#define FILE_HASH_BITS 5
+#define FILE_NRHASH (1<<FILE_HASH_BITS)
static struct nlm_file * nlm_files[FILE_NRHASH];
static DECLARE_MUTEX(nlm_file_sema);
-static unsigned int file_hash(dev_t dev, ino_t ino)
+static inline unsigned int file_hash(struct nfs_fh *f)
{
- unsigned long tmp = (unsigned long) ino | (unsigned long) dev;
- tmp = tmp + (tmp >> FILE_HASH_BITS) + (tmp >> FILE_HASH_BITS*2);
+ unsigned int tmp=0;
+ int i;
+ for (i=0; i<NFS_FHSIZE;i++)
+ tmp += f->data[i];
return tmp & (FILE_NRHASH - 1);
}
@@ -50,34 +52,35 @@ u32
nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
struct nfs_fh *f)
{
- struct knfs_fh *fh = (struct knfs_fh *) f;
struct nlm_file *file;
unsigned int hash;
u32 nfserr;
+ u32 *fhp = (u32*)f->data;
- dprintk("lockd: nlm_file_lookup(%s/%u)\n",
- kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
+ dprintk("lockd: nlm_file_lookup(%08x %08x %08x %08x %08x %08x)\n",
+ fhp[0], fhp[1], fhp[2], fhp[3], fhp[4], fhp[5]);
- hash = file_hash(u32_to_kdev_t(fh->fh_dev), u32_to_ino_t(fh->fh_ino));
+
+ hash = file_hash(f);
/* Lock file table */
down(&nlm_file_sema);
- for (file = nlm_files[hash]; file; file = file->f_next) {
- if (file->f_handle.fh_dcookie == fh->fh_dcookie &&
- !memcmp(&file->f_handle, fh, sizeof(*fh)))
+ for (file = nlm_files[hash]; file; file = file->f_next)
+ if (!memcmp(&file->f_handle, f, sizeof(*f)))
goto found;
- }
- dprintk("lockd: creating file for %s/%u\n",
- kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
+ dprintk("lockd: creating file for (%08x %08x %08x %08x %08x %08x)\n",
+ fhp[0], fhp[1], fhp[2], fhp[3], fhp[4], fhp[5]);
+
nfserr = nlm_lck_denied_nolocks;
file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL);
if (!file)
goto out_unlock;
memset(file, 0, sizeof(*file));
- file->f_handle = *fh;
+ file->f_handle = *f;
+ file->f_hash = hash;
init_MUTEX(&file->f_sema);
/* Open the file. Note that this must not sleep for too long, else
@@ -86,7 +89,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
* We have to make sure we have the right credential to open
* the file.
*/
- if ((nfserr = nlmsvc_ops->fopen(rqstp, fh, &file->f_file)) != 0) {
+ if ((nfserr = nlmsvc_ops->fopen(rqstp, f, &file->f_file)) != 0) {
dprintk("lockd: open failed (nfserr %d)\n", ntohl(nfserr));
goto out_free;
}
@@ -126,7 +129,7 @@ nlm_delete_file(struct nlm_file *file)
dprintk("lockd: closing file %s/%ld\n",
kdevname(inode->i_dev), inode->i_ino);
- fp = nlm_files + file_hash(inode->i_dev, inode->i_ino);
+ fp = nlm_files + file->f_hash;
while ((f = *fp) != NULL) {
if (f == file) {
*fp = file->f_next;
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index c0797a16f..eba3aaef6 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -20,44 +20,7 @@
#include <linux/lockd/sm_inter.h>
#define NLMDBG_FACILITY NLMDBG_XDR
-#define NLM_MAXSTRLEN 1024
-#define QUADLEN(len) (((len) + 3) >> 2)
-
-
-u32 nlm_granted, nlm_lck_denied, nlm_lck_denied_nolocks,
- nlm_lck_blocked, nlm_lck_denied_grace_period;
-
-
-typedef struct nlm_args nlm_args;
-
-/*
- * Initialization of NFS status variables
- */
-void
-nlmxdr_init(void)
-{
- static int inited = 0;
-
- if (inited)
- return;
-
- nlm_granted = htonl(NLM_LCK_GRANTED);
- nlm_lck_denied = htonl(NLM_LCK_DENIED);
- nlm_lck_denied_nolocks = htonl(NLM_LCK_DENIED_NOLOCKS);
- nlm_lck_blocked = htonl(NLM_LCK_BLOCKED);
- nlm_lck_denied_grace_period = htonl(NLM_LCK_DENIED_GRACE_PERIOD);
-
-#ifdef CONFIG_LOCKD_V4
- nlm4_deadlock = htonl(NLM_DEADLCK);
- nlm4_rofs = htonl(NLM_ROFS);
- nlm4_stale_fh = htonl(NLM_STALE_FH);
- nlm4_fbig = htonl(NLM_FBIG);
- nlm4_failed = htonl(NLM_FAILED);
-#endif
-
- inited = 1;
-}
/*
* XDR functions for basic NLM types
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 7cedcd849..025e3c5b0 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -20,16 +20,8 @@
#include <linux/lockd/sm_inter.h>
#define NLMDBG_FACILITY NLMDBG_XDR
-#define NLM_MAXSTRLEN 1024
#define OFFSET_MAX ((off_t)LONG_MAX)
-#define QUADLEN(len) (((len) + 3) >> 2)
-
-u32 nlm4_deadlock, nlm4_rofs, nlm4_stale_fh, nlm4_fbig,
- nlm4_failed;
-
-
-typedef struct nlm_args nlm_args;
static inline off_t
size_to_off_t(__s64 size)
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 1d9ebb062..31d4c99c7 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -23,14 +23,13 @@
#include <linux/highuid.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/minix_fs.h>
static void minix_read_inode(struct inode * inode);
static void minix_write_inode(struct inode * inode);
-static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int minix_statfs(struct super_block *sb, struct statfs *buf);
static int minix_remount (struct super_block * sb, int * flags, char * data);
static void minix_delete_inode(struct inode *inode)
@@ -80,7 +79,6 @@ static void minix_put_super(struct super_block *sb)
brelse (sb->u.minix_sb.s_sbh);
kfree(sb->u.minix_sb.s_imap);
- MOD_DEC_USE_COUNT;
return;
}
@@ -189,13 +187,10 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
if (64 != sizeof(struct minix2_inode))
panic("bad V2 i-node size");
- MOD_INC_USE_COUNT;
-
hblock = get_hardblocksize(dev);
if (hblock && hblock > BLOCK_SIZE)
goto out_bad_hblock;
- lock_super(s);
set_blocksize(dev, BLOCK_SIZE);
if (!(bh = bread(dev,1,BLOCK_SIZE)))
goto out_bad_sb;
@@ -287,7 +282,6 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
mark_buffer_dirty(bh, 1);
s->s_dirt = 1;
}
- unlock_super(s);
if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
printk ("MINIX-fs: mounting unchecked file system, "
"running fsck is recommended.\n");
@@ -329,7 +323,7 @@ out_no_fs:
"%s.\n", kdevname(dev));
out_release:
brelse(bh);
- goto out_unlock;
+ goto out;
out_bad_hblock:
printk("MINIX-fs: blocksize too small for device.\n");
@@ -337,27 +331,21 @@ out_bad_hblock:
out_bad_sb:
printk("MINIX-fs: unable to read superblock\n");
- out_unlock:
- unlock_super(s);
out:
- s->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
-static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int minix_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = sb->s_magic;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = (sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone) << sb->u.minix_sb.s_log_zone_size;
- tmp.f_bfree = minix_count_free_blocks(sb);
- tmp.f_bavail = tmp.f_bfree;
- tmp.f_files = sb->u.minix_sb.s_ninodes;
- tmp.f_ffree = minix_count_free_inodes(sb);
- tmp.f_namelen = sb->u.minix_sb.s_namelen;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = sb->s_magic;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = (sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone) << sb->u.minix_sb.s_log_zone_size;
+ buf->f_bfree = minix_count_free_blocks(sb);
+ buf->f_bavail = buf->f_bfree;
+ buf->f_files = sb->u.minix_sb.s_ninodes;
+ buf->f_ffree = minix_count_free_inodes(sb);
+ buf->f_namelen = sb->u.minix_sb.s_namelen;
+ return 0;
}
/*
@@ -1277,12 +1265,7 @@ int minix_sync_inode(struct inode * inode)
return err;
}
-static struct file_system_type minix_fs_type = {
- "minix",
- FS_REQUIRES_DEV,
- minix_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
int __init init_minix_fs(void)
{
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index c18b46a37..211556d4a 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -399,7 +399,7 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
retval = -ENOENT;
goto end_rmdir;
}
- if (!list_empty(&dentry->d_hash)) {
+ if (!d_unhashed(dentry)) {
retval = -EBUSY;
goto end_rmdir;
}
@@ -569,6 +569,9 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
}
if (S_ISDIR(old_inode->i_mode)) {
if (new_inode) {
+ retval = -EBUSY;
+ if (!d_unhashed(new_dentry))
+ goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
goto end_rename;
diff --git a/fs/msdos/msdosfs_syms.c b/fs/msdos/msdosfs_syms.c
index df865b482..8e9897f2f 100644
--- a/fs/msdos/msdosfs_syms.c
+++ b/fs/msdos/msdosfs_syms.c
@@ -27,12 +27,7 @@ EXPORT_SYMBOL(msdos_read_super);
EXPORT_SYMBOL(msdos_put_super);
-struct file_system_type msdos_fs_type = {
- "msdos",
- FS_REQUIRES_DEV,
- msdos_read_super,
- NULL
-};
+DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
int __init init_msdos_fs(void)
{
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 87a49fb47..7febeaa8b 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -326,7 +326,7 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
* whether it is empty.
*/
res = -EBUSY;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
goto rmdir_done;
res = fat_dir_empty(inode);
if (res)
@@ -463,6 +463,9 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
goto degenerate_case;
if (is_dir) {
if (new_inode) {
+ error = -EBUSY;
+ if (!d_unhashed(new_dentry))
+ goto out;
error = fat_dir_empty(new_inode);
if (error)
goto out;
@@ -590,28 +593,18 @@ struct inode_operations msdos_dir_inode_operations = {
setattr: fat_notify_change,
};
-static void msdos_put_super_callback(struct super_block *sb)
-{
- MOD_DEC_USE_COUNT;
-}
-
struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
{
struct super_block *res;
- MOD_INC_USE_COUNT;
-
MSDOS_SB(sb)->options.isvfat = 0;
res = fat_read_super(sb, data, silent, &msdos_dir_inode_operations);
if (res == NULL)
goto out_fail;
- MSDOS_SB(sb)->put_super_callback=msdos_put_super_callback;
sb->s_root->d_op = &msdos_dentry_operations;
return res;
out_fail:
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
diff --git a/fs/namei.c b/fs/namei.c
index 5f148b5a8..97c239929 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -580,6 +580,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
mode &= S_IALLUGO & ~current->fs->umask;
mode |= S_IFREG;
+ down(&dir->i_zombie);
error = may_create(dir, dentry);
if (error)
goto exit_lock;
@@ -591,6 +592,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
DQUOT_INIT(dir);
error = dir->i_op->create(dir, dentry, mode);
exit_lock:
+ up(&dir->i_zombie);
return error;
}
@@ -745,7 +747,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
mode &= ~current->fs->umask;
- if (!S_ISFIFO(mode) && !capable(CAP_MKNOD))
+ down(&dir->i_zombie);
+ if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
goto exit_lock;
error = may_create(dir, dentry);
@@ -759,6 +762,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
DQUOT_INIT(dir);
error = dir->i_op->mknod(dir, dentry, mode, dev);
exit_lock:
+ up(&dir->i_zombie);
return error;
}
@@ -836,6 +840,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
int error;
+ down(&dir->i_zombie);
error = may_create(dir, dentry);
if (error)
goto exit_lock;
@@ -849,6 +854,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
error = dir->i_op->mkdir(dir, dentry, mode);
exit_lock:
+ up(&dir->i_zombie);
return error;
}
@@ -901,6 +907,34 @@ asmlinkage long sys_mkdir(const char * pathname, int mode)
return error;
}
+/*
+ * We try to drop the dentry early: we should have
+ * a usage count of 2 if we're the only user of this
+ * dentry, and if that is true (possibly after pruning
+ * the dcache), then we drop the dentry now.
+ *
+ * A low-level filesystem can, if it choses, legally
+ * do a
+ *
+ * if (!d_unhashed(dentry))
+ * return -EBUSY;
+ *
+ * if it cannot handle the case of removing a directory
+ * that is still in use by something else..
+ */
+static void d_unhash(struct dentry *dentry)
+{
+ dget(dentry);
+ switch (dentry->d_count) {
+ default:
+ shrink_dcache_parent(dentry);
+ if (dentry->d_count != 2)
+ break;
+ case 2:
+ d_drop(dentry);
+ }
+}
+
int vfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
@@ -914,31 +948,11 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
DQUOT_INIT(dir);
- /*
- * We try to drop the dentry early: we should have
- * a usage count of 2 if we're the only user of this
- * dentry, and if that is true (possibly after pruning
- * the dcache), then we drop the dentry now.
- *
- * A low-level filesystem can, if it choses, legally
- * do a
- *
- * if (!list_empty(&dentry->d_hash))
- * return -EBUSY;
- *
- * if it cannot handle the case of removing a directory
- * that is still in use by something else..
- */
- switch (dentry->d_count) {
- default:
- shrink_dcache_parent(dentry);
- if (dentry->d_count != 2)
- break;
- case 2:
- d_drop(dentry);
- }
-
+ double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
+ d_unhash(dentry);
error = dir->i_op->rmdir(dir, dentry);
+ double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
+ dput(dentry);
return error;
}
@@ -954,27 +968,11 @@ static inline int do_rmdir(const char * name)
if (IS_ERR(dentry))
goto exit;
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-
- dir = dget(dentry->d_parent);
-
- /*
- * The dentry->d_count stuff confuses d_delete() enough to
- * not kill the inode from under us while it is locked. This
- * wouldn't be needed, except the dentry semaphore is really
- * in the inode, not in the dentry..
- */
- dentry->d_count++;
- double_lock(dir, dentry);
-
+ dir = lock_parent(dentry);
error = -ENOENT;
if (check_parent(dir, dentry))
error = vfs_rmdir(dir->d_inode, dentry);
-
- double_unlock(dentry, dir);
-exit_dput:
+ unlock_dir(dir);
dput(dentry);
exit:
return error;
@@ -1001,6 +999,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error;
+ down(&dir->i_zombie);
error = may_delete(dir, dentry, 0);
if (!error) {
error = -EPERM;
@@ -1009,10 +1008,11 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
error = dir->i_op->unlink(dir, dentry);
}
}
+ up(&dir->i_zombie);
return error;
}
-static inline int do_unlink(const char * name)
+int do_unlink(const char * name)
{
int error;
struct dentry *dir;
@@ -1054,6 +1054,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
int error;
+ down(&dir->i_zombie);
error = may_create(dir, dentry);
if (error)
goto exit_lock;
@@ -1066,6 +1067,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
error = dir->i_op->symlink(dir, dentry, oldname);
exit_lock:
+ up(&dir->i_zombie);
return error;
}
@@ -1121,6 +1123,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
struct inode *inode;
int error;
+ down(&dir->i_zombie);
error = -ENOENT;
inode = old_dentry->d_inode;
if (!inode)
@@ -1147,6 +1150,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
error = dir->i_op->link(old_dentry, dir, new_dentry);
exit_lock:
+ up(&dir->i_zombie);
return error;
}
@@ -1212,11 +1216,37 @@ asmlinkage long sys_link(const char * oldname, const char * newname)
return error;
}
+/*
+ * The worst of all namespace operations - renaming directory. "Perverted"
+ * doesn't even start to describe it. Somebody in UCB had a heck of a trip...
+ * Problems:
+ * a) we can get into loop creation. Check is done in is_subdir().
+ * b) race potential - two innocent renames can create a loop together.
+ * That's where 4.4 screws up. Current fix: serialization on
+ * sb->s_vfs_rename_sem. We might be more accurate, but that's another
+ * story.
+ * c) we have to lock _three_ objects - parents and victim (if it exists).
+ * And that - after we got ->i_sem on parents (until then we don't know
+ * whether the target exists at all, let alone whether it is a directory
+ * or not). Solution: ->i_zombie. Taken only after ->i_sem. Always taken
+ * on link creation/removal of any kind. And taken (without ->i_sem) on
+ * directory that will be removed (both in rmdir() and here).
+ * d) some filesystems don't support opened-but-unlinked directories,
+ * either because of layout or because they are not ready to deal with
+ * all cases correctly. The latter will be fixed (taking this sort of
+ * stuff into VFS), but the former is not going away. Solution: the same
+ * trick as in rmdir().
+ * e) conversion from fhandle to dentry may come in the wrong moment - when
+ * we are removing the target. Solution: we will have to grab ->i_zombie
+ * in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on
+ * ->i_sem on parents, which works but leads to some truely excessive
+ * locking].
+ */
int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
int error;
- int need_rehash = 0;
+ struct inode *target;
if (old_dentry->d_inode == new_dentry->d_inode)
return 0;
@@ -1254,15 +1284,26 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
error = -EINVAL;
if (is_subdir(new_dentry, old_dentry))
goto out_unlock;
- if (new_dentry->d_inode) {
- error = -EBUSY;
- if (d_invalidate(new_dentry)<0)
- goto out_unlock;
- need_rehash = 1;
- }
+ target = new_dentry->d_inode;
+ if (target) { /* Hastur! Hastur! Hastur! */
+ triple_down(&old_dir->i_zombie,
+ &new_dir->i_zombie,
+ &target->i_zombie);
+ d_unhash(new_dentry);
+ } else
+ double_down(&old_dir->i_zombie,
+ &new_dir->i_zombie);
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
- if (need_rehash)
+ if (target) {
+ triple_up(&old_dir->i_zombie,
+ &new_dir->i_zombie,
+ &target->i_zombie);
d_rehash(new_dentry);
+ dput(new_dentry);
+ } else
+ double_up(&old_dir->i_zombie,
+ &new_dir->i_zombie);
+
if (!error)
d_move(old_dentry,new_dentry);
out_unlock:
@@ -1297,7 +1338,9 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
DQUOT_INIT(old_dir);
DQUOT_INIT(new_dir);
+ double_down(&old_dir->i_zombie, &new_dir->i_zombie);
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+ double_up(&old_dir->i_zombie, &new_dir->i_zombie);
if (error)
return error;
/* The following d_move() should become unconditional */
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index ae5c13962..f5a5856f3 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -929,7 +929,7 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
goto out;
error = -EBUSY;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
goto out;
error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -1072,7 +1072,6 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
case 0x00:
DPRINTK("ncp renamed %s -> %s.\n",
old_dentry->d_name.name,new_dentry->d_name.name);
- /* d_move(old_dentry, new_dentry); */
break;
case 0x9E:
error = -ENAMETOOLONG;
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 85cc9bd39..349eec589 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -34,7 +34,7 @@
static void ncp_put_inode(struct inode *);
static void ncp_delete_inode(struct inode *);
static void ncp_put_super(struct super_block *);
-static int ncp_statfs(struct super_block *, struct statfs *, int);
+static int ncp_statfs(struct super_block *, struct statfs *);
static struct super_operations ncp_sops =
{
@@ -273,7 +273,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
#endif
struct ncp_entry_info finfo;
- MOD_INC_USE_COUNT;
if (raw_data == NULL)
goto out_no_data;
switch (*(int*)raw_data) {
@@ -323,8 +322,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
goto out_bad_file2;
- lock_super(sb);
-
sb->s_blocksize = 1024; /* Eh... Is this correct? */
sb->s_blocksize_bits = 10;
sb->s_magic = NCP_SUPER_MAGIC;
@@ -441,7 +438,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
if (!sb->s_root)
goto out_no_root;
sb->s_root->d_op = &ncp_dentry_operations;
- unlock_super(sb);
return sb;
out_no_root:
@@ -473,7 +469,6 @@ out_free_server:
* it doesn't proper unlocking.
*/
fput(ncp_filp);
- unlock_super(sb);
goto out;
out_bad_file2:
@@ -488,8 +483,6 @@ out_bad_mount:
out_no_data:
printk(KERN_ERR "ncp_read_super: missing data argument\n");
out:
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -524,28 +517,23 @@ static void ncp_put_super(struct super_block *sb)
ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
ncp_kfree_s(server->packet, server->packet_size);
- MOD_DEC_USE_COUNT;
}
-static int ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int ncp_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
/* We cannot say how much disk space is left on a mounted
NetWare Server, because free space is distributed over
volumes, and the current user might have disk quotas. So
free space is not that simple to determine. Our decision
here is to err conservatively. */
- tmp.f_type = NCP_SUPER_MAGIC;
- tmp.f_bsize = NCP_BLOCK_SIZE;
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = -1;
- tmp.f_ffree = -1;
- tmp.f_namelen = 12;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = NCP_SUPER_MAGIC;
+ buf->f_bsize = NCP_BLOCK_SIZE;
+ buf->f_blocks = 0;
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_namelen = 12;
+ return 0;
}
int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
@@ -708,12 +696,7 @@ int ncp_malloced;
int ncp_current_malloced;
#endif
-static struct file_system_type ncp_fs_type = {
- "ncpfs",
- 0 /* FS_NO_DCACHE doesn't work correctly */,
- ncp_read_super,
- NULL
-};
+static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
int __init init_ncp_fs(void)
{
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d111076c0..37b2b682b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -672,7 +672,7 @@ static void show_dentry(struct list_head * dlist)
struct dentry * dentry = list_entry(tmp, struct dentry, d_alias);
const char * unhashed = "";
- if (list_empty(&dentry->d_hash))
+ if (d_unhashed(dentry))
unhashed = "(unhashed)";
printk("show_dentry: %s/%s, d_count=%d%s\n",
@@ -1027,7 +1027,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
/*
* Unhash the dentry while we remove the file ...
*/
- if (!list_empty(&dentry->d_hash)) {
+ if (!d_unhashed(dentry)) {
d_drop(dentry);
rehash = 1;
}
@@ -1194,11 +1194,13 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* For files, make a copy of the dentry and then do a
* silly-rename. If the silly-rename succeeds, the
* copied dentry is hashed and becomes the new target.
- *
- * With directories check is done in VFS.
*/
+ if (!new_inode)
+ goto go_ahead;
error = -EBUSY;
- if (new_dentry->d_count > 1 && new_inode) {
+ if (S_ISDIR(new_inode->i_mode))
+ goto out;
+ else if (new_dentry->d_count > 1) {
int err;
/* copy the target dentry's name */
dentry = d_alloc(new_dentry->d_parent,
@@ -1227,6 +1229,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
}
}
+go_ahead:
/*
* ... prune child dentries and writebacks if needed.
*/
@@ -1235,21 +1238,11 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
shrink_dcache_parent(old_dentry);
}
- if (new_dentry->d_count > 1 && new_inode) {
-#ifdef NFS_PARANOIA
- printk("nfs_rename: new dentry %s/%s busy, d_count=%d\n",
- new_dentry->d_parent->d_name.name,
- new_dentry->d_name.name,
- new_dentry->d_count);
-#endif
- goto out;
- }
-
/*
* To prevent any new references to the target during the rename,
* we unhash the dentry and free the inode in advance.
*/
- if (!list_empty(&new_dentry->d_hash)) {
+ if (!d_unhashed(new_dentry)) {
d_drop(new_dentry);
rehash = 1;
}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 7d2a6c146..441d62edc 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -46,7 +46,7 @@ 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_umount_begin(struct super_block *);
-static int nfs_statfs(struct super_block *, struct statfs *, int);
+static int nfs_statfs(struct super_block *, struct statfs *);
static struct super_operations nfs_sops = {
read_inode: nfs_read_inode,
@@ -143,8 +143,6 @@ nfs_put_super(struct super_block *sb)
rpciod_down(); /* release rpciod */
kfree(server->hostname);
-
- MOD_DEC_USE_COUNT;
}
void
@@ -209,7 +207,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
struct rpc_timeout timeparms;
struct nfs_fattr fattr;
- MOD_INC_USE_COUNT;
if (!data)
goto out_miss_args;
@@ -227,8 +224,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
if (srvaddr.sin_addr.s_addr == INADDR_ANY)
goto out_no_remote;
- lock_super(sb);
-
sb->s_flags |= MS_ODD_RENAME; /* This should go away */
sb->s_magic = NFS_SUPER_MAGIC;
@@ -312,7 +307,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_root->d_fsdata = root_fh;
/* We're airborne */
- unlock_super(sb);
/* Check whether to start the lockd process */
if (!(server->flags & NFS_MOUNT_NONLM))
@@ -350,7 +344,6 @@ out_no_xprt:
out_free_host:
kfree(server->hostname);
out_unlock:
- unlock_super(sb);
goto out_fail;
out_no_remote:
@@ -361,33 +354,28 @@ out_miss_args:
printk("nfs_read_super: missing data argument\n");
out_fail:
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
static int
-nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+nfs_statfs(struct super_block *sb, struct statfs *buf)
{
int error;
struct nfs_fsinfo res;
- struct statfs tmp;
error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root,
&res);
if (error) {
printk("nfs_statfs: statfs error = %d\n", -error);
- res.bsize = res.blocks = res.bfree = res.bavail = 0;
+ res.bsize = res.blocks = res.bfree = res.bavail = -1;
}
- tmp.f_type = NFS_SUPER_MAGIC;
- tmp.f_bsize = res.bsize;
- tmp.f_blocks = res.blocks;
- tmp.f_bfree = res.bfree;
- tmp.f_bavail = res.bavail;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = NFS_SUPER_MAGIC;
+ buf->f_bsize = res.bsize;
+ buf->f_blocks = res.blocks;
+ buf->f_bfree = res.bfree;
+ buf->f_bavail = res.bavail;
+ buf->f_namelen = NAME_MAX;
+ return 0;
}
/*
@@ -413,7 +401,7 @@ restart:
struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
dprintk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
- dentry->d_count, !list_empty(&dentry->d_hash));
+ dentry->d_count, !d_unhashed(dentry));
if (!list_empty(&dentry->d_subdirs))
shrink_dcache_parent(dentry);
if (!dentry->d_count) {
@@ -422,7 +410,7 @@ restart:
dput(dentry);
goto restart;
}
- if (list_empty(&dentry->d_hash))
+ if (d_unhashed(dentry))
unhashed++;
}
return unhashed;
@@ -934,12 +922,7 @@ printk("nfs_refresh_inode: invalidating %ld pages\n", inode->i_nrpages);
/*
* File system information
*/
-static struct file_system_type nfs_fs_type = {
- "nfs",
- 0 /* FS_NO_DCACHE - this doesn't work right now*/,
- nfs_read_super,
- NULL
-};
+static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, 0);
extern int nfs_init_fhcache(void);
extern int nfs_init_wreqcache(void);
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 24a8208bb..8d2b610a8 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -66,8 +66,6 @@ static int want_lock = 0;
static int hash_count = 0;
static DECLARE_WAIT_QUEUE_HEAD( hash_wait );
-#define READLOCK 0
-#define WRITELOCK 1
/*
* Find a client's export for a device.
@@ -435,7 +433,7 @@ out:
*/
int
exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
- char *path, struct knfs_fh *f)
+ char *path, struct knfsd_fh *f, int maxsize)
{
struct svc_export *exp;
struct dentry *dentry = NULL;
@@ -484,11 +482,11 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
/*
* fh must be initialized before calling fh_compose
*/
- fh_init(&fh);
- fh_compose(&fh, exp, dentry);
- memcpy(f, &fh.fh_handle, sizeof(struct knfs_fh));
+ fh_init(&fh, maxsize);
+ err = fh_compose(&fh, exp, dentry);
+ memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
fh_put(&fh);
- return 0;
+ return err;
out:
dput(dentry);
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 4062410c6..c45d494ba 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -20,14 +20,14 @@
* Note: we hold the dentry use count while the file is open.
*/
static u32
-nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
+nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
{
u32 nfserr;
struct svc_fh fh;
- /* must initialize before using! */
- fh_init(&fh);
- fh.fh_handle = *f;
+ /* must initialize before using! but maxsize doesn't matter */
+ fh_init(&fh,0);
+ memcpy((char*)&fh.fh_handle.fh_base, (char*)f, NFS_FHSIZE);
fh.fh_export = NULL;
nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
@@ -39,11 +39,14 @@ nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
* 1 = stale file handle
* 2 = other error
*/
- if (nfserr == 0)
+ switch (nfserr) {
+ case nfs_ok:
return 0;
- else if (nfserr == nfserr_stale)
+ case nfserr_stale:
return 1;
- else return 2;
+ default:
+ return 2;
+ }
}
static void
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 3b0de5545..8f69cb53e 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -28,7 +28,7 @@
#define NFSDDBG_FACILITY NFSDDBG_PROC
-#define RETURN(st) { resp->status = (st); return (st); }
+#define RETURN_STATUS(st) { resp->status = (st); return (st); }
static int nfs3_ftypes[] = {
0, /* NF3NON */
@@ -69,13 +69,12 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: GETATTR(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: GETATTR(3) %s\n",
+ SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -87,13 +86,12 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
{
int nfserr;
- dprintk("nfsd: SETATTR(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: SETATTR(3) %s\n",
+ SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -105,17 +103,18 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: LOOKUP(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: LOOKUP(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
fh_copy(&resp->dirfh, &argp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
+
nfserr = nfsd_lookup(rqstp, &resp->dirfh,
argp->name,
argp->len,
&resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -127,15 +126,14 @@ nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
{
int nfserr;
- dprintk("nfsd: ACCESS(3) %x/%ld 0x%x\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: ACCESS(3) %s 0x%x\n",
+ SVCFH_fmt(&argp->fh),
argp->access);
fh_copy(&resp->fh, &argp->fh);
resp->access = argp->access;
nfserr = nfsd_access(rqstp, &resp->fh, &resp->access);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -148,9 +146,7 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
u32 *path;
int dummy, nfserr;
- dprintk("nfsd: READLINK(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
/* Reserve room for status, post_op_attr, and path length */
svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy,
@@ -160,7 +156,7 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
fh_copy(&resp->fh, &argp->fh);
resp->len = NFS3_MAXPATHLEN;
nfserr = nfsd_readlink(rqstp, &resp->fh, (char *) path, &resp->len);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -173,9 +169,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
u32 * buffer;
int nfserr, avail;
- dprintk("nfsd: READ(3) %x/%ld %lu bytes at %lu\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
+ SVCFH_fmt(&argp->fh),
(unsigned long) argp->count,
(unsigned long) argp->offset);
@@ -201,7 +196,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
resp->eof = (argp->offset + resp->count) >= inode->i_size;
}
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -213,22 +208,21 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
{
int nfserr;
- dprintk("nfsd: WRITE(3) %x/%ld %d bytes at %ld%s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n",
+ SVCFH_fmt(&argp->fh),
argp->len,
(unsigned long) argp->offset,
argp->stable? " stable" : "");
fh_copy(&resp->fh, &argp->fh);
+ resp->committed = argp->stable;
nfserr = nfsd_write(rqstp, &resp->fh,
argp->offset,
argp->data,
argp->len,
- argp->stable);
- resp->committed = argp->stable;
+ &resp->committed);
resp->count = argp->count;
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -244,19 +238,18 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
struct iattr *attr;
u32 nfserr;
- dprintk("nfsd: CREATE(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: CREATE(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
dirfhp = fh_copy(&resp->dirfh, &argp->fh);
- newfhp = fh_init(&resp->fh);
+ newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
attr = &argp->attrs;
/* Get the directory inode */
nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE);
if (nfserr)
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
/* Unfudge the mode bits */
attr->ia_mode &= ~S_IFMT;
@@ -272,7 +265,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
attr, newfhp,
argp->createmode, argp->verf);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -284,18 +277,17 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
{
int nfserr;
- dprintk("nfsd: MKDIR(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: MKDIR(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
argp->attrs.ia_valid &= ~ATTR_SIZE;
fh_copy(&resp->dirfh, &argp->fh);
- fh_init(&resp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
&argp->attrs, S_IFDIR, 0, &resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
static int
@@ -304,17 +296,16 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
{
int nfserr;
- dprintk("nfsd: SYMLINK(3) %x/%ld %s -> %s\n",
- SVCFH_DEV(&argp->ffh),
- (long)SVCFH_INO(&argp->ffh),
+ dprintk("nfsd: SYMLINK(3) %s %s -> %s\n",
+ SVCFH_fmt(&argp->ffh),
argp->fname, argp->tname);
fh_copy(&resp->dirfh, &argp->ffh);
- fh_init(&resp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
argp->tname, argp->tlen,
&resp->fh, &argp->attrs);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -327,31 +318,30 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
int nfserr, type;
dev_t rdev = 0;
- dprintk("nfsd: MKNOD(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: MKNOD(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
fh_copy(&resp->dirfh, &argp->fh);
- fh_init(&resp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
if (argp->ftype == 0 || argp->ftype >= NF3BAD)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
if ((argp->ftype == NF3CHR && argp->major >= MAX_CHRDEV)
|| (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV)
|| argp->minor > 0xFF)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
rdev = ((argp->major) << 8) | (argp->minor);
} else
if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
type = nfs3_ftypes[argp->ftype];
nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
&argp->attrs, type, rdev, &resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -363,15 +353,14 @@ nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: REMOVE(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: REMOVE(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
/* Unlink. -S_IFDIR means file must not be a directory */
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -383,14 +372,13 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: RMDIR(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: RMDIR(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
static int
@@ -399,19 +387,18 @@ nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp,
{
int nfserr;
- dprintk("nfsd: RENAME(3) %x/%ld %s -> %x/%ld %s\n",
- SVCFH_DEV(&argp->ffh),
- (long)SVCFH_INO(&argp->ffh),
- argp->fname,
- SVCFH_DEV(&argp->tfh),
- (long)SVCFH_INO(&argp->tfh),
+ dprintk("nfsd: RENAME(3) %s %s ->\n",
+ SVCFH_fmt(&argp->ffh),
+ argp->fname);
+ dprintk("nfsd: -> %s %s\n",
+ SVCFH_fmt(&argp->tfh),
argp->tname);
fh_copy(&resp->ffh, &argp->ffh);
fh_copy(&resp->tfh, &argp->tfh);
nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
&resp->tfh, argp->tname, argp->tlen);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
static int
@@ -420,18 +407,17 @@ nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp,
{
int nfserr;
- dprintk("nfsd: LINK(3) %x/%ld -> %x/%ld %s\n",
- SVCFH_DEV(&argp->ffh),
- (long)SVCFH_INO(&argp->ffh),
- SVCFH_DEV(&argp->tfh),
- (long)SVCFH_INO(&argp->tfh),
+ dprintk("nfsd: LINK(3) %s ->\n",
+ SVCFH_fmt(&argp->ffh));
+ dprintk("nfsd: -> %s %s\n",
+ SVCFH_fmt(&argp->tfh),
argp->tname);
fh_copy(&resp->fh, &argp->ffh);
fh_copy(&resp->tfh, &argp->tfh);
nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
&resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -445,9 +431,8 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
int nfserr, count;
unsigned int want;
- dprintk("nfsd: READDIR(3) %x/%ld %d bytes at %d\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, (u32) argp->cookie);
/* Reserve buffer space for status, attributes and verifier */
@@ -467,7 +452,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -481,9 +466,8 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
u32 * buffer;
int nfserr, count, want;
- dprintk("nfsd: READDIR+(3) %x/%ld %d bytes at %d\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, (u32) argp->cookie);
/* Reserve buffer space for status, attributes and verifier */
@@ -503,7 +487,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -515,13 +499,12 @@ nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: FSSTAT(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: FSSTAT(3) %s\n",
+ SVCFH_fmt(&argp->fh));
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
fh_put(&argp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -533,9 +516,8 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: FSINFO(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: FSINFO(3) %s\n",
+ SVCFH_fmt(&argp->fh));
resp->f_rtmax = NFSSVC_MAXBLKSIZE;
resp->f_rtpref = NFSSVC_MAXBLKSIZE;
@@ -562,7 +544,7 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
}
fh_put(&argp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -574,9 +556,8 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: PATHCONF(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: PATHCONF(3) %s\n",
+ SVCFH_fmt(&argp->fh));
/* Set default pathconf */
resp->p_link_max = 255; /* at least */
@@ -605,7 +586,7 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
}
fh_put(&argp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
@@ -618,19 +599,18 @@ nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp,
{
int nfserr;
- dprintk("nfsd: COMMIT(3) %x/%ld %d@%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: COMMIT(3) %s %d@%ld\n",
+ SVCFH_fmt(&argp->fh),
argp->count,
(unsigned long) argp->offset);
if (argp->offset > NFS_OFFSET_MAX)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 84ef13ded..7dc5739eb 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -21,10 +21,6 @@
# define inline
#endif
-/*
- * Size of encoded NFS3 file handle, in words
- */
-#define NFS3_FHANDLE_WORDS (1 + XDR_QUADLEN(sizeof(struct knfs_fh)))
/*
* Mapping of S_IF* types to NFS file types
@@ -64,19 +60,36 @@ decode_time3(u32 *p, time_t *secp)
static inline u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
- if (ntohl(*p++) != sizeof(struct knfs_fh))
+ int size;
+ fh_init(fhp, NFS3_FHSIZE);
+ size = ntohl(*p++);
+ if (size > NFS3_FHSIZE)
return NULL;
- memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
- return p + (sizeof(struct knfs_fh) >> 2);
+ memcpy(&fhp->fh_handle.fh_base, p, size);
+ fhp->fh_handle.fh_size = size;
+ return p + XDR_QUADLEN(size);
}
static inline u32 *
encode_fh(u32 *p, struct svc_fh *fhp)
{
- *p++ = htonl(sizeof(struct knfs_fh));
- memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
- return p + (sizeof(struct knfs_fh) >> 2);
+#if 0
+ int size = fhp->fh_handle.fh_size;
+ *p++ = htonl(size);
+ if (size) p[XDR_QUADLEN(size)-1]=0;
+ memcpy(p, &fhp->fh_handle.fh_base, size);
+ return p + XDR_QUADLEN(size);
+#else
+ /* until locked knows about var-length file handles,
+ * we always return NFS_FHSIZE handles
+ */
+ int size = fhp->fh_handle.fh_size;
+ *p++ = htonl(NFS_FHSIZE);
+ memset(p, 0, NFS_FHSIZE);
+ memcpy(p, &fhp->fh_handle.fh_base, size);
+ return p + XDR_QUADLEN(NFS_FHSIZE);
+#endif
}
/*
@@ -698,6 +711,7 @@ encode_entry(struct readdir_cd *cd, const char *name,
}
*p++ = xdr_one; /* mark entry present */
p = xdr_encode_hyper(p, ino); /* file id */
+ p[slen - 1] = 0; /* don't leak kernel data */
#ifdef XDR_ENCODE_STRING_TAKES_LENGTH
p = xdr_encode_string(p, name, namlen); /* name length & name */
#else
@@ -706,7 +720,6 @@ encode_entry(struct readdir_cd *cd, const char *name,
memcpy(p, name, namlen);
p += slen;
#endif
- p[slen - 1] = 0; /* don't leak kernel data */
cd->offset = p; /* remember pointer */
p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
@@ -715,7 +728,7 @@ encode_entry(struct readdir_cd *cd, const char *name,
if (plus) {
struct svc_fh fh;
- fh_init(&fh);
+ fh_init(&fh, NFS3_FHSIZE);
/* Disabled for now because of lock-up */
if (0 && nfsd_lookup(cd->rqstp, cd->dirfh, name, namlen, &fh) == 0) {
p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index b0aac3280..815208e09 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -40,8 +40,9 @@ static int nfsctl_addclient(struct nfsctl_client *data);
static int nfsctl_delclient(struct nfsctl_client *data);
static int nfsctl_export(struct nfsctl_export *data);
static int nfsctl_unexport(struct nfsctl_export *data);
-static int nfsctl_getfh(struct nfsctl_fhparm *, struct knfs_fh *);
-static int nfsctl_getfd(struct nfsctl_fdparm *, struct knfs_fh *);
+static int nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
+static int nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
+static int nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
/* static int nfsctl_ugidupdate(struct nfsctl_ugidmap *data); */
static int initialized = 0;
@@ -63,7 +64,6 @@ void proc_export_init(void)
static void
nfsd_init(void)
{
- nfsd_xdr_init(); /* XDR */
nfsd_stat_init(); /* Statistics */
nfsd_cache_init(); /* RPC reply cache */
nfsd_export_init(); /* Exports table */
@@ -110,12 +110,37 @@ nfsctl_ugidupdate(nfs_ugidmap *data)
}
#endif
+#ifdef notyet
+static inline int
+nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
+{
+ struct sockaddr_in *sin;
+ struct svc_client *clp;
+ int err = 0;
+
+ if (data->gd_addr.sa_family != AF_INET)
+ return -EPROTONOSUPPORT;
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ if (data->gd_maxlen > NFS3_FHSIZE)
+ data->gd_maxlen = NFS3_FHSIZE;
+ exp_readlock();
+ if (!(clp = exp_getclient(sin)))
+ err = -EPERM;
+ else
+ err = exp_rootfh(clp, 0, 0, data->gd_path, res, data->gd_maxlen);
+ exp_unlock();
+
+ return err;
+}
+#endif
+
static inline int
-nfsctl_getfd(struct nfsctl_fdparm *data, struct knfs_fh *res)
+nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
{
struct sockaddr_in *sin;
struct svc_client *clp;
int err = 0;
+ struct knfsd_fh fh;
if (data->gd_addr.sa_family != AF_INET)
return -EPROTONOSUPPORT;
@@ -127,18 +152,28 @@ nfsctl_getfd(struct nfsctl_fdparm *data, struct knfs_fh *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
- err = exp_rootfh(clp, 0, 0, data->gd_path, res);
+ err = exp_rootfh(clp, 0, 0, data->gd_path, &fh, NFS_FHSIZE);
exp_unlock();
+ if (err == 0) {
+ if (fh.fh_size > NFS_FHSIZE)
+ err = -EINVAL;
+ else {
+ memset(res,0, NFS_FHSIZE);
+ memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+ }
+ }
+
return err;
}
static inline int
-nfsctl_getfh(struct nfsctl_fhparm *data, struct knfs_fh *res)
+nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
{
struct sockaddr_in *sin;
struct svc_client *clp;
int err = 0;
+ struct knfsd_fh fh;
if (data->gf_addr.sa_family != AF_INET)
return -EPROTONOSUPPORT;
@@ -150,9 +185,18 @@ nfsctl_getfh(struct nfsctl_fhparm *data, struct knfs_fh *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
- err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, res);
+ err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
exp_unlock();
+ if (err == 0) {
+ if (fh.fh_size > NFS_FHSIZE)
+ err = -EINVAL;
+ else {
+ memset(res,0, NFS_FHSIZE);
+ memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+ }
+ }
+
return err;
}
@@ -218,11 +262,15 @@ asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
break;
#endif
case NFSCTL_GETFH:
- err = nfsctl_getfh(&arg->ca_getfh, &res->cr_getfh);
+ err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
break;
case NFSCTL_GETFD:
- err = nfsctl_getfd(&arg->ca_getfd, &res->cr_getfh);
+ err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
break;
+#ifdef notyet
+ case NFSCTL_GETFS:
+ err = nfsctl_getfs(&arg->ca_getfs, &res->cr_getfs);
+#endif
default:
err = -EINVAL;
}
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 084a17d9b..4a7e63dcb 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -328,7 +328,7 @@ static struct dentry *splice(struct dentry *child, struct dentry *parent)
* connection if made.
*/
static struct dentry *
-find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
+find_fh_dentry(struct super_block *sb, ino_t ino, int generation, ino_t dirino, int needpath)
{
struct dentry *dentry, *result = NULL;
struct dentry *tmp;
@@ -347,7 +347,7 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
* Attempt to find the inode.
*/
retry:
- result = nfsd_iget(sb, fh->fh_ino, fh->fh_generation);
+ result = nfsd_iget(sb, ino, generation);
err = PTR_ERR(result);
if (IS_ERR(result))
goto err_out;
@@ -370,10 +370,10 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
/* It's a directory, or we are required to confirm the file's
* location in the tree.
*/
- dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,fh->fh_ino);
+ dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino);
down(&sb->s_nfsd_free_path_sem);
- /* claiming the semaphore might have allow things to get fixed up */
+ /* claiming the semaphore might have allowed things to get fixed up */
if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
up(&sb->s_nfsd_free_path_sem);
return result;
@@ -383,11 +383,11 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
found = 0;
if (!S_ISDIR(result->d_inode->i_mode)) {
nfsdstats.fh_nocache_nondir++;
- if (fh->fh_dirino == 0)
+ if (dirino == 0)
goto err_result; /* don't know how to find parent */
else {
- /* need to iget fh->fh_dirino and make sure this inode is in that directory */
- dentry = nfsd_iget(sb, fh->fh_dirino, 0);
+ /* need to iget dirino and make sure this inode is in that directory */
+ dentry = nfsd_iget(sb, dirino, 0);
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto err_result;
@@ -490,38 +490,58 @@ err_out:
u32
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
{
- struct knfs_fh *fh = &fhp->fh_handle;
+ struct knfsd_fh *fh = &fhp->fh_handle;
struct svc_export *exp;
struct dentry *dentry;
struct inode *inode;
u32 error = 0;
- dprintk("nfsd: fh_verify(exp %s/%u file (%s/%u dir %u)\n",
- kdevname(fh->fh_xdev),
- fh->fh_xino,
- kdevname(fh->fh_dev),
- fh->fh_ino,
- fh->fh_dirino);
+ dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
if (!fhp->fh_dverified) {
- /*
- * Security: Check that the fh is internally consistant (from <gam3@acm.org>)
- */
- if (fh->fh_dev != fh->fh_xdev) {
- printk("fh_verify: Security: export on other device (%s, %s).\n",
- kdevname(fh->fh_dev), kdevname(fh->fh_xdev));
- error = nfserr_stale;
- nfsdstats.fh_stale++;
- goto out;
+ kdev_t xdev;
+ ino_t xino;
+ __u32 *datap=NULL;
+ int data_left = fh->fh_size/4;
+ int nfsdev;
+ error = nfserr_stale;
+#if CONFIG_NFSD_V3
+ if (rqstp->rq_vers == 3)
+ error = nfserr_badhandle;
+#endif
+ if (fh->fh_version == 1) {
+
+ datap = fh->fh_auth;
+ if (--data_left<0) goto out;
+ switch (fh->fh_auth_type) {
+ case 0: break;
+ default: goto out;
+ }
+
+ switch (fh->fh_fsid_type) {
+ case 0:
+ if ((data_left-=2)<0) goto out;
+ nfsdev = ntohl(*datap++);
+ xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
+ xino = *datap++;
+ break;
+ default:
+ goto out;
+ }
+ } else {
+ if (fh->fh_size != NFS_FHSIZE)
+ goto out;
+ /* assume old filehandle format */
+ xdev = u32_to_kdev_t(fh->ofh_xdev);
+ xino = u32_to_ino_t(fh->ofh_xino);
}
/*
* Look up the export entry.
*/
error = nfserr_stale;
- exp = exp_get(rqstp->rq_client,
- u32_to_kdev_t(fh->fh_xdev),
- u32_to_ino_t(fh->fh_xino));
+ exp = exp_get(rqstp->rq_client, xdev, xino);
+
if (!exp) {
/* export entry revoked */
nfsdstats.fh_stale++;
@@ -544,13 +564,44 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
/*
* Look up the dentry using the NFS file handle.
*/
+ error = nfserr_stale;
+#if CONFIG_NFSD_V3
+ if (rqstp->rq_vers == 3)
+ error = nfserr_badhandle;
+#endif
- dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
- fh,
- !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ if (fh->fh_version == 1) {
+ /* if fileid_type != 0, and super_operations provide fh_to_dentry lookup,
+ * then should use that */
+ switch (fh->fh_fileid_type) {
+ case 0:
+ dentry = dget(exp->ex_dentry);
+ break;
+ case 1:
+ if ((data_left-=2)<0) goto out;
+ dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+ datap[0], datap[1],
+ 0,
+ !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ break;
+ case 2:
+ if ((data_left-=3)<0) goto out;
+ dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+ datap[0], datap[1],
+ datap[2],
+ !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ break;
+ default: goto out;
+ }
+ } else {
+ dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+ fh->ofh_ino, fh->ofh_generation,
+ fh->ofh_dirino,
+ !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ }
if (IS_ERR(dentry)) {
- error = nfserrno(-PTR_ERR(dentry));
+ error = nfserrno(PTR_ERR(dentry));
goto out;
}
#ifdef NFSD_PARANOIA
@@ -652,72 +703,96 @@ out:
* an inode. In this case a call to fh_update should be made
* before the fh goes out on the wire ...
*/
-void
+inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
+ __u32 **datapp, int maxsize)
+{
+ __u32 *datap= *datapp;
+ if (dentry == exp->ex_dentry)
+ return 0;
+ /* if super_operations provides dentry_to_fh lookup, should use that */
+
+ *datap++ = ino_t_to_u32(dentry->d_inode->i_ino);
+ *datap++ = dentry->d_inode->i_generation;
+ if (S_ISDIR(dentry->d_inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK)){
+ *datapp = datap;
+ return 1;
+ }
+ *datap++ = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
+ *datapp = datap;
+ return 2;
+}
+
+int
fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
{
struct inode * inode = dentry->d_inode;
struct dentry *parent = dentry->d_parent;
+ __u32 *datap;
dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
exp->ex_dev, (long) exp->ex_ino,
parent->d_name.name, dentry->d_name.name,
(inode ? inode->i_ino : 0));
- /*
- * N.B. We shouldn't need to init the fh -- the call to fh_compose
- * may not be done on error paths, but the cleanup must call fh_put.
- * Fix this soon!
- */
if (fhp->fh_dverified || fhp->fh_locked || fhp->fh_dentry) {
printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
parent->d_name.name, dentry->d_name.name);
}
- fh_init(fhp);
-
- fhp->fh_handle.fh_dirino = ino_t_to_u32(parent->d_inode->i_ino);
- fhp->fh_handle.fh_dev = kdev_t_to_u32(parent->d_inode->i_dev);
- fhp->fh_handle.fh_xdev = kdev_t_to_u32(exp->ex_dev);
- fhp->fh_handle.fh_xino = ino_t_to_u32(exp->ex_ino);
- fhp->fh_handle.fh_dcookie = (struct dentry *)0xfeebbaca;
- if (inode) {
- fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
- fhp->fh_handle.fh_generation = inode->i_generation;
- if (S_ISDIR(inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
- fhp->fh_handle.fh_dirino = 0;
- }
+ if (fhp->fh_maxsize < NFS_FHSIZE)
+ printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
+ fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
fhp->fh_dentry = dentry; /* our internal copy */
fhp->fh_export = exp;
+ fhp->fh_handle.fh_version = 1;
+ fhp->fh_handle.fh_auth_type = 0;
+ fhp->fh_handle.fh_fsid_type = 0;
+ datap = fhp->fh_handle.fh_auth+0;
+ /* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
+ *datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+ *datap++ = ino_t_to_u32(exp->ex_ino);
+
+ if (inode)
+ fhp->fh_handle.fh_fileid_type =
+ _fh_update(dentry, exp, &datap, fhp->fh_maxsize-3);
+
+ fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
+
+
/* We stuck it there, we know it's good. */
fhp->fh_dverified = 1;
nfsd_nr_verified++;
+ if (fhp->fh_handle.fh_fileid_type == 255)
+ return nfserr_opnotsupp;
+ return 0;
}
/*
* Update file handle information after changing a dentry.
- * This is only called by nfsd_create
+ * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
*/
-void
+int
fh_update(struct svc_fh *fhp)
{
struct dentry *dentry;
- struct inode *inode;
-
+ __u32 *datap;
+
if (!fhp->fh_dverified)
goto out_bad;
dentry = fhp->fh_dentry;
- inode = dentry->d_inode;
- if (!inode)
+ if (!dentry->d_inode)
goto out_negative;
- fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
- fhp->fh_handle.fh_generation = inode->i_generation;
- if (S_ISDIR(inode->i_mode) || (fhp->fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
- fhp->fh_handle.fh_dirino = 0;
-
+ if (fhp->fh_handle.fh_fileid_type != 0)
+ goto out_uptodate;
+ datap = fhp->fh_handle.fh_auth+
+ fhp->fh_handle.fh_size/4 -1;
+ fhp->fh_handle.fh_fileid_type =
+ _fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size);
+ fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
out:
- return;
+ return 0;
out_bad:
printk(KERN_ERR "fh_update: fh not verified!\n");
@@ -726,6 +801,10 @@ out_negative:
printk(KERN_ERR "fh_update: %s/%s still negative!\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
goto out;
+out_uptodate:
+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ goto out;
}
/*
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index ef69be746..7d570299f 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -30,7 +30,6 @@ typedef struct svc_buf svc_buf;
#define NFSDDBG_FACILITY NFSDDBG_PROC
-#define RETURN(st) return st
static void
svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
@@ -42,7 +41,7 @@ svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
static int
nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
{
- RETURN(nfs_ok);
+ return nfs_ok;
}
/*
@@ -53,11 +52,10 @@ static int
nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
struct nfsd_attrstat *resp)
{
- dprintk("nfsd: GETATTR %d/%d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh));
+ dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
- RETURN(fh_verify(rqstp, &resp->fh, 0, MAY_NOP));
+ return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
}
/*
@@ -68,12 +66,12 @@ static int
nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
struct nfsd_attrstat *resp)
{
- dprintk("nfsd: SETATTR %d/%d, valid=%x, size=%ld\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
+ SVCFH_fmt(&argp->fh),
argp->attrs.ia_valid, (long) argp->attrs.ia_size);
fh_copy(&resp->fh, &argp->fh);
- RETURN(nfsd_setattr(rqstp, &resp->fh, &argp->attrs));
+ return nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
}
/*
@@ -88,14 +86,15 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: LOOKUP %d/%d %s\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh), argp->name);
+ dprintk("nfsd: LOOKUP %s %s\n",
+ SVCFH_fmt(&argp->fh), argp->name);
+ fh_init(&resp->fh, NFS_FHSIZE);
nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
&resp->fh);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -108,7 +107,7 @@ nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
u32 *path;
int dummy, nfserr;
- dprintk("nfsd: READLINK %p\n", SVCFH_DENTRY(&argp->fh));
+ dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
/* Reserve room for status and path length */
svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy, 2);
@@ -118,7 +117,7 @@ nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
nfserr = nfsd_readlink(rqstp, &argp->fh, (char *) path, &resp->len);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -132,8 +131,8 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
u32 * buffer;
int nfserr, avail;
- dprintk("nfsd: READ %d/%d %d bytes at %d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READ %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, argp->offset);
/* Obtain buffer pointer for payload. 19 is 1 word for
@@ -156,7 +155,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
(char *) buffer,
&resp->count);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -168,17 +167,18 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
struct nfsd_attrstat *resp)
{
int nfserr;
+ int stable = 1;
- dprintk("nfsd: WRITE %d/%d %d bytes at %d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: WRITE %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->len, argp->offset);
nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
argp->offset,
argp->data,
argp->len,
- 0);
- RETURN(nfserr);
+ &stable);
+ return nfserr;
}
/*
@@ -198,8 +198,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
int nfserr, type, mode, rdonly = 0;
dev_t rdev = NODEV;
- dprintk("nfsd: CREATE %d/%d %s\n",
- SVCFH_DEV(dirfhp), SVCFH_INO(dirfhp), argp->name);
+ dprintk("nfsd: CREATE %s %s\n",
+ SVCFH_fmt(dirfhp), argp->name);
/* First verify the parent file handle */
nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
@@ -217,6 +217,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
/*
* Do a lookup to verify the new file handle.
*/
+ fh_init(newfhp, NFS_FHSIZE);
nfserr = nfsd_lookup(rqstp, dirfhp, argp->name, argp->len, newfhp);
if (nfserr) {
if (nfserr != nfserr_noent)
@@ -240,9 +241,11 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
if (nfserr)
goto done;
inode = newfhp->fh_dentry->d_inode;
- if (inode && newfhp->fh_handle.fh_ino == 0)
+ if (inode && newfhp->fh_handle.fh_fileid_type == 0)
/* inode might have been instantiated while we slept */
- fh_update(newfhp);
+ nfserr = fh_update(newfhp);
+ if (nfserr)
+ goto done;
/* Unfudge the mode bits */
if (attr->ia_valid & ATTR_MODE) {
@@ -321,7 +324,7 @@ out_unlock:
done:
fh_put(dirfhp);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -330,12 +333,12 @@ nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: REMOVE %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+ dprintk("nfsd: REMOVE %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
/* Unlink. -SIFDIR means file must not be a directory */
nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -344,15 +347,16 @@ nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp,
{
int nfserr;
- dprintk("nfsd: RENAME %p %s -> %p %s\n",
- SVCFH_DENTRY(&argp->ffh), argp->fname,
- SVCFH_DENTRY(&argp->tfh), argp->tname);
+ dprintk("nfsd: RENAME %s %s -> \n",
+ SVCFH_fmt(&argp->ffh), argp->fname);
+ dprintk("nfsd: -> %s %s\n",
+ SVCFH_fmt(&argp->tfh), argp->tname);
nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
&argp->tfh, argp->tname, argp->tlen);
fh_put(&argp->ffh);
fh_put(&argp->tfh);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -361,16 +365,17 @@ nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp,
{
int nfserr;
- dprintk("nfsd: LINK %p -> %p %s\n",
- SVCFH_DENTRY(&argp->ffh),
- SVCFH_DENTRY(&argp->tfh),
+ dprintk("nfsd: LINK %s ->\n",
+ SVCFH_fmt(&argp->ffh));
+ dprintk("nfsd: %s %s\n",
+ SVCFH_fmt(&argp->tfh),
argp->tname);
nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
&argp->ffh);
fh_put(&argp->ffh);
fh_put(&argp->tfh);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -380,10 +385,10 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
struct svc_fh newfh;
int nfserr;
- dprintk("nfsd: SYMLINK %p %s -> %s\n",
- SVCFH_DENTRY(&argp->ffh), argp->fname, argp->tname);
+ dprintk("nfsd: SYMLINK %s %s -> %s\n",
+ SVCFH_fmt(&argp->ffh), argp->fname, argp->tname);
- memset(&newfh, 0, sizeof(struct svc_fh));
+ fh_init(&newfh, NFS_FHSIZE);
/*
* Create the link, look up new file and set attrs.
*/
@@ -394,7 +399,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
fh_put(&argp->ffh);
fh_put(&newfh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -407,7 +412,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
{
int nfserr;
- dprintk("nfsd: MKDIR %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+ dprintk("nfsd: MKDIR %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
if (resp->fh.fh_dverified) {
printk(KERN_WARNING
@@ -415,10 +420,11 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
}
argp->attrs.ia_valid &= ~ATTR_SIZE;
+ fh_init(&resp->fh, NFS_FHSIZE);
nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
&argp->attrs, S_IFDIR, 0, &resp->fh);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -430,11 +436,11 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: RMDIR %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+ dprintk("nfsd: RMDIR %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -447,8 +453,8 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
u32 * buffer;
int nfserr, count;
- dprintk("nfsd: READDIR %d/%d %d bytes at %d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READDIR %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, argp->cookie);
/* Reserve buffer space for status */
@@ -470,7 +476,7 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
resp->count = count;
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -482,11 +488,11 @@ nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: STATFS %p\n", SVCFH_DENTRY(&argp->fh));
+ dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -539,36 +545,36 @@ nfserrno (int errno)
int nfserr;
int syserr;
} nfs_errtbl[] = {
- { NFS_OK, 0 },
- { NFSERR_PERM, EPERM },
- { NFSERR_NOENT, ENOENT },
- { NFSERR_IO, EIO },
- { NFSERR_NXIO, ENXIO },
- { NFSERR_ACCES, EACCES },
- { NFSERR_EXIST, EEXIST },
- { NFSERR_XDEV, EXDEV },
- { NFSERR_MLINK, EMLINK },
- { NFSERR_NODEV, ENODEV },
- { NFSERR_NOTDIR, ENOTDIR },
- { NFSERR_ISDIR, EISDIR },
- { NFSERR_INVAL, EINVAL },
- { NFSERR_FBIG, EFBIG },
- { NFSERR_NOSPC, ENOSPC },
- { NFSERR_ROFS, EROFS },
- { NFSERR_MLINK, EMLINK },
- { NFSERR_NAMETOOLONG, ENAMETOOLONG },
- { NFSERR_NOTEMPTY, ENOTEMPTY },
+ { nfs_ok, 0 },
+ { nfserr_perm, -EPERM },
+ { nfserr_noent, -ENOENT },
+ { nfserr_io, -EIO },
+ { nfserr_nxio, -ENXIO },
+ { nfserr_acces, -EACCES },
+ { nfserr_exist, -EEXIST },
+ { nfserr_xdev, -EXDEV },
+ { nfserr_mlink, -EMLINK },
+ { nfserr_nodev, -ENODEV },
+ { nfserr_notdir, -ENOTDIR },
+ { nfserr_isdir, -EISDIR },
+ { nfserr_inval, -EINVAL },
+ { nfserr_fbig, -EFBIG },
+ { nfserr_nospc, -ENOSPC },
+ { nfserr_rofs, -EROFS },
+ { nfserr_mlink, -EMLINK },
+ { nfserr_nametoolong, -ENAMETOOLONG },
+ { nfserr_notempty, -ENOTEMPTY },
#ifdef EDQUOT
- { NFSERR_DQUOT, EDQUOT },
+ { nfserr_dquot, -EDQUOT },
#endif
- { NFSERR_STALE, ESTALE },
- { -1, EIO }
+ { nfserr_stale, -ESTALE },
+ { -1, -EIO }
};
int i;
for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
if (nfs_errtbl[i].syserr == errno)
- return htonl(nfs_errtbl[i].nfserr);
+ return nfs_errtbl[i].nfserr;
}
printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
return nfserr_io;
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 3afe9f83e..2984f0330 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -17,15 +17,6 @@
#define NFSDDBG_FACILITY NFSDDBG_XDR
-u32 nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
- nfserr_acces, nfserr_exist, nfserr_xdev, nfserr_nodev,
- nfserr_notdir, nfserr_isdir, nfserr_inval, nfserr_fbig,
- nfserr_nospc, nfserr_rofs, nfserr_mlink,
- nfserr_nametoolong, nfserr_notempty, nfserr_dquot, nfserr_stale,
- nfserr_remote, nfserr_badhandle, nfserr_notsync,
- nfserr_badcookie, nfserr_notsupp, nfserr_toosmall,
- nfserr_serverfault, nfserr_badtype, nfserr_jukebox;
-
#ifdef NFSD_OPTIMIZE_SPACE
# define inline
@@ -41,51 +32,6 @@ static u32 nfs_ftypes[] = {
NFSOCK, NFBAD, NFLNK, NFBAD,
};
-/*
- * Initialization of NFS status variables
- */
-void
-nfsd_xdr_init(void)
-{
- static int inited = 0;
-
- if (inited)
- return;
-
- nfs_ok = htonl(NFS_OK);
- nfserr_perm = htonl(NFSERR_PERM);
- nfserr_noent = htonl(NFSERR_NOENT);
- nfserr_io = htonl(NFSERR_IO);
- nfserr_inval = htonl(NFSERR_INVAL);
- nfserr_nxio = htonl(NFSERR_NXIO);
- nfserr_acces = htonl(NFSERR_ACCES);
- nfserr_exist = htonl(NFSERR_EXIST);
- nfserr_xdev = htonl(NFSERR_XDEV);
- nfserr_nodev = htonl(NFSERR_NODEV);
- nfserr_notdir = htonl(NFSERR_NOTDIR);
- nfserr_isdir = htonl(NFSERR_ISDIR);
- nfserr_inval = htonl(NFSERR_INVAL);
- nfserr_fbig = htonl(NFSERR_FBIG);
- nfserr_nospc = htonl(NFSERR_NOSPC);
- nfserr_rofs = htonl(NFSERR_ROFS);
- nfserr_mlink = htonl(NFSERR_MLINK);
- nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
- nfserr_notempty = htonl(NFSERR_NOTEMPTY);
- nfserr_dquot = htonl(NFSERR_DQUOT);
- nfserr_stale = htonl(NFSERR_STALE);
- nfserr_remote = htonl(NFSERR_REMOTE);
- nfserr_badhandle = htonl(NFSERR_BADHANDLE);
- nfserr_notsync = htonl(NFSERR_NOT_SYNC);
- nfserr_badcookie = htonl(NFSERR_BAD_COOKIE);
- nfserr_notsupp = htonl(NFSERR_NOTSUPP);
- nfserr_toosmall = htonl(NFSERR_TOOSMALL);
- nfserr_serverfault = htonl(NFSERR_SERVERFAULT);
- nfserr_badtype = htonl(NFSERR_BADTYPE);
- nfserr_jukebox = htonl(NFSERR_JUKEBOX);
-
-
- inited = 1;
-}
/*
* XDR functions for basic NFS types
@@ -93,19 +39,20 @@ nfsd_xdr_init(void)
static inline u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
- fh_init(fhp);
- memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
+ fh_init(fhp, NFS_FHSIZE);
+ memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
+ fhp->fh_handle.fh_size = NFS_FHSIZE;
/* FIXME: Look up export pointer here and verify
* Sun Secure RPC if requested */
- return p + (sizeof(struct knfs_fh) >> 2);
+ return p + (NFS_FHSIZE >> 2);
}
static inline u32 *
encode_fh(u32 *p, struct svc_fh *fhp)
{
- memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
- return p + (sizeof(struct knfs_fh) >> 2);
+ memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
+ return p + (NFS_FHSIZE>> 2);
}
/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c8389381f..06a795841 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/version.h>
+#include <linux/string.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/locks.h>
@@ -92,7 +93,7 @@ static struct raparms * raparm_cache = NULL;
* the check_parent in linux/fs/namei.c.
*/
#define nfsd_check_parent(dir, dentry) \
- ((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
+ ((dir) == (dentry)->d_parent && !d_unhashed(dentry))
/*
* Lock a parent directory following the VFS locking protocol.
@@ -137,7 +138,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
struct dentry *dparent, *dchild;
int err;
- dprintk("nfsd: nfsd_lookup(fh %p, %s)\n", SVCFH_DENTRY(fhp), name);
+ dprintk("nfsd: nfsd_lookup(fh %s, %s)\n", SVCFH_fmt(fhp), name);
/* Obtain dentry and export. */
err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC);
@@ -155,7 +156,10 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
err = nfserr_acces;
/* Lookup the name, but don't follow links */
- dchild = lookup_dentry(name, dget(dparent), 0);
+ if (strcmp(name,"..")==0 && dparent->d_covers != dparent)
+ dchild = dget(dparent);
+ else
+ dchild = lookup_dentry(name, dget(dparent), 0);
if (IS_ERR(dchild))
goto out_nfserr;
/*
@@ -187,15 +191,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
* Note: we compose the file handle now, but as the
* dentry may be negative, it may need to be updated.
*/
- fh_compose(resfh, exp, dchild);
- err = nfserr_noent;
- if (dchild->d_inode)
- err = 0;
+ err = fh_compose(resfh, exp, dchild);
+ if (!err && !dchild->d_inode)
+ err = nfserr_noent;
out:
return err;
out_nfserr:
- err = nfserrno(-PTR_ERR(dchild));
+ err = nfserrno(PTR_ERR(dchild));
goto out;
}
@@ -261,8 +264,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
/* The size case is special. It changes the file as well as the attributes. */
if (iap->ia_valid & ATTR_SIZE) {
-if (!S_ISREG(inode->i_mode))
-printk("nfsd_setattr: size change??\n");
if (iap->ia_size < inode->i_size) {
err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
if (err)
@@ -326,7 +327,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -393,18 +394,19 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
if (map->access & query) {
unsigned int err2;
err2 = nfsd_permission(export, dentry, map->how);
- /* cannot use a "switch" as nfserr_* are variables, even though they are constant :-( */
- if (err2 == 0)
+ switch (err2) {
+ case nfs_ok:
result |= map->access;
+ break;
+
/* the following error codes just mean the access was not allowed,
* rather than an error occurred */
- else if (err2 == nfserr_rofs ||
- err2 == nfserr_acces ||
- err2 == nfserr_perm
- )
+ case nfserr_rofs:
+ case nfserr_acces:
+ case nfserr_perm:
/* simply don't "or" in the access bit. */
- ;
- else {
+ break;
+ default:
error = err2;
goto out;
}
@@ -482,7 +484,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
}
out_nfserr:
if (err)
- err = nfserrno(-err);
+ err = nfserrno(err);
out:
return err;
}
@@ -587,7 +589,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
goto out_close;
/* Get readahead parameters */
- ra = nfsd_get_raparms(fhp->fh_handle.fh_dev, fhp->fh_handle.fh_ino);
+ ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);
if (ra) {
file.f_reada = ra->p_reada;
file.f_ramax = ra->p_ramax;
@@ -618,7 +620,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
*count = err;
err = 0;
} else
- err = nfserrno(-err);
+ err = nfserrno(err);
out_close:
nfsd_close(&file);
out:
@@ -632,7 +634,7 @@ out:
*/
int
nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
- char *buf, unsigned long cnt, int stable)
+ char *buf, unsigned long cnt, int *stablep)
{
struct svc_export *exp;
struct file file;
@@ -640,6 +642,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
struct inode *inode;
mm_segment_t oldfs;
int err = 0;
+ int stable = *stablep;
#ifdef CONFIG_QUOTA
uid_t saved_euid;
#endif
@@ -666,10 +669,12 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
* flushing the data to disk is handled separately below.
*/
#ifdef CONFIG_NFSD_V3
- if (rqstp->rq_vers == 2)
- stable = EX_ISSYNC(exp);
- else if (file.f_op->fsync == 0)
- stable = 1;
+ if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */
+ stable = 2;
+ *stablep = 2; /* FILE_SYNC */
+ }
+ if (!EX_ISSYNC(exp))
+ stable = 0;
if (stable && !EX_WGATHER(exp))
file.f_flags |= O_SYNC;
#else
@@ -749,7 +754,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (err >= 0)
err = 0;
else
- err = nfserrno(-err);
+ err = nfserrno(err);
out_close:
nfsd_close(&file);
out:
@@ -774,11 +779,12 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
return err;
-
- if (file.f_op && file.f_op->fsync) {
- nfsd_sync(&file);
- } else {
- err = nfserr_notsupp;
+ if (EX_ISSYNC(fhp->fh_export)) {
+ if (file.f_op && file.f_op->fsync) {
+ nfsd_sync(&file);
+ } else {
+ err = nfserr_notsupp;
+ }
}
nfsd_close(&file);
@@ -827,11 +833,13 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = PTR_ERR(dchild);
if (IS_ERR(dchild))
goto out_nfserr;
- fh_compose(resfhp, fhp->fh_export, dchild);
/* Lock the parent and check for errors ... */
err = fh_lock_parent(fhp, dchild);
if (err)
goto out;
+ err = fh_compose(resfhp, fhp->fh_export, dchild);
+ if (err)
+ goto out;
} else {
/* called from nfsd_proc_create */
dchild = resfhp->fh_dentry;
@@ -888,10 +896,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
write_inode_now(dchild->d_inode);
}
- /*
- * Update the file handle to get the new inode info.
- */
- fh_update(resfhp);
/* Set file attributes. Mode has already been set and
* setting uid/gid works only for root. Irix appears to
@@ -901,11 +905,16 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = 0;
if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
err = nfsd_setattr(rqstp, resfhp, iap);
+ /*
+ * Update the file handle to get the new inode info.
+ */
+ if (!err)
+ err = fh_update(resfhp);
out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -947,22 +956,20 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = PTR_ERR(dchild);
if(IS_ERR(dchild))
goto out_nfserr;
- fh_compose(resfhp, fhp->fh_export, dchild);
/*
* We must lock the directory before we check for the inode.
*/
err = fh_lock_parent(fhp, dchild);
if (err)
- goto out;
+ goto out;
+ err = fh_compose(resfhp, fhp->fh_export, dchild);
+ if (err)
+ goto out;
if (dchild->d_inode) {
err = 0;
- if (resfhp->fh_handle.fh_ino == 0)
- /* inode might have been instantiated while we slept */
- fh_update(resfhp);
-
switch (createmode) {
case NFS3_CREATE_UNCHECKED:
if (! S_ISREG(dchild->d_inode->i_mode))
@@ -997,8 +1004,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
/*
* Update the filehandle to get the new inode info.
*/
- fh_update(resfhp);
- err = 0;
+ err = fh_update(resfhp);
+ if (err)
+ goto out;
if (createmode == NFS3_CREATE_EXCLUSIVE) {
/* Cram the verifier into atime/mtime */
@@ -1021,7 +1029,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
#endif /* CONFIG_NFSD_V3 */
@@ -1067,7 +1075,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1083,7 +1091,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct iattr *iap)
{
struct dentry *dentry, *dnew;
- int err;
+ int err, cerr;
err = nfserr_noent;
if (!flen || !plen)
@@ -1122,17 +1130,18 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
}
}
} else
- err = nfserrno(-err);
+ err = nfserrno(err);
fh_unlock(fhp);
/* Compose the fh so the dentry will be freed ... */
out_compose:
- fh_compose(resfhp, fhp->fh_export, dnew);
+ cerr = fh_compose(resfhp, fhp->fh_export, dnew);
+ if (err==0) err = cerr;
out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1186,7 +1195,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
if (err == -EXDEV && rqstp->rq_vers == 2)
err = nfserr_acces;
else
- err = nfserrno(-err);
+ err = nfserrno(err);
}
fh_unlock(ffhp);
@@ -1196,7 +1205,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1318,7 +1327,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1356,47 +1365,21 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
goto out;
}
-
- if (type != S_IFDIR) {
- /* It's UNLINK */
-
- err = fh_lock_parent(fhp, rdentry);
- if (err)
- goto out;
-
- err = vfs_unlink(dirp, rdentry);
-
- fh_unlock(fhp);
-
+ err = fh_lock_parent(fhp, rdentry);
+ if (err) {
dput(rdentry);
+ goto out;
+ }
- } else {
- /* It's RMDIR */
- /* See comments in fs/namei.c:do_rmdir */
-
- rdentry->d_count++;
- nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem);
-
-#ifdef CONFIG_NFSD_V3
- fill_pre_wcc(fhp);
-#else
- fhp->fh_locked = 1;
-#endif /* CONFIG_NFSD_V3 */
+ if (type != S_IFDIR) { /* It's UNLINK */
+ err = vfs_unlink(dirp, rdentry);
+ } else { /* It's RMDIR */
+ err = vfs_rmdir(dirp, rdentry);
+ }
- err = -ENOENT;
- if (nfsd_check_parent(dentry, rdentry))
- err = vfs_rmdir(dirp, rdentry);
+ fh_unlock(fhp);
- rdentry->d_count--;
-#ifdef CONFIG_NFSD_V3
- fill_post_wcc(fhp);
-#else
- fhp->fh_locked = 0;
-#endif /* CONFIG_NFSD_V3 */
- nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem);
-
- dput(rdentry);
- }
+ dput(rdentry);
if (err)
goto out_nfserr;
@@ -1409,7 +1392,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1499,7 +1482,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out_close;
}
@@ -1510,29 +1493,9 @@ out_nfserr:
int
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct statfs *stat)
{
- struct dentry *dentry;
- struct inode *inode;
- struct super_block *sb;
- mm_segment_t oldfs;
- int err;
-
- err = fh_verify(rqstp, fhp, 0, MAY_NOP);
- if (err)
- goto out;
- dentry = fhp->fh_dentry;
- inode = dentry->d_inode;
-
- err = nfserr_io;
- if (!(sb = inode->i_sb) || !sb->s_op->statfs)
- goto out;
-
- oldfs = get_fs();
- set_fs (KERNEL_DS);
- sb->s_op->statfs(sb, stat, sizeof(*stat));
- set_fs (oldfs);
- err = 0;
-
-out:
+ int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
+ if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat))
+ err = nfserr_io;
return err;
}
@@ -1617,7 +1580,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
if (current->fsuid != 0)
current->cap_effective = saved_cap;
- return err? nfserrno(-err) : 0;
+ return err? nfserrno(err) : 0;
}
void
diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c
index 89888bb60..a24faac65 100644
--- a/fs/ntfs/fs.c
+++ b/fs/ntfs/fs.c
@@ -746,13 +746,11 @@ static void ntfs_put_super(struct super_block *sb)
ntfs_free(vol);
#endif
ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
- MOD_DEC_USE_COUNT;
}
/* Called by the kernel when asking for stats */
-static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize)
+static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
{
- struct statfs fs;
struct inode *mft;
ntfs_volume *vol;
ntfs_u64 size;
@@ -760,30 +758,26 @@ static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize)
ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
vol=NTFS_SB2VOL(sb);
- memset(&fs,0,sizeof(fs));
- fs.f_type=NTFS_SUPER_MAGIC;
- fs.f_bsize=vol->clustersize;
+ sf->f_type=NTFS_SUPER_MAGIC;
+ sf->f_bsize=vol->clustersize;
error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &size );
if( error )
return -error;
- fs.f_blocks = size; /* volumesize is in clusters */
- fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
- fs.f_bavail=fs.f_bfree;
+ sf->f_blocks = size; /* volumesize is in clusters */
+ sf->f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
+ sf->f_bavail=sf->f_bfree;
- /* Number of files is limited by free space only, so we lie here */
- fs.f_ffree=0;
mft=iget(sb,FILE_MFT);
if (!mft)
return -EIO;
/* So ... we lie... thus this following cast of loff_t value
is ok here.. */
- fs.f_files = (unsigned long)mft->i_size / vol->mft_recordsize;
+ sf->f_files = (unsigned long)mft->i_size / vol->mft_recordsize;
iput(mft);
/* should be read from volume */
- fs.f_namelen=255;
- copy_to_user(sf,&fs,bufsize);
+ sf->f_namelen=255;
return 0;
}
@@ -823,14 +817,6 @@ struct super_block * ntfs_read_super(struct super_block *sb,
struct buffer_head *bh;
int i;
- /* When the driver is compiled as a module, kmod must know when it
- * can safely remove it from memory. To do this, each module owns a
- * reference counter.
- */
- MOD_INC_USE_COUNT;
- /* Don't put ntfs_debug() before MOD_INC_USE_COUNT, printk() can block
- * so this could lead to a race condition with kmod.
- */
ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");
#ifdef NTFS_IN_LINUX_KERNEL
@@ -844,9 +830,6 @@ struct super_block * ntfs_read_super(struct super_block *sb,
if(!parse_options(vol,(char*)options))
goto ntfs_read_super_vol;
- /* Ensure that the super block won't be used until it is completed */
- lock_super(sb);
- ntfs_debug(DEBUG_OTHER, "lock_super\n");
#if 0
/* Set to read only, user option might reset it */
sb->s_flags |= MS_RDONLY;
@@ -919,48 +902,24 @@ struct super_block * ntfs_read_super(struct super_block *sb,
ntfs_error("Could not get root dir inode\n");
goto ntfs_read_super_mft;
}
- unlock_super(sb);
- ntfs_debug(DEBUG_OTHER, "unlock_super\n");
ntfs_debug(DEBUG_OTHER, "read_super: done\n");
return sb;
ntfs_read_super_mft:
ntfs_free(vol->mft);
ntfs_read_super_unl:
- sb->s_dev = 0;
- unlock_super(sb);
- ntfs_debug(DEBUG_OTHER, "unlock_super\n");
ntfs_read_super_vol:
#ifndef NTFS_IN_LINUX_KERNEL
ntfs_free(vol);
ntfs_read_super_dec:
#endif
ntfs_debug(DEBUG_OTHER, "read_super: done\n");
- MOD_DEC_USE_COUNT;
return NULL;
}
/* Define the filesystem
- *
- * Define SECOND if you cannot unload ntfs, and want to avoid rebooting
- * for just one more test
*/
-static struct file_system_type ntfs_fs_type = {
-/* Filesystem name, as used after mount -t */
-#ifndef SECOND
- "ntfs",
-#else
- "ntfs2",
-#endif
-/* This filesystem requires a device (a hard disk)
- * May want to add FS_IBASKET when it works
- */
- FS_REQUIRES_DEV,
-/* Entry point of the filesystem */
- ntfs_read_super,
-/* Will point to the next filesystem in the kernel table */
- NULL
-};
+static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
/* When this code is not compiled as a module, this is the main entry point,
* called by do_sys_setup() in fs/filesystems.c
diff --git a/fs/open.c b/fs/open.c
index e7b119df7..6b11f4ab0 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -4,6 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
+#include <linux/string.h>
#include <linux/mm.h>
#include <linux/utime.h>
#include <linux/file.h>
@@ -21,13 +22,10 @@ asmlinkage long sys_statfs(const char * path, struct statfs * buf)
dentry = namei(path);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
- struct inode * inode = dentry->d_inode;
- struct super_block * sb = inode->i_sb;
-
- error = -ENODEV;
- if (sb && sb->s_op && sb->s_op->statfs)
- error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
-
+ struct statfs tmp;
+ error = vfs_statfs(dentry->d_inode->i_sb, &tmp);
+ if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
+ error = -EFAULT;
dput(dentry);
}
unlock_kernel();
@@ -37,18 +35,17 @@ asmlinkage long sys_statfs(const char * path, struct statfs * buf)
asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf)
{
struct file * file;
- struct super_block * sb;
+ struct statfs tmp;
int error;
error = -EBADF;
file = fget(fd);
if (!file)
goto out;
- error = -ENODEV;
- sb = file->f_dentry->d_inode->i_sb;
lock_kernel();
- if (sb && sb->s_op && sb->s_op->statfs)
- error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
+ error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+ if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
+ error = -EFAULT;
unlock_kernel();
fput(file);
out:
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 1f9139a51..a95ad1acd 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -1,4 +1,4 @@
-/* $Id: inode.c,v 1.6 2000/02/27 08:19:47 davem Exp $
+/* $Id: inode.c,v 1.7 2000/03/10 04:45:50 davem Exp $
* openpromfs.c: /proc/openprom handling routines
*
* Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
@@ -982,22 +982,17 @@ static void openprom_read_inode(struct inode * inode)
static void openprom_put_super(struct super_block *sb)
{
- MOD_DEC_USE_COUNT;
}
-static int openprom_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int openprom_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = OPENPROM_SUPER_MAGIC;
- tmp.f_bsize = PAGE_SIZE/sizeof(long); /* ??? */
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = OPENPROM_SUPER_MAGIC;
+ buf->f_bsize = PAGE_SIZE/sizeof(long); /* ??? */
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_ffree = 0;
+ buf->f_namelen = NAME_MAX;
+ return 0;
}
static struct super_operations openprom_sops = {
@@ -1011,8 +1006,6 @@ struct super_block *openprom_read_super(struct super_block *s,void *data,
{
struct inode * root_inode;
- MOD_INC_USE_COUNT;
- lock_super(s);
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_magic = OPENPROM_SUPER_MAGIC;
@@ -1023,24 +1016,15 @@ struct super_block *openprom_read_super(struct super_block *s,void *data,
s->s_root = d_alloc_root(root_inode);
if (!s->s_root)
goto out_no_root;
- unlock_super(s);
return s;
out_no_root:
printk("openprom_read_super: get root inode failed\n");
iput(root_inode);
- s->s_dev = 0;
- unlock_super(s);
- MOD_DEC_USE_COUNT;
return NULL;
}
-static struct file_system_type openprom_fs_type = {
- "openpromfs",
- 0,
- openprom_read_super,
- NULL
-};
+static DECLARE_FSTYPE(openprom_fs_type, "openpromfs", openprom_read_super, 0);
int init_openprom_fs(void)
{
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 65bc80c88..3e1c58ad7 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -151,12 +151,13 @@ static inline char * task_state(struct task_struct *p, char *buffer)
"State:\t%s\n"
"Pid:\t%d\n"
"PPid:\t%d\n"
+ "TracerPid:\t%d\n"
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n"
"FDSize:\t%d\n"
"Groups:\t",
get_task_state(p),
- p->pid, p->p_pptr->pid,
+ p->pid, p->p_opptr->pid, p->p_pptr->pid != p->p_opptr->pid ? p->p_opptr->pid : 0,
p->uid, p->euid, p->suid, p->fsuid,
p->gid, p->egid, p->sgid, p->fsgid,
p->files ? p->files->max_fds : 0);
@@ -327,7 +328,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
task->pid,
task->comm,
state,
- task->p_pptr->pid,
+ task->p_opptr->pid,
task->pgrp,
task->session,
task->tty ? kdev_t_to_nr(task->tty->device) : 0,
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 84a23a7f5..90ed410b7 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -100,19 +100,15 @@ static void proc_read_inode(struct inode * inode)
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
}
-static int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int proc_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = PROC_SUPER_MAGIC;
- tmp.f_bsize = PAGE_SIZE/sizeof(long);
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = PROC_SUPER_MAGIC;
+ buf->f_bsize = PAGE_SIZE/sizeof(long);
+ buf->f_bfree = 0;
+ buf->f_bavail = 0;
+ buf->f_ffree = 0;
+ buf->f_namelen = NAME_MAX;
+ return 0;
}
static struct super_operations proc_sops = {
@@ -209,7 +205,6 @@ struct super_block *proc_read_super(struct super_block *s,void *data,
struct inode * root_inode;
struct task_struct *p;
- lock_super(s);
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_magic = PROC_SUPER_MAGIC;
@@ -229,13 +224,10 @@ struct super_block *proc_read_super(struct super_block *s,void *data,
parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
s->u.generic_sbp = (void*) proc_super_blocks;
proc_super_blocks = s;
- unlock_super(s);
return s;
out_no_root:
printk("proc_read_super: get root inode failed\n");
iput(root_inode);
- s->s_dev = 0;
- unlock_super(s);
return NULL;
}
diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c
index cc1ae7d96..0203b9776 100644
--- a/fs/proc/procfs_syms.c
+++ b/fs/proc/procfs_syms.c
@@ -20,12 +20,7 @@ EXPORT_SYMBOL(proc_net);
EXPORT_SYMBOL(proc_bus);
EXPORT_SYMBOL(proc_root_driver);
-static struct file_system_type proc_fs_type = {
- "proc",
- 0 /* FS_NO_DCACHE doesn't work correctly */,
- proc_read_super,
- NULL
-};
+static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, 0);
int __init init_proc_fs(void)
{
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 49bad450e..b85483d3d 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -117,7 +117,7 @@ static struct super_block *qnx4_read_super(struct super_block *, void *, int);
static void qnx4_put_super(struct super_block *sb);
static void qnx4_read_inode(struct inode *);
static int qnx4_remount(struct super_block *sb, int *flags, char *data);
-static int qnx4_statfs(struct super_block *, struct statfs *, int);
+static int qnx4_statfs(struct super_block *, struct statfs *);
static struct super_operations qnx4_sops =
{
@@ -269,22 +269,16 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
return block;
}
-static int qnx4_statfs(struct super_block *sb,
- struct statfs *buf, int bufsize)
+static int qnx4_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- memset(&tmp, 0, sizeof tmp);
- tmp.f_type = sb->s_magic;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
- tmp.f_bfree = qnx4_count_free_blocks(sb);
- tmp.f_bavail = tmp.f_bfree;
- tmp.f_files = -1; /* we don't count files */
- tmp.f_ffree = -1; /* inodes are allocated dynamically */
- tmp.f_namelen = QNX4_NAME_MAX;
-
- return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+ buf->f_type = sb->s_magic;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
+ buf->f_bfree = qnx4_count_free_blocks(sb);
+ buf->f_bavail = buf->f_bfree;
+ buf->f_namelen = QNX4_NAME_MAX;
+
+ return 0;
}
/*
@@ -343,8 +337,6 @@ static struct super_block *qnx4_read_super(struct super_block *s,
struct inode *root;
const char *errmsg;
- MOD_INC_USE_COUNT;
- lock_super(s);
set_blocksize(dev, QNX4_BLOCK_SIZE);
s->s_blocksize = QNX4_BLOCK_SIZE;
s->s_blocksize_bits = QNX4_BLOCK_SIZE_BITS;
@@ -399,7 +391,6 @@ static struct super_block *qnx4_read_super(struct super_block *s,
goto outi;
brelse(bh);
- unlock_super(s);
s->s_dirt = 1;
return s;
@@ -409,9 +400,6 @@ static struct super_block *qnx4_read_super(struct super_block *s,
out:
brelse(bh);
outnobh:
- s->s_dev = 0;
- unlock_super(s);
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -419,7 +407,6 @@ static struct super_block *qnx4_read_super(struct super_block *s,
static void qnx4_put_super(struct super_block *sb)
{
kfree_s( sb->u.qnx4_sb.BitMap, sizeof( struct qnx4_inode_entry ) );
- MOD_DEC_USE_COUNT;
return;
}
@@ -502,13 +489,7 @@ static void qnx4_read_inode(struct inode *inode)
brelse(bh);
}
-static struct file_system_type qnx4_fs_type =
-{
- "qnx4",
- FS_REQUIRES_DEV,
- qnx4_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(qnx4_fs_type, "qnx4", qnx4_read_super);
int __init init_qnx4_fs(void)
{
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c
index 0defa3dcb..a25200b14 100644
--- a/fs/qnx4/namei.c
+++ b/fs/qnx4/namei.c
@@ -171,7 +171,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
goto end_rmdir;
}
#endif
- if (!list_empty(&dentry->d_hash)) {
+ if (!d_unhashed(dentry)) {
retval = -EBUSY;
goto end_rmdir;
}
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index b95dfa219..15e80519f 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -105,11 +105,8 @@ romfs_read_super(struct super_block *s, void *data, int silent)
struct romfs_super_block *rsb;
int sz;
- MOD_INC_USE_COUNT;
-
/* I would parse the options here, but there are none.. :) */
- lock_super(s);
set_blocksize(dev, ROMBSIZE);
s->s_blocksize = ROMBSIZE;
s->s_blocksize_bits = ROMBSBITS;
@@ -153,16 +150,11 @@ romfs_read_super(struct super_block *s, void *data, int silent)
if (!s->s_root)
goto outnobh;
- unlock_super(s);
-
/* Ehrhm; sorry.. :) And thanks to Hans-Joachim Widmaier :) */
if (0) {
out:
brelse(bh);
outnobh:
- s->s_dev = 0;
- unlock_super(s);
- MOD_DEC_USE_COUNT;
s = NULL;
}
@@ -174,23 +166,20 @@ outnobh:
static void
romfs_put_super(struct super_block *sb)
{
- MOD_DEC_USE_COUNT;
return;
}
/* That's simple too. */
static int
-romfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+romfs_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- memset(&tmp, 0, sizeof(tmp));
- tmp.f_type = ROMFS_MAGIC;
- tmp.f_bsize = ROMBSIZE;
- tmp.f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS;
- tmp.f_namelen = ROMFS_MAXFN;
- return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+ buf->f_type = ROMFS_MAGIC;
+ buf->f_bsize = ROMBSIZE;
+ buf->f_bfree = buf->f_bavail = buf->f_ffree;
+ buf->f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS;
+ buf->f_namelen = ROMFS_MAXFN;
+ return 0;
}
/* some helper routines */
@@ -541,12 +530,7 @@ static struct super_operations romfs_ops = {
statfs: romfs_statfs,
};
-static struct file_system_type romfs_fs_type = {
- "romfs",
- FS_REQUIRES_DEV,
- romfs_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(romfs_fs_type, "romfs", romfs_read_super);
int __init init_romfs_fs(void)
{
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 91061a28f..a29e55c7a 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -443,7 +443,7 @@ smb_rmdir(struct inode *dir, struct dentry *dentry)
* Check that nobody else is using the directory..
*/
error = -EBUSY;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
goto out;
smb_invalid_dir_cache(dir);
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 3b13fdd80..94923fbad 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -32,7 +32,7 @@
static void smb_put_inode(struct inode *);
static void smb_delete_inode(struct inode *);
static void smb_put_super(struct super_block *);
-static int smb_statfs(struct super_block *, struct statfs *, int);
+static int smb_statfs(struct super_block *, struct statfs *);
static void smb_set_inode_attr(struct inode *, struct smb_fattr *);
static struct super_operations smb_sops =
@@ -315,8 +315,6 @@ smb_put_super(struct super_block *sb)
kfree(sb->u.smbfs_sb.temp_buf);
if (server->packet)
smb_vfree(server->packet);
-
- MOD_DEC_USE_COUNT;
}
struct super_block *
@@ -326,15 +324,11 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
struct inode *root_inode;
struct smb_fattr root;
- MOD_INC_USE_COUNT;
-
if (!raw_data)
goto out_no_data;
if (((struct smb_mount_data *) raw_data)->version != SMB_MOUNT_VERSION)
goto out_wrong_data;
- lock_super(sb);
-
sb->s_blocksize = 1024; /* Eh... Is this correct? */
sb->s_blocksize_bits = 10;
sb->s_magic = SMB_SUPER_MAGIC;
@@ -389,7 +383,6 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
if (!sb->s_root)
goto out_no_root;
- unlock_super(sb);
return sb;
out_no_root:
@@ -401,7 +394,6 @@ out_no_temp:
smb_vfree(sb->u.smbfs_sb.packet);
out_no_mem:
printk(KERN_ERR "smb_read_super: allocation failure\n");
- unlock_super(sb);
goto out_fail;
out_wrong_data:
printk(KERN_ERR "SMBFS: need mount version %d\n", SMB_MOUNT_VERSION);
@@ -409,25 +401,17 @@ out_wrong_data:
out_no_data:
printk("smb_read_super: missing data argument\n");
out_fail:
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
static int
-smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+smb_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs attr;
+ smb_proc_dskattr(sb, buf);
- memset(&attr, 0, sizeof(attr));
-
- smb_proc_dskattr(sb, &attr);
-
- attr.f_type = SMB_SUPER_MAGIC;
- attr.f_files = -1;
- attr.f_ffree = -1;
- attr.f_namelen = SMB_MAXPATHLEN;
- return copy_to_user(buf, &attr, bufsiz) ? -EFAULT : 0;
+ buf->f_type = SMB_SUPER_MAGIC;
+ buf->f_namelen = SMB_MAXPATHLEN;
+ return 0;
}
int
@@ -550,12 +534,7 @@ int smb_current_kmalloced;
int smb_current_vmalloced;
#endif
-static struct file_system_type smb_fs_type = {
- "smbfs",
- 0 /* FS_NO_DCACHE doesn't work correctly */,
- smb_read_super,
- NULL
-};
+static DECLARE_FSTYPE( smb_fs_type, "smbfs", smb_read_super, 0);
int __init init_smb_fs(void)
{
diff --git a/fs/super.c b/fs/super.c
index e41e1d71d..c365c556c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -19,6 +19,7 @@
*/
#include <linux/config.h>
+#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
@@ -34,9 +35,9 @@
#include <linux/nfs_fs_sb.h>
#include <linux/nfs_mount.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
+#define __NO_VERSION__
+#include <linux/module.h>
/*
* We use a semaphore to synchronize all mount/umount
@@ -59,7 +60,194 @@ int nr_super_blocks = 0;
int max_super_blocks = NR_SUPER;
LIST_HEAD(super_blocks);
+/*
+ * Handling of filesystem drivers list.
+ * Rules:
+ * Inclusion to/removals from/scanning of list are protected by spinlock.
+ * During the unload module must call unregister_filesystem().
+ * We can access the fields of list element if:
+ * 1) spinlock is held or
+ * 2) we hold the reference to the module.
+ * The latter can be guaranteed by call of try_inc_mod_count(); if it
+ * returned 0 we must skip the element, otherwise we got the reference.
+ * Once the reference is obtained we can drop the spinlock.
+ */
+
static struct file_system_type *file_systems = NULL;
+static spinlock_t file_systems_lock = SPIN_LOCK_UNLOCKED;
+
+static void put_filesystem(struct file_system_type *fs)
+{
+ if (fs->owner)
+ __MOD_DEC_USE_COUNT(fs->owner);
+}
+
+static struct file_system_type **find_filesystem(const char *name)
+{
+ struct file_system_type **p;
+ for (p=&file_systems; *p; p=&(*p)->next)
+ if (strcmp((*p)->name,name) == 0)
+ break;
+ return p;
+}
+
+int register_filesystem(struct file_system_type * fs)
+{
+ int res = 0;
+ struct file_system_type ** p;
+
+ if (!fs)
+ return -EINVAL;
+ if (fs->next)
+ return -EBUSY;
+ spin_lock(&file_systems_lock);
+ p = find_filesystem(fs->name);
+ if (*p)
+ res = -EBUSY;
+ else
+ *p = fs;
+ spin_unlock(&file_systems_lock);
+ return res;
+}
+
+int unregister_filesystem(struct file_system_type * fs)
+{
+ struct file_system_type ** tmp;
+
+ spin_lock(&file_systems_lock);
+ tmp = &file_systems;
+ while (*tmp) {
+ if (fs == *tmp) {
+ *tmp = fs->next;
+ fs->next = NULL;
+ spin_unlock(&file_systems_lock);
+ return 0;
+ }
+ tmp = &(*tmp)->next;
+ }
+ spin_unlock(&file_systems_lock);
+ return -EINVAL;
+}
+
+static int fs_index(const char * __name)
+{
+ struct file_system_type * tmp;
+ char * name;
+ int err, index;
+
+ name = getname(__name);
+ err = PTR_ERR(name);
+ if (IS_ERR(name))
+ return err;
+
+ err = -EINVAL;
+ spin_lock(&file_systems_lock);
+ for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
+ if (strcmp(tmp->name,name) == 0) {
+ err = index;
+ break;
+ }
+ index++;
+ }
+ spin_unlock(&file_systems_lock);
+ putname(name);
+ return err;
+}
+
+static int fs_name(unsigned int index, char * buf)
+{
+ struct file_system_type * tmp;
+ int len, res;
+
+ spin_lock(&file_systems_lock);
+ for (tmp = file_systems; tmp; tmp = tmp->next, index--)
+ if (index <= 0 && try_inc_mod_count(tmp->owner))
+ break;
+ spin_unlock(&file_systems_lock);
+ if (!tmp)
+ return -EINVAL;
+
+ /* OK, we got the reference, so we can safely block */
+ len = strlen(tmp->name) + 1;
+ res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
+ put_filesystem(tmp);
+ return res;
+}
+
+static int fs_maxindex(void)
+{
+ struct file_system_type * tmp;
+ int index;
+
+ spin_lock(&file_systems_lock);
+ for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
+ ;
+ spin_unlock(&file_systems_lock);
+ return index;
+}
+
+/*
+ * Whee.. Weird sysv syscall.
+ */
+asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
+{
+ int retval = -EINVAL;
+
+ lock_kernel();
+ switch (option) {
+ case 1:
+ retval = fs_index((const char *) arg1);
+ break;
+
+ case 2:
+ retval = fs_name(arg1, (char *) arg2);
+ break;
+
+ case 3:
+ retval = fs_maxindex();
+ break;
+ }
+ unlock_kernel();
+ return retval;
+}
+
+int get_filesystem_list(char * buf)
+{
+ int len = 0;
+ struct file_system_type * tmp;
+
+ spin_lock(&file_systems_lock);
+ tmp = file_systems;
+ while (tmp && len < PAGE_SIZE - 80) {
+ len += sprintf(buf+len, "%s\t%s\n",
+ (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
+ tmp->name);
+ tmp = tmp->next;
+ }
+ spin_unlock(&file_systems_lock);
+ return len;
+}
+
+static struct file_system_type *get_fs_type(const char *name)
+{
+ struct file_system_type *fs;
+
+ spin_lock(&file_systems_lock);
+ fs = *(find_filesystem(name));
+ if (fs && !try_inc_mod_count(fs->owner))
+ fs = NULL;
+ spin_unlock(&file_systems_lock);
+ if (!fs && (request_module(name) == 0)) {
+ spin_lock(&file_systems_lock);
+ fs = *(find_filesystem(name));
+ if (fs && !try_inc_mod_count(fs->owner))
+ fs = NULL;
+ spin_unlock(&file_systems_lock);
+ }
+ return fs;
+}
+
+
struct vfsmount *vfsmntlist = NULL;
static struct vfsmount *vfsmnttail = NULL, *mru_vfsmnt = NULL;
@@ -164,115 +352,6 @@ void remove_vfsmnt(kdev_t dev)
kfree_s(tofree, sizeof(struct vfsmount));
}
-int register_filesystem(struct file_system_type * fs)
-{
- struct file_system_type ** tmp;
-
- if (!fs)
- return -EINVAL;
- if (fs->next)
- return -EBUSY;
- tmp = &file_systems;
- while (*tmp) {
- if (strcmp((*tmp)->name, fs->name) == 0)
- return -EBUSY;
- tmp = &(*tmp)->next;
- }
- *tmp = fs;
- return 0;
-}
-
-int unregister_filesystem(struct file_system_type * fs)
-{
- struct file_system_type ** tmp;
-
- tmp = &file_systems;
- while (*tmp) {
- if (fs == *tmp) {
- *tmp = fs->next;
- fs->next = NULL;
- return 0;
- }
- tmp = &(*tmp)->next;
- }
- return -EINVAL;
-}
-
-static int fs_index(const char * __name)
-{
- struct file_system_type * tmp;
- char * name;
- int err, index;
-
- name = getname(__name);
- err = PTR_ERR(name);
- if (IS_ERR(name))
- return err;
-
- index = 0;
- for (tmp = file_systems ; tmp ; tmp = tmp->next) {
- if (strcmp(tmp->name, name) == 0) {
- putname(name);
- return index;
- }
- index++;
- }
- putname(name);
- return -EINVAL;
-}
-
-static int fs_name(unsigned int index, char * buf)
-{
- struct file_system_type * tmp;
- int len;
-
- tmp = file_systems;
- while (tmp && index > 0) {
- tmp = tmp->next;
- index--;
- }
- if (!tmp)
- return -EINVAL;
- len = strlen(tmp->name) + 1;
- return copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
-}
-
-static int fs_maxindex(void)
-{
- struct file_system_type * tmp;
- int index;
-
- index = 0;
- for (tmp = file_systems ; tmp ; tmp = tmp->next)
- index++;
- return index;
-}
-
-/*
- * Whee.. Weird sysv syscall.
- */
-asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
-{
- int retval = -EINVAL;
-
- lock_kernel();
- switch (option) {
- case 1:
- retval = fs_index((const char *) arg1);
- break;
-
- case 2:
- retval = fs_name(arg1, (char *) arg2);
- break;
-
- case 3:
- retval = fs_maxindex();
- break;
- }
- unlock_kernel();
- return retval;
-}
-
static struct proc_fs_info {
int flag;
char *str;
@@ -379,39 +458,6 @@ int get_filesystem_info( char *buf )
return len;
}
-int get_filesystem_list(char * buf)
-{
- int len = 0;
- struct file_system_type * tmp;
-
- tmp = file_systems;
- while (tmp && len < PAGE_SIZE - 80) {
- len += sprintf(buf+len, "%s\t%s\n",
- (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
- tmp->name);
- tmp = tmp->next;
- }
- return len;
-}
-
-struct file_system_type *get_fs_type(const char *name)
-{
- struct file_system_type * fs = file_systems;
-
- if (!name)
- return fs;
- for (fs = file_systems; fs && strcmp(fs->name, name); fs = fs->next)
- ;
-#ifdef CONFIG_KMOD
- if (!fs && (request_module(name) == 0)) {
- for (fs = file_systems; fs && strcmp(fs->name, name); fs = fs->next)
- ;
- }
-#endif
-
- return fs;
-}
-
void __wait_on_super(struct super_block * sb)
{
DECLARE_WAITQUEUE(wait, current);
@@ -480,21 +526,15 @@ asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf)
struct super_block *s;
struct ustat tmp;
struct statfs sbuf;
- mm_segment_t old_fs;
int err = -EINVAL;
lock_kernel();
s = get_super(to_kdev_t(dev));
if (s == NULL)
goto out;
- err = -ENOSYS;
- if (!(s->s_op->statfs))
- goto out;
-
- old_fs = get_fs();
- set_fs(get_ds());
- s->s_op->statfs(s,&sbuf,sizeof(struct statfs));
- set_fs(old_fs);
+ err = vfs_statfs(s, &sbuf);
+ if (err)
+ goto out;
memset(&tmp,0,sizeof(struct ustat));
tmp.f_tfree = sbuf.f_bfree;
@@ -538,25 +578,10 @@ struct super_block *get_empty_super(void)
}
static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
- const char *name, int flags,
+ struct file_system_type *type, int flags,
void *data, int silent)
{
struct super_block * s;
- struct file_system_type *type;
-
- if (!dev)
- goto out_null;
- check_disk_change(dev);
- s = get_super(dev);
- if (s)
- goto found; /* ought to set ->s_bdev */
-
- type = get_fs_type(name);
- if (!type) {
- printk("VFS: on device %s: get_fs_type(%s) failed\n",
- kdevname(dev), name);
- goto out;
- }
s = get_empty_super();
if (!s)
goto out;
@@ -566,11 +591,11 @@ static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
s->s_dirt = 0;
sema_init(&s->s_vfs_rename_sem,1);
sema_init(&s->s_nfsd_free_path_sem,1);
- /* N.B. Should lock superblock now ... */
+ s->s_type = type;
+ lock_super(s);
if (!type->read_super(s, data, silent))
goto out_fail;
- s->s_type = type;
-bd_get:
+ unlock_super(s);
/* tell bdcache that we are going to keep this one */
if (bdev)
atomic_inc(&bdev->bd_count);
@@ -580,12 +605,10 @@ out:
out_fail:
s->s_dev = 0;
s->s_bdev = 0;
-out_null:
- s = NULL;
- goto out;
-found:
- s->s_bdev = bdev;
- goto bd_get;
+ s->s_type = NULL;
+ put_filesystem(type);
+ unlock_super(s);
+ return NULL;
}
/*
@@ -725,6 +748,8 @@ static struct block_device *do_umount(kdev_t dev, int unmount_root, int flags)
sb->s_dev = 0; /* Free the superblock */
bdev = sb->s_bdev;
sb->s_bdev = NULL;
+ put_filesystem(sb->s_type);
+ sb->s_type = NULL;
unlock_super(sb);
remove_vfsmnt(dev);
@@ -859,6 +884,7 @@ int do_mount(struct block_device *bdev, const char *dev_name,
struct dentry * dir_d;
struct super_block * sb;
struct vfsmount *vfsmnt;
+ struct file_system_type *fs_type;
int error;
if (bdev) {
@@ -896,14 +922,27 @@ int do_mount(struct block_device *bdev, const char *dev_name,
if (dir_d->d_covers != dir_d)
goto dput_and_out;
- /*
- * Note: If the superblock already exists,
- * read_super just does a get_super().
- */
error = -EINVAL;
- sb = read_super(dev, bdev, type, flags, data, 0);
- if (!sb)
+ if (!dev)
goto dput_and_out;
+ check_disk_change(dev);
+ sb = get_super(dev);
+ if (sb) {
+ /* Already mounted */
+ error = -EBUSY;
+ goto dput_and_out;
+ }
+
+ fs_type = get_fs_type(type);
+ if (!fs_type) {
+ printk("VFS: on device %s: get_fs_type(%s) failed\n",
+ kdevname(dev), type);
+ goto dput_and_out;
+ }
+
+ sb = read_super(dev, bdev, fs_type, flags, data, 0);
+ if (!sb)
+ goto fsput_and_out;
/*
* We may have slept while reading the super block,
@@ -923,7 +962,12 @@ int do_mount(struct block_device *bdev, const char *dev_name,
}
bdput_and_out:
+ /* FIXME: ->put_super() is needed here */
sb->s_bdev = NULL;
+ sb->s_dev = 0;
+ sb->s_type = NULL;
+fsput_and_out:
+ put_filesystem(fs_type);
if (bdev)
bdput(bdev);
dput_and_out:
@@ -956,7 +1000,9 @@ static int do_remount_sb(struct super_block *sb, int flags, char *data)
if (!fs_may_remount_ro(sb))
return -EBUSY;
if (sb->s_op && sb->s_op->remount_fs) {
+ lock_super(sb);
retval = sb->s_op->remount_fs(sb, &flags, data);
+ unlock_super(sb);
if (retval)
return retval;
}
@@ -1159,6 +1205,7 @@ void __init mount_root(void)
}
put_unnamed_dev(sb->s_dev);
sb->s_dev = 0;
+ put_filesystem(fs_type);
}
if (!ROOT_DEV) {
printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
@@ -1200,6 +1247,14 @@ void __init mount_root(void)
devfs_get_maj_min (handle, &major, &minor);
ROOT_DEV = MKDEV (major, minor);
}
+
+ /*
+ * Probably pure paranoia, but I'm less than happy about delving into
+ * devfs crap and checking it right now. Later.
+ */
+ if (!ROOT_DEV)
+ panic("I have no root and I want to sream");
+
bdev = bdget(kdev_t_to_nr(ROOT_DEV));
if (!bdev)
panic(__FUNCTION__ ": unable to allocate root device");
@@ -1221,37 +1276,57 @@ void __init mount_root(void)
printk ("VFS: Cannot open root device \"%s\" or %s\n",
root_device_name, kdevname (ROOT_DEV));
printk ("Please append a correct \"root=\" boot option\n");
+ panic("VFS: Unable to mount root fs on %s",
+ kdevname(ROOT_DEV));
}
- else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
+
+ check_disk_change(ROOT_DEV);
+
+ spin_lock(&file_systems_lock);
+ for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if (!(fs_type->fs_flags & FS_REQUIRES_DEV))
continue;
- sb = read_super(ROOT_DEV,bdev,fs_type->name,root_mountflags,NULL,1);
+ if (!try_inc_mod_count(fs_type->owner))
+ continue;
+ spin_unlock(&file_systems_lock);
+ sb = get_super(ROOT_DEV);
if (sb) {
- sb->s_flags = root_mountflags;
- current->fs->root = dget(sb->s_root);
- current->fs->pwd = dget(sb->s_root);
- printk ("VFS: Mounted root (%s filesystem)%s.\n",
- fs_type->name,
- (sb->s_flags & MS_RDONLY) ? " readonly" : "");
- if (path_start >= 0) {
- devfs_mk_symlink (NULL,
- "root", 0, DEVFS_FL_DEFAULT,
- path + 5 + path_start, 0,
- NULL, NULL);
- memcpy (path + path_start, "/dev/", 5);
- vfsmnt = add_vfsmnt (sb, path + path_start,
- "/");
- }
- else vfsmnt = add_vfsmnt (sb, "/dev/root", "/");
- if (vfsmnt) {
- bdput(bdev); /* sb holds a reference */
- return;
- }
- panic("VFS: add_vfsmnt failed for root fs");
+ /* Shouldn't we fail here? Oh, well... */
+ sb->s_bdev = bdev;
+ goto mount_it;
}
+ sb = read_super(ROOT_DEV,bdev,fs_type,root_mountflags,NULL,1);
+ if (sb)
+ goto mount_it;
+ spin_lock(&file_systems_lock);
+ put_filesystem(fs_type);
}
+ spin_unlock(&file_systems_lock);
panic("VFS: Unable to mount root fs on %s",
kdevname(ROOT_DEV));
+
+mount_it:
+ sb->s_flags = root_mountflags;
+ current->fs->root = dget(sb->s_root);
+ current->fs->pwd = dget(sb->s_root);
+ printk ("VFS: Mounted root (%s filesystem)%s.\n",
+ fs_type->name,
+ (sb->s_flags & MS_RDONLY) ? " readonly" : "");
+ if (path_start >= 0) {
+ devfs_mk_symlink (NULL,
+ "root", 0, DEVFS_FL_DEFAULT,
+ path + 5 + path_start, 0,
+ NULL, NULL);
+ memcpy (path + path_start, "/dev/", 5);
+ vfsmnt = add_vfsmnt (sb, path + path_start,
+ "/");
+ }
+ else vfsmnt = add_vfsmnt (sb, "/dev/root", "/");
+ if (vfsmnt) {
+ bdput(bdev); /* sb holds a reference */
+ return;
+ }
+ panic("VFS: add_vfsmnt failed for root fs");
}
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 2c79b3c71..c1b95f28d 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -68,7 +68,7 @@ static void sysv_delete_inode(struct inode *inode)
static void sysv_put_super(struct super_block *);
static void sysv_write_super(struct super_block *);
static void sysv_read_inode(struct inode *);
-static int sysv_statfs(struct super_block *, struct statfs *, int);
+static int sysv_statfs(struct super_block *, struct statfs *);
static struct super_operations sysv_sops = {
read_inode: sysv_read_inode,
@@ -360,8 +360,6 @@ static struct super_block *sysv_read_super(struct super_block *sb,
panic("Coherent FS: bad super-block size");
if (64 != sizeof (struct sysv_inode))
panic("sysv fs: bad i-node size");
- MOD_INC_USE_COUNT;
- lock_super(sb);
set_blocksize(dev,BLOCK_SIZE);
sb->sv_block_base = 0;
@@ -407,13 +405,10 @@ static struct super_block *sysv_read_super(struct super_block *sb,
}
}
bad_shift:
- sb->s_dev = 0;
- unlock_super(sb);
if (!silent)
printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device "
"%s\n", kdevname(dev));
failed:
- MOD_DEC_USE_COUNT;
return NULL;
ok:
@@ -442,8 +437,6 @@ static struct super_block *sysv_read_super(struct super_block *sb,
goto superblock_ok;
bad_superblock:
brelse(bh);
- sb->s_dev = 0;
- unlock_super(sb);
printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size);
goto failed;
superblock_ok:
@@ -489,8 +482,6 @@ static struct super_block *sysv_read_super(struct super_block *sb,
brelse(bh1);
brelse(bh2);
set_blocksize(sb->s_dev,BLOCK_SIZE);
- sb->s_dev = 0;
- unlock_super(sb);
printk("SysV FS: cannot read superblock in 512 byte mode\n");
goto failed;
}
@@ -511,14 +502,11 @@ static struct super_block *sysv_read_super(struct super_block *sb,
if (!sb->s_root) {
printk("SysV FS: get root inode failed\n");
sysv_put_super(sb);
- sb->s_dev = 0;
- unlock_super(sb);
return NULL;
}
#ifndef CONFIG_SYSV_FS_WRITE
sb->s_flags |= MS_RDONLY;
#endif
- unlock_super(sb);
sb->s_dirt = 1;
/* brelse(bh); resp. brelse(bh1); brelse(bh2);
occurs when the disk is unmounted. */
@@ -558,24 +546,20 @@ static void sysv_put_super(struct super_block *sb)
/* switch back to default block size */
if (sb->s_blocksize != BLOCK_SIZE)
set_blocksize(sb->s_dev,BLOCK_SIZE);
-
- MOD_DEC_USE_COUNT;
}
-static int sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int sysv_statfs(struct super_block *sb, struct statfs *buf)
{
- struct statfs tmp;
-
- tmp.f_type = sb->s_magic; /* type of filesystem */
- tmp.f_bsize = sb->sv_block_size; /* block size */
- tmp.f_blocks = sb->sv_ndatazones; /* total data blocks in file system */
- tmp.f_bfree = sysv_count_free_blocks(sb); /* free blocks in fs */
- tmp.f_bavail = tmp.f_bfree; /* free blocks available to non-superuser */
- tmp.f_files = sb->sv_ninodes; /* total file nodes in file system */
- tmp.f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */
- tmp.f_namelen = SYSV_NAMELEN;
- /* Don't know what value to put in tmp.f_fsid */ /* file system id */
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_type = sb->s_magic; /* type of filesystem */
+ buf->f_bsize = sb->sv_block_size; /* block size */
+ buf->f_blocks = sb->sv_ndatazones; /* total data blocks in file system */
+ buf->f_bfree = sysv_count_free_blocks(sb); /* free blocks in fs */
+ buf->f_bavail = buf->f_bfree; /* free blocks available to non-superuser */
+ buf->f_files = sb->sv_ninodes; /* total file nodes in file system */
+ buf->f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */
+ buf->f_namelen = SYSV_NAMELEN;
+ /* Don't know what value to put in buf->f_fsid */ /* file system id */
+ return 0;
}
@@ -1202,20 +1186,11 @@ int sysv_sync_inode(struct inode * inode)
/* Every kernel module contains stuff like this. */
-static struct file_system_type sysv_fs_type[] = {
- {"sysv", FS_REQUIRES_DEV, sysv_read_super, NULL}
-};
+static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
int __init init_sysv_fs(void)
{
- int i;
- int ouch = 0;
-
- for (i = 0; i < sizeof(sysv_fs_type)/sizeof(sysv_fs_type[0]); i++) {
- if ((ouch = register_filesystem(&sysv_fs_type[i])) != 0)
- break;
- }
- return ouch;
+ return register_filesystem(&sysv_fs_type);
}
#ifdef MODULE
@@ -1228,11 +1203,7 @@ int init_module(void)
void cleanup_module(void)
{
- int i;
-
- for (i = 0; i < sizeof(sysv_fs_type)/sizeof(sysv_fs_type[0]); i++)
- /* No error message if this breaks... that's OK... */
- unregister_filesystem(&sysv_fs_type[i]);
+ unregister_filesystem(&sysv_fs_type);
}
#endif
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index a7b871073..6a7fbf34b 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -389,7 +389,7 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
retval = -ENOTEMPTY;
goto end_rmdir;
}
- if (!list_empty(&dentry->d_hash)) {
+ if (!d_unhashed(dentry)) {
retval = -EBUSY;
goto end_rmdir;
}
@@ -552,6 +552,9 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
}
if (S_ISDIR(old_inode->i_mode)) {
if (new_inode) {
+ retval = -EBUSY;
+ if (!d_unhashed(new_dentry))
+ goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
goto end_rename;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index db140e66e..c371b5d52 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1165,6 +1165,9 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
if (new_inode)
{
+ retval = -EBUSY;
+ if (!d_unhashed(new_dentry))
+ goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
goto end_rename;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 6b3e32f03..761cdcb6c 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -93,25 +93,21 @@ static void udf_load_partdesc(struct super_block *, struct buffer_head *);
static void udf_open_lvid(struct super_block *);
static void udf_close_lvid(struct super_block *);
static unsigned int udf_count_free(struct super_block *);
-static int udf_statfs(struct super_block *, struct statfs *, int);
+static int udf_statfs(struct super_block *, struct statfs *);
/* UDF filesystem type */
-static struct file_system_type udf_fstype = {
- name: "udf",
- fs_flags: FS_REQUIRES_DEV,
- read_super: udf_read_super,
-};
+static DECLARE_FSTYPE_DEV(udf_fstype, "udf", udf_read_super);
/* Superblock operations */
static struct super_operations udf_sb_ops = {
- read_inode: udf_read_inode,
+ read_inode: udf_read_inode,
write_inode: udf_write_inode,
- put_inode: udf_put_inode,
+ put_inode: udf_put_inode,
delete_inode: udf_delete_inode,
- put_super: udf_put_super,
+ put_super: udf_put_super,
write_super: udf_write_super,
- statfs: udf_statfs,
- remount_fs: udf_remount_fs,
+ statfs: udf_statfs,
+ remount_fs: udf_remount_fs,
};
struct udf_options
@@ -1326,10 +1322,6 @@ udf_read_super(struct super_block *sb, void *options, int silent)
uopt.gid = -1;
uopt.umask = 0;
- /* Lock the module in memory (if applicable) */
- MOD_INC_USE_COUNT;
-
- lock_super(sb);
memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
#if CONFIG_UDF_RW != 1
@@ -1438,7 +1430,6 @@ udf_read_super(struct super_block *sb, void *options, int silent)
}
if (!(sb->s_flags & MS_RDONLY))
udf_open_lvid(sb);
- unlock_super(sb);
/* Assign the root inode */
/* assign inodes by physical block number */
@@ -1470,8 +1461,6 @@ error_out:
udf_close_lvid(sb);
udf_release_data(UDF_SB_LVIDBH(sb));
UDF_SB_FREE(sb);
- unlock_super(sb);
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -1530,8 +1519,6 @@ udf_put_super(struct super_block *sb)
for (i=0; i<UDF_MAX_BLOCK_LOADED; i++)
udf_release_data(UDF_SB_BLOCK_BITMAP(sb, i));
UDF_SB_FREE(sb);
-
- MOD_DEC_USE_COUNT;
}
/*
@@ -1548,29 +1535,21 @@ udf_put_super(struct super_block *sb)
* Written, tested, and released.
*/
static int
-udf_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+udf_statfs(struct super_block *sb, struct statfs *buf)
{
- int size;
- struct statfs tmp;
- int rc;
-
- size = (bufsize < sizeof(tmp)) ? bufsize: sizeof(tmp);
-
- memset(&tmp, 0, sizeof(tmp));
- tmp.f_type = UDF_SUPER_MAGIC;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
- tmp.f_bfree = udf_count_free(sb);
- tmp.f_bavail = tmp.f_bfree;
- tmp.f_files = (UDF_SB_LVIDBH(sb) ?
+ buf->f_type = UDF_SUPER_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
+ buf->f_bfree = udf_count_free(sb);
+ buf->f_bavail = buf->f_bfree;
+ buf->f_files = (UDF_SB_LVIDBH(sb) ?
(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) +
- le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + tmp.f_bfree;
- tmp.f_ffree = tmp.f_bfree;
+ le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + buf->f_bfree;
+ buf->f_ffree = buf->f_bfree;
/* __kernel_fsid_t f_fsid */
- tmp.f_namelen = UDF_NAME_LEN;
+ buf->f_namelen = UDF_NAME_LEN;
- rc= copy_to_user(buf, &tmp, size) ? -EFAULT: 0;
- return rc;
+ return 0;
}
static unsigned char udf_bitmap_lookup[16] = {
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 80e97bb06..1fe9de9bd 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -451,9 +451,6 @@ struct super_block * ufs_read_super (struct super_block * sb, void * data,
UFSD(("ENTER\n"))
- MOD_INC_USE_COUNT;
- lock_super (sb);
-
UFSD(("flag %u\n", (int)(sb->s_flags & MS_RDONLY)))
#ifndef CONFIG_UFS_FS_WRITE
@@ -790,16 +787,12 @@ magic_found:
if (!ufs_read_cylinder_structures(sb))
goto failed;
- unlock_super(sb);
UFSD(("EXIT\n"))
return(sb);
failed:
if (ubh) ubh_brelse_uspi (uspi);
if (uspi) kfree (uspi);
- sb->s_dev = 0;
- unlock_super (sb);
- MOD_DEC_USE_COUNT;
UFSD(("EXIT (FAILED)\n"))
return(NULL);
}
@@ -843,8 +836,6 @@ void ufs_put_super (struct super_block * sb)
ubh_brelse_uspi (uspi);
kfree (sb->u.ufs_sb.s_uspi);
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
return;
}
@@ -924,28 +915,27 @@ int ufs_remount (struct super_block * sb, int * mount_flags, char * data)
return 0;
}
-int ufs_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
+int ufs_statfs (struct super_block * sb, struct statfs * buf)
{
struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1;
- struct statfs tmp;
unsigned swab;
swab = sb->u.ufs_sb.s_swab;
uspi = sb->u.ufs_sb.s_uspi;
usb1 = ubh_get_usb_first (USPI_UBH);
- tmp.f_type = UFS_MAGIC;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = uspi->s_dsize;
- tmp.f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) +
+ buf->f_type = UFS_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_blocks = uspi->s_dsize;
+ buf->f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) +
SWAB32(usb1->fs_cstotal.cs_nffree);
- tmp.f_bavail = (tmp.f_bfree > ((tmp.f_blocks / 100) * uspi->s_minfree))
- ? (tmp.f_bfree - ((tmp.f_blocks / 100) * uspi->s_minfree)) : 0;
- tmp.f_files = uspi->s_ncg * uspi->s_ipg;
- tmp.f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree);
- tmp.f_namelen = UFS_MAXNAMLEN;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+ buf->f_bavail = (buf->f_bfree > ((buf->f_blocks / 100) * uspi->s_minfree))
+ ? (buf->f_bfree - ((buf->f_blocks / 100) * uspi->s_minfree)) : 0;
+ buf->f_files = uspi->s_ncg * uspi->s_ipg;
+ buf->f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree);
+ buf->f_namelen = UFS_MAXNAMLEN;
+ return 0;
}
static struct super_operations ufs_super_ops = {
@@ -959,12 +949,7 @@ static struct super_operations ufs_super_ops = {
remount_fs: ufs_remount,
};
-static struct file_system_type ufs_fs_type = {
- "ufs",
- FS_REQUIRES_DEV,
- ufs_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(ufs_fs_type, "ufs", ufs_read_super);
int __init init_ufs_fs(void)
{
diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c
index 7908144d7..61c832ed4 100644
--- a/fs/umsdos/inode.c
+++ b/fs/umsdos/inode.c
@@ -75,7 +75,6 @@ saved_root->d_count);
pseudo_root = NULL;
}
msdos_put_super (sb);
- MOD_DEC_USE_COUNT;
}
@@ -334,7 +333,6 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
struct super_block *res;
struct dentry *new_root;
- MOD_INC_USE_COUNT;
MSDOS_SB(sb)->options.isvfat = 0;
/*
* Call msdos-fs to mount the disk.
@@ -381,8 +379,6 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
out_fail:
printk(KERN_INFO "UMSDOS: msdos_read_super failed, mount aborted.\n");
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -437,13 +433,7 @@ out_noroot:
}
-static struct file_system_type umsdos_fs_type =
-{
- "umsdos",
- FS_REQUIRES_DEV,
- UMSDOS_read_super,
- NULL
-};
+static DECLARE_FSTYPE_DEV(umsdos_fs_type, "umsdos", UMSDOS_read_super);
int __init init_umsdos_fs (void)
{
diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c
index 08bb7b340..75715116f 100644
--- a/fs/umsdos/namei.c
+++ b/fs/umsdos/namei.c
@@ -876,7 +876,7 @@ int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry)
goto out;
ret = -EBUSY;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
goto out;
/* check whether the EMD is empty */
diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
index d05dfed73..8c71dd727 100644
--- a/fs/umsdos/rdir.c
+++ b/fs/umsdos/rdir.c
@@ -157,7 +157,7 @@ static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
goto out;
ret = -EBUSY;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
goto out;
ret = msdos_rmdir (dir, dentry);
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 476a09e9c..212494142 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -78,11 +78,6 @@ static struct dentry_operations vfat_dentry_ops[4] = {
}
};
-static void vfat_put_super_callback(struct super_block *sb)
-{
- MOD_DEC_USE_COUNT;
-}
-
static int vfat_revalidate(struct dentry *dentry, int flags)
{
PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
@@ -978,7 +973,7 @@ static struct dentry *find_alias(struct inode *inode)
tmp = next;
next = tmp->next;
alias = list_entry(tmp, struct dentry, d_alias);
- if (!list_empty(&alias->d_hash))
+ if (!d_unhashed(alias))
return dget(alias);
}
return NULL;
@@ -1085,7 +1080,7 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
struct buffer_head *bh = NULL;
struct msdos_dir_entry *de;
- if (!list_empty(&dentry->d_hash))
+ if (!d_unhashed(dentry))
return -EBUSY;
res = fat_dir_empty(dentry->d_inode);
@@ -1207,6 +1202,9 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
}
if (is_dir) {
+ res =-EBUSY;
+ if (!d_unhashed(new_dentry))
+ goto rename_done;
res = fat_dir_empty(new_inode);
if (res)
goto rename_done;
@@ -1274,21 +1272,13 @@ struct super_block *vfat_read_super(struct super_block *sb,void *data,
{
struct super_block *res;
- MOD_INC_USE_COUNT;
-
MSDOS_SB(sb)->options.isvfat = 1;
res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
- if (res == NULL) {
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
+ if (res == NULL)
return NULL;
- }
- if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
- MOD_DEC_USE_COUNT;
- } else {
- MSDOS_SB(sb)->put_super_callback=vfat_put_super_callback;
+ if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
MSDOS_SB(sb)->options.dotsOK = 0;
if (MSDOS_SB(sb)->options.posixfs) {
MSDOS_SB(sb)->options.name_check = 's';
diff --git a/fs/vfat/vfatfs_syms.c b/fs/vfat/vfatfs_syms.c
index bccd300e7..d57d153ed 100644
--- a/fs/vfat/vfatfs_syms.c
+++ b/fs/vfat/vfatfs_syms.c
@@ -12,12 +12,7 @@
#include <linux/mm.h>
#include <linux/msdos_fs.h>
-struct file_system_type vfat_fs_type = {
- "vfat",
- FS_REQUIRES_DEV,
- vfat_read_super,
- NULL
-};
+DECLARE_FSTYPE_DEV(vfat_fs_type, "vfat", vfat_read_super);
EXPORT_SYMBOL(vfat_create);
EXPORT_SYMBOL(vfat_unlink);