Commit 607d44aa authored by Mark Fasheh's avatar Mark Fasheh
Browse files

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: default avatarMark Fasheh <mark.fasheh@oracle.com>
parent 3a307ffc
Loading
Loading
Loading
Loading
+80 −40
Original line number Diff line number Diff line
@@ -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,
				  struct ocfs2_super *osb, loff_t pos,
				  unsigned len)
				  unsigned len, struct buffer_head *di_bh)
{
	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_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))
		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,
		      struct page **pagep, void **fsdata)
				    struct page **pagep, void **fsdata,
				    struct buffer_head *di_bh)
{
	int ret, i, credits = OCFS2_INODE_UPDATE_CREDITS;
	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;
	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) {
		mlog_errno(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;

	/*
	 * 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++) {
		desc = &wc->w_desc[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);
			if (ret) {
				mlog_errno(ret);
				goto out_meta;
				goto out;
			}
		} else if (phys) {
			/*
@@ -1293,7 +1282,7 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
					    &data_ac, &meta_ac);
		if (ret) {
			mlog_errno(ret);
			goto out_meta;
			goto out;
		}

		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);

	ret = ocfs2_data_lock(inode, 1);
	if (ret) {
		mlog_errno(ret);
		goto out_meta;
	}

	handle = ocfs2_start_trans(osb, credits);
	if (IS_ERR(handle)) {
		ret = PTR_ERR(handle);
		mlog_errno(ret);
		goto out_data;
		goto out;
	}

	wc->w_handle = handle;
@@ -1363,13 +1346,6 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
out_commit:
	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:
	ocfs2_free_write_ctxt(wc);

@@ -1380,7 +1356,58 @@ int ocfs2_write_begin(struct file *file, struct address_space *mapping,
	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 flags,
		      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)
{
@@ -1444,12 +1471,25 @@ int ocfs2_write_end(struct file *file, struct address_space *mapping,
	ocfs2_journal_dirty(handle, wc->w_di_bh);

	ocfs2_commit_trans(osb, handle);
	ocfs2_free_write_ctxt(wc);

	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);
	ocfs2_free_write_ctxt(wc);

	return copied;
	return ret;
}

const struct address_space_operations ocfs2_aops = {