diff options
Diffstat (limited to 'fs/ext2')
| -rw-r--r-- | fs/ext2/balloc.c | 11 | ||||
| -rw-r--r-- | fs/ext2/dir.c | 23 | ||||
| -rw-r--r-- | fs/ext2/ext2.h | 5 | ||||
| -rw-r--r-- | fs/ext2/ialloc.c | 13 | ||||
| -rw-r--r-- | fs/ext2/inode.c | 87 | ||||
| -rw-r--r-- | fs/ext2/super.c | 14 | ||||
| -rw-r--r-- | fs/ext2/xattr.c | 25 |
7 files changed, 80 insertions, 98 deletions
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index e8766a396776..c6c684b44ea1 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c | |||
| @@ -571,7 +571,7 @@ do_more: | |||
| 571 | error_return: | 571 | error_return: |
| 572 | brelse(bitmap_bh); | 572 | brelse(bitmap_bh); |
| 573 | release_blocks(sb, freed); | 573 | release_blocks(sb, freed); |
| 574 | dquot_free_block(inode, freed); | 574 | dquot_free_block_nodirty(inode, freed); |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | /** | 577 | /** |
| @@ -1418,7 +1418,8 @@ allocated: | |||
| 1418 | 1418 | ||
| 1419 | *errp = 0; | 1419 | *errp = 0; |
| 1420 | brelse(bitmap_bh); | 1420 | brelse(bitmap_bh); |
| 1421 | dquot_free_block(inode, *count-num); | 1421 | dquot_free_block_nodirty(inode, *count-num); |
| 1422 | mark_inode_dirty(inode); | ||
| 1422 | *count = num; | 1423 | *count = num; |
| 1423 | return ret_block; | 1424 | return ret_block; |
| 1424 | 1425 | ||
| @@ -1428,8 +1429,10 @@ out: | |||
| 1428 | /* | 1429 | /* |
| 1429 | * Undo the block allocation | 1430 | * Undo the block allocation |
| 1430 | */ | 1431 | */ |
| 1431 | if (!performed_allocation) | 1432 | if (!performed_allocation) { |
| 1432 | dquot_free_block(inode, *count); | 1433 | dquot_free_block_nodirty(inode, *count); |
| 1434 | mark_inode_dirty(inode); | ||
| 1435 | } | ||
| 1433 | brelse(bitmap_bh); | 1436 | brelse(bitmap_bh); |
| 1434 | return 0; | 1437 | return 0; |
| 1435 | } | 1438 | } |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 7516957273ed..764109886ec0 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
| @@ -448,6 +448,11 @@ ino_t ext2_inode_by_name(struct inode *dir, struct qstr *child) | |||
| 448 | return res; | 448 | return res; |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len) | ||
| 452 | { | ||
| 453 | return __block_write_begin(page, pos, len, ext2_get_block); | ||
| 454 | } | ||
| 455 | |||
| 451 | /* Releases the page */ | 456 | /* Releases the page */ |
| 452 | void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, | 457 | void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, |
| 453 | struct page *page, struct inode *inode, int update_times) | 458 | struct page *page, struct inode *inode, int update_times) |
| @@ -458,8 +463,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, | |||
| 458 | int err; | 463 | int err; |
| 459 | 464 | ||
| 460 | lock_page(page); | 465 | lock_page(page); |
| 461 | err = __ext2_write_begin(NULL, page->mapping, pos, len, | 466 | err = ext2_prepare_chunk(page, pos, len); |
| 462 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
| 463 | BUG_ON(err); | 467 | BUG_ON(err); |
| 464 | de->inode = cpu_to_le32(inode->i_ino); | 468 | de->inode = cpu_to_le32(inode->i_ino); |
| 465 | ext2_set_de_type(de, inode); | 469 | ext2_set_de_type(de, inode); |
| @@ -542,8 +546,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) | |||
| 542 | got_it: | 546 | got_it: |
| 543 | pos = page_offset(page) + | 547 | pos = page_offset(page) + |
| 544 | (char*)de - (char*)page_address(page); | 548 | (char*)de - (char*)page_address(page); |
| 545 | err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, | 549 | err = ext2_prepare_chunk(page, pos, rec_len); |
| 546 | &page, NULL); | ||
| 547 | if (err) | 550 | if (err) |
| 548 | goto out_unlock; | 551 | goto out_unlock; |
| 549 | if (de->inode) { | 552 | if (de->inode) { |
| @@ -576,8 +579,7 @@ out_unlock: | |||
| 576 | */ | 579 | */ |
| 577 | int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | 580 | int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) |
| 578 | { | 581 | { |
| 579 | struct address_space *mapping = page->mapping; | 582 | struct inode *inode = page->mapping->host; |
| 580 | struct inode *inode = mapping->host; | ||
| 581 | char *kaddr = page_address(page); | 583 | char *kaddr = page_address(page); |
| 582 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); | 584 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); |
| 583 | unsigned to = ((char *)dir - kaddr) + | 585 | unsigned to = ((char *)dir - kaddr) + |
| @@ -601,8 +603,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | |||
| 601 | from = (char*)pde - (char*)page_address(page); | 603 | from = (char*)pde - (char*)page_address(page); |
| 602 | pos = page_offset(page) + from; | 604 | pos = page_offset(page) + from; |
| 603 | lock_page(page); | 605 | lock_page(page); |
| 604 | err = __ext2_write_begin(NULL, page->mapping, pos, to - from, 0, | 606 | err = ext2_prepare_chunk(page, pos, to - from); |
| 605 | &page, NULL); | ||
| 606 | BUG_ON(err); | 607 | BUG_ON(err); |
| 607 | if (pde) | 608 | if (pde) |
| 608 | pde->rec_len = ext2_rec_len_to_disk(to - from); | 609 | pde->rec_len = ext2_rec_len_to_disk(to - from); |
| @@ -621,8 +622,7 @@ out: | |||
| 621 | */ | 622 | */ |
| 622 | int ext2_make_empty(struct inode *inode, struct inode *parent) | 623 | int ext2_make_empty(struct inode *inode, struct inode *parent) |
| 623 | { | 624 | { |
| 624 | struct address_space *mapping = inode->i_mapping; | 625 | struct page *page = grab_cache_page(inode->i_mapping, 0); |
| 625 | struct page *page = grab_cache_page(mapping, 0); | ||
| 626 | unsigned chunk_size = ext2_chunk_size(inode); | 626 | unsigned chunk_size = ext2_chunk_size(inode); |
| 627 | struct ext2_dir_entry_2 * de; | 627 | struct ext2_dir_entry_2 * de; |
| 628 | int err; | 628 | int err; |
| @@ -631,8 +631,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) | |||
| 631 | if (!page) | 631 | if (!page) |
| 632 | return -ENOMEM; | 632 | return -ENOMEM; |
| 633 | 633 | ||
| 634 | err = __ext2_write_begin(NULL, page->mapping, 0, chunk_size, 0, | 634 | err = ext2_prepare_chunk(page, 0, chunk_size); |
| 635 | &page, NULL); | ||
| 636 | if (err) { | 635 | if (err) { |
| 637 | unlock_page(page); | 636 | unlock_page(page); |
| 638 | goto fail; | 637 | goto fail; |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 52b34f1d2738..416daa62242c 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
| @@ -119,7 +119,7 @@ extern unsigned long ext2_count_free (struct buffer_head *, unsigned); | |||
| 119 | /* inode.c */ | 119 | /* inode.c */ |
| 120 | extern struct inode *ext2_iget (struct super_block *, unsigned long); | 120 | extern struct inode *ext2_iget (struct super_block *, unsigned long); |
| 121 | extern int ext2_write_inode (struct inode *, struct writeback_control *); | 121 | extern int ext2_write_inode (struct inode *, struct writeback_control *); |
| 122 | extern void ext2_delete_inode (struct inode *); | 122 | extern void ext2_evict_inode(struct inode *); |
| 123 | extern int ext2_sync_inode (struct inode *); | 123 | extern int ext2_sync_inode (struct inode *); |
| 124 | extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int); | 124 | extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int); |
| 125 | extern int ext2_setattr (struct dentry *, struct iattr *); | 125 | extern int ext2_setattr (struct dentry *, struct iattr *); |
| @@ -127,9 +127,6 @@ extern void ext2_set_inode_flags(struct inode *inode); | |||
| 127 | extern void ext2_get_inode_flags(struct ext2_inode_info *); | 127 | extern void ext2_get_inode_flags(struct ext2_inode_info *); |
| 128 | extern int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 128 | extern int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
| 129 | u64 start, u64 len); | 129 | u64 start, u64 len); |
| 130 | int __ext2_write_begin(struct file *file, struct address_space *mapping, | ||
| 131 | loff_t pos, unsigned len, unsigned flags, | ||
| 132 | struct page **pagep, void **fsdata); | ||
| 133 | 130 | ||
| 134 | /* ioctl.c */ | 131 | /* ioctl.c */ |
| 135 | extern long ext2_ioctl(struct file *, unsigned int, unsigned long); | 132 | extern long ext2_ioctl(struct file *, unsigned int, unsigned long); |
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 938dbc739d00..ad70479aabff 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
| @@ -118,19 +118,14 @@ void ext2_free_inode (struct inode * inode) | |||
| 118 | * Note: we must free any quota before locking the superblock, | 118 | * Note: we must free any quota before locking the superblock, |
| 119 | * as writing the quota to disk may need the lock as well. | 119 | * as writing the quota to disk may need the lock as well. |
| 120 | */ | 120 | */ |
| 121 | if (!is_bad_inode(inode)) { | 121 | /* Quota is already initialized in iput() */ |
| 122 | /* Quota is already initialized in iput() */ | 122 | ext2_xattr_delete_inode(inode); |
| 123 | ext2_xattr_delete_inode(inode); | 123 | dquot_free_inode(inode); |
| 124 | dquot_free_inode(inode); | 124 | dquot_drop(inode); |
| 125 | dquot_drop(inode); | ||
| 126 | } | ||
| 127 | 125 | ||
| 128 | es = EXT2_SB(sb)->s_es; | 126 | es = EXT2_SB(sb)->s_es; |
| 129 | is_directory = S_ISDIR(inode->i_mode); | 127 | is_directory = S_ISDIR(inode->i_mode); |
| 130 | 128 | ||
| 131 | /* Do this BEFORE marking the inode not in use or returning an error */ | ||
| 132 | clear_inode (inode); | ||
| 133 | |||
| 134 | if (ino < EXT2_FIRST_INO(sb) || | 129 | if (ino < EXT2_FIRST_INO(sb) || |
| 135 | ino > le32_to_cpu(es->s_inodes_count)) { | 130 | ino > le32_to_cpu(es->s_inodes_count)) { |
| 136 | ext2_error (sb, "ext2_free_inode", | 131 | ext2_error (sb, "ext2_free_inode", |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 3675088cb88c..940c96168868 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
| @@ -69,26 +69,42 @@ static void ext2_write_failed(struct address_space *mapping, loff_t to) | |||
| 69 | /* | 69 | /* |
| 70 | * Called at the last iput() if i_nlink is zero. | 70 | * Called at the last iput() if i_nlink is zero. |
| 71 | */ | 71 | */ |
| 72 | void ext2_delete_inode (struct inode * inode) | 72 | void ext2_evict_inode(struct inode * inode) |
| 73 | { | 73 | { |
| 74 | if (!is_bad_inode(inode)) | 74 | struct ext2_block_alloc_info *rsv; |
| 75 | int want_delete = 0; | ||
| 76 | |||
| 77 | if (!inode->i_nlink && !is_bad_inode(inode)) { | ||
| 78 | want_delete = 1; | ||
| 75 | dquot_initialize(inode); | 79 | dquot_initialize(inode); |
| 80 | } else { | ||
| 81 | dquot_drop(inode); | ||
| 82 | } | ||
| 83 | |||
| 76 | truncate_inode_pages(&inode->i_data, 0); | 84 | truncate_inode_pages(&inode->i_data, 0); |
| 77 | 85 | ||
| 78 | if (is_bad_inode(inode)) | 86 | if (want_delete) { |
| 79 | goto no_delete; | 87 | /* set dtime */ |
| 80 | EXT2_I(inode)->i_dtime = get_seconds(); | 88 | EXT2_I(inode)->i_dtime = get_seconds(); |
| 81 | mark_inode_dirty(inode); | 89 | mark_inode_dirty(inode); |
| 82 | __ext2_write_inode(inode, inode_needs_sync(inode)); | 90 | __ext2_write_inode(inode, inode_needs_sync(inode)); |
| 91 | /* truncate to 0 */ | ||
| 92 | inode->i_size = 0; | ||
| 93 | if (inode->i_blocks) | ||
| 94 | ext2_truncate_blocks(inode, 0); | ||
| 95 | } | ||
| 83 | 96 | ||
| 84 | inode->i_size = 0; | 97 | invalidate_inode_buffers(inode); |
| 85 | if (inode->i_blocks) | 98 | end_writeback(inode); |
| 86 | ext2_truncate_blocks(inode, 0); | ||
| 87 | ext2_free_inode (inode); | ||
| 88 | 99 | ||
| 89 | return; | 100 | ext2_discard_reservation(inode); |
| 90 | no_delete: | 101 | rsv = EXT2_I(inode)->i_block_alloc_info; |
| 91 | clear_inode(inode); /* We must guarantee clearing of inode... */ | 102 | EXT2_I(inode)->i_block_alloc_info = NULL; |
| 103 | if (unlikely(rsv)) | ||
| 104 | kfree(rsv); | ||
| 105 | |||
| 106 | if (want_delete) | ||
| 107 | ext2_free_inode(inode); | ||
| 92 | } | 108 | } |
| 93 | 109 | ||
| 94 | typedef struct { | 110 | typedef struct { |
| @@ -423,6 +439,8 @@ static int ext2_alloc_blocks(struct inode *inode, | |||
| 423 | failed_out: | 439 | failed_out: |
| 424 | for (i = 0; i <index; i++) | 440 | for (i = 0; i <index; i++) |
| 425 | ext2_free_blocks(inode, new_blocks[i], 1); | 441 | ext2_free_blocks(inode, new_blocks[i], 1); |
| 442 | if (index) | ||
| 443 | mark_inode_dirty(inode); | ||
| 426 | return ret; | 444 | return ret; |
| 427 | } | 445 | } |
| 428 | 446 | ||
| @@ -765,14 +783,6 @@ ext2_readpages(struct file *file, struct address_space *mapping, | |||
| 765 | return mpage_readpages(mapping, pages, nr_pages, ext2_get_block); | 783 | return mpage_readpages(mapping, pages, nr_pages, ext2_get_block); |
| 766 | } | 784 | } |
| 767 | 785 | ||
| 768 | int __ext2_write_begin(struct file *file, struct address_space *mapping, | ||
| 769 | loff_t pos, unsigned len, unsigned flags, | ||
| 770 | struct page **pagep, void **fsdata) | ||
| 771 | { | ||
| 772 | return block_write_begin_newtrunc(file, mapping, pos, len, flags, | ||
| 773 | pagep, fsdata, ext2_get_block); | ||
| 774 | } | ||
| 775 | |||
| 776 | static int | 786 | static int |
| 777 | ext2_write_begin(struct file *file, struct address_space *mapping, | 787 | ext2_write_begin(struct file *file, struct address_space *mapping, |
| 778 | loff_t pos, unsigned len, unsigned flags, | 788 | loff_t pos, unsigned len, unsigned flags, |
| @@ -780,8 +790,8 @@ ext2_write_begin(struct file *file, struct address_space *mapping, | |||
| 780 | { | 790 | { |
| 781 | int ret; | 791 | int ret; |
| 782 | 792 | ||
| 783 | *pagep = NULL; | 793 | ret = block_write_begin(mapping, pos, len, flags, pagep, |
| 784 | ret = __ext2_write_begin(file, mapping, pos, len, flags, pagep, fsdata); | 794 | ext2_get_block); |
| 785 | if (ret < 0) | 795 | if (ret < 0) |
| 786 | ext2_write_failed(mapping, pos + len); | 796 | ext2_write_failed(mapping, pos + len); |
| 787 | return ret; | 797 | return ret; |
| @@ -806,13 +816,8 @@ ext2_nobh_write_begin(struct file *file, struct address_space *mapping, | |||
| 806 | { | 816 | { |
| 807 | int ret; | 817 | int ret; |
| 808 | 818 | ||
| 809 | /* | 819 | ret = nobh_write_begin(mapping, pos, len, flags, pagep, fsdata, |
| 810 | * Dir-in-pagecache still uses ext2_write_begin. Would have to rework | 820 | ext2_get_block); |
| 811 | * directory handling code to pass around offsets rather than struct | ||
| 812 | * pages in order to make this work easily. | ||
| 813 | */ | ||
| 814 | ret = nobh_write_begin_newtrunc(file, mapping, pos, len, flags, pagep, | ||
| 815 | fsdata, ext2_get_block); | ||
| 816 | if (ret < 0) | 821 | if (ret < 0) |
| 817 | ext2_write_failed(mapping, pos + len); | 822 | ext2_write_failed(mapping, pos + len); |
| 818 | return ret; | 823 | return ret; |
| @@ -838,7 +843,7 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
| 838 | struct inode *inode = mapping->host; | 843 | struct inode *inode = mapping->host; |
| 839 | ssize_t ret; | 844 | ssize_t ret; |
| 840 | 845 | ||
| 841 | ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev, | 846 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, |
| 842 | iov, offset, nr_segs, ext2_get_block, NULL); | 847 | iov, offset, nr_segs, ext2_get_block, NULL); |
| 843 | if (ret < 0 && (rw & WRITE)) | 848 | if (ret < 0 && (rw & WRITE)) |
| 844 | ext2_write_failed(mapping, offset + iov_length(iov, nr_segs)); | 849 | ext2_write_failed(mapping, offset + iov_length(iov, nr_segs)); |
| @@ -1006,8 +1011,8 @@ static inline void ext2_free_data(struct inode *inode, __le32 *p, __le32 *q) | |||
| 1006 | else if (block_to_free == nr - count) | 1011 | else if (block_to_free == nr - count) |
| 1007 | count++; | 1012 | count++; |
| 1008 | else { | 1013 | else { |
| 1009 | mark_inode_dirty(inode); | ||
| 1010 | ext2_free_blocks (inode, block_to_free, count); | 1014 | ext2_free_blocks (inode, block_to_free, count); |
| 1015 | mark_inode_dirty(inode); | ||
| 1011 | free_this: | 1016 | free_this: |
| 1012 | block_to_free = nr; | 1017 | block_to_free = nr; |
| 1013 | count = 1; | 1018 | count = 1; |
| @@ -1015,8 +1020,8 @@ static inline void ext2_free_data(struct inode *inode, __le32 *p, __le32 *q) | |||
| 1015 | } | 1020 | } |
| 1016 | } | 1021 | } |
| 1017 | if (count > 0) { | 1022 | if (count > 0) { |
| 1018 | mark_inode_dirty(inode); | ||
| 1019 | ext2_free_blocks (inode, block_to_free, count); | 1023 | ext2_free_blocks (inode, block_to_free, count); |
| 1024 | mark_inode_dirty(inode); | ||
| 1020 | } | 1025 | } |
| 1021 | } | 1026 | } |
| 1022 | 1027 | ||
| @@ -1169,15 +1174,10 @@ static void ext2_truncate_blocks(struct inode *inode, loff_t offset) | |||
| 1169 | __ext2_truncate_blocks(inode, offset); | 1174 | __ext2_truncate_blocks(inode, offset); |
| 1170 | } | 1175 | } |
| 1171 | 1176 | ||
| 1172 | int ext2_setsize(struct inode *inode, loff_t newsize) | 1177 | static int ext2_setsize(struct inode *inode, loff_t newsize) |
| 1173 | { | 1178 | { |
| 1174 | loff_t oldsize; | ||
| 1175 | int error; | 1179 | int error; |
| 1176 | 1180 | ||
| 1177 | error = inode_newsize_ok(inode, newsize); | ||
| 1178 | if (error) | ||
| 1179 | return error; | ||
| 1180 | |||
| 1181 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 1181 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
| 1182 | S_ISLNK(inode->i_mode))) | 1182 | S_ISLNK(inode->i_mode))) |
| 1183 | return -EINVAL; | 1183 | return -EINVAL; |
| @@ -1197,10 +1197,7 @@ int ext2_setsize(struct inode *inode, loff_t newsize) | |||
| 1197 | if (error) | 1197 | if (error) |
| 1198 | return error; | 1198 | return error; |
| 1199 | 1199 | ||
| 1200 | oldsize = inode->i_size; | 1200 | truncate_setsize(inode, newsize); |
| 1201 | i_size_write(inode, newsize); | ||
| 1202 | truncate_pagecache(inode, oldsize, newsize); | ||
| 1203 | |||
| 1204 | __ext2_truncate_blocks(inode, newsize); | 1201 | __ext2_truncate_blocks(inode, newsize); |
| 1205 | 1202 | ||
| 1206 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 1203 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
| @@ -1557,7 +1554,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr) | |||
| 1557 | if (error) | 1554 | if (error) |
| 1558 | return error; | 1555 | return error; |
| 1559 | } | 1556 | } |
| 1560 | generic_setattr(inode, iattr); | 1557 | setattr_copy(inode, iattr); |
| 1561 | if (iattr->ia_valid & ATTR_MODE) | 1558 | if (iattr->ia_valid & ATTR_MODE) |
| 1562 | error = ext2_acl_chmod(inode); | 1559 | error = ext2_acl_chmod(inode); |
| 1563 | mark_inode_dirty(inode); | 1560 | mark_inode_dirty(inode); |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 7ff43f4a59cd..1ec602673ea8 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -195,17 +195,6 @@ static void destroy_inodecache(void) | |||
| 195 | kmem_cache_destroy(ext2_inode_cachep); | 195 | kmem_cache_destroy(ext2_inode_cachep); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static void ext2_clear_inode(struct inode *inode) | ||
| 199 | { | ||
| 200 | struct ext2_block_alloc_info *rsv = EXT2_I(inode)->i_block_alloc_info; | ||
| 201 | |||
| 202 | dquot_drop(inode); | ||
| 203 | ext2_discard_reservation(inode); | ||
| 204 | EXT2_I(inode)->i_block_alloc_info = NULL; | ||
| 205 | if (unlikely(rsv)) | ||
| 206 | kfree(rsv); | ||
| 207 | } | ||
| 208 | |||
| 209 | static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs) | 198 | static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs) |
| 210 | { | 199 | { |
| 211 | struct super_block *sb = vfs->mnt_sb; | 200 | struct super_block *sb = vfs->mnt_sb; |
| @@ -299,13 +288,12 @@ static const struct super_operations ext2_sops = { | |||
| 299 | .alloc_inode = ext2_alloc_inode, | 288 | .alloc_inode = ext2_alloc_inode, |
| 300 | .destroy_inode = ext2_destroy_inode, | 289 | .destroy_inode = ext2_destroy_inode, |
| 301 | .write_inode = ext2_write_inode, | 290 | .write_inode = ext2_write_inode, |
| 302 | .delete_inode = ext2_delete_inode, | 291 | .evict_inode = ext2_evict_inode, |
| 303 | .put_super = ext2_put_super, | 292 | .put_super = ext2_put_super, |
| 304 | .write_super = ext2_write_super, | 293 | .write_super = ext2_write_super, |
| 305 | .sync_fs = ext2_sync_fs, | 294 | .sync_fs = ext2_sync_fs, |
| 306 | .statfs = ext2_statfs, | 295 | .statfs = ext2_statfs, |
| 307 | .remount_fs = ext2_remount, | 296 | .remount_fs = ext2_remount, |
| 308 | .clear_inode = ext2_clear_inode, | ||
| 309 | .show_options = ext2_show_options, | 297 | .show_options = ext2_show_options, |
| 310 | #ifdef CONFIG_QUOTA | 298 | #ifdef CONFIG_QUOTA |
| 311 | .quota_read = ext2_quota_read, | 299 | .quota_read = ext2_quota_read, |
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 7c3915780b19..8c29ae15129e 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c | |||
| @@ -674,6 +674,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, | |||
| 674 | new_bh = sb_getblk(sb, block); | 674 | new_bh = sb_getblk(sb, block); |
| 675 | if (!new_bh) { | 675 | if (!new_bh) { |
| 676 | ext2_free_blocks(inode, block, 1); | 676 | ext2_free_blocks(inode, block, 1); |
| 677 | mark_inode_dirty(inode); | ||
| 677 | error = -EIO; | 678 | error = -EIO; |
| 678 | goto cleanup; | 679 | goto cleanup; |
| 679 | } | 680 | } |
| @@ -703,8 +704,10 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, | |||
| 703 | * written (only some dirty data were not) so we just proceed | 704 | * written (only some dirty data were not) so we just proceed |
| 704 | * as if nothing happened and cleanup the unused block */ | 705 | * as if nothing happened and cleanup the unused block */ |
| 705 | if (error && error != -ENOSPC) { | 706 | if (error && error != -ENOSPC) { |
| 706 | if (new_bh && new_bh != old_bh) | 707 | if (new_bh && new_bh != old_bh) { |
| 707 | dquot_free_block(inode, 1); | 708 | dquot_free_block_nodirty(inode, 1); |
| 709 | mark_inode_dirty(inode); | ||
| 710 | } | ||
| 708 | goto cleanup; | 711 | goto cleanup; |
| 709 | } | 712 | } |
| 710 | } else | 713 | } else |
| @@ -727,6 +730,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, | |||
| 727 | mb_cache_entry_free(ce); | 730 | mb_cache_entry_free(ce); |
| 728 | ea_bdebug(old_bh, "freeing"); | 731 | ea_bdebug(old_bh, "freeing"); |
| 729 | ext2_free_blocks(inode, old_bh->b_blocknr, 1); | 732 | ext2_free_blocks(inode, old_bh->b_blocknr, 1); |
| 733 | mark_inode_dirty(inode); | ||
| 730 | /* We let our caller release old_bh, so we | 734 | /* We let our caller release old_bh, so we |
| 731 | * need to duplicate the buffer before. */ | 735 | * need to duplicate the buffer before. */ |
| 732 | get_bh(old_bh); | 736 | get_bh(old_bh); |
| @@ -736,7 +740,8 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, | |||
| 736 | le32_add_cpu(&HDR(old_bh)->h_refcount, -1); | 740 | le32_add_cpu(&HDR(old_bh)->h_refcount, -1); |
| 737 | if (ce) | 741 | if (ce) |
| 738 | mb_cache_entry_release(ce); | 742 | mb_cache_entry_release(ce); |
| 739 | dquot_free_block(inode, 1); | 743 | dquot_free_block_nodirty(inode, 1); |
| 744 | mark_inode_dirty(inode); | ||
| 740 | mark_buffer_dirty(old_bh); | 745 | mark_buffer_dirty(old_bh); |
| 741 | ea_bdebug(old_bh, "refcount now=%d", | 746 | ea_bdebug(old_bh, "refcount now=%d", |
| 742 | le32_to_cpu(HDR(old_bh)->h_refcount)); | 747 | le32_to_cpu(HDR(old_bh)->h_refcount)); |
| @@ -799,7 +804,7 @@ ext2_xattr_delete_inode(struct inode *inode) | |||
| 799 | mark_buffer_dirty(bh); | 804 | mark_buffer_dirty(bh); |
| 800 | if (IS_SYNC(inode)) | 805 | if (IS_SYNC(inode)) |
| 801 | sync_dirty_buffer(bh); | 806 | sync_dirty_buffer(bh); |
| 802 | dquot_free_block(inode, 1); | 807 | dquot_free_block_nodirty(inode, 1); |
| 803 | } | 808 | } |
| 804 | EXT2_I(inode)->i_file_acl = 0; | 809 | EXT2_I(inode)->i_file_acl = 0; |
| 805 | 810 | ||
| @@ -838,7 +843,7 @@ ext2_xattr_cache_insert(struct buffer_head *bh) | |||
| 838 | ce = mb_cache_entry_alloc(ext2_xattr_cache, GFP_NOFS); | 843 | ce = mb_cache_entry_alloc(ext2_xattr_cache, GFP_NOFS); |
| 839 | if (!ce) | 844 | if (!ce) |
| 840 | return -ENOMEM; | 845 | return -ENOMEM; |
| 841 | error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, &hash); | 846 | error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, hash); |
| 842 | if (error) { | 847 | if (error) { |
| 843 | mb_cache_entry_free(ce); | 848 | mb_cache_entry_free(ce); |
| 844 | if (error == -EBUSY) { | 849 | if (error == -EBUSY) { |
| @@ -912,8 +917,8 @@ ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header) | |||
| 912 | return NULL; /* never share */ | 917 | return NULL; /* never share */ |
| 913 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); | 918 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); |
| 914 | again: | 919 | again: |
| 915 | ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, | 920 | ce = mb_cache_entry_find_first(ext2_xattr_cache, inode->i_sb->s_bdev, |
| 916 | inode->i_sb->s_bdev, hash); | 921 | hash); |
| 917 | while (ce) { | 922 | while (ce) { |
| 918 | struct buffer_head *bh; | 923 | struct buffer_head *bh; |
| 919 | 924 | ||
| @@ -945,7 +950,7 @@ again: | |||
| 945 | unlock_buffer(bh); | 950 | unlock_buffer(bh); |
| 946 | brelse(bh); | 951 | brelse(bh); |
| 947 | } | 952 | } |
| 948 | ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash); | 953 | ce = mb_cache_entry_find_next(ce, inode->i_sb->s_bdev, hash); |
| 949 | } | 954 | } |
| 950 | return NULL; | 955 | return NULL; |
| 951 | } | 956 | } |
| @@ -1021,9 +1026,7 @@ static void ext2_xattr_rehash(struct ext2_xattr_header *header, | |||
| 1021 | int __init | 1026 | int __init |
| 1022 | init_ext2_xattr(void) | 1027 | init_ext2_xattr(void) |
| 1023 | { | 1028 | { |
| 1024 | ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, | 1029 | ext2_xattr_cache = mb_cache_create("ext2_xattr", 6); |
| 1025 | sizeof(struct mb_cache_entry) + | ||
| 1026 | sizeof(((struct mb_cache_entry *) 0)->e_indexes[0]), 1, 6); | ||
| 1027 | if (!ext2_xattr_cache) | 1030 | if (!ext2_xattr_cache) |
| 1028 | return -ENOMEM; | 1031 | return -ENOMEM; |
| 1029 | return 0; | 1032 | return 0; |
