X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=fs%2Ffile_table.c;h=3176fefc92e139771a9c9065524c26e8e437e7fa;hb=c548f08a4f7b89b93c805e0c4024b8302afa7121;hp=bc35a40417d7ada53223f5c93ed26875af97a646;hpb=3b9f6cb8a1ec791be79c6c7595fea922f12d1e64;p=deliverable%2Flinux.git diff --git a/fs/file_table.c b/fs/file_table.c index bc35a40417d7..3176fefc92e1 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -99,16 +98,15 @@ struct file *get_empty_filp(void) * percpu_counters are inaccurate. Do an expensive check before * we go and fail. */ - if (percpu_counter_sum(&nr_files) >= files_stat.max_files) + if (percpu_counter_sum_positive(&nr_files) >= files_stat.max_files) goto over; } - f = kmem_cache_alloc(filp_cachep, GFP_KERNEL); + f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL); if (f == NULL) goto fail; percpu_counter_inc(&nr_files); - memset(f, 0, sizeof(*f)); if (security_file_alloc(f)) goto fail_sec; @@ -139,6 +137,66 @@ fail: EXPORT_SYMBOL(get_empty_filp); +/** + * alloc_file - allocate and initialize a 'struct file' + * @mnt: the vfsmount on which the file will reside + * @dentry: the dentry representing the new file + * @mode: the mode with which the new file will be opened + * @fop: the 'struct file_operations' for the new file + * + * Use this instead of get_empty_filp() to get a new + * 'struct file'. Do so because of the same initialization + * pitfalls reasons listed for init_file(). This is a + * preferred interface to using init_file(). + * + * If all the callers of init_file() are eliminated, its + * code should be moved into this function. + */ +struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry, + mode_t mode, const struct file_operations *fop) +{ + struct file *file; + struct path; + + file = get_empty_filp(); + if (!file) + return NULL; + + init_file(file, mnt, dentry, mode, fop); + return file; +} +EXPORT_SYMBOL(alloc_file); + +/** + * init_file - initialize a 'struct file' + * @file: the already allocated 'struct file' to initialized + * @mnt: the vfsmount on which the file resides + * @dentry: the dentry representing this file + * @mode: the mode the file is opened with + * @fop: the 'struct file_operations' for this file + * + * Use this instead of setting the members directly. Doing so + * avoids making mistakes like forgetting the mntget() or + * forgetting to take a write on the mnt. + * + * Note: This is a crappy interface. It is here to make + * merging with the existing users of get_empty_filp() + * who have complex failure logic easier. All users + * of this should be moving to alloc_file(). + */ +int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry, + mode_t mode, const struct file_operations *fop) +{ + int error = 0; + file->f_path.dentry = dentry; + file->f_path.mnt = mntget(mnt); + file->f_mapping = dentry->d_inode->i_mapping; + file->f_mode = mode; + file->f_op = fop; + return error; +} +EXPORT_SYMBOL(init_file); + void fastcall fput(struct file *file) { if (atomic_dec_and_test(&file->f_count)) @@ -152,8 +210,8 @@ EXPORT_SYMBOL(fput); */ void fastcall __fput(struct file *file) { - struct dentry *dentry = file->f_dentry; - struct vfsmount *mnt = file->f_vfsmnt; + struct dentry *dentry = file->f_path.dentry; + struct vfsmount *mnt = file->f_path.mnt; struct inode *inode = dentry->d_inode; might_sleep(); @@ -174,9 +232,10 @@ void fastcall __fput(struct file *file) fops_put(file->f_op); if (file->f_mode & FMODE_WRITE) put_write_access(inode); + put_pid(file->f_owner.pid); file_kill(file); - file->f_dentry = NULL; - file->f_vfsmnt = NULL; + file->f_path.dentry = NULL; + file->f_path.mnt = NULL; file_free(file); dput(dentry); mntput(mnt); @@ -270,7 +329,7 @@ int fs_may_remount_ro(struct super_block *sb) file_list_lock(); list_for_each(p, &sb->s_files) { struct file *file = list_entry(p, struct file, f_u.fu_list); - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; /* File with pending delete? */ if (inode->i_nlink == 0)