diff options
-rw-r--r-- | fs/ocfs2/alloc.c | 245 | ||||
-rw-r--r-- | fs/ocfs2/alloc.h | 6 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 173 | ||||
-rw-r--r-- | fs/ocfs2/aops.h | 4 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 99 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/journal.h | 3 |
7 files changed, 526 insertions, 8 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index c81bfdfb9929..72cefe25382b 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -3726,6 +3726,8 @@ int ocfs2_insert_extent(struct ocfs2_super *osb, | |||
3726 | struct ocfs2_insert_type insert = {0, }; | 3726 | struct ocfs2_insert_type insert = {0, }; |
3727 | struct ocfs2_extent_rec rec; | 3727 | struct ocfs2_extent_rec rec; |
3728 | 3728 | ||
3729 | BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL); | ||
3730 | |||
3729 | mlog(0, "add %u clusters at position %u to inode %llu\n", | 3731 | mlog(0, "add %u clusters at position %u to inode %llu\n", |
3730 | new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno); | 3732 | new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno); |
3731 | 3733 | ||
@@ -5826,6 +5828,174 @@ out: | |||
5826 | return ret; | 5828 | return ret; |
5827 | } | 5829 | } |
5828 | 5830 | ||
5831 | static void ocfs2_zero_dinode_id2(struct inode *inode, struct ocfs2_dinode *di) | ||
5832 | { | ||
5833 | unsigned int blocksize = 1 << inode->i_sb->s_blocksize_bits; | ||
5834 | |||
5835 | memset(&di->id2, 0, blocksize - offsetof(struct ocfs2_dinode, id2)); | ||
5836 | } | ||
5837 | |||
5838 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di) | ||
5839 | { | ||
5840 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
5841 | struct ocfs2_inline_data *idata = &di->id2.i_data; | ||
5842 | |||
5843 | spin_lock(&oi->ip_lock); | ||
5844 | oi->ip_dyn_features |= OCFS2_INLINE_DATA_FL; | ||
5845 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
5846 | spin_unlock(&oi->ip_lock); | ||
5847 | |||
5848 | /* | ||
5849 | * We clear the entire i_data structure here so that all | ||
5850 | * fields can be properly initialized. | ||
5851 | */ | ||
5852 | ocfs2_zero_dinode_id2(inode, di); | ||
5853 | |||
5854 | idata->id_count = cpu_to_le16(ocfs2_max_inline_data(inode->i_sb)); | ||
5855 | } | ||
5856 | |||
5857 | int ocfs2_convert_inline_data_to_extents(struct inode *inode, | ||
5858 | struct buffer_head *di_bh) | ||
5859 | { | ||
5860 | int ret, i, has_data, num_pages = 0; | ||
5861 | handle_t *handle; | ||
5862 | u64 uninitialized_var(block); | ||
5863 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
5864 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
5865 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
5866 | struct ocfs2_extent_list *el = &di->id2.i_list; | ||
5867 | struct ocfs2_alloc_context *data_ac = NULL; | ||
5868 | struct page **pages = NULL; | ||
5869 | loff_t end = osb->s_clustersize; | ||
5870 | |||
5871 | has_data = i_size_read(inode) ? 1 : 0; | ||
5872 | |||
5873 | if (has_data) { | ||
5874 | pages = kcalloc(ocfs2_pages_per_cluster(osb->sb), | ||
5875 | sizeof(struct page *), GFP_NOFS); | ||
5876 | if (pages == NULL) { | ||
5877 | ret = -ENOMEM; | ||
5878 | mlog_errno(ret); | ||
5879 | goto out; | ||
5880 | } | ||
5881 | |||
5882 | ret = ocfs2_reserve_clusters(osb, 1, &data_ac); | ||
5883 | if (ret) { | ||
5884 | mlog_errno(ret); | ||
5885 | goto out; | ||
5886 | } | ||
5887 | } | ||
5888 | |||
5889 | handle = ocfs2_start_trans(osb, OCFS2_INLINE_TO_EXTENTS_CREDITS); | ||
5890 | if (IS_ERR(handle)) { | ||
5891 | ret = PTR_ERR(handle); | ||
5892 | mlog_errno(ret); | ||
5893 | goto out_unlock; | ||
5894 | } | ||
5895 | |||
5896 | ret = ocfs2_journal_access(handle, inode, di_bh, | ||
5897 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
5898 | if (ret) { | ||
5899 | mlog_errno(ret); | ||
5900 | goto out_commit; | ||
5901 | } | ||
5902 | |||
5903 | if (has_data) { | ||
5904 | u32 bit_off, num; | ||
5905 | unsigned int page_end; | ||
5906 | u64 phys; | ||
5907 | |||
5908 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, | ||
5909 | &num); | ||
5910 | if (ret) { | ||
5911 | mlog_errno(ret); | ||
5912 | goto out_commit; | ||
5913 | } | ||
5914 | |||
5915 | /* | ||
5916 | * Save two copies, one for insert, and one that can | ||
5917 | * be changed by ocfs2_map_and_dirty_page() below. | ||
5918 | */ | ||
5919 | block = phys = ocfs2_clusters_to_blocks(inode->i_sb, bit_off); | ||
5920 | |||
5921 | /* | ||
5922 | * Non sparse file systems zero on extend, so no need | ||
5923 | * to do that now. | ||
5924 | */ | ||
5925 | if (!ocfs2_sparse_alloc(osb) && | ||
5926 | PAGE_CACHE_SIZE < osb->s_clustersize) | ||
5927 | end = PAGE_CACHE_SIZE; | ||
5928 | |||
5929 | ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages); | ||
5930 | if (ret) { | ||
5931 | mlog_errno(ret); | ||
5932 | goto out_commit; | ||
5933 | } | ||
5934 | |||
5935 | /* | ||
5936 | * This should populate the 1st page for us and mark | ||
5937 | * it up to date. | ||
5938 | */ | ||
5939 | ret = ocfs2_read_inline_data(inode, pages[0], di_bh); | ||
5940 | if (ret) { | ||
5941 | mlog_errno(ret); | ||
5942 | goto out_commit; | ||
5943 | } | ||
5944 | |||
5945 | page_end = PAGE_CACHE_SIZE; | ||
5946 | if (PAGE_CACHE_SIZE > osb->s_clustersize) | ||
5947 | page_end = osb->s_clustersize; | ||
5948 | |||
5949 | for (i = 0; i < num_pages; i++) | ||
5950 | ocfs2_map_and_dirty_page(inode, handle, 0, page_end, | ||
5951 | pages[i], i > 0, &phys); | ||
5952 | } | ||
5953 | |||
5954 | spin_lock(&oi->ip_lock); | ||
5955 | oi->ip_dyn_features &= ~OCFS2_INLINE_DATA_FL; | ||
5956 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
5957 | spin_unlock(&oi->ip_lock); | ||
5958 | |||
5959 | ocfs2_zero_dinode_id2(inode, di); | ||
5960 | |||
5961 | el->l_tree_depth = 0; | ||
5962 | el->l_next_free_rec = 0; | ||
5963 | el->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(inode->i_sb)); | ||
5964 | |||
5965 | ocfs2_journal_dirty(handle, di_bh); | ||
5966 | |||
5967 | if (has_data) { | ||
5968 | /* | ||
5969 | * An error at this point should be extremely rare. If | ||
5970 | * this proves to be false, we could always re-build | ||
5971 | * the in-inode data from our pages. | ||
5972 | */ | ||
5973 | ret = ocfs2_insert_extent(osb, handle, inode, di_bh, | ||
5974 | 0, block, 1, 0, NULL); | ||
5975 | if (ret) { | ||
5976 | mlog_errno(ret); | ||
5977 | goto out_commit; | ||
5978 | } | ||
5979 | |||
5980 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
5981 | } | ||
5982 | |||
5983 | out_commit: | ||
5984 | ocfs2_commit_trans(osb, handle); | ||
5985 | |||
5986 | out_unlock: | ||
5987 | if (data_ac) | ||
5988 | ocfs2_free_alloc_context(data_ac); | ||
5989 | |||
5990 | out: | ||
5991 | if (pages) { | ||
5992 | ocfs2_unlock_and_free_pages(pages, num_pages); | ||
5993 | kfree(pages); | ||
5994 | } | ||
5995 | |||
5996 | return ret; | ||
5997 | } | ||
5998 | |||
5829 | /* | 5999 | /* |
5830 | * It is expected, that by the time you call this function, | 6000 | * It is expected, that by the time you call this function, |
5831 | * inode->i_size and fe->i_size have been adjusted. | 6001 | * inode->i_size and fe->i_size have been adjusted. |
@@ -6051,6 +6221,81 @@ bail: | |||
6051 | return status; | 6221 | return status; |
6052 | } | 6222 | } |
6053 | 6223 | ||
6224 | /* | ||
6225 | * 'start' is inclusive, 'end' is not. | ||
6226 | */ | ||
6227 | int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, | ||
6228 | unsigned int start, unsigned int end, int trunc) | ||
6229 | { | ||
6230 | int ret; | ||
6231 | unsigned int numbytes; | ||
6232 | handle_t *handle; | ||
6233 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
6234 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
6235 | struct ocfs2_inline_data *idata = &di->id2.i_data; | ||
6236 | |||
6237 | if (end > i_size_read(inode)) | ||
6238 | end = i_size_read(inode); | ||
6239 | |||
6240 | BUG_ON(start >= end); | ||
6241 | |||
6242 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) || | ||
6243 | !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || | ||
6244 | !ocfs2_supports_inline_data(osb)) { | ||
6245 | ocfs2_error(inode->i_sb, | ||
6246 | "Inline data flags for inode %llu don't agree! " | ||
6247 | "Disk: 0x%x, Memory: 0x%x, Superblock: 0x%x\n", | ||
6248 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | ||
6249 | le16_to_cpu(di->i_dyn_features), | ||
6250 | OCFS2_I(inode)->ip_dyn_features, | ||
6251 | osb->s_feature_incompat); | ||
6252 | ret = -EROFS; | ||
6253 | goto out; | ||
6254 | } | ||
6255 | |||
6256 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
6257 | if (IS_ERR(handle)) { | ||
6258 | ret = PTR_ERR(handle); | ||
6259 | mlog_errno(ret); | ||
6260 | goto out; | ||
6261 | } | ||
6262 | |||
6263 | ret = ocfs2_journal_access(handle, inode, di_bh, | ||
6264 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
6265 | if (ret) { | ||
6266 | mlog_errno(ret); | ||
6267 | goto out_commit; | ||
6268 | } | ||
6269 | |||
6270 | numbytes = end - start; | ||
6271 | memset(idata->id_data + start, 0, numbytes); | ||
6272 | |||
6273 | /* | ||
6274 | * No need to worry about the data page here - it's been | ||
6275 | * truncated already and inline data doesn't need it for | ||
6276 | * pushing zero's to disk, so we'll let readpage pick it up | ||
6277 | * later. | ||
6278 | */ | ||
6279 | if (trunc) { | ||
6280 | i_size_write(inode, start); | ||
6281 | di->i_size = cpu_to_le64(start); | ||
6282 | } | ||
6283 | |||
6284 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
6285 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | ||
6286 | |||
6287 | di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec); | ||
6288 | di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); | ||
6289 | |||
6290 | ocfs2_journal_dirty(handle, di_bh); | ||
6291 | |||
6292 | out_commit: | ||
6293 | ocfs2_commit_trans(osb, handle); | ||
6294 | |||
6295 | out: | ||
6296 | return ret; | ||
6297 | } | ||
6298 | |||
6054 | static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) | 6299 | static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) |
6055 | { | 6300 | { |
6056 | /* | 6301 | /* |
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h index 990df48ae8d3..826e0a6cf5c7 100644 --- a/fs/ocfs2/alloc.h +++ b/fs/ocfs2/alloc.h | |||
@@ -62,6 +62,10 @@ static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe) | |||
62 | return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2; | 62 | return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2; |
63 | } | 63 | } |
64 | 64 | ||
65 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di); | ||
66 | int ocfs2_convert_inline_data_to_extents(struct inode *inode, | ||
67 | struct buffer_head *di_bh); | ||
68 | |||
65 | int ocfs2_truncate_log_init(struct ocfs2_super *osb); | 69 | int ocfs2_truncate_log_init(struct ocfs2_super *osb); |
66 | void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb); | 70 | void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb); |
67 | void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb, | 71 | void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb, |
@@ -115,6 +119,8 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, | |||
115 | struct inode *inode, | 119 | struct inode *inode, |
116 | struct buffer_head *fe_bh, | 120 | struct buffer_head *fe_bh, |
117 | struct ocfs2_truncate_context *tc); | 121 | struct ocfs2_truncate_context *tc); |
122 | int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, | ||
123 | unsigned int start, unsigned int end, int trunc); | ||
118 | 124 | ||
119 | int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el, | 125 | int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el, |
120 | u32 cpos, struct buffer_head **leaf_bh); | 126 | u32 cpos, struct buffer_head **leaf_bh); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index fef0186a91cd..34d10452c56d 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -206,8 +206,8 @@ bail: | |||
206 | return err; | 206 | return err; |
207 | } | 207 | } |
208 | 208 | ||
209 | static int ocfs2_read_inline_data(struct inode *inode, struct page *page, | 209 | int ocfs2_read_inline_data(struct inode *inode, struct page *page, |
210 | struct buffer_head *di_bh) | 210 | struct buffer_head *di_bh) |
211 | { | 211 | { |
212 | void *kaddr; | 212 | void *kaddr; |
213 | unsigned int size; | 213 | unsigned int size; |
@@ -1432,6 +1432,130 @@ out: | |||
1432 | return ret; | 1432 | return ret; |
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | static int ocfs2_write_begin_inline(struct address_space *mapping, | ||
1436 | struct inode *inode, | ||
1437 | struct ocfs2_write_ctxt *wc) | ||
1438 | { | ||
1439 | int ret; | ||
1440 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1441 | struct page *page; | ||
1442 | handle_t *handle; | ||
1443 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; | ||
1444 | |||
1445 | page = find_or_create_page(mapping, 0, GFP_NOFS); | ||
1446 | if (!page) { | ||
1447 | ret = -ENOMEM; | ||
1448 | mlog_errno(ret); | ||
1449 | goto out; | ||
1450 | } | ||
1451 | /* | ||
1452 | * If we don't set w_num_pages then this page won't get unlocked | ||
1453 | * and freed on cleanup of the write context. | ||
1454 | */ | ||
1455 | wc->w_pages[0] = wc->w_target_page = page; | ||
1456 | wc->w_num_pages = 1; | ||
1457 | |||
1458 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
1459 | if (IS_ERR(handle)) { | ||
1460 | ret = PTR_ERR(handle); | ||
1461 | mlog_errno(ret); | ||
1462 | goto out; | ||
1463 | } | ||
1464 | |||
1465 | ret = ocfs2_journal_access(handle, inode, wc->w_di_bh, | ||
1466 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1467 | if (ret) { | ||
1468 | ocfs2_commit_trans(osb, handle); | ||
1469 | |||
1470 | mlog_errno(ret); | ||
1471 | goto out; | ||
1472 | } | ||
1473 | |||
1474 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)) | ||
1475 | ocfs2_set_inode_data_inline(inode, di); | ||
1476 | |||
1477 | if (!PageUptodate(page)) { | ||
1478 | ret = ocfs2_read_inline_data(inode, page, wc->w_di_bh); | ||
1479 | if (ret) { | ||
1480 | ocfs2_commit_trans(osb, handle); | ||
1481 | |||
1482 | goto out; | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1486 | wc->w_handle = handle; | ||
1487 | out: | ||
1488 | return ret; | ||
1489 | } | ||
1490 | |||
1491 | int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size) | ||
1492 | { | ||
1493 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
1494 | |||
1495 | if (new_size < le16_to_cpu(di->id2.i_data.id_count)) | ||
1496 | return 1; | ||
1497 | return 0; | ||
1498 | } | ||
1499 | |||
1500 | static int ocfs2_try_to_write_inline_data(struct address_space *mapping, | ||
1501 | struct inode *inode, loff_t pos, | ||
1502 | unsigned len, struct page *mmap_page, | ||
1503 | struct ocfs2_write_ctxt *wc) | ||
1504 | { | ||
1505 | int ret, written = 0; | ||
1506 | loff_t end = pos + len; | ||
1507 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
1508 | |||
1509 | mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n", | ||
1510 | (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos, | ||
1511 | oi->ip_dyn_features); | ||
1512 | |||
1513 | /* | ||
1514 | * Handle inodes which already have inline data 1st. | ||
1515 | */ | ||
1516 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1517 | if (mmap_page == NULL && | ||
1518 | ocfs2_size_fits_inline_data(wc->w_di_bh, end)) | ||
1519 | goto do_inline_write; | ||
1520 | |||
1521 | /* | ||
1522 | * The write won't fit - we have to give this inode an | ||
1523 | * inline extent list now. | ||
1524 | */ | ||
1525 | ret = ocfs2_convert_inline_data_to_extents(inode, wc->w_di_bh); | ||
1526 | if (ret) | ||
1527 | mlog_errno(ret); | ||
1528 | goto out; | ||
1529 | } | ||
1530 | |||
1531 | /* | ||
1532 | * Check whether the inode can accept inline data. | ||
1533 | */ | ||
1534 | if (oi->ip_clusters != 0 || i_size_read(inode) != 0) | ||
1535 | return 0; | ||
1536 | |||
1537 | /* | ||
1538 | * Check whether the write can fit. | ||
1539 | */ | ||
1540 | if (mmap_page || end > ocfs2_max_inline_data(inode->i_sb)) | ||
1541 | return 0; | ||
1542 | |||
1543 | do_inline_write: | ||
1544 | ret = ocfs2_write_begin_inline(mapping, inode, wc); | ||
1545 | if (ret) { | ||
1546 | mlog_errno(ret); | ||
1547 | goto out; | ||
1548 | } | ||
1549 | |||
1550 | /* | ||
1551 | * This signals to the caller that the data can be written | ||
1552 | * inline. | ||
1553 | */ | ||
1554 | written = 1; | ||
1555 | out: | ||
1556 | return written ? written : ret; | ||
1557 | } | ||
1558 | |||
1435 | /* | 1559 | /* |
1436 | * This function only does anything for file systems which can't | 1560 | * This function only does anything for file systems which can't |
1437 | * handle sparse files. | 1561 | * handle sparse files. |
@@ -1483,6 +1607,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
1483 | return ret; | 1607 | return ret; |
1484 | } | 1608 | } |
1485 | 1609 | ||
1610 | if (ocfs2_supports_inline_data(osb)) { | ||
1611 | ret = ocfs2_try_to_write_inline_data(mapping, inode, pos, len, | ||
1612 | mmap_page, wc); | ||
1613 | if (ret == 1) { | ||
1614 | ret = 0; | ||
1615 | goto success; | ||
1616 | } | ||
1617 | if (ret < 0) { | ||
1618 | mlog_errno(ret); | ||
1619 | goto out; | ||
1620 | } | ||
1621 | } | ||
1622 | |||
1486 | ret = ocfs2_expand_nonsparse_inode(inode, pos, len, wc); | 1623 | ret = ocfs2_expand_nonsparse_inode(inode, pos, len, wc); |
1487 | if (ret) { | 1624 | if (ret) { |
1488 | mlog_errno(ret); | 1625 | mlog_errno(ret); |
@@ -1570,6 +1707,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
1570 | if (meta_ac) | 1707 | if (meta_ac) |
1571 | ocfs2_free_alloc_context(meta_ac); | 1708 | ocfs2_free_alloc_context(meta_ac); |
1572 | 1709 | ||
1710 | success: | ||
1573 | *pagep = wc->w_target_page; | 1711 | *pagep = wc->w_target_page; |
1574 | *fsdata = wc; | 1712 | *fsdata = wc; |
1575 | return 0; | 1713 | return 0; |
@@ -1637,6 +1775,31 @@ out_fail: | |||
1637 | return ret; | 1775 | return ret; |
1638 | } | 1776 | } |
1639 | 1777 | ||
1778 | static void ocfs2_write_end_inline(struct inode *inode, loff_t pos, | ||
1779 | unsigned len, unsigned *copied, | ||
1780 | struct ocfs2_dinode *di, | ||
1781 | struct ocfs2_write_ctxt *wc) | ||
1782 | { | ||
1783 | void *kaddr; | ||
1784 | |||
1785 | if (unlikely(*copied < len)) { | ||
1786 | if (!PageUptodate(wc->w_target_page)) { | ||
1787 | *copied = 0; | ||
1788 | return; | ||
1789 | } | ||
1790 | } | ||
1791 | |||
1792 | kaddr = kmap_atomic(wc->w_target_page, KM_USER0); | ||
1793 | memcpy(di->id2.i_data.id_data + pos, kaddr + pos, *copied); | ||
1794 | kunmap_atomic(kaddr, KM_USER0); | ||
1795 | |||
1796 | mlog(0, "Data written to inode at offset %llu. " | ||
1797 | "id_count = %u, copied = %u, i_dyn_features = 0x%x\n", | ||
1798 | (unsigned long long)pos, *copied, | ||
1799 | le16_to_cpu(di->id2.i_data.id_count), | ||
1800 | le16_to_cpu(di->i_dyn_features)); | ||
1801 | } | ||
1802 | |||
1640 | int ocfs2_write_end_nolock(struct address_space *mapping, | 1803 | int ocfs2_write_end_nolock(struct address_space *mapping, |
1641 | loff_t pos, unsigned len, unsigned copied, | 1804 | loff_t pos, unsigned len, unsigned copied, |
1642 | struct page *page, void *fsdata) | 1805 | struct page *page, void *fsdata) |
@@ -1650,6 +1813,11 @@ int ocfs2_write_end_nolock(struct address_space *mapping, | |||
1650 | handle_t *handle = wc->w_handle; | 1813 | handle_t *handle = wc->w_handle; |
1651 | struct page *tmppage; | 1814 | struct page *tmppage; |
1652 | 1815 | ||
1816 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1817 | ocfs2_write_end_inline(inode, pos, len, &copied, di, wc); | ||
1818 | goto out_write_size; | ||
1819 | } | ||
1820 | |||
1653 | if (unlikely(copied < len)) { | 1821 | if (unlikely(copied < len)) { |
1654 | if (!PageUptodate(wc->w_target_page)) | 1822 | if (!PageUptodate(wc->w_target_page)) |
1655 | copied = 0; | 1823 | copied = 0; |
@@ -1687,6 +1855,7 @@ int ocfs2_write_end_nolock(struct address_space *mapping, | |||
1687 | block_commit_write(tmppage, from, to); | 1855 | block_commit_write(tmppage, from, to); |
1688 | } | 1856 | } |
1689 | 1857 | ||
1858 | out_write_size: | ||
1690 | pos += copied; | 1859 | pos += copied; |
1691 | if (pos > inode->i_size) { | 1860 | if (pos > inode->i_size) { |
1692 | i_size_write(inode, pos); | 1861 | i_size_write(inode, pos); |
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index b4fa37d40db4..113560877dbb 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h | |||
@@ -61,6 +61,10 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
61 | struct page **pagep, void **fsdata, | 61 | struct page **pagep, void **fsdata, |
62 | struct buffer_head *di_bh, struct page *mmap_page); | 62 | struct buffer_head *di_bh, struct page *mmap_page); |
63 | 63 | ||
64 | int ocfs2_read_inline_data(struct inode *inode, struct page *page, | ||
65 | struct buffer_head *di_bh); | ||
66 | int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size); | ||
67 | |||
64 | /* all ocfs2_dio_end_io()'s fault */ | 68 | /* all ocfs2_dio_end_io()'s fault */ |
65 | #define ocfs2_iocb_is_rw_locked(iocb) \ | 69 | #define ocfs2_iocb_is_rw_locked(iocb) \ |
66 | test_bit(0, (unsigned long *)&iocb->private) | 70 | test_bit(0, (unsigned long *)&iocb->private) |
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 | ||
959 | out_unlock: | 1002 | out_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 | ||
963 | out: | 1006 | out: |
@@ -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; |
1278 | out: | 1346 | out: |
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 |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index c8923bab422a..1d5e0cb0fda1 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -514,6 +514,10 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, | |||
514 | 514 | ||
515 | fe = (struct ocfs2_dinode *) fe_bh->b_data; | 515 | fe = (struct ocfs2_dinode *) fe_bh->b_data; |
516 | 516 | ||
517 | /* | ||
518 | * This check will also skip truncate of inodes with inline | ||
519 | * data and fast symlinks. | ||
520 | */ | ||
517 | if (fe->i_clusters) { | 521 | if (fe->i_clusters) { |
518 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 522 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); |
519 | if (IS_ERR(handle)) { | 523 | if (IS_ERR(handle)) { |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index ce60aab013aa..4b32e0961568 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
@@ -282,6 +282,9 @@ int ocfs2_journal_dirty_data(handle_t *handle, | |||
282 | * prev. group desc. if we relink. */ | 282 | * prev. group desc. if we relink. */ |
283 | #define OCFS2_SUBALLOC_ALLOC (3) | 283 | #define OCFS2_SUBALLOC_ALLOC (3) |
284 | 284 | ||
285 | #define OCFS2_INLINE_TO_EXTENTS_CREDITS (OCFS2_SUBALLOC_ALLOC \ | ||
286 | + OCFS2_INODE_UPDATE_CREDITS) | ||
287 | |||
285 | /* dinode + group descriptor update. We don't relink on free yet. */ | 288 | /* dinode + group descriptor update. We don't relink on free yet. */ |
286 | #define OCFS2_SUBALLOC_FREE (2) | 289 | #define OCFS2_SUBALLOC_FREE (2) |
287 | 290 | ||