aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/aops.c120
1 files changed, 80 insertions, 40 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 3e5758ebd932..fc723fb9c981 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -849,7 +849,7 @@ static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
849 849
850static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, 850static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
851 struct ocfs2_super *osb, loff_t pos, 851 struct ocfs2_super *osb, loff_t pos,
852 unsigned len) 852 unsigned len, struct buffer_head *di_bh)
853{ 853{
854 struct ocfs2_write_ctxt *wc; 854 struct ocfs2_write_ctxt *wc;
855 855
@@ -859,6 +859,8 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
859 859
860 wc->w_cpos = pos >> osb->s_clustersize_bits; 860 wc->w_cpos = pos >> osb->s_clustersize_bits;
861 wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len); 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 if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits)) 865 if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
864 wc->w_large_pages = 1; 866 wc->w_large_pages = 1;
@@ -1211,9 +1213,10 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
1211 } 1213 }
1212} 1214}
1213 1215
1214int ocfs2_write_begin(struct file *file, struct address_space *mapping, 1216static int ocfs2_write_begin_nolock(struct address_space *mapping,
1215 loff_t pos, unsigned len, unsigned flags, 1217 loff_t pos, unsigned len, unsigned flags,
1216 struct page **pagep, void **fsdata) 1218 struct page **pagep, void **fsdata,
1219 struct buffer_head *di_bh)
1217{ 1220{
1218 int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS; 1221 int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS;
1219 unsigned int num_clusters = 0, clusters_to_alloc = 0; 1222 unsigned int num_clusters = 0, clusters_to_alloc = 0;
@@ -1227,28 +1230,14 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
1227 handle_t *handle; 1230 handle_t *handle;
1228 struct ocfs2_write_cluster_desc *desc; 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 if (ret) { 1234 if (ret) {
1232 mlog_errno(ret); 1235 mlog_errno(ret);
1233 return ret; 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 di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; 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 for (i = 0; i < wc->w_clen; i++) { 1241 for (i = 0; i < wc->w_clen; i++) {
1253 desc = &wc->w_desc[i]; 1242 desc = &wc->w_desc[i];
1254 desc->c_cpos = wc->w_cpos + i; 1243 desc->c_cpos = wc->w_cpos + i;
@@ -1258,7 +1247,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
1258 &num_clusters, NULL); 1247 &num_clusters, NULL);
1259 if (ret) { 1248 if (ret) {
1260 mlog_errno(ret); 1249 mlog_errno(ret);
1261 goto out_meta; 1250 goto out;
1262 } 1251 }
1263 } else if (phys) { 1252 } else if (phys) {
1264 /* 1253 /*
@@ -1293,7 +1282,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
1293 &data_ac, &meta_ac); 1282 &data_ac, &meta_ac);
1294 if (ret) { 1283 if (ret) {
1295 mlog_errno(ret); 1284 mlog_errno(ret);
1296 goto out_meta; 1285 goto out;
1297 } 1286 }
1298 1287
1299 credits = ocfs2_calc_extend_credits(inode->i_sb, di, 1288 credits = ocfs2_calc_extend_credits(inode->i_sb, di,
@@ -1303,17 +1292,11 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
1303 1292
1304 ocfs2_set_target_boundaries(osb, wc, pos, len, clusters_to_alloc); 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 handle = ocfs2_start_trans(osb, credits); 1295 handle = ocfs2_start_trans(osb, credits);
1313 if (IS_ERR(handle)) { 1296 if (IS_ERR(handle)) {
1314 ret = PTR_ERR(handle); 1297 ret = PTR_ERR(handle);
1315 mlog_errno(ret); 1298 mlog_errno(ret);
1316 goto out_data; 1299 goto out;
1317 } 1300 }
1318 1301
1319 wc->w_handle = handle; 1302 wc->w_handle = handle;
@@ -1363,13 +1346,6 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
1363out_commit: 1346out_commit:
1364 ocfs2_commit_trans(osb, handle); 1347 ocfs2_commit_trans(osb, handle);
1365 1348
1366out_data:
1367 ocfs2_data_unlock(inode, 1);
1368
1369out_meta:
1370 up_write(&OCFS2_I(inode)->ip_alloc_sem);
1371 ocfs2_meta_unlock(inode, 1);
1372
1373out: 1349out:
1374 ocfs2_free_write_ctxt(wc); 1350 ocfs2_free_write_ctxt(wc);
1375 1351
@@ -1380,9 +1356,60 @@ out:
1380 return ret; 1356 return ret;
1381} 1357}
1382 1358
1383int ocfs2_write_end(struct file *file, struct address_space *mapping, 1359int ocfs2_write_begin(struct file *file, struct address_space *mapping,
1384 loff_t pos, unsigned len, unsigned copied, 1360 loff_t pos, unsigned len, unsigned flags,
1385 struct page *page, void *fsdata) 1361 struct page **pagep, void **fsdata)
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
1399out_fail_data:
1400 ocfs2_data_unlock(inode, 1);
1401out_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
1410static int ocfs2_write_end_nolock(struct address_space *mapping,
1411 loff_t pos, unsigned len, unsigned copied,
1412 struct page *page, void *fsdata)
1386{ 1413{
1387 int i; 1414 int i;
1388 unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1); 1415 unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
@@ -1444,12 +1471,25 @@ int ocfs2_write_end(struct file *file, struct address_space *mapping,
1444 ocfs2_journal_dirty(handle, wc->w_di_bh); 1471 ocfs2_journal_dirty(handle, wc->w_di_bh);
1445 1472
1446 ocfs2_commit_trans(osb, handle); 1473 ocfs2_commit_trans(osb, handle);
1474 ocfs2_free_write_ctxt(wc);
1475
1476 return copied;
1477}
1478
1479int 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 ocfs2_data_unlock(inode, 1); 1488 ocfs2_data_unlock(inode, 1);
1448 up_write(&OCFS2_I(inode)->ip_alloc_sem); 1489 up_write(&OCFS2_I(inode)->ip_alloc_sem);
1449 ocfs2_meta_unlock(inode, 1); 1490 ocfs2_meta_unlock(inode, 1);
1450 ocfs2_free_write_ctxt(wc);
1451 1491
1452 return copied; 1492 return ret;
1453} 1493}
1454 1494
1455const struct address_space_operations ocfs2_aops = { 1495const struct address_space_operations ocfs2_aops = {