diff options
Diffstat (limited to 'fs/ext2')
| -rw-r--r-- | fs/ext2/ext2.h | 9 | ||||
| -rw-r--r-- | fs/ext2/ialloc.c | 6 | ||||
| -rw-r--r-- | fs/ext2/inode.c | 2 | ||||
| -rw-r--r-- | fs/ext2/super.c | 83 | ||||
| -rw-r--r-- | fs/ext2/symlink.c | 4 | ||||
| -rw-r--r-- | fs/ext2/xattr.c | 2 | ||||
| -rw-r--r-- | fs/ext2/xattr.h | 8 | ||||
| -rw-r--r-- | fs/ext2/xattr_security.c | 22 | ||||
| -rw-r--r-- | fs/ext2/xip.c | 81 |
9 files changed, 170 insertions, 47 deletions
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index eed521d22cf0..e977f8566d14 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -2,6 +2,15 @@ #include <linux/ext2_fs.h> /* + * ext2 mount options + */ +struct ext2_mount_options { + unsigned long s_mount_opt; + uid_t s_resuid; + gid_t s_resgid; +}; + +/* * second extended file system inode data in memory */ struct ext2_inode_info { diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 77e059149212..c8d07030c897 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -612,6 +612,12 @@ got: err = ext2_init_acl(inode, dir); if (err) { DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); + goto fail2; + } + err = ext2_init_security(inode,dir); + if (err) { + DQUOT_FREE_INODE(inode); goto fail2; } mark_inode_dirty(inode); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 53dceb0c6593..fdba4d1d3c60 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -71,6 +71,8 @@ void ext2_put_inode(struct inode *inode) */ void ext2_delete_inode (struct inode * inode) { + truncate_inode_pages(&inode->i_data, 0); + if (is_bad_inode(inode)) goto no_delete; EXT2_I(inode)->i_dtime = get_seconds(); diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 876e391f2871..3c0c7c6a5b44 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -19,6 +19,7 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/string.h> +#include <linux/fs.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/blkdev.h> @@ -27,6 +28,8 @@ #include <linux/buffer_head.h> #include <linux/smp_lock.h> #include <linux/vfs.h> +#include <linux/seq_file.h> +#include <linux/mount.h> #include <asm/uaccess.h> #include "ext2.h" #include "xattr.h" @@ -201,6 +204,26 @@ static void ext2_clear_inode(struct inode *inode) #endif } +static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs) +{ + struct ext2_sb_info *sbi = EXT2_SB(vfs->mnt_sb); + + if (sbi->s_mount_opt & EXT2_MOUNT_GRPID) + seq_puts(seq, ",grpid"); + else + seq_puts(seq, ",nogrpid"); + +#if defined(CONFIG_QUOTA) + if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA) + seq_puts(seq, ",usrquota"); + + if (sbi->s_mount_opt & EXT2_MOUNT_GRPQUOTA) + seq_puts(seq, ",grpquota"); +#endif + + return 0; +} + #ifdef CONFIG_QUOTA static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off); static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); @@ -218,6 +241,7 @@ static struct super_operations ext2_sops = { .statfs = ext2_statfs, .remount_fs = ext2_remount, .clear_inode = ext2_clear_inode, + .show_options = ext2_show_options, #ifdef CONFIG_QUOTA .quota_read = ext2_quota_read, .quota_write = ext2_quota_write, @@ -256,10 +280,11 @@ static unsigned long get_sb_block(void **data) enum { Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, - Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, - Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, - Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip, - Opt_ignore, Opt_err, + Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, + Opt_err_ro, Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, + Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr, + Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota, + Opt_usrquota, Opt_grpquota }; static match_table_t tokens = { @@ -288,10 +313,10 @@ static match_table_t tokens = { {Opt_acl, "acl"}, {Opt_noacl, "noacl"}, {Opt_xip, "xip"}, - {Opt_ignore, "grpquota"}, + {Opt_grpquota, "grpquota"}, {Opt_ignore, "noquota"}, - {Opt_ignore, "quota"}, - {Opt_ignore, "usrquota"}, + {Opt_quota, "quota"}, + {Opt_usrquota, "usrquota"}, {Opt_err, NULL} }; @@ -406,6 +431,26 @@ static int parse_options (char * options, printk("EXT2 xip option not supported\n"); #endif break; + +#if defined(CONFIG_QUOTA) + case Opt_quota: + case Opt_usrquota: + set_opt(sbi->s_mount_opt, USRQUOTA); + break; + + case Opt_grpquota: + set_opt(sbi->s_mount_opt, GRPQUOTA); + break; +#else + case Opt_quota: + case Opt_usrquota: + case Opt_grpquota: + printk(KERN_ERR + "EXT2-fs: quota operations not supported.\n"); + + break; +#endif + case Opt_ignore: break; default: @@ -936,12 +981,23 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) struct ext2_sb_info * sbi = EXT2_SB(sb); struct ext2_super_block * es; unsigned long old_mount_opt = sbi->s_mount_opt; + struct ext2_mount_options old_opts; + unsigned long old_sb_flags; + int err; + + /* Store the old options */ + old_sb_flags = sb->s_flags; + old_opts.s_mount_opt = sbi->s_mount_opt; + old_opts.s_resuid = sbi->s_resuid; + old_opts.s_resgid = sbi->s_resgid; /* * Allow the "check" option to be passed as a remount option. */ - if (!parse_options (data, sbi)) - return -EINVAL; + if (!parse_options (data, sbi)) { + err = -EINVAL; + goto restore_opts; + } sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); @@ -971,7 +1027,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) printk("EXT2-fs: %s: couldn't remount RDWR because of " "unsupported optional features (%x).\n", sb->s_id, le32_to_cpu(ret)); - return -EROFS; + err = -EROFS; + goto restore_opts; } /* * Mounting a RDONLY partition read-write, so reread and @@ -984,6 +1041,12 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) } ext2_sync_super(sb, es); return 0; +restore_opts: + sbi->s_mount_opt = old_opts.s_mount_opt; + sbi->s_resuid = old_opts.s_resuid; + sbi->s_resgid = old_opts.s_resgid; + sb->s_flags = old_sb_flags; + return err; } static int ext2_statfs (struct super_block * sb, struct kstatfs * buf) diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 9f7bac01d557..1e67d87cfa91 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -21,11 +21,11 @@ #include "xattr.h" #include <linux/namei.h> -static int ext2_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct ext2_inode_info *ei = EXT2_I(dentry->d_inode); nd_set_link(nd, (char *)ei->i_data); - return 0; + return NULL; } struct inode_operations ext2_symlink_inode_operations = { diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 27982b500e84..0099462d4271 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -823,7 +823,7 @@ cleanup: void ext2_xattr_put_super(struct super_block *sb) { - mb_cache_shrink(ext2_xattr_cache, sb->s_bdev); + mb_cache_shrink(sb->s_bdev); } diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h index 5f3bfde3b810..67cfeb66e897 100644 --- a/fs/ext2/xattr.h +++ b/fs/ext2/xattr.h @@ -116,3 +116,11 @@ exit_ext2_xattr(void) # endif /* CONFIG_EXT2_FS_XATTR */ +#ifdef CONFIG_EXT2_FS_SECURITY +extern int ext2_init_security(struct inode *inode, struct inode *dir); +#else +static inline int ext2_init_security(struct inode *inode, struct inode *dir) +{ + return 0; +} +#endif diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index 6a6c59fbe599..a26612798471 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c @@ -8,6 +8,7 @@ #include <linux/fs.h> #include <linux/smp_lock.h> #include <linux/ext2_fs.h> +#include <linux/security.h> #include "xattr.h" static size_t @@ -45,6 +46,27 @@ ext2_xattr_security_set(struct inode *inode, const char *name, value, size, flags); } +int +ext2_init_security(struct inode *inode, struct inode *dir) +{ + int err; + size_t len; + void *value; + char *name; + + err = security_inode_init_security(inode, dir, &name, &value, &len); + if (err) { + if (err == -EOPNOTSUPP) + return 0; + return err; + } + err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, + name, value, len, 0); + kfree(name); + kfree(value); + return err; +} + struct xattr_handler ext2_xattr_security_handler = { .prefix = XATTR_SECURITY_PREFIX, .list = ext2_xattr_security_list, diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index d44431d1a338..ca7f00312388 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c @@ -15,66 +15,79 @@ #include "xip.h" static inline int -__inode_direct_access(struct inode *inode, sector_t sector, unsigned long *data) { +__inode_direct_access(struct inode *inode, sector_t sector, + unsigned long *data) +{ BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access); return inode->i_sb->s_bdev->bd_disk->fops ->direct_access(inode->i_sb->s_bdev,sector,data); } +static inline int +__ext2_get_sector(struct inode *inode, sector_t offset, int create, + sector_t *result) +{ + struct buffer_head tmp; + int rc; + + memset(&tmp, 0, sizeof(struct buffer_head)); + rc = ext2_get_block(inode, offset/ (PAGE_SIZE/512), &tmp, + create); + *result = tmp.b_blocknr; + + /* did we get a sparse block (hole in the file)? */ + if (!tmp.b_blocknr && !rc) { + BUG_ON(create); + rc = -ENODATA; + } + + return rc; +} + int -ext2_clear_xip_target(struct inode *inode, int block) { - sector_t sector = block*(PAGE_SIZE/512); +ext2_clear_xip_target(struct inode *inode, int block) +{ + sector_t sector = block * (PAGE_SIZE/512); unsigned long data; int rc; rc = __inode_direct_access(inode, sector, &data); - if (rc) - return rc; - clear_page((void*)data); - return 0; + if (!rc) + clear_page((void*)data); + return rc; } void ext2_xip_verify_sb(struct super_block *sb) { struct ext2_sb_info *sbi = EXT2_SB(sb); - if ((sbi->s_mount_opt & EXT2_MOUNT_XIP)) { - if ((sb->s_bdev == NULL) || - sb->s_bdev->bd_disk == NULL || - sb->s_bdev->bd_disk->fops == NULL || - sb->s_bdev->bd_disk->fops->direct_access == NULL) { - sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); - ext2_warning(sb, __FUNCTION__, - "ignoring xip option - not supported by bdev"); - } + if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) && + !sb->s_bdev->bd_disk->fops->direct_access) { + sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); + ext2_warning(sb, __FUNCTION__, + "ignoring xip option - not supported by bdev"); } } -struct page* -ext2_get_xip_page(struct address_space *mapping, sector_t blockno, +struct page * +ext2_get_xip_page(struct address_space *mapping, sector_t offset, int create) { int rc; unsigned long data; - struct buffer_head tmp; + sector_t sector; - tmp.b_state = 0; - tmp.b_blocknr = 0; - rc = ext2_get_block(mapping->host, blockno/(PAGE_SIZE/512) , &tmp, - create); + /* first, retrieve the sector number */ + rc = __ext2_get_sector(mapping->host, offset, create, §or); if (rc) - return ERR_PTR(rc); - if (tmp.b_blocknr == 0) { - /* SPARSE block */ - BUG_ON(create); - return ERR_PTR(-ENODATA); - } + goto error; + /* retrieve address of the target data */ rc = __inode_direct_access - (mapping->host,tmp.b_blocknr*(PAGE_SIZE/512) ,&data); - if (rc) - return ERR_PTR(rc); + (mapping->host, sector * (PAGE_SIZE/512), &data); + if (!rc) + return virt_to_page(data); - SetPageUptodate(virt_to_page(data)); - return virt_to_page(data); + error: + return ERR_PTR(rc); } |
