diff options
Diffstat (limited to 'fs/ext2/inode.c')
| -rw-r--r-- | fs/ext2/inode.c | 87 |
1 files changed, 42 insertions, 45 deletions
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); |
