diff options
Diffstat (limited to 'fs/ext2/super.c')
-rw-r--r-- | fs/ext2/super.c | 122 |
1 files changed, 111 insertions, 11 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 639a32c3c9c..77bd5f9262f 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/vfs.h> | 30 | #include <linux/vfs.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/mount.h> | 32 | #include <linux/mount.h> |
33 | #include <linux/log2.h> | ||
33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
34 | #include "ext2.h" | 35 | #include "ext2.h" |
35 | #include "xattr.h" | 36 | #include "xattr.h" |
@@ -148,6 +149,7 @@ static struct inode *ext2_alloc_inode(struct super_block *sb) | |||
148 | ei->i_acl = EXT2_ACL_NOT_CACHED; | 149 | ei->i_acl = EXT2_ACL_NOT_CACHED; |
149 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; | 150 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; |
150 | #endif | 151 | #endif |
152 | ei->i_block_alloc_info = NULL; | ||
151 | ei->vfs_inode.i_version = 1; | 153 | ei->vfs_inode.i_version = 1; |
152 | return &ei->vfs_inode; | 154 | return &ei->vfs_inode; |
153 | } | 155 | } |
@@ -157,7 +159,7 @@ static void ext2_destroy_inode(struct inode *inode) | |||
157 | kmem_cache_free(ext2_inode_cachep, EXT2_I(inode)); | 159 | kmem_cache_free(ext2_inode_cachep, EXT2_I(inode)); |
158 | } | 160 | } |
159 | 161 | ||
160 | static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) | 162 | static void init_once(struct kmem_cache * cachep, void *foo) |
161 | { | 163 | { |
162 | struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; | 164 | struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; |
163 | 165 | ||
@@ -165,6 +167,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag | |||
165 | #ifdef CONFIG_EXT2_FS_XATTR | 167 | #ifdef CONFIG_EXT2_FS_XATTR |
166 | init_rwsem(&ei->xattr_sem); | 168 | init_rwsem(&ei->xattr_sem); |
167 | #endif | 169 | #endif |
170 | mutex_init(&ei->truncate_mutex); | ||
168 | inode_init_once(&ei->vfs_inode); | 171 | inode_init_once(&ei->vfs_inode); |
169 | } | 172 | } |
170 | 173 | ||
@@ -187,6 +190,7 @@ static void destroy_inodecache(void) | |||
187 | 190 | ||
188 | static void ext2_clear_inode(struct inode *inode) | 191 | static void ext2_clear_inode(struct inode *inode) |
189 | { | 192 | { |
193 | struct ext2_block_alloc_info *rsv = EXT2_I(inode)->i_block_alloc_info; | ||
190 | #ifdef CONFIG_EXT2_FS_POSIX_ACL | 194 | #ifdef CONFIG_EXT2_FS_POSIX_ACL |
191 | struct ext2_inode_info *ei = EXT2_I(inode); | 195 | struct ext2_inode_info *ei = EXT2_I(inode); |
192 | 196 | ||
@@ -199,14 +203,74 @@ static void ext2_clear_inode(struct inode *inode) | |||
199 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; | 203 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; |
200 | } | 204 | } |
201 | #endif | 205 | #endif |
206 | ext2_discard_reservation(inode); | ||
207 | EXT2_I(inode)->i_block_alloc_info = NULL; | ||
208 | if (unlikely(rsv)) | ||
209 | kfree(rsv); | ||
202 | } | 210 | } |
203 | 211 | ||
204 | static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs) | 212 | static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs) |
205 | { | 213 | { |
206 | struct ext2_sb_info *sbi = EXT2_SB(vfs->mnt_sb); | 214 | struct super_block *sb = vfs->mnt_sb; |
215 | struct ext2_sb_info *sbi = EXT2_SB(sb); | ||
216 | struct ext2_super_block *es = sbi->s_es; | ||
217 | unsigned long def_mount_opts; | ||
218 | |||
219 | def_mount_opts = le32_to_cpu(es->s_default_mount_opts); | ||
207 | 220 | ||
208 | if (sbi->s_mount_opt & EXT2_MOUNT_GRPID) | 221 | if (sbi->s_sb_block != 1) |
222 | seq_printf(seq, ",sb=%lu", sbi->s_sb_block); | ||
223 | if (test_opt(sb, MINIX_DF)) | ||
224 | seq_puts(seq, ",minixdf"); | ||
225 | if (test_opt(sb, GRPID)) | ||
209 | seq_puts(seq, ",grpid"); | 226 | seq_puts(seq, ",grpid"); |
227 | if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS)) | ||
228 | seq_puts(seq, ",nogrpid"); | ||
229 | if (sbi->s_resuid != EXT2_DEF_RESUID || | ||
230 | le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) { | ||
231 | seq_printf(seq, ",resuid=%u", sbi->s_resuid); | ||
232 | } | ||
233 | if (sbi->s_resgid != EXT2_DEF_RESGID || | ||
234 | le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) { | ||
235 | seq_printf(seq, ",resgid=%u", sbi->s_resgid); | ||
236 | } | ||
237 | if (test_opt(sb, ERRORS_CONT)) { | ||
238 | int def_errors = le16_to_cpu(es->s_errors); | ||
239 | |||
240 | if (def_errors == EXT2_ERRORS_PANIC || | ||
241 | def_errors == EXT2_ERRORS_RO) { | ||
242 | seq_puts(seq, ",errors=continue"); | ||
243 | } | ||
244 | } | ||
245 | if (test_opt(sb, ERRORS_RO)) | ||
246 | seq_puts(seq, ",errors=remount-ro"); | ||
247 | if (test_opt(sb, ERRORS_PANIC)) | ||
248 | seq_puts(seq, ",errors=panic"); | ||
249 | if (test_opt(sb, NO_UID32)) | ||
250 | seq_puts(seq, ",nouid32"); | ||
251 | if (test_opt(sb, DEBUG)) | ||
252 | seq_puts(seq, ",debug"); | ||
253 | if (test_opt(sb, OLDALLOC)) | ||
254 | seq_puts(seq, ",oldalloc"); | ||
255 | |||
256 | #ifdef CONFIG_EXT2_FS_XATTR | ||
257 | if (test_opt(sb, XATTR_USER)) | ||
258 | seq_puts(seq, ",user_xattr"); | ||
259 | if (!test_opt(sb, XATTR_USER) && | ||
260 | (def_mount_opts & EXT2_DEFM_XATTR_USER)) { | ||
261 | seq_puts(seq, ",nouser_xattr"); | ||
262 | } | ||
263 | #endif | ||
264 | |||
265 | #ifdef CONFIG_EXT2_FS_POSIX_ACL | ||
266 | if (test_opt(sb, POSIX_ACL)) | ||
267 | seq_puts(seq, ",acl"); | ||
268 | if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT2_DEFM_ACL)) | ||
269 | seq_puts(seq, ",noacl"); | ||
270 | #endif | ||
271 | |||
272 | if (test_opt(sb, NOBH)) | ||
273 | seq_puts(seq, ",nobh"); | ||
210 | 274 | ||
211 | #if defined(CONFIG_QUOTA) | 275 | #if defined(CONFIG_QUOTA) |
212 | if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA) | 276 | if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA) |
@@ -234,7 +298,6 @@ static const struct super_operations ext2_sops = { | |||
234 | .destroy_inode = ext2_destroy_inode, | 298 | .destroy_inode = ext2_destroy_inode, |
235 | .read_inode = ext2_read_inode, | 299 | .read_inode = ext2_read_inode, |
236 | .write_inode = ext2_write_inode, | 300 | .write_inode = ext2_write_inode, |
237 | .put_inode = ext2_put_inode, | ||
238 | .delete_inode = ext2_delete_inode, | 301 | .delete_inode = ext2_delete_inode, |
239 | .put_super = ext2_put_super, | 302 | .put_super = ext2_put_super, |
240 | .write_super = ext2_write_super, | 303 | .write_super = ext2_write_super, |
@@ -322,7 +385,7 @@ enum { | |||
322 | Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, | 385 | Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, |
323 | Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr, | 386 | Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr, |
324 | Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota, | 387 | Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota, |
325 | Opt_usrquota, Opt_grpquota | 388 | Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation |
326 | }; | 389 | }; |
327 | 390 | ||
328 | static match_table_t tokens = { | 391 | static match_table_t tokens = { |
@@ -354,6 +417,8 @@ static match_table_t tokens = { | |||
354 | {Opt_ignore, "noquota"}, | 417 | {Opt_ignore, "noquota"}, |
355 | {Opt_quota, "quota"}, | 418 | {Opt_quota, "quota"}, |
356 | {Opt_usrquota, "usrquota"}, | 419 | {Opt_usrquota, "usrquota"}, |
420 | {Opt_reservation, "reservation"}, | ||
421 | {Opt_noreservation, "noreservation"}, | ||
357 | {Opt_err, NULL} | 422 | {Opt_err, NULL} |
358 | }; | 423 | }; |
359 | 424 | ||
@@ -486,6 +551,14 @@ static int parse_options (char * options, | |||
486 | break; | 551 | break; |
487 | #endif | 552 | #endif |
488 | 553 | ||
554 | case Opt_reservation: | ||
555 | set_opt(sbi->s_mount_opt, RESERVATION); | ||
556 | printk("reservations ON\n"); | ||
557 | break; | ||
558 | case Opt_noreservation: | ||
559 | clear_opt(sbi->s_mount_opt, RESERVATION); | ||
560 | printk("reservations OFF\n"); | ||
561 | break; | ||
489 | case Opt_ignore: | 562 | case Opt_ignore: |
490 | break; | 563 | break; |
491 | default: | 564 | default: |
@@ -653,11 +726,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
653 | int db_count; | 726 | int db_count; |
654 | int i, j; | 727 | int i, j; |
655 | __le32 features; | 728 | __le32 features; |
729 | int err; | ||
656 | 730 | ||
657 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 731 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
658 | if (!sbi) | 732 | if (!sbi) |
659 | return -ENOMEM; | 733 | return -ENOMEM; |
660 | sb->s_fs_info = sbi; | 734 | sb->s_fs_info = sbi; |
735 | sbi->s_sb_block = sb_block; | ||
661 | 736 | ||
662 | /* | 737 | /* |
663 | * See what the current blocksize for the device is, and | 738 | * See what the current blocksize for the device is, and |
@@ -725,6 +800,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
725 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); | 800 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); |
726 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 801 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); |
727 | 802 | ||
803 | set_opt(sbi->s_mount_opt, RESERVATION); | ||
804 | |||
728 | if (!parse_options ((char *) data, sbi)) | 805 | if (!parse_options ((char *) data, sbi)) |
729 | goto failed_mount; | 806 | goto failed_mount; |
730 | 807 | ||
@@ -804,7 +881,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
804 | sbi->s_inode_size = le16_to_cpu(es->s_inode_size); | 881 | sbi->s_inode_size = le16_to_cpu(es->s_inode_size); |
805 | sbi->s_first_ino = le32_to_cpu(es->s_first_ino); | 882 | sbi->s_first_ino = le32_to_cpu(es->s_first_ino); |
806 | if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) || | 883 | if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) || |
807 | (sbi->s_inode_size & (sbi->s_inode_size - 1)) || | 884 | !is_power_of_2(sbi->s_inode_size) || |
808 | (sbi->s_inode_size > blocksize)) { | 885 | (sbi->s_inode_size > blocksize)) { |
809 | printk ("EXT2-fs: unsupported inode size: %d\n", | 886 | printk ("EXT2-fs: unsupported inode size: %d\n", |
810 | sbi->s_inode_size); | 887 | sbi->s_inode_size); |
@@ -906,12 +983,35 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
906 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 983 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
907 | spin_lock_init(&sbi->s_next_gen_lock); | 984 | spin_lock_init(&sbi->s_next_gen_lock); |
908 | 985 | ||
909 | percpu_counter_init(&sbi->s_freeblocks_counter, | 986 | /* per fileystem reservation list head & lock */ |
987 | spin_lock_init(&sbi->s_rsv_window_lock); | ||
988 | sbi->s_rsv_window_root = RB_ROOT; | ||
989 | /* | ||
990 | * Add a single, static dummy reservation to the start of the | ||
991 | * reservation window list --- it gives us a placeholder for | ||
992 | * append-at-start-of-list which makes the allocation logic | ||
993 | * _much_ simpler. | ||
994 | */ | ||
995 | sbi->s_rsv_window_head.rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED; | ||
996 | sbi->s_rsv_window_head.rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED; | ||
997 | sbi->s_rsv_window_head.rsv_alloc_hit = 0; | ||
998 | sbi->s_rsv_window_head.rsv_goal_size = 0; | ||
999 | ext2_rsv_window_add(sb, &sbi->s_rsv_window_head); | ||
1000 | |||
1001 | err = percpu_counter_init(&sbi->s_freeblocks_counter, | ||
910 | ext2_count_free_blocks(sb)); | 1002 | ext2_count_free_blocks(sb)); |
911 | percpu_counter_init(&sbi->s_freeinodes_counter, | 1003 | if (!err) { |
1004 | err = percpu_counter_init(&sbi->s_freeinodes_counter, | ||
912 | ext2_count_free_inodes(sb)); | 1005 | ext2_count_free_inodes(sb)); |
913 | percpu_counter_init(&sbi->s_dirs_counter, | 1006 | } |
1007 | if (!err) { | ||
1008 | err = percpu_counter_init(&sbi->s_dirs_counter, | ||
914 | ext2_count_dirs(sb)); | 1009 | ext2_count_dirs(sb)); |
1010 | } | ||
1011 | if (err) { | ||
1012 | printk(KERN_ERR "EXT2-fs: insufficient memory\n"); | ||
1013 | goto failed_mount3; | ||
1014 | } | ||
915 | /* | 1015 | /* |
916 | * set up enough so that it can read an inode | 1016 | * set up enough so that it can read an inode |
917 | */ | 1017 | */ |
@@ -1193,7 +1293,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, | |||
1193 | 1293 | ||
1194 | tmp_bh.b_state = 0; | 1294 | tmp_bh.b_state = 0; |
1195 | err = ext2_get_block(inode, blk, &tmp_bh, 0); | 1295 | err = ext2_get_block(inode, blk, &tmp_bh, 0); |
1196 | if (err) | 1296 | if (err < 0) |
1197 | return err; | 1297 | return err; |
1198 | if (!buffer_mapped(&tmp_bh)) /* A hole? */ | 1298 | if (!buffer_mapped(&tmp_bh)) /* A hole? */ |
1199 | memset(data, 0, tocopy); | 1299 | memset(data, 0, tocopy); |
@@ -1232,7 +1332,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type, | |||
1232 | 1332 | ||
1233 | tmp_bh.b_state = 0; | 1333 | tmp_bh.b_state = 0; |
1234 | err = ext2_get_block(inode, blk, &tmp_bh, 1); | 1334 | err = ext2_get_block(inode, blk, &tmp_bh, 1); |
1235 | if (err) | 1335 | if (err < 0) |
1236 | goto out; | 1336 | goto out; |
1237 | if (offset || tocopy != EXT2_BLOCK_SIZE(sb)) | 1337 | if (offset || tocopy != EXT2_BLOCK_SIZE(sb)) |
1238 | bh = sb_bread(sb, tmp_bh.b_blocknr); | 1338 | bh = sb_bread(sb, tmp_bh.b_blocknr); |