Skip to content

Commit 607d44a

Browse files
author
Mark Fasheh
committed
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>
1 parent 3a307ff commit 607d44a

File tree

1 file changed

+80
-40
lines changed

1 file changed

+80
-40
lines changed

fs/ocfs2/aops.c

+80-40
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
849849

850850
static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
851851
struct ocfs2_super *osb, loff_t pos,
852-
unsigned len)
852+
unsigned len, struct buffer_head *di_bh)
853853
{
854854
struct ocfs2_write_ctxt *wc;
855855

@@ -859,6 +859,8 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
859859

860860
wc->w_cpos = pos >> osb->s_clustersize_bits;
861861
wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
862+
get_bh(di_bh);
863+
wc->w_di_bh = di_bh;
862864

863865
if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
864866
wc->w_large_pages = 1;
@@ -1211,9 +1213,10 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
12111213
}
12121214
}
12131215

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)
12171220
{
12181221
int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS;
12191222
unsigned int num_clusters = 0, clusters_to_alloc = 0;
@@ -1227,28 +1230,14 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
12271230
handle_t *handle;
12281231
struct ocfs2_write_cluster_desc *desc;
12291232

1230-
ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len);
1233+
ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
12311234
if (ret) {
12321235
mlog_errno(ret);
12331236
return ret;
12341237
}
12351238

1236-
ret = ocfs2_meta_lock(inode, &wc->w_di_bh, 1);
1237-
if (ret) {
1238-
mlog_errno(ret);
1239-
goto out;
1240-
}
12411239
di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
12421240

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-
12521241
for (i = 0; i < wc->w_clen; i++) {
12531242
desc = &wc->w_desc[i];
12541243
desc->c_cpos = wc->w_cpos + i;
@@ -1258,7 +1247,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
12581247
&num_clusters, NULL);
12591248
if (ret) {
12601249
mlog_errno(ret);
1261-
goto out_meta;
1250+
goto out;
12621251
}
12631252
} else if (phys) {
12641253
/*
@@ -1293,7 +1282,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
12931282
&data_ac, &meta_ac);
12941283
if (ret) {
12951284
mlog_errno(ret);
1296-
goto out_meta;
1285+
goto out;
12971286
}
12981287

12991288
credits = ocfs2_calc_extend_credits(inode->i_sb, di,
@@ -1303,17 +1292,11 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
13031292

13041293
ocfs2_set_target_boundaries(osb, wc, pos, len, clusters_to_alloc);
13051294

1306-
ret = ocfs2_data_lock(inode, 1);
1307-
if (ret) {
1308-
mlog_errno(ret);
1309-
goto out_meta;
1310-
}
1311-
13121295
handle = ocfs2_start_trans(osb, credits);
13131296
if (IS_ERR(handle)) {
13141297
ret = PTR_ERR(handle);
13151298
mlog_errno(ret);
1316-
goto out_data;
1299+
goto out;
13171300
}
13181301

13191302
wc->w_handle = handle;
@@ -1363,13 +1346,6 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
13631346
out_commit:
13641347
ocfs2_commit_trans(osb, handle);
13651348

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-
13731349
out:
13741350
ocfs2_free_write_ctxt(wc);
13751351

@@ -1380,9 +1356,60 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
13801356
return ret;
13811357
}
13821358

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)
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)
13861413
{
13871414
int i;
13881415
unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
@@ -1444,12 +1471,25 @@ int ocfs2_write_end(struct file *file, struct address_space *mapping,
14441471
ocfs2_journal_dirty(handle, wc->w_di_bh);
14451472

14461473
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+
14471488
ocfs2_data_unlock(inode, 1);
14481489
up_write(&OCFS2_I(inode)->ip_alloc_sem);
14491490
ocfs2_meta_unlock(inode, 1);
1450-
ocfs2_free_write_ctxt(wc);
14511491

1452-
return copied;
1492+
return ret;
14531493
}
14541494

14551495
const struct address_space_operations ocfs2_aops = {

0 commit comments

Comments
 (0)