diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-05-09 18:16:19 -0400 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-07-10 20:31:51 -0400 |
commit | 7307de80510a70e5e5aa98de1e80ccbb7d90a3a8 (patch) | |
tree | ba45bef3e0b875feb67b97aebe8295159852ef97 /fs/ocfs2/aops.c | |
parent | 607d44aa3fa6f40b0facaf1028886ed362b92682 (diff) |
ocfs2: shared writeable mmap
Implement cluster consistent shared writeable mappings using the
->page_mkwrite() callback.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/aops.c')
-rw-r--r-- | fs/ocfs2/aops.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index fc723fb9c981..b8869fd0884f 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1034,7 +1034,8 @@ out: | |||
1034 | */ | 1034 | */ |
1035 | static int ocfs2_grab_pages_for_write(struct address_space *mapping, | 1035 | static int ocfs2_grab_pages_for_write(struct address_space *mapping, |
1036 | struct ocfs2_write_ctxt *wc, | 1036 | struct ocfs2_write_ctxt *wc, |
1037 | u32 cpos, loff_t user_pos, int new) | 1037 | u32 cpos, loff_t user_pos, int new, |
1038 | struct page *mmap_page) | ||
1038 | { | 1039 | { |
1039 | int ret = 0, i; | 1040 | int ret = 0, i; |
1040 | unsigned long start, target_index, index; | 1041 | unsigned long start, target_index, index; |
@@ -1058,11 +1059,36 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping, | |||
1058 | for(i = 0; i < wc->w_num_pages; i++) { | 1059 | for(i = 0; i < wc->w_num_pages; i++) { |
1059 | index = start + i; | 1060 | index = start + i; |
1060 | 1061 | ||
1061 | wc->w_pages[i] = find_or_create_page(mapping, index, GFP_NOFS); | 1062 | if (index == target_index && mmap_page) { |
1062 | if (!wc->w_pages[i]) { | 1063 | /* |
1063 | ret = -ENOMEM; | 1064 | * ocfs2_pagemkwrite() is a little different |
1064 | mlog_errno(ret); | 1065 | * and wants us to directly use the page |
1065 | goto out; | 1066 | * passed in. |
1067 | */ | ||
1068 | lock_page(mmap_page); | ||
1069 | |||
1070 | if (mmap_page->mapping != mapping) { | ||
1071 | unlock_page(mmap_page); | ||
1072 | /* | ||
1073 | * Sanity check - the locking in | ||
1074 | * ocfs2_pagemkwrite() should ensure | ||
1075 | * that this code doesn't trigger. | ||
1076 | */ | ||
1077 | ret = -EINVAL; | ||
1078 | mlog_errno(ret); | ||
1079 | goto out; | ||
1080 | } | ||
1081 | |||
1082 | page_cache_get(mmap_page); | ||
1083 | wc->w_pages[i] = mmap_page; | ||
1084 | } else { | ||
1085 | wc->w_pages[i] = find_or_create_page(mapping, index, | ||
1086 | GFP_NOFS); | ||
1087 | if (!wc->w_pages[i]) { | ||
1088 | ret = -ENOMEM; | ||
1089 | mlog_errno(ret); | ||
1090 | goto out; | ||
1091 | } | ||
1066 | } | 1092 | } |
1067 | 1093 | ||
1068 | if (index == target_index) | 1094 | if (index == target_index) |
@@ -1213,10 +1239,10 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb, | |||
1213 | } | 1239 | } |
1214 | } | 1240 | } |
1215 | 1241 | ||
1216 | static int ocfs2_write_begin_nolock(struct address_space *mapping, | 1242 | int ocfs2_write_begin_nolock(struct address_space *mapping, |
1217 | loff_t pos, unsigned len, unsigned flags, | 1243 | loff_t pos, unsigned len, unsigned flags, |
1218 | struct page **pagep, void **fsdata, | 1244 | struct page **pagep, void **fsdata, |
1219 | struct buffer_head *di_bh) | 1245 | struct buffer_head *di_bh, struct page *mmap_page) |
1220 | { | 1246 | { |
1221 | int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS; | 1247 | int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS; |
1222 | unsigned int num_clusters = 0, clusters_to_alloc = 0; | 1248 | unsigned int num_clusters = 0, clusters_to_alloc = 0; |
@@ -1318,7 +1344,7 @@ static int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
1318 | * extent. | 1344 | * extent. |
1319 | */ | 1345 | */ |
1320 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, | 1346 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, |
1321 | clusters_to_alloc); | 1347 | clusters_to_alloc, mmap_page); |
1322 | if (ret) { | 1348 | if (ret) { |
1323 | mlog_errno(ret); | 1349 | mlog_errno(ret); |
1324 | goto out_commit; | 1350 | goto out_commit; |
@@ -1386,7 +1412,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping, | |||
1386 | } | 1412 | } |
1387 | 1413 | ||
1388 | ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep, | 1414 | ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep, |
1389 | fsdata, di_bh); | 1415 | fsdata, di_bh, NULL); |
1390 | if (ret) { | 1416 | if (ret) { |
1391 | mlog_errno(ret); | 1417 | mlog_errno(ret); |
1392 | goto out_fail_data; | 1418 | goto out_fail_data; |
@@ -1407,9 +1433,9 @@ out_fail: | |||
1407 | return ret; | 1433 | return ret; |
1408 | } | 1434 | } |
1409 | 1435 | ||
1410 | static int ocfs2_write_end_nolock(struct address_space *mapping, | 1436 | int ocfs2_write_end_nolock(struct address_space *mapping, |
1411 | loff_t pos, unsigned len, unsigned copied, | 1437 | loff_t pos, unsigned len, unsigned copied, |
1412 | struct page *page, void *fsdata) | 1438 | struct page *page, void *fsdata) |
1413 | { | 1439 | { |
1414 | int i; | 1440 | int i; |
1415 | unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1); | 1441 | unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1); |