diff options
Diffstat (limited to 'fs/logfs/readwrite.c')
-rw-r--r-- | fs/logfs/readwrite.c | 81 |
1 files changed, 44 insertions, 37 deletions
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 3159db6958e5..6127baf0e188 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c | |||
@@ -892,6 +892,8 @@ u64 logfs_seek_hole(struct inode *inode, u64 bix) | |||
892 | return bix; | 892 | return bix; |
893 | else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED) | 893 | else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED) |
894 | bix = maxbix(li->li_height); | 894 | bix = maxbix(li->li_height); |
895 | else if (bix >= maxbix(li->li_height)) | ||
896 | return bix; | ||
895 | else { | 897 | else { |
896 | bix = seek_holedata_loop(inode, bix, 0); | 898 | bix = seek_holedata_loop(inode, bix, 0); |
897 | if (bix < maxbix(li->li_height)) | 899 | if (bix < maxbix(li->li_height)) |
@@ -1093,17 +1095,25 @@ static int logfs_reserve_bytes(struct inode *inode, int bytes) | |||
1093 | int get_page_reserve(struct inode *inode, struct page *page) | 1095 | int get_page_reserve(struct inode *inode, struct page *page) |
1094 | { | 1096 | { |
1095 | struct logfs_super *super = logfs_super(inode->i_sb); | 1097 | struct logfs_super *super = logfs_super(inode->i_sb); |
1098 | struct logfs_block *block = logfs_block(page); | ||
1096 | int ret; | 1099 | int ret; |
1097 | 1100 | ||
1098 | if (logfs_block(page) && logfs_block(page)->reserved_bytes) | 1101 | if (block && block->reserved_bytes) |
1099 | return 0; | 1102 | return 0; |
1100 | 1103 | ||
1101 | logfs_get_wblocks(inode->i_sb, page, WF_LOCK); | 1104 | logfs_get_wblocks(inode->i_sb, page, WF_LOCK); |
1102 | ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE); | 1105 | while ((ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE)) && |
1106 | !list_empty(&super->s_writeback_list)) { | ||
1107 | block = list_entry(super->s_writeback_list.next, | ||
1108 | struct logfs_block, alias_list); | ||
1109 | block->ops->write_block(block); | ||
1110 | } | ||
1103 | if (!ret) { | 1111 | if (!ret) { |
1104 | alloc_data_block(inode, page); | 1112 | alloc_data_block(inode, page); |
1105 | logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE; | 1113 | block = logfs_block(page); |
1114 | block->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE; | ||
1106 | super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE; | 1115 | super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE; |
1116 | list_move_tail(&block->alias_list, &super->s_writeback_list); | ||
1107 | } | 1117 | } |
1108 | logfs_put_wblocks(inode->i_sb, page, WF_LOCK); | 1118 | logfs_put_wblocks(inode->i_sb, page, WF_LOCK); |
1109 | return ret; | 1119 | return ret; |
@@ -1861,7 +1871,7 @@ int logfs_truncate(struct inode *inode, u64 target) | |||
1861 | size = target; | 1871 | size = target; |
1862 | 1872 | ||
1863 | logfs_get_wblocks(sb, NULL, 1); | 1873 | logfs_get_wblocks(sb, NULL, 1); |
1864 | err = __logfs_truncate(inode, target); | 1874 | err = __logfs_truncate(inode, size); |
1865 | if (!err) | 1875 | if (!err) |
1866 | err = __logfs_write_inode(inode, 0); | 1876 | err = __logfs_write_inode(inode, 0); |
1867 | logfs_put_wblocks(sb, NULL, 1); | 1877 | logfs_put_wblocks(sb, NULL, 1); |
@@ -1962,31 +1972,6 @@ static struct page *inode_to_page(struct inode *inode) | |||
1962 | return page; | 1972 | return page; |
1963 | } | 1973 | } |
1964 | 1974 | ||
1965 | /* Cheaper version of write_inode. All changes are concealed in | ||
1966 | * aliases, which are moved back. No write to the medium happens. | ||
1967 | */ | ||
1968 | void logfs_clear_inode(struct inode *inode) | ||
1969 | { | ||
1970 | struct super_block *sb = inode->i_sb; | ||
1971 | struct logfs_inode *li = logfs_inode(inode); | ||
1972 | struct logfs_block *block = li->li_block; | ||
1973 | struct page *page; | ||
1974 | |||
1975 | /* Only deleted files may be dirty at this point */ | ||
1976 | BUG_ON(inode->i_state & I_DIRTY && inode->i_nlink); | ||
1977 | if (!block) | ||
1978 | return; | ||
1979 | if ((logfs_super(sb)->s_flags & LOGFS_SB_FLAG_SHUTDOWN)) { | ||
1980 | block->ops->free_block(inode->i_sb, block); | ||
1981 | return; | ||
1982 | } | ||
1983 | |||
1984 | BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS); | ||
1985 | page = inode_to_page(inode); | ||
1986 | BUG_ON(!page); /* FIXME: Use emergency page */ | ||
1987 | logfs_put_write_page(page); | ||
1988 | } | ||
1989 | |||
1990 | static int do_write_inode(struct inode *inode) | 1975 | static int do_write_inode(struct inode *inode) |
1991 | { | 1976 | { |
1992 | struct super_block *sb = inode->i_sb; | 1977 | struct super_block *sb = inode->i_sb; |
@@ -2154,18 +2139,40 @@ static int do_delete_inode(struct inode *inode) | |||
2154 | * ZOMBIE inodes have already been deleted before and should remain dead, | 2139 | * ZOMBIE inodes have already been deleted before and should remain dead, |
2155 | * if it weren't for valid checking. No need to kill them again here. | 2140 | * if it weren't for valid checking. No need to kill them again here. |
2156 | */ | 2141 | */ |
2157 | void logfs_delete_inode(struct inode *inode) | 2142 | void logfs_evict_inode(struct inode *inode) |
2158 | { | 2143 | { |
2144 | struct super_block *sb = inode->i_sb; | ||
2159 | struct logfs_inode *li = logfs_inode(inode); | 2145 | struct logfs_inode *li = logfs_inode(inode); |
2146 | struct logfs_block *block = li->li_block; | ||
2147 | struct page *page; | ||
2160 | 2148 | ||
2161 | if (!(li->li_flags & LOGFS_IF_ZOMBIE)) { | 2149 | if (!inode->i_nlink) { |
2162 | li->li_flags |= LOGFS_IF_ZOMBIE; | 2150 | if (!(li->li_flags & LOGFS_IF_ZOMBIE)) { |
2163 | if (i_size_read(inode) > 0) | 2151 | li->li_flags |= LOGFS_IF_ZOMBIE; |
2164 | logfs_truncate(inode, 0); | 2152 | if (i_size_read(inode) > 0) |
2165 | do_delete_inode(inode); | 2153 | logfs_truncate(inode, 0); |
2154 | do_delete_inode(inode); | ||
2155 | } | ||
2166 | } | 2156 | } |
2167 | truncate_inode_pages(&inode->i_data, 0); | 2157 | truncate_inode_pages(&inode->i_data, 0); |
2168 | clear_inode(inode); | 2158 | end_writeback(inode); |
2159 | |||
2160 | /* Cheaper version of write_inode. All changes are concealed in | ||
2161 | * aliases, which are moved back. No write to the medium happens. | ||
2162 | */ | ||
2163 | /* Only deleted files may be dirty at this point */ | ||
2164 | BUG_ON(inode->i_state & I_DIRTY && inode->i_nlink); | ||
2165 | if (!block) | ||
2166 | return; | ||
2167 | if ((logfs_super(sb)->s_flags & LOGFS_SB_FLAG_SHUTDOWN)) { | ||
2168 | block->ops->free_block(inode->i_sb, block); | ||
2169 | return; | ||
2170 | } | ||
2171 | |||
2172 | BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS); | ||
2173 | page = inode_to_page(inode); | ||
2174 | BUG_ON(!page); /* FIXME: Use emergency page */ | ||
2175 | logfs_put_write_page(page); | ||
2169 | } | 2176 | } |
2170 | 2177 | ||
2171 | void btree_write_block(struct logfs_block *block) | 2178 | void btree_write_block(struct logfs_block *block) |
@@ -2249,6 +2256,7 @@ int logfs_init_rw(struct super_block *sb) | |||
2249 | int min_fill = 3 * super->s_no_blocks; | 2256 | int min_fill = 3 * super->s_no_blocks; |
2250 | 2257 | ||
2251 | INIT_LIST_HEAD(&super->s_object_alias); | 2258 | INIT_LIST_HEAD(&super->s_object_alias); |
2259 | INIT_LIST_HEAD(&super->s_writeback_list); | ||
2252 | mutex_init(&super->s_write_mutex); | 2260 | mutex_init(&super->s_write_mutex); |
2253 | super->s_block_pool = mempool_create_kmalloc_pool(min_fill, | 2261 | super->s_block_pool = mempool_create_kmalloc_pool(min_fill, |
2254 | sizeof(struct logfs_block)); | 2262 | sizeof(struct logfs_block)); |
@@ -2261,7 +2269,6 @@ void logfs_cleanup_rw(struct super_block *sb) | |||
2261 | { | 2269 | { |
2262 | struct logfs_super *super = logfs_super(sb); | 2270 | struct logfs_super *super = logfs_super(sb); |
2263 | 2271 | ||
2264 | destroy_meta_inode(super->s_segfile_inode); | ||
2265 | logfs_mempool_destroy(super->s_block_pool); | 2272 | logfs_mempool_destroy(super->s_block_pool); |
2266 | logfs_mempool_destroy(super->s_shadow_pool); | 2273 | logfs_mempool_destroy(super->s_shadow_pool); |
2267 | } | 2274 | } |