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>
This commit is contained in:
parent
3a307ffc27
commit
607d44aa3f
122
fs/ocfs2/aops.c
122
fs/ocfs2/aops.c
@ -849,7 +849,7 @@ static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
|
|||||||
|
|
||||||
static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
|
static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
|
||||||
struct ocfs2_super *osb, loff_t pos,
|
struct ocfs2_super *osb, loff_t pos,
|
||||||
unsigned len)
|
unsigned len, struct buffer_head *di_bh)
|
||||||
{
|
{
|
||||||
struct ocfs2_write_ctxt *wc;
|
struct ocfs2_write_ctxt *wc;
|
||||||
|
|
||||||
@ -859,6 +859,8 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
|
|||||||
|
|
||||||
wc->w_cpos = pos >> osb->s_clustersize_bits;
|
wc->w_cpos = pos >> osb->s_clustersize_bits;
|
||||||
wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
|
wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
|
||||||
|
get_bh(di_bh);
|
||||||
|
wc->w_di_bh = di_bh;
|
||||||
|
|
||||||
if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
|
if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
|
||||||
wc->w_large_pages = 1;
|
wc->w_large_pages = 1;
|
||||||
@ -1211,9 +1213,10 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocfs2_write_begin(struct file *file, struct address_space *mapping,
|
static int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned flags,
|
loff_t pos, unsigned len, unsigned flags,
|
||||||
struct page **pagep, void **fsdata)
|
struct page **pagep, void **fsdata,
|
||||||
|
struct buffer_head *di_bh)
|
||||||
{
|
{
|
||||||
int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS;
|
int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS;
|
||||||
unsigned int num_clusters = 0, clusters_to_alloc = 0;
|
unsigned int num_clusters = 0, clusters_to_alloc = 0;
|
||||||
@ -1227,28 +1230,14 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
|
|||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
struct ocfs2_write_cluster_desc *desc;
|
struct ocfs2_write_cluster_desc *desc;
|
||||||
|
|
||||||
ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len);
|
ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ocfs2_meta_lock(inode, &wc->w_di_bh, 1);
|
|
||||||
if (ret) {
|
|
||||||
mlog_errno(ret);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
|
di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
|
||||||
|
|
||||||
/*
|
|
||||||
* Take alloc sem here to prevent concurrent lookups. That way
|
|
||||||
* the mapping, zeroing and tree manipulation within
|
|
||||||
* ocfs2_write() will be safe against ->readpage(). This
|
|
||||||
* should also serve to lock out allocation from a shared
|
|
||||||
* writeable region.
|
|
||||||
*/
|
|
||||||
down_write(&OCFS2_I(inode)->ip_alloc_sem);
|
|
||||||
|
|
||||||
for (i = 0; i < wc->w_clen; i++) {
|
for (i = 0; i < wc->w_clen; i++) {
|
||||||
desc = &wc->w_desc[i];
|
desc = &wc->w_desc[i];
|
||||||
desc->c_cpos = wc->w_cpos + i;
|
desc->c_cpos = wc->w_cpos + i;
|
||||||
@ -1258,7 +1247,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
|
|||||||
&num_clusters, NULL);
|
&num_clusters, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
goto out_meta;
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (phys) {
|
} else if (phys) {
|
||||||
/*
|
/*
|
||||||
@ -1293,7 +1282,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
|
|||||||
&data_ac, &meta_ac);
|
&data_ac, &meta_ac);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
goto out_meta;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
credits = ocfs2_calc_extend_credits(inode->i_sb, di,
|
credits = ocfs2_calc_extend_credits(inode->i_sb, di,
|
||||||
@ -1303,17 +1292,11 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
|
|||||||
|
|
||||||
ocfs2_set_target_boundaries(osb, wc, pos, len, clusters_to_alloc);
|
ocfs2_set_target_boundaries(osb, wc, pos, len, clusters_to_alloc);
|
||||||
|
|
||||||
ret = ocfs2_data_lock(inode, 1);
|
|
||||||
if (ret) {
|
|
||||||
mlog_errno(ret);
|
|
||||||
goto out_meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle = ocfs2_start_trans(osb, credits);
|
handle = ocfs2_start_trans(osb, credits);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
ret = PTR_ERR(handle);
|
ret = PTR_ERR(handle);
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
goto out_data;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
wc->w_handle = handle;
|
wc->w_handle = handle;
|
||||||
@ -1363,13 +1346,6 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
|
|||||||
out_commit:
|
out_commit:
|
||||||
ocfs2_commit_trans(osb, handle);
|
ocfs2_commit_trans(osb, handle);
|
||||||
|
|
||||||
out_data:
|
|
||||||
ocfs2_data_unlock(inode, 1);
|
|
||||||
|
|
||||||
out_meta:
|
|
||||||
up_write(&OCFS2_I(inode)->ip_alloc_sem);
|
|
||||||
ocfs2_meta_unlock(inode, 1);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ocfs2_free_write_ctxt(wc);
|
ocfs2_free_write_ctxt(wc);
|
||||||
|
|
||||||
@ -1380,9 +1356,60 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocfs2_write_end(struct file *file, struct address_space *mapping,
|
int ocfs2_write_begin(struct file *file, struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned copied,
|
loff_t pos, unsigned len, unsigned flags,
|
||||||
struct page *page, void *fsdata)
|
struct page **pagep, void **fsdata)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct buffer_head *di_bh = NULL;
|
||||||
|
struct inode *inode = mapping->host;
|
||||||
|
|
||||||
|
ret = ocfs2_meta_lock(inode, &di_bh, 1);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take alloc sem here to prevent concurrent lookups. That way
|
||||||
|
* the mapping, zeroing and tree manipulation within
|
||||||
|
* ocfs2_write() will be safe against ->readpage(). This
|
||||||
|
* should also serve to lock out allocation from a shared
|
||||||
|
* writeable region.
|
||||||
|
*/
|
||||||
|
down_write(&OCFS2_I(inode)->ip_alloc_sem);
|
||||||
|
|
||||||
|
ret = ocfs2_data_lock(inode, 1);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
|
||||||
|
fsdata, di_bh);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out_fail_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
brelse(di_bh);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_fail_data:
|
||||||
|
ocfs2_data_unlock(inode, 1);
|
||||||
|
out_fail:
|
||||||
|
up_write(&OCFS2_I(inode)->ip_alloc_sem);
|
||||||
|
|
||||||
|
brelse(di_bh);
|
||||||
|
ocfs2_meta_unlock(inode, 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ocfs2_write_end_nolock(struct address_space *mapping,
|
||||||
|
loff_t pos, unsigned len, unsigned copied,
|
||||||
|
struct page *page, void *fsdata)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
|
unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
|
||||||
@ -1444,14 +1471,27 @@ int ocfs2_write_end(struct file *file, struct address_space *mapping,
|
|||||||
ocfs2_journal_dirty(handle, wc->w_di_bh);
|
ocfs2_journal_dirty(handle, wc->w_di_bh);
|
||||||
|
|
||||||
ocfs2_commit_trans(osb, handle);
|
ocfs2_commit_trans(osb, handle);
|
||||||
ocfs2_data_unlock(inode, 1);
|
|
||||||
up_write(&OCFS2_I(inode)->ip_alloc_sem);
|
|
||||||
ocfs2_meta_unlock(inode, 1);
|
|
||||||
ocfs2_free_write_ctxt(wc);
|
ocfs2_free_write_ctxt(wc);
|
||||||
|
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ocfs2_write_end(struct file *file, struct address_space *mapping,
|
||||||
|
loff_t pos, unsigned len, unsigned copied,
|
||||||
|
struct page *page, void *fsdata)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct inode *inode = mapping->host;
|
||||||
|
|
||||||
|
ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
|
||||||
|
|
||||||
|
ocfs2_data_unlock(inode, 1);
|
||||||
|
up_write(&OCFS2_I(inode)->ip_alloc_sem);
|
||||||
|
ocfs2_meta_unlock(inode, 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
const struct address_space_operations ocfs2_aops = {
|
const struct address_space_operations ocfs2_aops = {
|
||||||
.readpage = ocfs2_readpage,
|
.readpage = ocfs2_readpage,
|
||||||
.writepage = ocfs2_writepage,
|
.writepage = ocfs2_writepage,
|
||||||
|
Loading…
Reference in New Issue
Block a user