summaryrefslogtreecommitdiffstats
path: root/fs/ramfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ramfs')
-rw-r--r--fs/ramfs/file-nommu.c21
-rw-r--r--fs/ramfs/inode.c94
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",
OpenPOWER on IntegriCloud