diff options
| author | Jens Axboe <axboe@burns.home.kernel.dk> | 2002-02-07 10:37:19 +0100 |
|---|---|---|
| committer | Jens Axboe <axboe@burns.home.kernel.dk> | 2002-02-07 10:37:19 +0100 |
| commit | 2adf779dd193e1c8673f5896da4fef1dda830774 (patch) | |
| tree | f8014bbf33b023dd09bda6f9145bb776f73389d2 /fs | |
| parent | 07916eb45f4a6c63acb93e269c10490e4e623a0c (diff) | |
| parent | 0ec120046dee44027a28b66a3c28d1031982a9eb (diff) | |
Merge http://linux.bkbits.net/linux-2.5
into burns.home.kernel.dk:/usr/local/kernel/BK/linux-2.5
Diffstat (limited to 'fs')
47 files changed, 642 insertions, 483 deletions
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 6d6a334b3717..354af8325576 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -145,7 +145,7 @@ extern struct file_operations autofs_dir_operations; /* Initializing function */ -struct super_block *autofs_read_super(struct super_block *, void *,int); +int autofs_fill_super(struct super_block *, void *, int); /* Queue management functions */ diff --git a/fs/autofs/init.c b/fs/autofs/init.c index 0e7fff94f254..b73fec09f7c2 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@ -14,7 +14,17 @@ #include <linux/init.h> #include "autofs_i.h" -static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs_read_super, 0); +static struct super_block *autofs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_nodev(fs_type, flags, data, autofs_fill_super); +} + +static struct file_system_type autofs_fs_type = { + owner: THIS_MODULE, + name: "autofs", + get_sb: autofs_get_sb, +}; static int __init init_autofs_fs(void) { diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index d275c5f81e57..8a0f463dfaf6 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -111,8 +111,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid return (*pipefd < 0); } -struct super_block *autofs_read_super(struct super_block *s, void *data, - int silent) +int autofs_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; struct dentry * root; @@ -175,7 +174,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data, * Success! Install the root dentry now to indicate completion. */ s->s_root = root; - return s; + return 0; fail_fput: printk("autofs: pipe file descriptor does not contain proper ops\n"); @@ -189,7 +188,7 @@ fail_iput: fail_free: kfree(sbi); fail_unlock: - return NULL; + return -EINVAL; } static int autofs_statfs(struct super_block *sb, struct statfs *buf) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 4dcdcaafcca9..7e43620bca87 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -144,7 +144,7 @@ extern struct file_operations autofs4_root_operations; /* Initializing function */ -struct super_block *autofs4_read_super(struct super_block *, void *,int); +int autofs4_fill_super(struct super_block *, void *, int); struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info *sbi, mode_t mode); /* Queue management functions */ diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c index dbb3e5385ded..fdce6b04367c 100644 --- a/fs/autofs4/init.c +++ b/fs/autofs4/init.c @@ -14,7 +14,17 @@ #include <linux/init.h> #include "autofs_i.h" -static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs4_read_super, 0); +static struct super_block *autofs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_nodev(fs_type, flags, data, autofs4_fill_super); +} + +static struct file_system_type autofs_fs_type = { + owner: THIS_MODULE, + name: "autofs", + get_sb: autofs_get_sb, +}; static int __init init_autofs4_fs(void) { diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 1f2d29f6d0cd..a7331fd67fa9 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -173,8 +173,7 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi) return ino; } -struct super_block *autofs4_read_super(struct super_block *s, void *data, - int silent) +int autofs4_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; struct dentry * root; @@ -251,7 +250,7 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data, * Success! Install the root dentry now to indicate completion. */ s->s_root = root; - return s; + return 0; /* * Failure ... clean up. @@ -278,7 +277,7 @@ fail_iput: fail_free: kfree(sbi); fail_unlock: - return NULL; + return -EINVAL; } static int autofs4_statfs(struct super_block *sb, struct statfs *buf) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index dcbc3a688ae7..7f371ea86066 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -656,7 +656,7 @@ static struct super_operations s_ops = { clear_inode: bm_clear_inode, }; -static struct super_block *bm_read_super(struct super_block * sb, void * data, int silent) +static int bm_fill_super(struct super_block * sb, void * data, int silent) { struct qstr names[2] = {{name:"status"}, {name:"register"}}; struct inode * inode; @@ -675,13 +675,13 @@ static struct super_block *bm_read_super(struct super_block * sb, void * data, i inode = bm_get_inode(sb, S_IFDIR | 0755); if (!inode) - return NULL; + return -ENOMEM; inode->i_op = &bm_dir_inode_operations; inode->i_fop = &bm_dir_operations; dentry[0] = d_alloc_root(inode); if (!dentry[0]) { iput(inode); - return NULL; + return -ENOMEM; } dentry[1] = d_alloc(dentry[0], &names[0]); if (!dentry[1]) @@ -701,7 +701,7 @@ static struct super_block *bm_read_super(struct super_block * sb, void * data, i d_add(dentry[2], inode); sb->s_root = dentry[0]; - return sb; + return 0; out3: dput(dentry[2]); @@ -709,14 +709,26 @@ out2: dput(dentry[1]); out1: dput(dentry[0]); - return NULL; + return -ENOMEM; +} + +static struct super_block *bm_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, bm_fill_super); } static struct linux_binfmt misc_format = { - NULL, THIS_MODULE, load_misc_binary, NULL, NULL, 0 + module: THIS_MODULE, + load_binary: load_misc_binary, }; -static DECLARE_FSTYPE(bm_fs_type, "binfmt_misc", bm_read_super, FS_SINGLE|FS_LITTER); +static struct file_system_type bm_fs_type = { + owner: THIS_MODULE, + name: "binfmt_misc", + get_sb: bm_get_sb, + fs_flags: FS_LITTER, +}; static int __init init_misc_binfmt(void) { @@ -33,20 +33,24 @@ static kmem_cache_t *bio_slab; struct biovec_pool { int size; + char *name; kmem_cache_t *slab; mempool_t *pool; }; -static struct biovec_pool bvec_array[BIOVEC_NR_POOLS]; - /* * if you change this list, also change bvec_alloc or things will * break badly! cannot be bigger than what you can fit into an * unsigned short */ -static const int bvec_pool_sizes[BIOVEC_NR_POOLS] = { 1, 4, 16, 64, 128, 256 }; -#define BIO_MAX_PAGES (bvec_pool_sizes[BIOVEC_NR_POOLS - 1]) +#define BV(x) { x, "biovec-" #x } +static struct biovec_pool bvec_array[BIOVEC_NR_POOLS] = { + BV(1), BV(4), BV(16), BV(64), BV(128), BV(256) +}; +#undef BV + +#define BIO_MAX_PAGES (bvec_array[BIOVEC_NR_POOLS - 1].size) static void *slab_pool_alloc(int gfp_mask, void *data) { @@ -64,7 +68,7 @@ static inline struct bio_vec *bvec_alloc(int gfp_mask, int nr, int *idx) struct bio_vec *bvl; /* - * see comment near bvec_pool_sizes define! + * see comment near bvec_array define! */ switch (nr) { case 1 : *idx = 0; break; @@ -452,21 +456,17 @@ int bio_endio(struct bio *bio, int uptodate, int nr_sectors) static void __init biovec_init_pool(void) { - char name[16]; int i, size; - memset(&bvec_array, 0, sizeof(bvec_array)); - for (i = 0; i < BIOVEC_NR_POOLS; i++) { struct biovec_pool *bp = bvec_array + i; - size = bvec_pool_sizes[i] * sizeof(struct bio_vec); + size = bp->size * sizeof(struct bio_vec); printk("biovec: init pool %d, %d entries, %d bytes\n", i, - bvec_pool_sizes[i], size); + bp->size, size); - snprintf(name, sizeof(name) - 1,"biovec-%d",bvec_pool_sizes[i]); - bp->slab = kmem_cache_create(name, size, 0, + bp->slab = kmem_cache_create(bp->name, size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!bp->slab) panic("biovec: can't init slab cache\n"); @@ -474,7 +474,7 @@ static void __init biovec_init_pool(void) slab_pool_free, bp->slab); if (!bp->pool) panic("biovec: can't init mempool\n"); - bp->size = size; + bp->size = size; } } diff --git a/fs/block_dev.c b/fs/block_dev.c index ef9fb9f89aa2..5bdffee5760e 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -220,7 +220,7 @@ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync) * pseudo-fs */ -static struct super_block *bd_read_super(struct super_block *sb, void *data, int silent) +static int bd_fill_super(struct super_block *sb, void *data, int silent) { static struct super_operations sops = {}; struct inode *root; @@ -232,22 +232,32 @@ static struct super_block *bd_read_super(struct super_block *sb, void *data, int sb->s_op = &sops; root = new_inode(sb); if (!root) - return NULL; + return -ENOMEM; root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_uid = root->i_gid = 0; root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME; sb->s_root = d_alloc(NULL, &(const struct qstr) { "bdev:", 5, 0 }); if (!sb->s_root) { iput(root); - return NULL; + return -ENOMEM; } sb->s_root->d_sb = sb; sb->s_root->d_parent = sb->s_root; d_instantiate(sb->s_root, root); - return sb; + return 0; } -static DECLARE_FSTYPE(bd_type, "bdev", bd_read_super, FS_NOMOUNT); +static struct super_block *bd_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_nodev(fs_type, flags, data, bd_fill_super); +} + +static struct file_system_type bd_type = { + name: "bdev", + get_sb: bd_get_sb, + fs_flags: FS_NOMOUNT, +}; static struct vfsmount *bd_mnt; diff --git a/fs/dcache.c b/fs/dcache.c index 7246506fff37..a421788191fb 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1283,6 +1283,7 @@ void __init vfs_caches_init(unsigned long mempages) dcache_init(mempages); inode_init(mempages); + files_init(mempages); mnt_init(mempages); bdev_cache_init(); cdev_cache_init(); diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 89a698a63ea6..6372557356d9 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -3218,8 +3218,7 @@ static struct inode_operations devfs_symlink_iops = setattr: devfs_notify_change, }; -static struct super_block *devfs_read_super (struct super_block *sb, - void *data, int silent) +static int devfs_fill_super (struct super_block *sb, void *data, int silent) { struct inode *root_inode = NULL; @@ -3238,17 +3237,24 @@ static struct super_block *devfs_read_super (struct super_block *sb, sb->s_root = d_alloc_root (root_inode); if (!sb->s_root) goto out_no_root; DPRINTK (DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->u.generic_sbp); - return sb; + return 0; out_no_root: PRINTK ("(): get root inode failed\n"); if (root_inode) iput (root_inode); - return NULL; + return -EINVAL; } /* End Function devfs_read_super */ +static struct super_block *devfs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, devfs_fill_super); +} -static DECLARE_FSTYPE (devfs_fs_type, DEVFS_NAME, devfs_read_super, FS_SINGLE); - +static struct file_system_type devfs_fs_type = { + name: DEVFS_NAME, + get_sb: devfs_get_sb, +}; /* File operations for devfsd follow */ diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 393ca3ececc6..1816bd4137c7 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -118,9 +118,9 @@ static int devpts_remount(struct super_block * sb, int * flags, char * data) return 0; } -struct super_block *devpts_read_super(struct super_block *s, void *data, - int silent) +static int devpts_fill_super(struct super_block *s, void *data, int silent) { + int error = -ENOMEM; struct inode * inode; struct devpts_sb_info *sbi; @@ -136,6 +136,7 @@ struct super_block *devpts_read_super(struct super_block *s, void *data, memset(sbi->inodes, 0, sizeof(struct inode *) * sbi->max_ptys); if ( devpts_parse_options(data,sbi) && !silent) { + error = -EINVAL; printk("devpts: called with bogus options\n"); goto fail_free; } @@ -160,14 +161,14 @@ struct super_block *devpts_read_super(struct super_block *s, void *data, s->s_root = d_alloc_root(inode); if (s->s_root) - return s; + return 0; printk("devpts: get root dentry failed\n"); iput(inode); fail_free: kfree(sbi); fail: - return NULL; + return error; } static int devpts_statfs(struct super_block *sb, struct statfs *buf) @@ -178,7 +179,17 @@ static int devpts_statfs(struct super_block *sb, struct statfs *buf) return 0; } -static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, FS_SINGLE); +static struct super_block *devpts_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, devpts_fill_super); +} + +static struct file_system_type devpts_fs_type = { + owner: THIS_MODULE, + name: "devpts", + get_sb: devpts_get_sb, +}; void devpts_pty_new(int number, kdev_t device) { diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c index 802d5f8597f9..54e35bce866d 100644 --- a/fs/driverfs/inode.c +++ b/fs/driverfs/inode.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/device.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> @@ -341,6 +342,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig) { loff_t retval = -EINVAL; + lock_kernel(); switch(orig) { case 0: if (offset > 0) { @@ -357,6 +359,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig) default: break; } + unlock_kernel(); return retval; } @@ -446,8 +449,7 @@ static struct super_operations driverfs_ops = { put_inode: force_delete, }; -static struct super_block* -driverfs_read_super(struct super_block *sb, void *data, int silent) +static int driverfs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct dentry *root; @@ -460,20 +462,31 @@ driverfs_read_super(struct super_block *sb, void *data, int silent) if (!inode) { DBG("%s: could not get inode!\n",__FUNCTION__); - return NULL; + return -ENOMEM; } root = d_alloc_root(inode); if (!root) { DBG("%s: could not get root dentry!\n",__FUNCTION__); iput(inode); - return NULL; + return -ENOMEM; } sb->s_root = root; - return sb; + return 0; } -static DECLARE_FSTYPE(driverfs_fs_type, "driverfs", driverfs_read_super, FS_SINGLE | FS_LITTER); +static struct super_block *driverfs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, driverfs_fill_super); +} + +static struct file_system_type driverfs_fs_type = { + owner: THIS_MODULE, + name: "driverfs", + get_sb: driverfs_get_sb, + fs_flags: FS_LITTER, +}; static int get_mount(void) { diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 09d13d60ef31..b6ffc9337824 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -96,7 +96,6 @@ extern void ext2_update_dynamic_rev (struct super_block *sb); extern void ext2_put_super (struct super_block *); extern void ext2_write_super (struct super_block *); extern int ext2_remount (struct super_block *, int *, char *); -extern struct super_block * ext2_read_super (struct super_block *,void *,int); extern int ext2_statfs (struct super_block *, struct statfs *); /* diff --git a/fs/ext2/super.c b/fs/ext2/super.c index bb14991cf85f..d46639635c61 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -441,8 +441,7 @@ static loff_t ext2_max_size(int bits) return res; } -struct super_block * ext2_read_super (struct super_block * sb, void * data, - int silent) +static int ext2_fill_super(struct super_block *sb, void *data, int silent) { struct buffer_head * bh; struct ext2_super_block * es; @@ -465,14 +464,13 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, sb->u.ext2_sb.s_mount_opt = 0; if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, - &sb->u.ext2_sb.s_mount_opt)) { - return NULL; - } + &sb->u.ext2_sb.s_mount_opt)) + return -EINVAL; blocksize = sb_min_blocksize(sb, BLOCK_SIZE); if (!blocksize) { printk ("EXT2-fs: unable to set blocksize\n"); - return NULL; + return -EINVAL; } /* @@ -487,7 +485,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, if (!(bh = sb_bread(sb, logic_sb_block))) { printk ("EXT2-fs: unable to read superblock\n"); - return NULL; + return -EINVAL; } /* * Note: s_es must be initialized as soon as possible because @@ -533,7 +531,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, if (!sb_set_blocksize(sb, blocksize)) { printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n"); - return NULL; + return -EINVAL; } logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; @@ -684,14 +682,14 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, goto failed_mount2; } ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); - return sb; + return 0; failed_mount2: for (i = 0; i < db_count; i++) brelse(sb->u.ext2_sb.s_group_desc[i]); kfree(sb->u.ext2_sb.s_group_desc); failed_mount: brelse(bh); - return NULL; + return -EINVAL; } static void ext2_commit_super (struct super_block * sb, @@ -843,7 +841,18 @@ int ext2_statfs (struct super_block * sb, struct statfs * buf) return 0; } -static DECLARE_FSTYPE_DEV(ext2_fs_type, "ext2", ext2_read_super); +static struct super_block *ext2_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); +} + +static struct file_system_type ext2_fs_type = { + owner: THIS_MODULE, + name: "ext2", + get_sb: ext2_get_sb, + fs_flags: FS_REQUIRES_DEV, +}; static int __init init_ext2_fs(void) { diff --git a/fs/fat/fatfs_syms.c b/fs/fat/fatfs_syms.c index 1ebb2731f60f..8b7152af25ae 100644 --- a/fs/fat/fatfs_syms.c +++ b/fs/fat/fatfs_syms.c @@ -47,5 +47,10 @@ static int __init init_fat_fs(void) return fat_init_inodecache(); } +static void __exit exit_fat_fs(void) +{ + fat_destroy_inodecache(); +} + module_init(init_fat_fs) -module_exit(fat_destroy_inodecache) +module_exit(exit_fat_fs) diff --git a/fs/file_table.c b/fs/file_table.c index 27713eb016fc..e7248739e3d4 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -186,3 +186,17 @@ too_bad: file_list_unlock(); return 0; } + +void __init files_init(unsigned long mempages) +{ + int n; + /* One file with associated inode and dcache is very roughly 1K. + * Per default don't use more than 10% of our memory for files. + */ + + n = (mempages * (PAGE_SIZE / 1024)) / 10; + files_stat.max_files = n; + if (files_stat.max_files < NR_FILE) + files_stat.max_files = NR_FILE; +} + diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c index 3bcdaae4e024..a82753c462d9 100644 --- a/fs/hfs/catalog.c +++ b/fs/hfs/catalog.c @@ -1346,13 +1346,6 @@ int hfs_cat_move(struct hfs_cat_entry *old_dir, struct hfs_cat_entry *new_dir, return -EINVAL; } - while (mdb->rename_lock) { - hfs_sleep_on(&mdb->rename_wait); - } - spin_lock(&entry_lock); - mdb->rename_lock = 1; /* XXX: should be atomic_inc */ - spin_unlock(&entry_lock); - /* keep readers from getting confused by changing dir size */ start_write(new_dir); if (old_dir != new_dir) { @@ -1567,11 +1560,6 @@ done: end_write(old_dir); } end_write(new_dir); - spin_lock(&entry_lock); - mdb->rename_lock = 0; /* XXX: should use atomic_dec */ - hfs_wake_up(&mdb->rename_wait); - spin_unlock(&entry_lock); - return error; } diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index 5df23375add4..4b7d36f5f2fb 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c @@ -48,10 +48,7 @@ static inline void build_key(struct hfs_ext_key *key, * Get an exclusive lock on the B-tree bitmap. */ static inline void lock_bitmap(struct hfs_mdb *mdb) { - while (mdb->bitmap_lock) { - hfs_sleep_on(&mdb->bitmap_wait); - } - mdb->bitmap_lock = 1; + down(&mdb->bitmap_sem); } /* @@ -60,8 +57,7 @@ static inline void lock_bitmap(struct hfs_mdb *mdb) { * Relinquish an exclusive lock on the B-tree bitmap. */ static inline void unlock_bitmap(struct hfs_mdb *mdb) { - mdb->bitmap_lock = 0; - hfs_wake_up(&mdb->bitmap_wait); + up(&mdb->bitmap_sem); } /* diff --git a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c index 494d43249c44..7a02ebaa6154 100644 --- a/fs/hfs/file_cap.c +++ b/fs/hfs/file_cap.c @@ -24,6 +24,7 @@ #include <linux/hfs_fs_sb.h> #include <linux/hfs_fs_i.h> #include <linux/hfs_fs.h> +#include <linux/smp_lock.h> /*================ Forward declarations ================*/ static loff_t cap_info_llseek(struct file *, loff_t, diff --git a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c index 2ac3182437a7..8dad9e76d20b 100644 --- a/fs/hfs/file_hdr.c +++ b/fs/hfs/file_hdr.c @@ -29,6 +29,7 @@ #include <linux/hfs_fs_sb.h> #include <linux/hfs_fs_i.h> #include <linux/hfs_fs.h> +#include <linux/smp_lock.h> /* prodos types */ #define PRODOSI_FTYPE_DIR 0x0F diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h index e328a14aeed7..ad9f70d74294 100644 --- a/fs/hfs/hfs.h +++ b/fs/hfs/hfs.h @@ -271,10 +271,7 @@ struct hfs_mdb { 512-byte blocks per "allocation block" */ hfs_u16 attrib; /* Attribute word */ - hfs_wait_queue rename_wait; - int rename_lock; - hfs_wait_queue bitmap_wait; - int bitmap_lock; + struct semaphore bitmap_sem; struct list_head entry_dirty; }; diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index d907a632dad9..b3f8477f58cb 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -100,8 +100,7 @@ struct hfs_mdb *hfs_mdb_get(hfs_sysmdb sys_mdb, int readonly, mdb->magic = HFS_MDB_MAGIC; mdb->sys_mdb = sys_mdb; INIT_LIST_HEAD(&mdb->entry_dirty); - hfs_init_waitqueue(&mdb->rename_wait); - hfs_init_waitqueue(&mdb->bitmap_wait); + init_MUTEX(&mdb->bitmap_sem); /* See if this is an HFS filesystem */ buf = hfs_buffer_get(sys_mdb, part_start + HFS_MDB_BLK, 1); diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 0049e5ee48fa..94b663656ac4 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -14,8 +14,7 @@ void hpfs_lock_creation(struct super_block *s) #ifdef DEBUG_LOCKS printk("lock creation\n"); #endif - while (s->s_hpfs_creation_de_lock) sleep_on(&s->s_hpfs_creation_de); - s->s_hpfs_creation_de_lock = 1; + down(&s->u.hpfs_sb.hpfs_creation_de); } void hpfs_unlock_creation(struct super_block *s) @@ -23,8 +22,7 @@ void hpfs_unlock_creation(struct super_block *s) #ifdef DEBUG_LOCKS printk("unlock creation\n"); #endif - s->s_hpfs_creation_de_lock = 0; - wake_up(&s->s_hpfs_creation_de); + up(&s->u.hpfs_sb.hpfs_creation_de); } void hpfs_lock_iget(struct super_block *s, int mode) diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 2483e920b597..3d59f27c82b8 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -427,8 +427,8 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options, s->s_hpfs_bmp_dir = NULL; s->s_hpfs_cp_table = NULL; - s->s_hpfs_creation_de_lock = s->s_hpfs_rd_inode = 0; - init_waitqueue_head(&s->s_hpfs_creation_de); + s->s_hpfs_rd_inode = 0; + init_MUTEX(&s->u.hpfs_sb.hpfs_creation_de); init_waitqueue_head(&s->s_hpfs_iget_q); uid = current->uid; diff --git a/fs/namespace.c b/fs/namespace.c index fdcc369fbe38..1419b179c74c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1048,15 +1048,9 @@ void __init mnt_init(unsigned long mempages) if (!mnt_cache) panic("Cannot create vfsmount cache"); - mempages >>= (16 - PAGE_SHIFT); - mempages *= sizeof(struct list_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) - ; - - do { - mount_hashtable = (struct list_head *) - __get_free_pages(GFP_ATOMIC, order); - } while (mount_hashtable == NULL && --order >= 0); + order = 0; + mount_hashtable = (struct list_head *) + __get_free_pages(GFP_ATOMIC, order); if (!mount_hashtable) panic("Failed to allocate mount hash table\n"); diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 1f70ec451ce7..bc7b38e5530c 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -18,6 +18,7 @@ #include <linux/locks.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <linux/smp_lock.h> #include <linux/ncp_fs.h> #include "ncplib_kernel.h" @@ -281,7 +282,7 @@ static int ncp_release(struct inode *inode, struct file *file) { struct file_operations ncp_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: ncp_file_read, write: ncp_file_write, ioctl: ncp_ioctl, diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 32e089bd5ec0..e4ed0426d766 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -365,7 +365,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent) sock_inode = ncp_filp->f_dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_bad_file2; - sock = &sock_inode->u.socket_i; + sock = SOCKET_I(sock_inode); if (!sock) goto out_bad_file2; diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index 470ea5e96ae3..095498a2b5b8 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c @@ -101,7 +101,7 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size, struct ncp_reply_header reply; file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); init_timeout = server->m.time_out; max_timeout = NCP_MAX_RPC_TIMEOUT; @@ -269,7 +269,7 @@ static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) { int result = 0; file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); dataread = 0; @@ -348,7 +348,7 @@ static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size, *((struct ncp_request_header *) (server->packet)); file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC); ncptcp_xmit_hdr[1] = htonl(size + 16); @@ -444,7 +444,7 @@ static int ncp_do_request(struct ncp_server *server, int size, } #endif /* CONFIG_NCPFS_PACKET_SIGNING */ file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); /* N.B. this isn't needed ... check socket type? */ if (!sock) { printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n"); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 1d5e7dbde28a..d25cb4968931 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -41,7 +41,7 @@ static int nfs_file_flush(struct file *); static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); struct file_operations nfs_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: nfs_file_read, write: nfs_file_write, mmap: nfs_file_mmap, diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 261cadb58635..28d57bf19bad 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -245,8 +245,7 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh) * and the root file handle obtained from the server's mount * daemon. We stash these away in the private superblock fields. */ -struct super_block * -nfs_read_super(struct super_block *sb, void *raw_data, int silent) +int nfs_fill_super(struct super_block *sb, void *raw_data, int silent) { struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data; struct nfs_server *server; @@ -455,6 +454,8 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) server->namelen = maxlen; sb->s_maxbytes = fsinfo.maxfilesize; + if (sb->s_maxbytes > MAX_LFS_FILESIZE) + sb->s_maxbytes = MAX_LFS_FILESIZE; /* Fire up the writeback cache */ if (nfs_reqlist_alloc(server) < 0) { @@ -467,7 +468,7 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) /* Check whether to start the lockd process */ if (!(server->flags & NFS_MOUNT_NONLM)) lockd_up(); - return sb; + return 0; /* Yargs. It didn't work out. */ failure_kill_reqlist: @@ -506,7 +507,7 @@ out_miss_args: printk("nfs_read_super: missing data argument\n"); out_fail: - return NULL; + return -EINVAL; } static int @@ -1137,7 +1138,25 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) /* * File system information */ -static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, FS_ODD_RENAME); + +/* + * Right now we are using get_sb_nodev, but we ought to switch to + * get_anon_super() with appropriate comparison function. The only + * question being, when two NFS mounts are the same? Identical IP + * of server + identical root fhandle? Trond? + */ +static struct super_block *nfs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_nodev(fs_type, flags, data, nfs_fill_super); +} + +static struct file_system_type nfs_fs_type = { + owner: THIS_MODULE, + name: "nfs", + get_sb: nfs_get_sb, + fs_flags: FS_ODD_RENAME, +}; extern int nfs_init_nfspagecache(void); extern void nfs_destroy_nfspagecache(void); diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index 4fa8e2f018e4..d28ea94084a9 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -1130,7 +1130,7 @@ struct super_block *ntfs_read_super(struct super_block *sb, void *options, /* Inform the kernel about which super operations are available. */ sb->s_op = &ntfs_super_operations; sb->s_magic = NTFS_SUPER_MAGIC; - sb->s_maxbytes = ~0ULL >> 1; + sb->s_maxbytes = MAX_LFS_FILESIZE; ntfs_debug(DEBUG_OTHER, "Reading special files\n"); if (ntfs_load_special_files(vol)) { ntfs_error("Error loading special files\n"); diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 61c8b2b73111..fb86cd505779 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -998,8 +998,7 @@ static struct super_operations openprom_sops = { statfs: openprom_statfs, }; -struct super_block *openprom_read_super(struct super_block *s,void *data, - int silent) +static int openprom_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; @@ -1013,15 +1012,25 @@ 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; - return s; + return 0; out_no_root: - printk("openprom_read_super: get root inode failed\n"); + printk("openprom_fill_super: get root inode failed\n"); iput(root_inode); - return NULL; + return -ENOMEM; +} + +static struct super_block *openprom_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, openprom_fill_super); } -static DECLARE_FSTYPE(openprom_fs_type, "openpromfs", openprom_read_super, 0); +static struct file_system_type openprom_fs_type = { + owner: THIS_MODULE, + name: "openpromfs", + get_sb: openprom_get_sb, +}; static int __init init_openprom_fs(void) { diff --git a/fs/pipe.c b/fs/pipe.c index 5910c168288f..90734730ca62 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -246,12 +246,6 @@ sigpipe: return -EPIPE; } -static loff_t -pipe_lseek(struct file *file, loff_t offset, int orig) -{ - return -ESPIPE; -} - static ssize_t bad_pipe_r(struct file *filp, char *buf, size_t count, loff_t *ppos) { @@ -381,7 +375,7 @@ pipe_rdwr_open(struct inode *inode, struct file *filp) * are also used in linux/fs/fifo.c to do operations on FIFOs. */ struct file_operations read_fifo_fops = { - llseek: pipe_lseek, + llseek: no_llseek, read: pipe_read, write: bad_pipe_w, poll: fifo_poll, @@ -391,7 +385,7 @@ struct file_operations read_fifo_fops = { }; struct file_operations write_fifo_fops = { - llseek: pipe_lseek, + llseek: no_llseek, read: bad_pipe_r, write: pipe_write, poll: fifo_poll, @@ -401,7 +395,7 @@ struct file_operations write_fifo_fops = { }; struct file_operations rdwr_fifo_fops = { - llseek: pipe_lseek, + llseek: no_llseek, read: pipe_read, write: pipe_write, poll: fifo_poll, @@ -411,7 +405,7 @@ struct file_operations rdwr_fifo_fops = { }; struct file_operations read_pipe_fops = { - llseek: pipe_lseek, + llseek: no_llseek, read: pipe_read, write: bad_pipe_w, poll: pipe_poll, @@ -421,7 +415,7 @@ struct file_operations read_pipe_fops = { }; struct file_operations write_pipe_fops = { - llseek: pipe_lseek, + llseek: no_llseek, read: bad_pipe_r, write: pipe_write, poll: pipe_poll, @@ -431,7 +425,7 @@ struct file_operations write_pipe_fops = { }; struct file_operations rdwr_pipe_fops = { - llseek: pipe_lseek, + llseek: no_llseek, read: pipe_read, write: pipe_write, poll: pipe_poll, @@ -606,7 +600,7 @@ static struct super_operations pipefs_ops = { statfs: pipefs_statfs, }; -static struct super_block * pipefs_read_super(struct super_block *sb, void *data, int silent) +static int pipefs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *root; @@ -616,22 +610,32 @@ static struct super_block * pipefs_read_super(struct super_block *sb, void *data sb->s_op = &pipefs_ops; root = new_inode(sb); if (!root) - return NULL; + return -ENOMEM; root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_uid = root->i_gid = 0; root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME; sb->s_root = d_alloc(NULL, &(const struct qstr) { "pipe:", 5, 0 }); if (!sb->s_root) { iput(root); - return NULL; + return -ENOMEM; } sb->s_root->d_sb = sb; sb->s_root->d_parent = sb->s_root; d_instantiate(sb->s_root, root); - return sb; + return 0; } -static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, FS_NOMOUNT); +static struct super_block *pipefs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_nodev(fs_type, flags, data, pipefs_fill_super); +} + +static struct file_system_type pipe_fs_type = { + name: "pipefs", + get_sb: pipefs_get_sb, + fs_flags: FS_NOMOUNT, +}; static int __init init_pipe_fs(void) { diff --git a/fs/proc/base.c b/fs/proc/base.c index ed0da13a0e91..e472c395cccd 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -37,6 +37,11 @@ #define fake_ino(pid,ino) (((pid)<<16)|(ino)) +static inline struct task_struct *proc_task(struct inode *inode) +{ + return PROC_I(inode)->task; +} + ssize_t proc_pid_read_maps(struct task_struct*,struct file*,char*,size_t,loff_t*); int proc_pid_stat(struct task_struct*,char*); int proc_pid_status(struct task_struct*,char*); @@ -45,9 +50,10 @@ int proc_pid_cpu(struct task_struct*,char*); static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) { - if (inode->u.proc_i.file) { - *mnt = mntget(inode->u.proc_i.file->f_vfsmnt); - *dentry = dget(inode->u.proc_i.file->f_dentry); + struct file *file = PROC_I(inode)->file; + if (file) { + *mnt = mntget(file->f_vfsmnt); + *dentry = dget(file->f_dentry); return 0; } return -ENOENT; @@ -58,7 +64,7 @@ static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfs struct mm_struct * mm; struct vm_area_struct * vma; int result = -ENOENT; - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); task_lock(task); mm = task->mm; @@ -89,11 +95,11 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs { struct fs_struct *fs; int result = -ENOENT; - task_lock(inode->u.proc_i.task); - fs = inode->u.proc_i.task->fs; + task_lock(proc_task(inode)); + fs = proc_task(inode)->fs; if(fs) atomic_inc(&fs->count); - task_unlock(inode->u.proc_i.task); + task_unlock(proc_task(inode)); if (fs) { read_lock(&fs->lock); *mnt = mntget(fs->pwdmnt); @@ -109,11 +115,11 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf { struct fs_struct *fs; int result = -ENOENT; - task_lock(inode->u.proc_i.task); - fs = inode->u.proc_i.task->fs; + task_lock(proc_task(inode)); + fs = proc_task(inode)->fs; if(fs) atomic_inc(&fs->count); - task_unlock(inode->u.proc_i.task); + task_unlock(proc_task(inode)); if (fs) { read_lock(&fs->lock); *mnt = mntget(fs->rootmnt); @@ -238,7 +244,7 @@ static ssize_t pid_maps_read(struct file * file, char * buf, size_t count, loff_t *ppos) { struct inode * inode = file->f_dentry->d_inode; - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); ssize_t res; res = proc_pid_read_maps(task, file, buf, count, ppos); @@ -252,7 +258,7 @@ static struct file_operations proc_maps_operations = { extern struct seq_operations mounts_op; static int mounts_open(struct inode *inode, struct file *file) { - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); int ret = seq_open(file, &mounts_op); if (!ret) { @@ -298,14 +304,14 @@ static ssize_t proc_info_read(struct file * file, char * buf, unsigned long page; ssize_t length; ssize_t end; - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); if (count > PROC_BLOCK_SIZE) count = PROC_BLOCK_SIZE; if (!(page = __get_free_page(GFP_KERNEL))) return -ENOMEM; - length = inode->u.proc_i.op.proc_read(task, (char*)page); + length = PROC_I(inode)->op.proc_read(task, (char*)page); if (length < 0) { free_page(page); @@ -342,7 +348,7 @@ static int mem_open(struct inode* inode, struct file* file) static ssize_t mem_read(struct file * file, char * buf, size_t count, loff_t *ppos) { - struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; + struct task_struct *task = proc_task(file->f_dentry->d_inode); char *page; unsigned long src = *ppos; int copied = 0; @@ -404,7 +410,7 @@ static ssize_t mem_write(struct file * file, const char * buf, { int copied = 0; char *page; - struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; + struct task_struct *task = proc_task(file->f_dentry->d_inode); unsigned long dst = *ppos; if (!MAY_PTRACE(task)) @@ -463,7 +469,7 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) if (error) goto out; - error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt); + error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); nd->last_type = LAST_BIND; out: return error; @@ -503,7 +509,7 @@ static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen) if (error) goto out; - error = inode->u.proc_i.op.proc_get_link(inode, &de, &mnt); + error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt); if (error) goto out; @@ -570,7 +576,7 @@ static struct pid_entry base_stuff[] = { static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - struct task_struct *p = inode->u.proc_i.task; + struct task_struct *p = proc_task(inode); unsigned int fd, pid, ino; int retval; char buf[NUMBUF]; @@ -598,6 +604,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) task_unlock(p); if (!files) goto out; + read_lock(&files->file_lock); for (fd = filp->f_pos-2; fd < files->max_fds; fd++, filp->f_pos++) { @@ -605,6 +612,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) if (!fcheck_files(files, fd)) continue; + read_unlock(&files->file_lock); j = NUMBUF; i = fd; @@ -617,7 +625,9 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) ino = fake_ino(pid, PROC_PID_FD_DIR + fd); if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) break; + read_lock(&files->file_lock); } + read_unlock(&files->file_lock); put_files_struct(files); } out: @@ -632,7 +642,7 @@ static int proc_base_readdir(struct file * filp, struct inode *inode = filp->f_dentry->d_inode; struct pid_entry *p; - pid = inode->u.proc_i.task->pid; + pid = proc_task(inode)->pid; if (!pid) return -ENOENT; i = filp->f_pos; @@ -684,6 +694,7 @@ static int task_dumpable(struct task_struct *task) static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino) { struct inode * inode; + struct proc_inode *ei; /* We need a new inode */ @@ -692,7 +703,9 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st goto out; /* Common stuff */ - + ei = PROC_I(inode); + ei->task = NULL; + ei->file = NULL; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(task->pid, ino); @@ -703,7 +716,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st * grab the reference to task. */ get_task_struct(task); - inode->u.proc_i.task = task; + ei->task = task; inode->i_uid = 0; inode->i_gid = 0; if (ino == PROC_PID_INO || task_dumpable(task)) { @@ -733,7 +746,7 @@ static int pid_fd_revalidate(struct dentry * dentry, int flags) */ static int pid_base_revalidate(struct dentry * dentry, int flags) { - if (dentry->d_inode->u.proc_i.task->pid) + if (proc_task(dentry->d_inode)->pid) return 1; d_drop(dentry); return 0; @@ -767,10 +780,11 @@ static struct dentry_operations pid_base_dentry_operations = static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) { unsigned int fd, c; - struct task_struct *task = dir->u.proc_i.task; + struct task_struct *task = proc_task(dir); struct file * file; struct files_struct * files; struct inode *inode; + struct proc_inode *ei; const char *name; int len; @@ -792,6 +806,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd); if (!inode) goto out; + ei = PROC_I(inode); task_lock(task); files = task->files; if (files) @@ -800,7 +815,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) if (!files) goto out_unlock; read_lock(&files->file_lock); - file = inode->u.proc_i.file = fcheck_files(files, fd); + file = ei->file = fcheck_files(files, fd); if (!file) goto out_unlock2; get_file(file); @@ -809,7 +824,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) inode->i_op = &proc_pid_link_inode_operations; inode->i_size = 64; inode->i_mode = S_IFLNK; - inode->u.proc_i.op.proc_get_link = proc_fd_link; + ei->op.proc_get_link = proc_fd_link; if (file->f_mode & 1) inode->i_mode |= S_IRUSR | S_IXUSR; if (file->f_mode & 2) @@ -844,8 +859,9 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) { struct inode *inode; int error; - struct task_struct *task = dir->u.proc_i.task; + struct task_struct *task = proc_task(dir); struct pid_entry *p; + struct proc_inode *ei; error = -ENOENT; inode = NULL; @@ -864,6 +880,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) if (!inode) goto out; + ei = PROC_I(inode); inode->i_mode = p->mode; /* * Yes, it does not scale. And it should not. Don't add @@ -877,35 +894,35 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) break; case PROC_PID_EXE: inode->i_op = &proc_pid_link_inode_operations; - inode->u.proc_i.op.proc_get_link = proc_exe_link; + ei->op.proc_get_link = proc_exe_link; break; case PROC_PID_CWD: inode->i_op = &proc_pid_link_inode_operations; - inode->u.proc_i.op.proc_get_link = proc_cwd_link; + ei->op.proc_get_link = proc_cwd_link; break; case PROC_PID_ROOT: inode->i_op = &proc_pid_link_inode_operations; - inode->u.proc_i.op.proc_get_link = proc_root_link; + ei->op.proc_get_link = proc_root_link; break; case PROC_PID_ENVIRON: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_environ; + ei->op.proc_read = proc_pid_environ; break; case PROC_PID_STATUS: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_status; + ei->op.proc_read = proc_pid_status; break; case PROC_PID_STAT: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_stat; + ei->op.proc_read = proc_pid_stat; break; case PROC_PID_CMDLINE: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_cmdline; + ei->op.proc_read = proc_pid_cmdline; break; case PROC_PID_STATM: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_statm; + ei->op.proc_read = proc_pid_statm; break; case PROC_PID_MAPS: inode->i_fop = &proc_maps_operations; @@ -913,7 +930,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) #ifdef CONFIG_SMP case PROC_PID_CPU: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_cpu; + ei->op.proc_read = proc_pid_cpu; break; #endif case PROC_PID_MEM: @@ -973,6 +990,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry) struct task_struct *task; const char *name; struct inode *inode; + struct proc_inode *ei; int len; pid = 0; @@ -982,10 +1000,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry) inode = new_inode(dir->i_sb); if (!inode) return ERR_PTR(-ENOMEM); + ei = PROC_I(inode); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(0, PROC_PID_INO); - inode->u.proc_i.file = NULL; - inode->u.proc_i.task = NULL; + ei->file = NULL; + ei->task = NULL; inode->i_mode = S_IFLNK|S_IRWXUGO; inode->i_uid = inode->i_gid = 0; inode->i_size = 64; @@ -1035,10 +1054,10 @@ out: void proc_pid_delete_inode(struct inode *inode) { - if (inode->u.proc_i.file) - fput(inode->u.proc_i.file); - if (inode->u.proc_i.task) - free_task_struct(inode->u.proc_i.task); + if (PROC_I(inode)->file) + fput(PROC_I(inode)->file); + if (proc_task(inode)) + free_task_struct(proc_task(inode)); } #define PROC_NUMBUF 10 diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 3e31f65e266b..f50b13026f27 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -58,7 +58,7 @@ proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) char *start; struct proc_dir_entry * dp; - dp = (struct proc_dir_entry *) inode->u.generic_ip; + dp = PDE(inode); if (!(page = (char*) __get_free_page(GFP_KERNEL))) return -ENOMEM; @@ -128,7 +128,7 @@ proc_file_write(struct file * file, const char * buffer, struct inode *inode = file->f_dentry->d_inode; struct proc_dir_entry * dp; - dp = (struct proc_dir_entry *) inode->u.generic_ip; + dp = PDE(inode); if (!dp->write_proc) return -EIO; @@ -221,13 +221,13 @@ out: static int proc_readlink(struct dentry *dentry, char *buffer, int buflen) { - char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data; + char *s=PDE(dentry->d_inode)->data; return vfs_readlink(dentry, buffer, buflen, s); } static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) { - char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data; + char *s=PDE(dentry->d_inode)->data; return vfs_follow_link(nd, s); } @@ -264,7 +264,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry) error = -ENOENT; inode = NULL; - de = (struct proc_dir_entry *) dir->u.generic_ip; + de = PDE(dir); if (de) { for (de = de->subdir; de ; de = de->next) { if (!de || !de->low_ino) @@ -306,7 +306,7 @@ int proc_readdir(struct file * filp, struct inode *inode = filp->f_dentry->d_inode; ino = inode->i_ino; - de = (struct proc_dir_entry *) inode->u.generic_ip; + de = PDE(inode); if (!de) return -EINVAL; i = filp->f_pos; @@ -413,7 +413,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) if (dentry->d_op != &proc_dentry_operations) continue; inode = dentry->d_inode; - if (inode->u.generic_ip != de) + if (PDE(inode) != de) continue; fops = filp->f_op; filp->f_op = NULL; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 8af8a6868e92..c96bde47f090 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -58,7 +58,7 @@ void de_put(struct proc_dir_entry *de) */ static void proc_delete_inode(struct inode *inode) { - struct proc_dir_entry *de = inode->u.generic_ip; + struct proc_dir_entry *de = PDE(inode); inode->i_state = I_CLEAR; @@ -91,14 +91,51 @@ static int proc_statfs(struct super_block *sb, struct statfs *buf) return 0; } +static kmem_cache_t * proc_inode_cachep; + +static struct inode *proc_alloc_inode(struct super_block *sb) +{ + struct proc_inode *ei; + ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, SLAB_KERNEL); + if (!ei) + return NULL; + return &ei->vfs_inode; +} + +static void proc_destroy_inode(struct inode *inode) +{ + kmem_cache_free(proc_inode_cachep, PROC_I(inode)); +} + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct proc_inode *ei = (struct proc_inode *) foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + +int __init proc_init_inodecache(void) +{ + proc_inode_cachep = kmem_cache_create("proc_inode_cache", + sizeof(struct proc_inode), + 0, SLAB_HWCACHE_ALIGN, + init_once, NULL); + if (proc_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + static struct super_operations proc_sops = { + alloc_inode: proc_alloc_inode, + destroy_inode: proc_destroy_inode, read_inode: proc_read_inode, put_inode: force_delete, delete_inode: proc_delete_inode, statfs: proc_statfs, }; - static int parse_options(char *options,uid_t *uid,gid_t *gid) { char *this_char,*value; @@ -147,7 +184,7 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, atomic_read(&d if (!inode) goto out_fail; - inode->u.generic_ip = (void *) de; + PROC_I(inode)->pde = de; if (de) { if (de->mode) { inode->i_mode = de->mode; @@ -176,8 +213,7 @@ out_fail: goto out; } -struct super_block *proc_read_super(struct super_block *s,void *data, - int silent) +int proc_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; struct task_struct *p; @@ -200,11 +236,11 @@ struct super_block *proc_read_super(struct super_block *s,void *data, if (!s->s_root) goto out_no_root; parse_options(data, &root_inode->i_uid, &root_inode->i_gid); - return s; + return 0; out_no_root: printk("proc_read_super: get root inode failed\n"); iput(root_inode); - return NULL; + return -ENOMEM; } MODULE_LICENSE("GPL"); diff --git a/fs/proc/root.c b/fs/proc/root.c index 3db40a53bc0f..666166bfcf57 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -23,11 +23,24 @@ struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver; struct proc_dir_entry *proc_sys_root; #endif -static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE); +static struct super_block *proc_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, proc_fill_super); +} + +static struct file_system_type proc_fs_type = { + name: "proc", + get_sb: proc_get_sb, +}; +extern int __init proc_init_inodecache(void); void __init proc_root_init(void) { - int err = register_filesystem(&proc_fs_type); + int err = proc_init_inodecache(); + if (err) + return; + err = register_filesystem(&proc_fs_type); if (err) return; proc_mnt = kern_mount(&proc_fs_type); diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index b8994583f13a..3bed425ec3b8 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -302,7 +302,7 @@ static struct super_operations ramfs_ops = { put_inode: force_delete, }; -static struct super_block *ramfs_read_super(struct super_block * sb, void * data, int silent) +static int ramfs_fill_super(struct super_block * sb, void * data, int silent) { struct inode * inode; struct dentry * root; @@ -313,19 +313,33 @@ static struct super_block *ramfs_read_super(struct super_block * sb, void * data sb->s_op = &ramfs_ops; inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0); if (!inode) - return NULL; + return -ENOMEM; root = d_alloc_root(inode); if (!root) { iput(inode); - return NULL; + return -ENOMEM; } sb->s_root = root; - return sb; + return 0; +} + +static struct super_block *ramfs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_nodev(fs_type, flags, data, ramfs_fill_super); } -static DECLARE_FSTYPE(ramfs_fs_type, "ramfs", ramfs_read_super, FS_LITTER); -static DECLARE_FSTYPE(rootfs_fs_type, "rootfs", ramfs_read_super, FS_NOMOUNT|FS_LITTER); +static struct file_system_type ramfs_fs_type = { + name: "ramfs", + get_sb: ramfs_get_sb, + fs_flags: FS_LITTER, +}; +static struct file_system_type rootfs_fs_type = { + name: "rootfs", + get_sb: ramfs_get_sb, + fs_flags: FS_NOMOUNT|FS_LITTER, +}; static int __init init_ramfs_fs(void) { diff --git a/fs/read_write.c b/fs/read_write.c index 31cee2a6aa4e..ce5230669579 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -51,6 +51,31 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) return retval; } +loff_t remote_llseek(struct file *file, loff_t offset, int origin) +{ + long long retval; + + lock_kernel(); + switch (origin) { + case 2: + offset += file->f_dentry->d_inode->i_size; + break; + case 1: + offset += file->f_pos; + } + retval = -EINVAL; + if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) { + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_reada = 0; + file->f_version = ++event; + } + retval = offset; + } + unlock_kernel(); + return retval; +} + loff_t no_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 4fe8843c5899..c35cb51a9a48 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -890,6 +890,13 @@ static void init_inode (struct inode * inode, struct path * path) inode->i_blksize = PAGE_SIZE; INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list )); + REISERFS_I(inode)->i_flags = 0; + REISERFS_I(inode)->i_prealloc_block = 0; + REISERFS_I(inode)->i_prealloc_count = 0; + REISERFS_I(inode)->i_trans_id = 0; + REISERFS_I(inode)->i_trans_index = 0; + /* nopack = 0, by default */ + REISERFS_I(inode)->i_flags &= ~i_nopack_mask; if (stat_data_v1 (ih)) { struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); @@ -950,13 +957,6 @@ static void init_inode (struct inode * inode, struct path * path) set_inode_item_key_version (inode, KEY_FORMAT_3_6); REISERFS_I(inode)->i_first_direct_byte = 0; } - REISERFS_I(inode)->i_flags = 0; - REISERFS_I(inode)->i_prealloc_block = 0; - REISERFS_I(inode)->i_prealloc_count = 0; - REISERFS_I(inode)->i_trans_id = 0; - REISERFS_I(inode)->i_trans_index = 0; - /* nopack = 0, by default */ - REISERFS_I(inode)->i_flags &= ~i_nopack_mask; pathrelse (path); if (S_ISREG (inode->i_mode)) { diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index b3feaa56924a..39badd71692f 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -381,7 +381,7 @@ smb_file_permission(struct inode *inode, int mask) struct file_operations smb_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: smb_file_read, write: smb_file_write, ioctl: smb_ioctl, diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c index 46313b623c7b..8c66f4c5e655 100644 --- a/fs/smbfs/sock.c +++ b/fs/smbfs/sock.c @@ -176,7 +176,7 @@ int smb_valid_socket(struct inode * inode) { return (inode && S_ISSOCK(inode->i_mode) && - inode->u.socket_i.type == SOCK_STREAM); + SOCKET_I(inode)->type == SOCK_STREAM); } static struct socket * @@ -190,7 +190,7 @@ server_sock(struct smb_sb_info *server) if (!smb_valid_socket(file->f_dentry->d_inode)) PARANOIA("bad socket!\n"); #endif - return &file->f_dentry->d_inode->u.socket_i; + return SOCKET_I(file->f_dentry->d_inode); } return NULL; } diff --git a/fs/stat.c b/fs/stat.c index d7ed42c77f59..20bd373580c5 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -25,68 +25,28 @@ do_revalidate(struct dentry *dentry) return 0; } - -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) - -/* - * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? - */ -static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf) +static int do_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { - static int warncount = 5; - struct __old_kernel_stat tmp; - - if (warncount > 0) { - warncount--; - printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n", - current->comm); - } else if (warncount < 0) { - /* it's laughable, but... */ - warncount = 0; - } - - tmp.st_dev = kdev_t_to_nr(inode->i_dev); - tmp.st_ino = inode->i_ino; - tmp.st_mode = inode->i_mode; - tmp.st_nlink = inode->i_nlink; - SET_OLDSTAT_UID(tmp, inode->i_uid); - SET_OLDSTAT_GID(tmp, inode->i_gid); - tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); -#if BITS_PER_LONG == 32 - if (inode->i_size > MAX_NON_LFS) - return -EOVERFLOW; -#endif - tmp.st_size = inode->i_size; - tmp.st_atime = inode->i_atime; - tmp.st_mtime = inode->i_mtime; - tmp.st_ctime = inode->i_ctime; - return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; -} - -#endif - -static int cp_new_stat(struct inode * inode, struct stat * statbuf) -{ - struct stat tmp; + int res = 0; unsigned int blocks, indirect; - - memset(&tmp, 0, sizeof(tmp)); - tmp.st_dev = kdev_t_to_nr(inode->i_dev); - tmp.st_ino = inode->i_ino; - tmp.st_mode = inode->i_mode; - tmp.st_nlink = inode->i_nlink; - SET_STAT_UID(tmp, inode->i_uid); - SET_STAT_GID(tmp, inode->i_gid); - tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); -#if BITS_PER_LONG == 32 - if (inode->i_size > MAX_NON_LFS) - return -EOVERFLOW; -#endif - tmp.st_size = inode->i_size; - tmp.st_atime = inode->i_atime; - tmp.st_mtime = inode->i_mtime; - tmp.st_ctime = inode->i_ctime; + struct inode *inode = dentry->d_inode; + + res = do_revalidate(dentry); + if (res) + return res; + + stat->dev = kdev_t_to_nr(inode->i_dev); + stat->ino = inode->i_ino; + stat->mode = inode->i_mode; + stat->nlink = inode->i_nlink; + stat->uid = inode->i_uid; + stat->gid = inode->i_gid; + stat->rdev = kdev_t_to_nr(inode->i_rdev); + stat->atime = inode->i_atime; + stat->mtime = inode->i_mtime; + stat->ctime = inode->i_ctime; + stat->ctime = inode->i_ctime; + stat->size = inode->i_size; /* * st_blocks and st_blksize are approximated with a simple algorithm if * they aren't supported directly by the filesystem. The minix and msdos @@ -106,7 +66,7 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf) #define I_B (BLOCK_SIZE / sizeof(unsigned short)) if (!inode->i_blksize) { - blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE; + blocks = (stat->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; if (blocks > D_B) { indirect = (blocks - D_B + I_B - 1) / I_B; blocks += indirect; @@ -117,130 +77,178 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf) blocks++; } } - tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; - tmp.st_blksize = BLOCK_SIZE; + stat->blocks = (BLOCK_SIZE / 512) * blocks; + stat->blksize = BLOCK_SIZE; } else { - tmp.st_blocks = inode->i_blocks; - tmp.st_blksize = inode->i_blksize; + stat->blocks = inode->i_blocks; + stat->blksize = inode->i_blksize; } - return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; + return 0; } - -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) -/* - * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? - */ -asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) +int vfs_stat(char *name, struct kstat *stat) { struct nameidata nd; int error; - error = user_path_walk(filename, &nd); + error = user_path_walk(name, &nd); if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); + error = do_getattr(nd.mnt, nd.dentry, stat); path_release(&nd); } return error; } -#endif -asmlinkage long sys_newstat(char * filename, struct stat * statbuf) +int vfs_lstat(char *name, struct kstat *stat) { struct nameidata nd; int error; - error = user_path_walk(filename, &nd); + error = user_path_walk_link(name, &nd); if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); + error = do_getattr(nd.mnt, nd.dentry, stat); path_release(&nd); } return error; } +int vfs_fstat(unsigned int fd, struct kstat *stat) +{ + struct file *f = fget(fd); + int error = -EBADF; + + if (f) { + error = do_getattr(f->f_vfsmnt, f->f_dentry, stat); + fput(f); + } + return error; +} + #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) /* * For backward compatibility? Maybe this should be moved * into arch/i386 instead? */ -asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) +static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat * statbuf) { - struct nameidata nd; - int error; + static int warncount = 5; + struct __old_kernel_stat tmp; - error = user_path_walk_link(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); - path_release(&nd); + if (warncount > 0) { + warncount--; + printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n", + current->comm); + } else if (warncount < 0) { + /* it's laughable, but... */ + warncount = 0; } - return error; -} -#endif + tmp.st_dev = stat->dev; + tmp.st_ino = stat->ino; + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + SET_OLDSTAT_UID(tmp, stat->uid); + SET_OLDSTAT_GID(tmp, stat->gid); + tmp.st_rdev = stat->rdev; +#if BITS_PER_LONG == 32 + if (stat->size > MAX_NON_LFS) + return -EOVERFLOW; +#endif + tmp.st_size = stat->size; + tmp.st_atime = stat->atime; + tmp.st_mtime = stat->mtime; + tmp.st_ctime = stat->ctime; + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} -asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) +asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) { - struct nameidata nd; - int error; + struct kstat stat; + int error = vfs_stat(filename, &stat); + + if (!error) + error = cp_old_stat(&stat, statbuf); - error = user_path_walk_link(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); - path_release(&nd); - } return error; } +asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) +{ + struct kstat stat; + int error = vfs_lstat(filename, &stat); -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) + if (!error) + error = cp_old_stat(&stat, statbuf); -/* - * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? - */ + return error; +} asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf) { - struct file * f; - int err = -EBADF; + struct kstat stat; + int error = vfs_fstat(fd, &stat); - f = fget(fd); - if (f) { - struct dentry * dentry = f->f_dentry; + if (!error) + error = cp_old_stat(&stat, statbuf); - err = do_revalidate(dentry); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); - } - return err; + return error; } #endif +static int cp_new_stat(struct kstat *stat, struct stat *statbuf) +{ + struct stat tmp; + + memset(&tmp, 0, sizeof(tmp)); + tmp.st_dev = stat->dev; + tmp.st_ino = stat->ino; + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + SET_STAT_UID(tmp, stat->uid); + SET_STAT_GID(tmp, stat->gid); + tmp.st_rdev = stat->rdev; +#if BITS_PER_LONG == 32 + if (stat->size > MAX_NON_LFS) + return -EOVERFLOW; +#endif + tmp.st_size = stat->size; + tmp.st_atime = stat->atime; + tmp.st_mtime = stat->mtime; + tmp.st_ctime = stat->ctime; + tmp.st_blocks = stat->blocks; + tmp.st_blksize = stat->blksize; + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} + +asmlinkage long sys_newstat(char * filename, struct stat * statbuf) +{ + struct kstat stat; + int error = vfs_stat(filename, &stat); + + if (!error) + error = cp_new_stat(&stat, statbuf); + + return error; +} +asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) +{ + struct kstat stat; + int error = vfs_lstat(filename, &stat); + + if (!error) + error = cp_new_stat(&stat, statbuf); + + return error; +} asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf) { - struct file * f; - int err = -EBADF; + struct kstat stat; + int error = vfs_fstat(fd, &stat); - f = fget(fd); - if (f) { - struct dentry * dentry = f->f_dentry; + if (!error) + error = cp_new_stat(&stat, statbuf); - err = do_revalidate(dentry); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); - } - return err; + return error; } asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz) @@ -270,110 +278,59 @@ asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz) /* ---------- LFS-64 ----------- */ #if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X) -static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf) +static long cp_new_stat64(struct kstat *stat, struct stat64 *statbuf) { struct stat64 tmp; - unsigned int blocks, indirect; memset(&tmp, 0, sizeof(tmp)); - tmp.st_dev = kdev_t_to_nr(inode->i_dev); - tmp.st_ino = inode->i_ino; + tmp.st_dev = stat->dev; + tmp.st_ino = stat->ino; #ifdef STAT64_HAS_BROKEN_ST_INO - tmp.__st_ino = inode->i_ino; + tmp.__st_ino = stat->ino; #endif - tmp.st_mode = inode->i_mode; - tmp.st_nlink = inode->i_nlink; - tmp.st_uid = inode->i_uid; - tmp.st_gid = inode->i_gid; - tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); - tmp.st_atime = inode->i_atime; - tmp.st_mtime = inode->i_mtime; - tmp.st_ctime = inode->i_ctime; - tmp.st_size = inode->i_size; -/* - * st_blocks and st_blksize are approximated with a simple algorithm if - * they aren't supported directly by the filesystem. The minix and msdos - * filesystems don't keep track of blocks, so they would either have to - * be counted explicitly (by delving into the file itself), or by using - * this simple algorithm to get a reasonable (although not 100% accurate) - * value. - */ - -/* - * Use minix fs values for the number of direct and indirect blocks. The - * count is now exact for the minix fs except that it counts zero blocks. - * Everything is in units of BLOCK_SIZE until the assignment to - * tmp.st_blksize. - */ -#define D_B 7 -#define I_B (BLOCK_SIZE / sizeof(unsigned short)) - - if (!inode->i_blksize) { - blocks = (tmp.st_size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; - if (blocks > D_B) { - indirect = (blocks - D_B + I_B - 1) / I_B; - blocks += indirect; - if (indirect > 1) { - indirect = (indirect - 1 + I_B - 1) / I_B; - blocks += indirect; - if (indirect > 1) - blocks++; - } - } - tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; - tmp.st_blksize = BLOCK_SIZE; - } else { - tmp.st_blocks = inode->i_blocks; - tmp.st_blksize = inode->i_blksize; - } + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + tmp.st_uid = stat->uid; + tmp.st_gid = stat->gid; + tmp.st_rdev = stat->rdev; + tmp.st_atime = stat->atime; + tmp.st_mtime = stat->mtime; + tmp.st_ctime = stat->ctime; + tmp.st_size = stat->size; + tmp.st_blocks = stat->blocks; + tmp.st_blksize = stat->blksize; return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags) { - struct nameidata nd; - int error; + struct kstat stat; + int error = vfs_stat(filename, &stat); + + if (!error) + error = cp_new_stat64(&stat, statbuf); - error = user_path_walk(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); - path_release(&nd); - } return error; } - asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags) { - struct nameidata nd; - int error; + struct kstat stat; + int error = vfs_lstat(filename, &stat); + + if (!error) + error = cp_new_stat64(&stat, statbuf); - error = user_path_walk_link(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); - path_release(&nd); - } return error; } - asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags) { - struct file * f; - int err = -EBADF; + struct kstat stat; + int error = vfs_fstat(fd, &stat); - f = fget(fd); - if (f) { - struct dentry * dentry = f->f_dentry; + if (!error) + error = cp_new_stat64(&stat, statbuf); - err = do_revalidate(dentry); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); - } - return err; + return error; } #endif /* LFS-64 */ diff --git a/fs/super.c b/fs/super.c index fb70602790ae..f9f6a9802ad4 100644 --- a/fs/super.c +++ b/fs/super.c @@ -641,8 +641,9 @@ retry: return s; } -static struct super_block *get_sb_bdev(struct file_system_type *fs_type, - int flags, char *dev_name, void * data) +struct super_block *get_sb_bdev(struct file_system_type *fs_type, + int flags, char *dev_name, void * data, + int (*fill_super)(struct super_block *, void *, int)) { struct inode *inode; struct block_device *bdev; @@ -698,7 +699,7 @@ restart: list_for_each(p, &super_blocks) { struct super_block *old = sb_entry(p); - if (!kdev_same(old->s_dev, dev)) + if (old->s_bdev != bdev) continue; if (old->s_type != fs_type || ((flags ^ old->s_flags) & MS_RDONLY)) { @@ -718,8 +719,8 @@ restart: s->s_flags = flags; insert_super(s, fs_type); strncpy(s->s_id, bdevname(dev), sizeof(s->s_id)); - error = -EINVAL; - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); + if (error) goto failed; s->s_flags |= MS_ACTIVE; path_release(&nd); @@ -736,19 +737,23 @@ out: return ERR_PTR(error); } -static struct super_block *get_sb_nodev(struct file_system_type *fs_type, - int flags, char *dev_name, void *data) +struct super_block *get_sb_nodev(struct file_system_type *fs_type, + int flags, void *data, + int (*fill_super)(struct super_block *, void *, int)) { + int error; struct super_block *s = get_anon_super(fs_type, NULL, NULL); if (IS_ERR(s)) return s; s->s_flags = flags; - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) { + + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); + if (error) { deactivate_super(s); remove_super(s); - return ERR_PTR(-EINVAL); + return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; return s; @@ -759,19 +764,22 @@ static int compare_single(struct super_block *s, void *p) return 1; } -static struct super_block *get_sb_single(struct file_system_type *fs_type, - int flags, char *dev_name, void *data) +struct super_block *get_sb_single(struct file_system_type *fs_type, + int flags, void *data, + int (*fill_super)(struct super_block *, void *, int)) { + int error; struct super_block *s = get_anon_super(fs_type, compare_single, NULL); if (IS_ERR(s)) return s; if (!s->s_root) { s->s_flags = flags; - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) { + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); + if (error) { deactivate_super(s); remove_super(s); - return ERR_PTR(-EINVAL); + return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; } @@ -779,6 +787,22 @@ static struct super_block *get_sb_single(struct file_system_type *fs_type, return s; } +/* Will go away */ +static int fill_super(struct super_block *sb, void *data, int verbose) +{ + return sb->s_type->read_super(sb, data, verbose) ? 0 : -EINVAL; +} +static struct super_block *__get_sb_bdev(struct file_system_type *fs_type, + int flags, char *dev_name, void * data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, fill_super); +} +static struct super_block *__get_sb_nodev(struct file_system_type *fs_type, + int flags, char *dev_name, void * data) +{ + return get_sb_nodev(fs_type, flags, data, fill_super); +} + struct vfsmount * do_kern_mount(const char *fstype, int flags, char *name, void *data) { @@ -792,12 +816,12 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data) mnt = alloc_vfsmnt(name); if (!mnt) goto out; - if (type->fs_flags & FS_REQUIRES_DEV) - sb = get_sb_bdev(type, flags, name, data); - else if (type->fs_flags & FS_SINGLE) - sb = get_sb_single(type, flags, name, data); + if (type->get_sb) + sb = type->get_sb(type, flags, name, data); + else if (type->fs_flags & FS_REQUIRES_DEV) + sb = __get_sb_bdev(type, flags, name, data); else - sb = get_sb_nodev(type, flags, name, data); + sb = __get_sb_nodev(type, flags, name, data); if (IS_ERR(sb)) goto out_mnt; if (type->fs_flags & FS_NOMOUNT) diff --git a/fs/udf/super.c b/fs/udf/super.c index a4984734a384..cf78cf53cc76 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1544,7 +1544,7 @@ udf_read_super(struct super_block *sb, void *options, int silent) iput(inode); goto error_out; } - sb->s_maxbytes = ~0ULL; + sb->s_maxbytes = MAX_LFS_FILESIZE; return sb; error_out: diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 7af092555ad0..819e6945b112 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c @@ -38,46 +38,12 @@ #include <linux/smp_lock.h> /* - * Make sure the offset never goes beyond the 32-bit mark.. - */ -static long long ufs_file_lseek( - struct file *file, - long long offset, - int origin ) -{ - long long retval; - struct inode *inode = file->f_dentry->d_inode; - - lock_kernel(); - - switch (origin) { - case 2: - offset += inode->i_size; - break; - case 1: - offset += file->f_pos; - } - retval = -EINVAL; - /* make sure the offset fits in 32 bits */ - if (((unsigned long long) offset >> 32) == 0) { - if (offset != file->f_pos) { - file->f_pos = offset; - file->f_reada = 0; - file->f_version = ++event; - } - retval = offset; - } - unlock_kernel(); - return retval; -} - -/* * We have mostly NULL's here: the current defaults are ok for * the ufs filesystem. */ struct file_operations ufs_file_operations = { - llseek: ufs_file_lseek, + llseek: generic_file_llseek, read: generic_file_read, write: generic_file_write, mmap: generic_file_mmap, |
