Commit 607d44aa3fa6f40b0facaf1028886ed362b92682
1 parent
3a307ffc27
ocfs2: factor out write aops into nolock variants
ocfs2_mkwrite() will want this so that it can add some mmap specific checks before asking for a write. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Showing 1 changed file with 80 additions and 40 deletions Side-by-side Diff
fs/ocfs2/aops.c
... | ... | @@ -849,7 +849,7 @@ |
849 | 849 | |
850 | 850 | static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, |
851 | 851 | struct ocfs2_super *osb, loff_t pos, |
852 | - unsigned len) | |
852 | + unsigned len, struct buffer_head *di_bh) | |
853 | 853 | { |
854 | 854 | struct ocfs2_write_ctxt *wc; |
855 | 855 | |
... | ... | @@ -859,6 +859,8 @@ |
859 | 859 | |
860 | 860 | wc->w_cpos = pos >> osb->s_clustersize_bits; |
861 | 861 | wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len); |
862 | + get_bh(di_bh); | |
863 | + wc->w_di_bh = di_bh; | |
862 | 864 | |
863 | 865 | if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits)) |
864 | 866 | wc->w_large_pages = 1; |
... | ... | @@ -1211,9 +1213,10 @@ |
1211 | 1213 | } |
1212 | 1214 | } |
1213 | 1215 | |
1214 | -int ocfs2_write_begin(struct file *file, struct address_space *mapping, | |
1215 | - loff_t pos, unsigned len, unsigned flags, | |
1216 | - struct page **pagep, void **fsdata) | |
1216 | +static int ocfs2_write_begin_nolock(struct address_space *mapping, | |
1217 | + loff_t pos, unsigned len, unsigned flags, | |
1218 | + struct page **pagep, void **fsdata, | |
1219 | + struct buffer_head *di_bh) | |
1217 | 1220 | { |
1218 | 1221 | int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS; |
1219 | 1222 | unsigned int num_clusters = 0, clusters_to_alloc = 0; |
1220 | 1223 | |
1221 | 1224 | |
... | ... | @@ -1227,28 +1230,14 @@ |
1227 | 1230 | handle_t *handle; |
1228 | 1231 | struct ocfs2_write_cluster_desc *desc; |
1229 | 1232 | |
1230 | - ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len); | |
1233 | + ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh); | |
1231 | 1234 | if (ret) { |
1232 | 1235 | mlog_errno(ret); |
1233 | 1236 | return ret; |
1234 | 1237 | } |
1235 | 1238 | |
1236 | - ret = ocfs2_meta_lock(inode, &wc->w_di_bh, 1); | |
1237 | - if (ret) { | |
1238 | - mlog_errno(ret); | |
1239 | - goto out; | |
1240 | - } | |
1241 | 1239 | di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; |
1242 | 1240 | |
1243 | - /* | |
1244 | - * Take alloc sem here to prevent concurrent lookups. That way | |
1245 | - * the mapping, zeroing and tree manipulation within | |
1246 | - * ocfs2_write() will be safe against ->readpage(). This | |
1247 | - * should also serve to lock out allocation from a shared | |
1248 | - * writeable region. | |
1249 | - */ | |
1250 | - down_write(&OCFS2_I(inode)->ip_alloc_sem); | |
1251 | - | |
1252 | 1241 | for (i = 0; i < wc->w_clen; i++) { |
1253 | 1242 | desc = &wc->w_desc[i]; |
1254 | 1243 | desc->c_cpos = wc->w_cpos + i; |
... | ... | @@ -1258,7 +1247,7 @@ |
1258 | 1247 | &num_clusters, NULL); |
1259 | 1248 | if (ret) { |
1260 | 1249 | mlog_errno(ret); |
1261 | - goto out_meta; | |
1250 | + goto out; | |
1262 | 1251 | } |
1263 | 1252 | } else if (phys) { |
1264 | 1253 | /* |
... | ... | @@ -1293,7 +1282,7 @@ |
1293 | 1282 | &data_ac, &meta_ac); |
1294 | 1283 | if (ret) { |
1295 | 1284 | mlog_errno(ret); |
1296 | - goto out_meta; | |
1285 | + goto out; | |
1297 | 1286 | } |
1298 | 1287 | |
1299 | 1288 | credits = ocfs2_calc_extend_credits(inode->i_sb, di, |
1300 | 1289 | |
... | ... | @@ -1303,17 +1292,11 @@ |
1303 | 1292 | |
1304 | 1293 | ocfs2_set_target_boundaries(osb, wc, pos, len, clusters_to_alloc); |
1305 | 1294 | |
1306 | - ret = ocfs2_data_lock(inode, 1); | |
1307 | - if (ret) { | |
1308 | - mlog_errno(ret); | |
1309 | - goto out_meta; | |
1310 | - } | |
1311 | - | |
1312 | 1295 | handle = ocfs2_start_trans(osb, credits); |
1313 | 1296 | if (IS_ERR(handle)) { |
1314 | 1297 | ret = PTR_ERR(handle); |
1315 | 1298 | mlog_errno(ret); |
1316 | - goto out_data; | |
1299 | + goto out; | |
1317 | 1300 | } |
1318 | 1301 | |
1319 | 1302 | wc->w_handle = handle; |
... | ... | @@ -1363,13 +1346,6 @@ |
1363 | 1346 | out_commit: |
1364 | 1347 | ocfs2_commit_trans(osb, handle); |
1365 | 1348 | |
1366 | -out_data: | |
1367 | - ocfs2_data_unlock(inode, 1); | |
1368 | - | |
1369 | -out_meta: | |
1370 | - up_write(&OCFS2_I(inode)->ip_alloc_sem); | |
1371 | - ocfs2_meta_unlock(inode, 1); | |
1372 | - | |
1373 | 1349 | out: |
1374 | 1350 | ocfs2_free_write_ctxt(wc); |
1375 | 1351 | |
1376 | 1352 | |
... | ... | @@ -1380,10 +1356,61 @@ |
1380 | 1356 | return ret; |
1381 | 1357 | } |
1382 | 1358 | |
1383 | -int ocfs2_write_end(struct file *file, struct address_space *mapping, | |
1384 | - loff_t pos, unsigned len, unsigned copied, | |
1385 | - struct page *page, void *fsdata) | |
1359 | +int ocfs2_write_begin(struct file *file, struct address_space *mapping, | |
1360 | + loff_t pos, unsigned len, unsigned flags, | |
1361 | + struct page **pagep, void **fsdata) | |
1386 | 1362 | { |
1363 | + int ret; | |
1364 | + struct buffer_head *di_bh = NULL; | |
1365 | + struct inode *inode = mapping->host; | |
1366 | + | |
1367 | + ret = ocfs2_meta_lock(inode, &di_bh, 1); | |
1368 | + if (ret) { | |
1369 | + mlog_errno(ret); | |
1370 | + return ret; | |
1371 | + } | |
1372 | + | |
1373 | + /* | |
1374 | + * Take alloc sem here to prevent concurrent lookups. That way | |
1375 | + * the mapping, zeroing and tree manipulation within | |
1376 | + * ocfs2_write() will be safe against ->readpage(). This | |
1377 | + * should also serve to lock out allocation from a shared | |
1378 | + * writeable region. | |
1379 | + */ | |
1380 | + down_write(&OCFS2_I(inode)->ip_alloc_sem); | |
1381 | + | |
1382 | + ret = ocfs2_data_lock(inode, 1); | |
1383 | + if (ret) { | |
1384 | + mlog_errno(ret); | |
1385 | + goto out_fail; | |
1386 | + } | |
1387 | + | |
1388 | + ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep, | |
1389 | + fsdata, di_bh); | |
1390 | + if (ret) { | |
1391 | + mlog_errno(ret); | |
1392 | + goto out_fail_data; | |
1393 | + } | |
1394 | + | |
1395 | + brelse(di_bh); | |
1396 | + | |
1397 | + return 0; | |
1398 | + | |
1399 | +out_fail_data: | |
1400 | + ocfs2_data_unlock(inode, 1); | |
1401 | +out_fail: | |
1402 | + up_write(&OCFS2_I(inode)->ip_alloc_sem); | |
1403 | + | |
1404 | + brelse(di_bh); | |
1405 | + ocfs2_meta_unlock(inode, 1); | |
1406 | + | |
1407 | + return ret; | |
1408 | +} | |
1409 | + | |
1410 | +static int ocfs2_write_end_nolock(struct address_space *mapping, | |
1411 | + loff_t pos, unsigned len, unsigned copied, | |
1412 | + struct page *page, void *fsdata) | |
1413 | +{ | |
1387 | 1414 | int i; |
1388 | 1415 | unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1); |
1389 | 1416 | struct inode *inode = mapping->host; |
1390 | 1417 | |
1391 | 1418 | |
... | ... | @@ -1444,12 +1471,25 @@ |
1444 | 1471 | ocfs2_journal_dirty(handle, wc->w_di_bh); |
1445 | 1472 | |
1446 | 1473 | ocfs2_commit_trans(osb, handle); |
1474 | + ocfs2_free_write_ctxt(wc); | |
1475 | + | |
1476 | + return copied; | |
1477 | +} | |
1478 | + | |
1479 | +int ocfs2_write_end(struct file *file, struct address_space *mapping, | |
1480 | + loff_t pos, unsigned len, unsigned copied, | |
1481 | + struct page *page, void *fsdata) | |
1482 | +{ | |
1483 | + int ret; | |
1484 | + struct inode *inode = mapping->host; | |
1485 | + | |
1486 | + ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata); | |
1487 | + | |
1447 | 1488 | ocfs2_data_unlock(inode, 1); |
1448 | 1489 | up_write(&OCFS2_I(inode)->ip_alloc_sem); |
1449 | 1490 | ocfs2_meta_unlock(inode, 1); |
1450 | - ocfs2_free_write_ctxt(wc); | |
1451 | 1491 | |
1452 | - return copied; | |
1492 | + return ret; | |
1453 | 1493 | } |
1454 | 1494 | |
1455 | 1495 | const struct address_space_operations ocfs2_aops = { |