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); |