Commit 6f70fa51 authored by Tao Ma's avatar Tao Ma Committed by Joel Becker

ocfs2: Add CoW support.

This patch try CoW support for a refcounted record.

the whole process will be:
1. Calculate how many clusters we need to CoW and where we start.
   Extents that are not completely encompassed by the write will
   be broken on 1MB boundaries.
2. Do CoW for the clusters with the help of page cache.
3. Change the b-tree structure with the new allocated clusters.
Signed-off-by: default avatarTao Ma <tao.ma@oracle.com>
parent bcbbb24a
...@@ -6998,7 +6998,7 @@ static int ocfs2_zero_func(handle_t *handle, struct buffer_head *bh) ...@@ -6998,7 +6998,7 @@ static int ocfs2_zero_func(handle_t *handle, struct buffer_head *bh)
return 0; return 0;
} }
static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle, void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
unsigned int from, unsigned int to, unsigned int from, unsigned int to,
struct page *page, int zero, u64 *phys) struct page *page, int zero, u64 *phys)
{ {
...@@ -7068,20 +7068,16 @@ out: ...@@ -7068,20 +7068,16 @@ out:
ocfs2_unlock_and_free_pages(pages, numpages); ocfs2_unlock_and_free_pages(pages, numpages);
} }
static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end, int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end,
struct page **pages, int *num) struct page **pages, int *num)
{ {
int numpages, ret = 0; int numpages, ret = 0;
struct super_block *sb = inode->i_sb;
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
unsigned long index; unsigned long index;
loff_t last_page_bytes; loff_t last_page_bytes;
BUG_ON(start > end); BUG_ON(start > end);
BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
(end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
numpages = 0; numpages = 0;
last_page_bytes = PAGE_ALIGN(end); last_page_bytes = PAGE_ALIGN(end);
index = start >> PAGE_CACHE_SHIFT; index = start >> PAGE_CACHE_SHIFT;
...@@ -7109,6 +7105,17 @@ out: ...@@ -7109,6 +7105,17 @@ out:
return ret; return ret;
} }
static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
struct page **pages, int *num)
{
struct super_block *sb = inode->i_sb;
BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
(end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
return ocfs2_grab_pages(inode, start, end, pages, num);
}
/* /*
* Zero the area past i_size but still within an allocated * Zero the area past i_size but still within an allocated
* cluster. This avoids exposing nonzero data on subsequent file * cluster. This avoids exposing nonzero data on subsequent file
......
...@@ -271,6 +271,11 @@ static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec) ...@@ -271,6 +271,11 @@ static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec)
return !rec->e_leaf_clusters; return !rec->e_leaf_clusters;
} }
int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end,
struct page **pages, int *num);
void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
unsigned int from, unsigned int to,
struct page *page, int zero, u64 *phys);
/* /*
* Structures which describe a path through a btree, and functions to * Structures which describe a path through a btree, and functions to
* manipulate them. * manipulate them.
......
...@@ -126,7 +126,7 @@ bail: ...@@ -126,7 +126,7 @@ bail:
return err; return err;
} }
static int ocfs2_get_block(struct inode *inode, sector_t iblock, int ocfs2_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create) struct buffer_head *bh_result, int create)
{ {
int err = 0; int err = 0;
......
...@@ -57,6 +57,8 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page, ...@@ -57,6 +57,8 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page,
struct buffer_head *di_bh); struct buffer_head *di_bh);
int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size); int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size);
int ocfs2_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create);
/* all ocfs2_dio_end_io()'s fault */ /* all ocfs2_dio_end_io()'s fault */
#define ocfs2_iocb_is_rw_locked(iocb) \ #define ocfs2_iocb_is_rw_locked(iocb) \
test_bit(0, (unsigned long *)&iocb->private) test_bit(0, (unsigned long *)&iocb->private)
......
This diff is collapsed.
...@@ -51,4 +51,6 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode, ...@@ -51,4 +51,6 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
u32 clusters, u32 clusters,
int *credits, int *credits,
struct ocfs2_alloc_context **meta_ac); struct ocfs2_alloc_context **meta_ac);
int ocfs2_refcount_cow(struct inode *inode, struct buffer_head *di_bh,
u32 cpos, u32 write_len);
#endif /* OCFS2_REFCOUNTTREE_H */ #endif /* OCFS2_REFCOUNTTREE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment