mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
ocfs2: teach extend/truncate about sparse files
For ocfs2_truncate_file(), we eliminate the "simple" truncate case which no longer exists since i_size is not tied to i_clusters. In ocfs2_extend_file(), we skip the allocation / page zeroing code for file systems which understand sparse files. The core truncate code is changed to do a bottom up tree traversal. This gets abstracted out into it's own function. To make things more readable, most of the special case handling for in-inode extents from ocfs2_do_truncate() is also removed. Though write support for sparse files comes in a later patch, we at least update ocfs2_prepare_inode_for_write() to skip allocation for sparse files. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
This commit is contained in:
480
fs/ocfs2/alloc.c
480
fs/ocfs2/alloc.c
File diff suppressed because it is too large
Load Diff
@@ -344,18 +344,6 @@ static int ocfs2_truncate_file(struct inode *inode,
|
||||
}
|
||||
ocfs2_data_unlock(inode, 1);
|
||||
|
||||
if (le32_to_cpu(fe->i_clusters) ==
|
||||
ocfs2_clusters_for_bytes(osb->sb, new_i_size)) {
|
||||
mlog(0, "fe->i_clusters = %u, so we do a simple truncate\n",
|
||||
fe->i_clusters);
|
||||
/* No allocation change is required, so lets fast path
|
||||
* this truncate. */
|
||||
status = ocfs2_simple_size_update(inode, di_bh, new_i_size);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* alright, we're going to need to do a full blown alloc size
|
||||
* change. Orphan the inode so that recovery can complete the
|
||||
* truncate if necessary. This does the task of marking
|
||||
@@ -785,7 +773,7 @@ static int ocfs2_extend_file(struct inode *inode,
|
||||
size_t tail_to_skip)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 clusters_to_add;
|
||||
u32 clusters_to_add = 0;
|
||||
|
||||
BUG_ON(!tail_to_skip && !di_bh);
|
||||
|
||||
@@ -797,6 +785,11 @@ static int ocfs2_extend_file(struct inode *inode,
|
||||
goto out;
|
||||
BUG_ON(new_i_size < i_size_read(inode));
|
||||
|
||||
if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) {
|
||||
BUG_ON(tail_to_skip != 0);
|
||||
goto out_update_size;
|
||||
}
|
||||
|
||||
clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) -
|
||||
OCFS2_I(inode)->ip_clusters;
|
||||
|
||||
@@ -832,6 +825,7 @@ static int ocfs2_extend_file(struct inode *inode,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
out_update_size:
|
||||
if (!tail_to_skip) {
|
||||
/* We're being called from ocfs2_setattr() which wants
|
||||
* us to update i_size */
|
||||
@@ -841,7 +835,8 @@ static int ocfs2_extend_file(struct inode *inode,
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
ocfs2_data_unlock(inode, 1);
|
||||
if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
|
||||
ocfs2_data_unlock(inode, 1);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@@ -1097,6 +1092,14 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
|
||||
} else {
|
||||
saved_pos = *ppos;
|
||||
}
|
||||
|
||||
/*
|
||||
* The rest of this loop is concerned with legacy file
|
||||
* systems which don't support sparse files.
|
||||
*/
|
||||
if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
|
||||
break;
|
||||
|
||||
newsize = count + saved_pos;
|
||||
|
||||
mlog(0, "pos=%lld newsize=%lld cursize=%lld\n",
|
||||
|
||||
@@ -487,7 +487,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
struct buffer_head *fe_bh)
|
||||
{
|
||||
int status = 0;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_truncate_context *tc = NULL;
|
||||
struct ocfs2_dinode *fe;
|
||||
|
||||
@@ -495,41 +494,20 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
|
||||
fe = (struct ocfs2_dinode *) fe_bh->b_data;
|
||||
|
||||
/* zero allocation, zero truncate :) */
|
||||
if (!fe->i_clusters)
|
||||
goto bail;
|
||||
if (fe->i_clusters) {
|
||||
status = ocfs2_prepare_truncate(osb, inode, fe_bh, &tc);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
status = ocfs2_commit_truncate(osb, inode, fe_bh, tc);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
status = ocfs2_set_inode_size(handle, inode, fe_bh, 0ULL);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
handle = NULL;
|
||||
|
||||
status = ocfs2_prepare_truncate(osb, inode, fe_bh, &tc);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_commit_truncate(osb, inode, fe_bh, tc);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out:
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
|
||||
Reference in New Issue
Block a user