Commit 607d44aa3fa6f40b0facaf1028886ed362b92682

Authored by Mark Fasheh
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

... ... @@ -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 = {