diff options
Diffstat (limited to 'fs/ramfs')
-rw-r--r-- | fs/ramfs/file-nommu.c | 21 | ||||
-rw-r--r-- | fs/ramfs/inode.c | 94 |
2 files changed, 90 insertions, 25 deletions
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 5d7c7ececa64..ebb2c417912c 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -18,7 +18,6 @@ #include <linux/string.h> #include <linux/backing-dev.h> #include <linux/ramfs.h> -#include <linux/quotaops.h> #include <linux/pagevec.h> #include <linux/mman.h> @@ -60,7 +59,6 @@ const struct inode_operations ramfs_file_inode_operations = { */ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) { - struct pagevec lru_pvec; unsigned long npages, xpages, loop, limit; struct page *pages; unsigned order; @@ -103,24 +101,20 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) memset(data, 0, newsize); /* attach all the pages to the inode's address space */ - pagevec_init(&lru_pvec, 0); for (loop = 0; loop < npages; loop++) { struct page *page = pages + loop; - ret = add_to_page_cache(page, inode->i_mapping, loop, GFP_KERNEL); + ret = add_to_page_cache_lru(page, inode->i_mapping, loop, + GFP_KERNEL); if (ret < 0) goto add_error; - if (!pagevec_add(&lru_pvec, page)) - __pagevec_lru_add_file(&lru_pvec); - /* prevent the page from being discarded on memory pressure */ SetPageDirty(page); unlock_page(page); } - pagevec_lru_add_file(&lru_pvec); return 0; fsize_exceeded: @@ -129,10 +123,8 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) return -EFBIG; add_error: - pagevec_lru_add_file(&lru_pvec); - page_cache_release(pages + loop); - for (loop++; loop < npages; loop++) - __free_page(pages + loop); + while (loop < npages) + __free_page(pages + loop++); return ret; } @@ -205,11 +197,6 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) if (ret) return ret; - /* by providing our own setattr() method, we skip this quotaism */ - if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) || - (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid)) - ret = DQUOT_TRANSFER(inode, ia) ? -EDQUOT : 0; - /* pick out size-changing events */ if (ia->ia_valid & ATTR_SIZE) { loff_t size = i_size_read(inode); diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index b7e6ac706b87..a404fb88e456 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -33,12 +33,15 @@ #include <linux/backing-dev.h> #include <linux/ramfs.h> #include <linux/sched.h> +#include <linux/parser.h> #include <asm/uaccess.h> #include "internal.h" /* some random number */ #define RAMFS_MAGIC 0x858458f6 +#define RAMFS_DEFAULT_MODE 0755 + static const struct super_operations ramfs_ops; static const struct inode_operations ramfs_dir_inode_operations; @@ -158,12 +161,75 @@ static const struct inode_operations ramfs_dir_inode_operations = { static const struct super_operations ramfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, + .show_options = generic_show_options, +}; + +struct ramfs_mount_opts { + umode_t mode; +}; + +enum { + Opt_mode, + Opt_err +}; + +static const match_table_t tokens = { + {Opt_mode, "mode=%o"}, + {Opt_err, NULL} +}; + +struct ramfs_fs_info { + struct ramfs_mount_opts mount_opts; }; +static int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts) +{ + substring_t args[MAX_OPT_ARGS]; + int option; + int token; + char *p; + + opts->mode = RAMFS_DEFAULT_MODE; + + while ((p = strsep(&data, ",")) != NULL) { + if (!*p) + continue; + + token = match_token(p, tokens, args); + switch (token) { + case Opt_mode: + if (match_octal(&args[0], &option)) + return -EINVAL; + opts->mode = option & S_IALLUGO; + break; + default: + printk(KERN_ERR "ramfs: bad mount option: %s\n", p); + return -EINVAL; + } + } + + return 0; +} + static int ramfs_fill_super(struct super_block * sb, void * data, int silent) { - struct inode * inode; - struct dentry * root; + struct ramfs_fs_info *fsi; + struct inode *inode = NULL; + struct dentry *root; + int err; + + save_mount_options(sb, data); + + fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); + if (!fsi) { + err = -ENOMEM; + goto fail; + } + sb->s_fs_info = fsi; + + err = ramfs_parse_options(data, &fsi->mount_opts); + if (err) + goto fail; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = PAGE_CACHE_SIZE; @@ -171,17 +237,23 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) sb->s_magic = RAMFS_MAGIC; sb->s_op = &ramfs_ops; sb->s_time_gran = 1; - inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0); - if (!inode) - return -ENOMEM; + inode = ramfs_get_inode(sb, S_IFDIR | fsi->mount_opts.mode, 0); + if (!inode) { + err = -ENOMEM; + goto fail; + } root = d_alloc_root(inode); if (!root) { - iput(inode); - return -ENOMEM; + err = -ENOMEM; + goto fail; } sb->s_root = root; return 0; +fail: + kfree(fsi); + iput(inode); + return err; } int ramfs_get_sb(struct file_system_type *fs_type, @@ -197,10 +269,16 @@ static int rootfs_get_sb(struct file_system_type *fs_type, mnt); } +static void ramfs_kill_sb(struct super_block *sb) +{ + kfree(sb->s_fs_info); + kill_litter_super(sb); +} + static struct file_system_type ramfs_fs_type = { .name = "ramfs", .get_sb = ramfs_get_sb, - .kill_sb = kill_litter_super, + .kill_sb = ramfs_kill_sb, }; static struct file_system_type rootfs_fs_type = { .name = "rootfs", |