diff options
Diffstat (limited to 'fs/ext2/super.c')
-rw-r--r-- | fs/ext2/super.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 51b4c43b97e4..77bd5f9262f9 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -149,6 +149,7 @@ static struct inode *ext2_alloc_inode(struct super_block *sb) | |||
149 | ei->i_acl = EXT2_ACL_NOT_CACHED; | 149 | ei->i_acl = EXT2_ACL_NOT_CACHED; |
150 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; | 150 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; |
151 | #endif | 151 | #endif |
152 | ei->i_block_alloc_info = NULL; | ||
152 | ei->vfs_inode.i_version = 1; | 153 | ei->vfs_inode.i_version = 1; |
153 | return &ei->vfs_inode; | 154 | return &ei->vfs_inode; |
154 | } | 155 | } |
@@ -166,6 +167,7 @@ static void init_once(struct kmem_cache * cachep, void *foo) | |||
166 | #ifdef CONFIG_EXT2_FS_XATTR | 167 | #ifdef CONFIG_EXT2_FS_XATTR |
167 | init_rwsem(&ei->xattr_sem); | 168 | init_rwsem(&ei->xattr_sem); |
168 | #endif | 169 | #endif |
170 | mutex_init(&ei->truncate_mutex); | ||
169 | inode_init_once(&ei->vfs_inode); | 171 | inode_init_once(&ei->vfs_inode); |
170 | } | 172 | } |
171 | 173 | ||
@@ -188,6 +190,7 @@ static void destroy_inodecache(void) | |||
188 | 190 | ||
189 | static void ext2_clear_inode(struct inode *inode) | 191 | static void ext2_clear_inode(struct inode *inode) |
190 | { | 192 | { |
193 | struct ext2_block_alloc_info *rsv = EXT2_I(inode)->i_block_alloc_info; | ||
191 | #ifdef CONFIG_EXT2_FS_POSIX_ACL | 194 | #ifdef CONFIG_EXT2_FS_POSIX_ACL |
192 | struct ext2_inode_info *ei = EXT2_I(inode); | 195 | struct ext2_inode_info *ei = EXT2_I(inode); |
193 | 196 | ||
@@ -200,6 +203,10 @@ static void ext2_clear_inode(struct inode *inode) | |||
200 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; | 203 | ei->i_default_acl = EXT2_ACL_NOT_CACHED; |
201 | } | 204 | } |
202 | #endif | 205 | #endif |
206 | ext2_discard_reservation(inode); | ||
207 | EXT2_I(inode)->i_block_alloc_info = NULL; | ||
208 | if (unlikely(rsv)) | ||
209 | kfree(rsv); | ||
203 | } | 210 | } |
204 | 211 | ||
205 | 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) |
@@ -291,7 +298,6 @@ static const struct super_operations ext2_sops = { | |||
291 | .destroy_inode = ext2_destroy_inode, | 298 | .destroy_inode = ext2_destroy_inode, |
292 | .read_inode = ext2_read_inode, | 299 | .read_inode = ext2_read_inode, |
293 | .write_inode = ext2_write_inode, | 300 | .write_inode = ext2_write_inode, |
294 | .put_inode = ext2_put_inode, | ||
295 | .delete_inode = ext2_delete_inode, | 301 | .delete_inode = ext2_delete_inode, |
296 | .put_super = ext2_put_super, | 302 | .put_super = ext2_put_super, |
297 | .write_super = ext2_write_super, | 303 | .write_super = ext2_write_super, |
@@ -379,7 +385,7 @@ enum { | |||
379 | Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, | 385 | Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, |
380 | 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, |
381 | 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, |
382 | Opt_usrquota, Opt_grpquota | 388 | Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation |
383 | }; | 389 | }; |
384 | 390 | ||
385 | static match_table_t tokens = { | 391 | static match_table_t tokens = { |
@@ -411,6 +417,8 @@ static match_table_t tokens = { | |||
411 | {Opt_ignore, "noquota"}, | 417 | {Opt_ignore, "noquota"}, |
412 | {Opt_quota, "quota"}, | 418 | {Opt_quota, "quota"}, |
413 | {Opt_usrquota, "usrquota"}, | 419 | {Opt_usrquota, "usrquota"}, |
420 | {Opt_reservation, "reservation"}, | ||
421 | {Opt_noreservation, "noreservation"}, | ||
414 | {Opt_err, NULL} | 422 | {Opt_err, NULL} |
415 | }; | 423 | }; |
416 | 424 | ||
@@ -543,6 +551,14 @@ static int parse_options (char * options, | |||
543 | break; | 551 | break; |
544 | #endif | 552 | #endif |
545 | 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; | ||
546 | case Opt_ignore: | 562 | case Opt_ignore: |
547 | break; | 563 | break; |
548 | default: | 564 | default: |
@@ -784,6 +800,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
784 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); | 800 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); |
785 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 801 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); |
786 | 802 | ||
803 | set_opt(sbi->s_mount_opt, RESERVATION); | ||
804 | |||
787 | if (!parse_options ((char *) data, sbi)) | 805 | if (!parse_options ((char *) data, sbi)) |
788 | goto failed_mount; | 806 | goto failed_mount; |
789 | 807 | ||
@@ -965,6 +983,21 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
965 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 983 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
966 | spin_lock_init(&sbi->s_next_gen_lock); | 984 | spin_lock_init(&sbi->s_next_gen_lock); |
967 | 985 | ||
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 | |||
968 | err = percpu_counter_init(&sbi->s_freeblocks_counter, | 1001 | err = percpu_counter_init(&sbi->s_freeblocks_counter, |
969 | ext2_count_free_blocks(sb)); | 1002 | ext2_count_free_blocks(sb)); |
970 | if (!err) { | 1003 | if (!err) { |
@@ -1260,7 +1293,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, | |||
1260 | 1293 | ||
1261 | tmp_bh.b_state = 0; | 1294 | tmp_bh.b_state = 0; |
1262 | err = ext2_get_block(inode, blk, &tmp_bh, 0); | 1295 | err = ext2_get_block(inode, blk, &tmp_bh, 0); |
1263 | if (err) | 1296 | if (err < 0) |
1264 | return err; | 1297 | return err; |
1265 | if (!buffer_mapped(&tmp_bh)) /* A hole? */ | 1298 | if (!buffer_mapped(&tmp_bh)) /* A hole? */ |
1266 | memset(data, 0, tocopy); | 1299 | memset(data, 0, tocopy); |
@@ -1299,7 +1332,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type, | |||
1299 | 1332 | ||
1300 | tmp_bh.b_state = 0; | 1333 | tmp_bh.b_state = 0; |
1301 | err = ext2_get_block(inode, blk, &tmp_bh, 1); | 1334 | err = ext2_get_block(inode, blk, &tmp_bh, 1); |
1302 | if (err) | 1335 | if (err < 0) |
1303 | goto out; | 1336 | goto out; |
1304 | if (offset || tocopy != EXT2_BLOCK_SIZE(sb)) | 1337 | if (offset || tocopy != EXT2_BLOCK_SIZE(sb)) |
1305 | bh = sb_bread(sb, tmp_bh.b_blocknr); | 1338 | bh = sb_bread(sb, tmp_bh.b_blocknr); |