aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2007-10-16 04:25:05 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:42:55 -0400
commitbfc1af650a8f36feba6b90a6c398325f885c00bc (patch)
treec7db5bbfad01d2c18533e7a128027e26d1992a42 /fs/ext4
parentf4fc66a894546bdc88a775d0e83ad20a65210bcb (diff)
ext4: convert to new aops
Convert ext4 to use write_begin()/write_end() methods. Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com> Signed-off-by: Nick Piggin <npiggin@suse.de> Cc: Dmitriy Monakhov <dmonakhov@sw.ru> Cc: Mark Fasheh <mark.fasheh@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/inode.c174
1 files changed, 120 insertions, 54 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a4848e04a5ed..0df2b1e06d0b 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1146,34 +1146,50 @@ static int do_journal_get_write_access(handle_t *handle,
1146 return ext4_journal_get_write_access(handle, bh); 1146 return ext4_journal_get_write_access(handle, bh);
1147} 1147}
1148 1148
1149static int ext4_prepare_write(struct file *file, struct page *page, 1149static int ext4_write_begin(struct file *file, struct address_space *mapping,
1150 unsigned from, unsigned to) 1150 loff_t pos, unsigned len, unsigned flags,
1151 struct page **pagep, void **fsdata)
1151{ 1152{
1152 struct inode *inode = page->mapping->host; 1153 struct inode *inode = mapping->host;
1153 int ret, needed_blocks = ext4_writepage_trans_blocks(inode); 1154 int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
1154 handle_t *handle; 1155 handle_t *handle;
1155 int retries = 0; 1156 int retries = 0;
1157 struct page *page;
1158 pgoff_t index;
1159 unsigned from, to;
1160
1161 index = pos >> PAGE_CACHE_SHIFT;
1162 from = pos & (PAGE_CACHE_SIZE - 1);
1163 to = from + len;
1156 1164
1157retry: 1165retry:
1158 handle = ext4_journal_start(inode, needed_blocks); 1166 page = __grab_cache_page(mapping, index);
1159 if (IS_ERR(handle)) { 1167 if (!page)
1160 ret = PTR_ERR(handle); 1168 return -ENOMEM;
1161 goto out; 1169 *pagep = page;
1170
1171 handle = ext4_journal_start(inode, needed_blocks);
1172 if (IS_ERR(handle)) {
1173 unlock_page(page);
1174 page_cache_release(page);
1175 ret = PTR_ERR(handle);
1176 goto out;
1162 } 1177 }
1163 if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
1164 ret = nobh_prepare_write(page, from, to, ext4_get_block);
1165 else
1166 ret = block_prepare_write(page, from, to, ext4_get_block);
1167 if (ret)
1168 goto prepare_write_failed;
1169 1178
1170 if (ext4_should_journal_data(inode)) { 1179 ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
1180 ext4_get_block);
1181
1182 if (!ret && ext4_should_journal_data(inode)) {
1171 ret = walk_page_buffers(handle, page_buffers(page), 1183 ret = walk_page_buffers(handle, page_buffers(page),
1172 from, to, NULL, do_journal_get_write_access); 1184 from, to, NULL, do_journal_get_write_access);
1173 } 1185 }
1174prepare_write_failed: 1186
1175 if (ret) 1187 if (ret) {
1176 ext4_journal_stop(handle); 1188 ext4_journal_stop(handle);
1189 unlock_page(page);
1190 page_cache_release(page);
1191 }
1192
1177 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 1193 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
1178 goto retry; 1194 goto retry;
1179out: 1195out:
@@ -1185,12 +1201,12 @@ int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
1185 int err = jbd2_journal_dirty_data(handle, bh); 1201 int err = jbd2_journal_dirty_data(handle, bh);
1186 if (err) 1202 if (err)
1187 ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__, 1203 ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__,
1188 bh, handle,err); 1204 bh, handle, err);
1189 return err; 1205 return err;
1190} 1206}
1191 1207
1192/* For commit_write() in data=journal mode */ 1208/* For write_end() in data=journal mode */
1193static int commit_write_fn(handle_t *handle, struct buffer_head *bh) 1209static int write_end_fn(handle_t *handle, struct buffer_head *bh)
1194{ 1210{
1195 if (!buffer_mapped(bh) || buffer_freed(bh)) 1211 if (!buffer_mapped(bh) || buffer_freed(bh))
1196 return 0; 1212 return 0;
@@ -1199,84 +1215,130 @@ static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
1199} 1215}
1200 1216
1201/* 1217/*
1218 * Generic write_end handler for ordered and writeback ext4 journal modes.
1219 * We can't use generic_write_end, because that unlocks the page and we need to
1220 * unlock the page after ext4_journal_stop, but ext4_journal_stop must run
1221 * after block_write_end.
1222 */
1223static int ext4_generic_write_end(struct file *file,
1224 struct address_space *mapping,
1225 loff_t pos, unsigned len, unsigned copied,
1226 struct page *page, void *fsdata)
1227{
1228 struct inode *inode = file->f_mapping->host;
1229
1230 copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
1231
1232 if (pos+copied > inode->i_size) {
1233 i_size_write(inode, pos+copied);
1234 mark_inode_dirty(inode);
1235 }
1236
1237 return copied;
1238}
1239
1240/*
1202 * We need to pick up the new inode size which generic_commit_write gave us 1241 * We need to pick up the new inode size which generic_commit_write gave us
1203 * `file' can be NULL - eg, when called from page_symlink(). 1242 * `file' can be NULL - eg, when called from page_symlink().
1204 * 1243 *
1205 * ext4 never places buffers on inode->i_mapping->private_list. metadata 1244 * ext4 never places buffers on inode->i_mapping->private_list. metadata
1206 * buffers are managed internally. 1245 * buffers are managed internally.
1207 */ 1246 */
1208static int ext4_ordered_commit_write(struct file *file, struct page *page, 1247static int ext4_ordered_write_end(struct file *file,
1209 unsigned from, unsigned to) 1248 struct address_space *mapping,
1249 loff_t pos, unsigned len, unsigned copied,
1250 struct page *page, void *fsdata)
1210{ 1251{
1211 handle_t *handle = ext4_journal_current_handle(); 1252 handle_t *handle = ext4_journal_current_handle();
1212 struct inode *inode = page->mapping->host; 1253 struct inode *inode = file->f_mapping->host;
1254 unsigned from, to;
1213 int ret = 0, ret2; 1255 int ret = 0, ret2;
1214 1256
1257 from = pos & (PAGE_CACHE_SIZE - 1);
1258 to = from + len;
1259
1215 ret = walk_page_buffers(handle, page_buffers(page), 1260 ret = walk_page_buffers(handle, page_buffers(page),
1216 from, to, NULL, ext4_journal_dirty_data); 1261 from, to, NULL, ext4_journal_dirty_data);
1217 1262
1218 if (ret == 0) { 1263 if (ret == 0) {
1219 /* 1264 /*
1220 * generic_commit_write() will run mark_inode_dirty() if i_size 1265 * generic_write_end() will run mark_inode_dirty() if i_size
1221 * changes. So let's piggyback the i_disksize mark_inode_dirty 1266 * changes. So let's piggyback the i_disksize mark_inode_dirty
1222 * into that. 1267 * into that.
1223 */ 1268 */
1224 loff_t new_i_size; 1269 loff_t new_i_size;
1225 1270
1226 new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; 1271 new_i_size = pos + copied;
1227 if (new_i_size > EXT4_I(inode)->i_disksize) 1272 if (new_i_size > EXT4_I(inode)->i_disksize)
1228 EXT4_I(inode)->i_disksize = new_i_size; 1273 EXT4_I(inode)->i_disksize = new_i_size;
1229 ret = generic_commit_write(file, page, from, to); 1274 copied = ext4_generic_write_end(file, mapping, pos, len, copied,
1275 page, fsdata);
1276 if (copied < 0)
1277 ret = copied;
1230 } 1278 }
1231 ret2 = ext4_journal_stop(handle); 1279 ret2 = ext4_journal_stop(handle);
1232 if (!ret) 1280 if (!ret)
1233 ret = ret2; 1281 ret = ret2;
1234 return ret; 1282 unlock_page(page);
1283 page_cache_release(page);
1284
1285 return ret ? ret : copied;
1235} 1286}
1236 1287
1237static int ext4_writeback_commit_write(struct file *file, struct page *page, 1288static int ext4_writeback_write_end(struct file *file,
1238 unsigned from, unsigned to) 1289 struct address_space *mapping,
1290 loff_t pos, unsigned len, unsigned copied,
1291 struct page *page, void *fsdata)
1239{ 1292{
1240 handle_t *handle = ext4_journal_current_handle(); 1293 handle_t *handle = ext4_journal_current_handle();
1241 struct inode *inode = page->mapping->host; 1294 struct inode *inode = file->f_mapping->host;
1242 int ret = 0, ret2; 1295 int ret = 0, ret2;
1243 loff_t new_i_size; 1296 loff_t new_i_size;
1244 1297
1245 new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; 1298 new_i_size = pos + copied;
1246 if (new_i_size > EXT4_I(inode)->i_disksize) 1299 if (new_i_size > EXT4_I(inode)->i_disksize)
1247 EXT4_I(inode)->i_disksize = new_i_size; 1300 EXT4_I(inode)->i_disksize = new_i_size;
1248 1301
1249 if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) 1302 copied = ext4_generic_write_end(file, mapping, pos, len, copied,
1250 ret = nobh_commit_write(file, page, from, to); 1303 page, fsdata);
1251 else 1304 if (copied < 0)
1252 ret = generic_commit_write(file, page, from, to); 1305 ret = copied;
1253 1306
1254 ret2 = ext4_journal_stop(handle); 1307 ret2 = ext4_journal_stop(handle);
1255 if (!ret) 1308 if (!ret)
1256 ret = ret2; 1309 ret = ret2;
1257 return ret; 1310 unlock_page(page);
1311 page_cache_release(page);
1312
1313 return ret ? ret : copied;
1258} 1314}
1259 1315
1260static int ext4_journalled_commit_write(struct file *file, 1316static int ext4_journalled_write_end(struct file *file,
1261 struct page *page, unsigned from, unsigned to) 1317 struct address_space *mapping,
1318 loff_t pos, unsigned len, unsigned copied,
1319 struct page *page, void *fsdata)
1262{ 1320{
1263 handle_t *handle = ext4_journal_current_handle(); 1321 handle_t *handle = ext4_journal_current_handle();
1264 struct inode *inode = page->mapping->host; 1322 struct inode *inode = mapping->host;
1265 int ret = 0, ret2; 1323 int ret = 0, ret2;
1266 int partial = 0; 1324 int partial = 0;
1267 loff_t pos; 1325 unsigned from, to;
1268 1326
1269 /* 1327 from = pos & (PAGE_CACHE_SIZE - 1);
1270 * Here we duplicate the generic_commit_write() functionality 1328 to = from + len;
1271 */ 1329
1272 pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; 1330 if (copied < len) {
1331 if (!PageUptodate(page))
1332 copied = 0;
1333 page_zero_new_buffers(page, from+copied, to);
1334 }
1273 1335
1274 ret = walk_page_buffers(handle, page_buffers(page), from, 1336 ret = walk_page_buffers(handle, page_buffers(page), from,
1275 to, &partial, commit_write_fn); 1337 to, &partial, write_end_fn);
1276 if (!partial) 1338 if (!partial)
1277 SetPageUptodate(page); 1339 SetPageUptodate(page);
1278 if (pos > inode->i_size) 1340 if (pos+copied > inode->i_size)
1279 i_size_write(inode, pos); 1341 i_size_write(inode, pos+copied);
1280 EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; 1342 EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
1281 if (inode->i_size > EXT4_I(inode)->i_disksize) { 1343 if (inode->i_size > EXT4_I(inode)->i_disksize) {
1282 EXT4_I(inode)->i_disksize = inode->i_size; 1344 EXT4_I(inode)->i_disksize = inode->i_size;
@@ -1284,10 +1346,14 @@ static int ext4_journalled_commit_write(struct file *file,
1284 if (!ret) 1346 if (!ret)
1285 ret = ret2; 1347 ret = ret2;
1286 } 1348 }
1349
1287 ret2 = ext4_journal_stop(handle); 1350 ret2 = ext4_journal_stop(handle);
1288 if (!ret) 1351 if (!ret)
1289 ret = ret2; 1352 ret = ret2;
1290 return ret; 1353 unlock_page(page);
1354 page_cache_release(page);
1355
1356 return ret ? ret : copied;
1291} 1357}
1292 1358
1293/* 1359/*
@@ -1545,7 +1611,7 @@ static int ext4_journalled_writepage(struct page *page,
1545 PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); 1611 PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
1546 1612
1547 err = walk_page_buffers(handle, page_buffers(page), 0, 1613 err = walk_page_buffers(handle, page_buffers(page), 0,
1548 PAGE_CACHE_SIZE, NULL, commit_write_fn); 1614 PAGE_CACHE_SIZE, NULL, write_end_fn);
1549 if (ret == 0) 1615 if (ret == 0)
1550 ret = err; 1616 ret = err;
1551 EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; 1617 EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
@@ -1705,8 +1771,8 @@ static const struct address_space_operations ext4_ordered_aops = {
1705 .readpages = ext4_readpages, 1771 .readpages = ext4_readpages,
1706 .writepage = ext4_ordered_writepage, 1772 .writepage = ext4_ordered_writepage,
1707 .sync_page = block_sync_page, 1773 .sync_page = block_sync_page,
1708 .prepare_write = ext4_prepare_write, 1774 .write_begin = ext4_write_begin,
1709 .commit_write = ext4_ordered_commit_write, 1775 .write_end = ext4_ordered_write_end,
1710 .bmap = ext4_bmap, 1776 .bmap = ext4_bmap,
1711 .invalidatepage = ext4_invalidatepage, 1777 .invalidatepage = ext4_invalidatepage,
1712 .releasepage = ext4_releasepage, 1778 .releasepage = ext4_releasepage,
@@ -1719,8 +1785,8 @@ static const struct address_space_operations ext4_writeback_aops = {
1719 .readpages = ext4_readpages, 1785 .readpages = ext4_readpages,
1720 .writepage = ext4_writeback_writepage, 1786 .writepage = ext4_writeback_writepage,
1721 .sync_page = block_sync_page, 1787 .sync_page = block_sync_page,
1722 .prepare_write = ext4_prepare_write, 1788 .write_begin = ext4_write_begin,
1723 .commit_write = ext4_writeback_commit_write, 1789 .write_end = ext4_writeback_write_end,
1724 .bmap = ext4_bmap, 1790 .bmap = ext4_bmap,
1725 .invalidatepage = ext4_invalidatepage, 1791 .invalidatepage = ext4_invalidatepage,
1726 .releasepage = ext4_releasepage, 1792 .releasepage = ext4_releasepage,
@@ -1733,8 +1799,8 @@ static const struct address_space_operations ext4_journalled_aops = {
1733 .readpages = ext4_readpages, 1799 .readpages = ext4_readpages,
1734 .writepage = ext4_journalled_writepage, 1800 .writepage = ext4_journalled_writepage,
1735 .sync_page = block_sync_page, 1801 .sync_page = block_sync_page,
1736 .prepare_write = ext4_prepare_write, 1802 .write_begin = ext4_write_begin,
1737 .commit_write = ext4_journalled_commit_write, 1803 .write_end = ext4_journalled_write_end,
1738 .set_page_dirty = ext4_journalled_set_page_dirty, 1804 .set_page_dirty = ext4_journalled_set_page_dirty,
1739 .bmap = ext4_bmap, 1805 .bmap = ext4_bmap,
1740 .invalidatepage = ext4_invalidatepage, 1806 .invalidatepage = ext4_invalidatepage,