aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-09-07 17:46:51 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-10-12 14:54:40 -0400
commit1afc32b952335f665327a1a9001ba1b44bb76fd9 (patch)
treec914afd0ef5d32b426c3cf65820de7599e570656 /fs/ocfs2/file.c
parent6798d35a31c413bbb3f83bbaa844bd2598168ccc (diff)
ocfs2: Write support for inline data
This fixes up write, truncate, mmap, and RESVSP/UNRESVP to understand inline inode data. For the most part, the changes to the core write code can be relied on to do the heavy lifting. Any code calling ocfs2_write_begin (including shared writeable mmap) can count on it doing the right thing with respect to growing inline data to an extent tree. Size reducing truncates, including UNRESVP can simply zero that portion of the inode block being removed. Size increasing truncatesm, including RESVP have to be a little bit smarter and grow the inode to an extent tree if necessary. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com> Reviewed-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c99
1 files changed, 93 insertions, 6 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 781ba6c4ef85..a62b14eb4065 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -397,6 +397,15 @@ static int ocfs2_truncate_file(struct inode *inode,
397 unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); 397 unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
398 truncate_inode_pages(inode->i_mapping, new_i_size); 398 truncate_inode_pages(inode->i_mapping, new_i_size);
399 399
400 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
401 status = ocfs2_truncate_inline(inode, di_bh, new_i_size,
402 i_size_read(inode), 0);
403 if (status)
404 mlog_errno(status);
405
406 goto bail_unlock_data;
407 }
408
400 /* alright, we're going to need to do a full blown alloc size 409 /* alright, we're going to need to do a full blown alloc size
401 * change. Orphan the inode so that recovery can complete the 410 * change. Orphan the inode so that recovery can complete the
402 * truncate if necessary. This does the task of marking 411 * truncate if necessary. This does the task of marking
@@ -908,7 +917,8 @@ static int ocfs2_extend_file(struct inode *inode,
908 struct buffer_head *di_bh, 917 struct buffer_head *di_bh,
909 u64 new_i_size) 918 u64 new_i_size)
910{ 919{
911 int ret = 0; 920 int ret = 0, data_locked = 0;
921 struct ocfs2_inode_info *oi = OCFS2_I(inode);
912 922
913 BUG_ON(!di_bh); 923 BUG_ON(!di_bh);
914 924
@@ -920,7 +930,17 @@ static int ocfs2_extend_file(struct inode *inode,
920 goto out; 930 goto out;
921 BUG_ON(new_i_size < i_size_read(inode)); 931 BUG_ON(new_i_size < i_size_read(inode));
922 932
923 if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) 933 /*
934 * Fall through for converting inline data, even if the fs
935 * supports sparse files.
936 *
937 * The check for inline data here is legal - nobody can add
938 * the feature since we have i_mutex. We must check it again
939 * after acquiring ip_alloc_sem though, as paths like mmap
940 * might have raced us to converting the inode to extents.
941 */
942 if (!(oi->ip_dyn_features & OCFS2_INLINE_DATA_FL)
943 && ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
924 goto out_update_size; 944 goto out_update_size;
925 945
926 /* 946 /*
@@ -935,6 +955,7 @@ static int ocfs2_extend_file(struct inode *inode,
935 mlog_errno(ret); 955 mlog_errno(ret);
936 goto out; 956 goto out;
937 } 957 }
958 data_locked = 1;
938 959
939 /* 960 /*
940 * The alloc sem blocks people in read/write from reading our 961 * The alloc sem blocks people in read/write from reading our
@@ -942,9 +963,31 @@ static int ocfs2_extend_file(struct inode *inode,
942 * i_mutex to block other extend/truncate calls while we're 963 * i_mutex to block other extend/truncate calls while we're
943 * here. 964 * here.
944 */ 965 */
945 down_write(&OCFS2_I(inode)->ip_alloc_sem); 966 down_write(&oi->ip_alloc_sem);
946 ret = ocfs2_extend_no_holes(inode, new_i_size, new_i_size); 967
947 up_write(&OCFS2_I(inode)->ip_alloc_sem); 968 if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
969 /*
970 * We can optimize small extends by keeping the inodes
971 * inline data.
972 */
973 if (ocfs2_size_fits_inline_data(di_bh, new_i_size)) {
974 up_write(&oi->ip_alloc_sem);
975 goto out_update_size;
976 }
977
978 ret = ocfs2_convert_inline_data_to_extents(inode, di_bh);
979 if (ret) {
980 up_write(&oi->ip_alloc_sem);
981
982 mlog_errno(ret);
983 goto out_unlock;
984 }
985 }
986
987 if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
988 ret = ocfs2_extend_no_holes(inode, new_i_size, new_i_size);
989
990 up_write(&oi->ip_alloc_sem);
948 991
949 if (ret < 0) { 992 if (ret < 0) {
950 mlog_errno(ret); 993 mlog_errno(ret);
@@ -957,7 +1000,7 @@ out_update_size:
957 mlog_errno(ret); 1000 mlog_errno(ret);
958 1001
959out_unlock: 1002out_unlock:
960 if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) 1003 if (data_locked)
961 ocfs2_data_unlock(inode, 1); 1004 ocfs2_data_unlock(inode, 1);
962 1005
963out: 1006out:
@@ -1231,6 +1274,31 @@ static int ocfs2_allocate_unwritten_extents(struct inode *inode,
1231{ 1274{
1232 int ret; 1275 int ret;
1233 u32 cpos, phys_cpos, clusters, alloc_size; 1276 u32 cpos, phys_cpos, clusters, alloc_size;
1277 u64 end = start + len;
1278 struct buffer_head *di_bh = NULL;
1279
1280 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
1281 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
1282 OCFS2_I(inode)->ip_blkno, &di_bh,
1283 OCFS2_BH_CACHED, inode);
1284 if (ret) {
1285 mlog_errno(ret);
1286 goto out;
1287 }
1288
1289 /*
1290 * Nothing to do if the requested reservation range
1291 * fits within the inode.
1292 */
1293 if (ocfs2_size_fits_inline_data(di_bh, end))
1294 goto out;
1295
1296 ret = ocfs2_convert_inline_data_to_extents(inode, di_bh);
1297 if (ret) {
1298 mlog_errno(ret);
1299 goto out;
1300 }
1301 }
1234 1302
1235 /* 1303 /*
1236 * We consider both start and len to be inclusive. 1304 * We consider both start and len to be inclusive.
@@ -1276,6 +1344,8 @@ next:
1276 1344
1277 ret = 0; 1345 ret = 0;
1278out: 1346out:
1347
1348 brelse(di_bh);
1279 return ret; 1349 return ret;
1280} 1350}
1281 1351
@@ -1457,6 +1527,14 @@ static int ocfs2_remove_inode_range(struct inode *inode,
1457 if (byte_len == 0) 1527 if (byte_len == 0)
1458 return 0; 1528 return 0;
1459 1529
1530 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
1531 ret = ocfs2_truncate_inline(inode, di_bh, byte_start,
1532 byte_start + byte_len, 1);
1533 if (ret)
1534 mlog_errno(ret);
1535 return ret;
1536 }
1537
1460 trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); 1538 trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start);
1461 trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits; 1539 trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits;
1462 if (trunc_len >= trunc_start) 1540 if (trunc_len >= trunc_start)
@@ -1759,6 +1837,15 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
1759 break; 1837 break;
1760 1838
1761 /* 1839 /*
1840 * There's no sane way to do direct writes to an inode
1841 * with inline data.
1842 */
1843 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
1844 *direct_io = 0;
1845 break;
1846 }
1847
1848 /*
1762 * Allowing concurrent direct writes means 1849 * Allowing concurrent direct writes means
1763 * i_size changes wouldn't be synchronized, so 1850 * i_size changes wouldn't be synchronized, so
1764 * one node could wind up truncating another 1851 * one node could wind up truncating another