diff options
Diffstat (limited to 'fs/omfs/inode.c')
| -rw-r--r-- | fs/omfs/inode.c | 97 |
1 files changed, 64 insertions, 33 deletions
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index f3b7c1541f3..ec58c765918 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c @@ -3,14 +3,15 @@ * Copyright (C) 2006 Bob Copeland <me@bobcopeland.com> * Released under GPL v2. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/sched.h> +#include <linux/slab.h> #include <linux/fs.h> #include <linux/vfs.h> #include <linux/parser.h> #include <linux/buffer_head.h> #include <linux/vmalloc.h> +#include <linux/writeback.h> #include <linux/crc-itu-t.h> #include "omfs.h" @@ -18,7 +19,16 @@ MODULE_AUTHOR("Bob Copeland <me@bobcopeland.com>"); MODULE_DESCRIPTION("OMFS (ReplayTV/Karma) Filesystem for Linux"); MODULE_LICENSE("GPL"); -struct inode *omfs_new_inode(struct inode *dir, int mode) +struct buffer_head *omfs_bread(struct super_block *sb, sector_t block) +{ + struct omfs_sb_info *sbi = OMFS_SB(sb); + if (block >= sbi->s_num_blocks) + return NULL; + + return sb_bread(sb, clus_to_blk(sbi, block)); +} + +struct inode *omfs_new_inode(struct inode *dir, umode_t mode) { struct inode *inode; u64 new_block; @@ -36,9 +46,7 @@ struct inode *omfs_new_inode(struct inode *dir, int mode) goto fail; inode->i_ino = new_block; - inode->i_mode = mode; - inode->i_uid = current_fsuid(); - inode->i_gid = current_fsgid(); + inode_init_owner(inode, NULL, mode); inode->i_mapping->a_ops = &omfs_aops; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; @@ -89,20 +97,18 @@ static void omfs_update_checksums(struct omfs_inode *oi) oi->i_head.h_check_xor = xor; } -static int omfs_write_inode(struct inode *inode, int wait) +static int __omfs_write_inode(struct inode *inode, int wait) { struct omfs_inode *oi; struct omfs_sb_info *sbi = OMFS_SB(inode->i_sb); struct buffer_head *bh, *bh2; - unsigned int block; u64 ctime; int i; int ret = -EIO; int sync_failed = 0; /* get current inode since we may have written sibling ptrs etc. */ - block = clus_to_blk(sbi, inode->i_ino); - bh = sb_bread(inode->i_sb, block); + bh = omfs_bread(inode->i_sb, inode->i_ino); if (!bh) goto out; @@ -141,8 +147,7 @@ static int omfs_write_inode(struct inode *inode, int wait) /* if mirroring writes, copy to next fsblock */ for (i = 1; i < sbi->s_mirrors; i++) { - bh2 = sb_bread(inode->i_sb, block + i * - (sbi->s_blocksize / sbi->s_sys_blocksize)); + bh2 = omfs_bread(inode->i_sb, inode->i_ino + i); if (!bh2) goto out_brelse; @@ -162,18 +167,27 @@ out: return ret; } +static int omfs_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + return __omfs_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); +} + int omfs_sync_inode(struct inode *inode) { - return omfs_write_inode(inode, 1); + return __omfs_write_inode(inode, 1); } /* * called when an entry is deleted, need to clear the bits in the * bitmaps. */ -static void omfs_delete_inode(struct inode *inode) +static void omfs_evict_inode(struct inode *inode) { - truncate_inode_pages(&inode->i_data, 0); + truncate_inode_pages_final(&inode->i_data); + clear_inode(inode); + + if (inode->i_nlink) + return; if (S_ISREG(inode->i_mode)) { inode->i_size = 0; @@ -181,7 +195,6 @@ static void omfs_delete_inode(struct inode *inode) } omfs_clear_range(inode->i_sb, inode->i_ino, 2); - clear_inode(inode); } struct inode *omfs_iget(struct super_block *sb, ino_t ino) @@ -189,7 +202,6 @@ struct inode *omfs_iget(struct super_block *sb, ino_t ino) struct omfs_sb_info *sbi = OMFS_SB(sb); struct omfs_inode *oi; struct buffer_head *bh; - unsigned int block; u64 ctime; unsigned long nsecs; struct inode *inode; @@ -200,8 +212,7 @@ struct inode *omfs_iget(struct super_block *sb, ino_t ino) if (!(inode->i_state & I_NEW)) return inode; - block = clus_to_blk(sbi, ino); - bh = sb_bread(inode->i_sb, block); + bh = omfs_bread(inode->i_sb, ino); if (!bh) goto iget_failed; @@ -280,7 +291,7 @@ static int omfs_statfs(struct dentry *dentry, struct kstatfs *buf) static const struct super_operations omfs_sops = { .write_inode = omfs_write_inode, - .delete_inode = omfs_delete_inode, + .evict_inode = omfs_evict_inode, .put_super = omfs_put_super, .statfs = omfs_statfs, .show_options = generic_show_options, @@ -315,6 +326,9 @@ static int omfs_get_imap(struct super_block *sb) goto nomem; block = clus_to_blk(sbi, sbi->s_bitmap_ino); + if (block >= sbi->s_num_blocks) + goto nomem; + ptr = sbi->s_imap; for (count = bitmap_size; count > 0; count -= sb->s_blocksize) { bh = sb_bread(sb, block++); @@ -377,12 +391,16 @@ static int parse_options(char *options, struct omfs_sb_info *sbi) case Opt_uid: if (match_int(&args[0], &option)) return 0; - sbi->s_uid = option; + sbi->s_uid = make_kuid(current_user_ns(), option); + if (!uid_valid(sbi->s_uid)) + return 0; break; case Opt_gid: if (match_int(&args[0], &option)) return 0; - sbi->s_gid = option; + sbi->s_gid = make_kgid(current_user_ns(), option); + if (!gid_valid(sbi->s_gid)) + return 0; break; case Opt_umask: if (match_octal(&args[0], &option)) @@ -413,7 +431,6 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) struct omfs_root_block *omfs_rb; struct omfs_sb_info *sbi; struct inode *root; - sector_t start; int ret = -EINVAL; save_mount_options(sb, (char *) data); @@ -482,8 +499,7 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) sbi->s_block_shift = get_bitmask_order(sbi->s_blocksize) - get_bitmask_order(sbi->s_sys_blocksize); - start = clus_to_blk(sbi, be64_to_cpu(omfs_sb->s_root_block)); - bh2 = sb_bread(sb, start); + bh2 = omfs_bread(sb, be64_to_cpu(omfs_sb->s_root_block)); if (!bh2) goto out_brelse_bh; @@ -500,6 +516,21 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) goto out_brelse_bh2; } + if (sbi->s_bitmap_ino != ~0ULL && + sbi->s_bitmap_ino > sbi->s_num_blocks) { + printk(KERN_ERR "omfs: free space bitmap location is corrupt " + "(%llx, total blocks %llx)\n", + (unsigned long long) sbi->s_bitmap_ino, + (unsigned long long) sbi->s_num_blocks); + goto out_brelse_bh2; + } + if (sbi->s_clustersize < 1 || + sbi->s_clustersize > OMFS_MAX_CLUSTER_SIZE) { + printk(KERN_ERR "omfs: cluster size out of range (%d)", + sbi->s_clustersize); + goto out_brelse_bh2; + } + ret = omfs_get_imap(sb); if (ret) goto out_brelse_bh2; @@ -512,11 +543,9 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) goto out_brelse_bh2; } - sb->s_root = d_alloc_root(root); - if (!sb->s_root) { - iput(root); + sb->s_root = d_make_root(root); + if (!sb->s_root) goto out_brelse_bh2; - } printk(KERN_DEBUG "omfs: Mounted volume %s\n", omfs_rb->r_name); ret = 0; @@ -525,23 +554,25 @@ out_brelse_bh2: out_brelse_bh: brelse(bh); end: + if (ret) + kfree(sbi); return ret; } -static int omfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data, struct vfsmount *m) +static struct dentry *omfs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) { - return get_sb_bdev(fs_type, flags, dev_name, data, omfs_fill_super, m); + return mount_bdev(fs_type, flags, dev_name, data, omfs_fill_super); } static struct file_system_type omfs_fs_type = { .owner = THIS_MODULE, .name = "omfs", - .get_sb = omfs_get_sb, + .mount = omfs_mount, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; +MODULE_ALIAS_FS("omfs"); static int __init init_omfs_fs(void) { |
