Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
f6d31f4b
Commit
f6d31f4b
authored
Sep 23, 2014
by
Dave Chinner
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'xfs-shift-extents-rework' into for-next
parents
a4241aeb
8b5279e3
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
289 additions
and
153 deletions
+289
-153
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.c
+241
-124
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_bmap.h
+3
-4
fs/xfs/xfs_aops.c
fs/xfs/xfs_aops.c
+14
-2
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_bmap_util.c
+31
-23
No files found.
fs/xfs/libxfs/xfs_bmap.c
View file @
f6d31f4b
...
...
@@ -5403,23 +5403,224 @@ xfs_bunmapi(
return
error
;
}
/*
* Determine whether an extent shift can be accomplished by a merge with the
* extent that precedes the target hole of the shift.
*/
STATIC
bool
xfs_bmse_can_merge
(
struct
xfs_bmbt_irec
*
left
,
/* preceding extent */
struct
xfs_bmbt_irec
*
got
,
/* current extent to shift */
xfs_fileoff_t
shift
)
/* shift fsb */
{
xfs_fileoff_t
startoff
;
startoff
=
got
->
br_startoff
-
shift
;
/*
* The extent, once shifted, must be adjacent in-file and on-disk with
* the preceding extent.
*/
if
((
left
->
br_startoff
+
left
->
br_blockcount
!=
startoff
)
||
(
left
->
br_startblock
+
left
->
br_blockcount
!=
got
->
br_startblock
)
||
(
left
->
br_state
!=
got
->
br_state
)
||
(
left
->
br_blockcount
+
got
->
br_blockcount
>
MAXEXTLEN
))
return
false
;
return
true
;
}
/*
* A bmap extent shift adjusts the file offset of an extent to fill a preceding
* hole in the file. If an extent shift would result in the extent being fully
* adjacent to the extent that currently precedes the hole, we can merge with
* the preceding extent rather than do the shift.
*
* This function assumes the caller has verified a shift-by-merge is possible
* with the provided extents via xfs_bmse_can_merge().
*/
STATIC
int
xfs_bmse_merge
(
struct
xfs_inode
*
ip
,
int
whichfork
,
xfs_fileoff_t
shift
,
/* shift fsb */
int
current_ext
,
/* idx of gotp */
struct
xfs_bmbt_rec_host
*
gotp
,
/* extent to shift */
struct
xfs_bmbt_rec_host
*
leftp
,
/* preceding extent */
struct
xfs_btree_cur
*
cur
,
int
*
logflags
)
/* output */
{
struct
xfs_ifork
*
ifp
;
struct
xfs_bmbt_irec
got
;
struct
xfs_bmbt_irec
left
;
xfs_filblks_t
blockcount
;
int
error
,
i
;
ifp
=
XFS_IFORK_PTR
(
ip
,
whichfork
);
xfs_bmbt_get_all
(
gotp
,
&
got
);
xfs_bmbt_get_all
(
leftp
,
&
left
);
blockcount
=
left
.
br_blockcount
+
got
.
br_blockcount
;
ASSERT
(
xfs_isilocked
(
ip
,
XFS_IOLOCK_EXCL
));
ASSERT
(
xfs_isilocked
(
ip
,
XFS_ILOCK_EXCL
));
ASSERT
(
xfs_bmse_can_merge
(
&
left
,
&
got
,
shift
));
/*
* Merge the in-core extents. Note that the host record pointers and
* current_ext index are invalid once the extent has been removed via
* xfs_iext_remove().
*/
xfs_bmbt_set_blockcount
(
leftp
,
blockcount
);
xfs_iext_remove
(
ip
,
current_ext
,
1
,
0
);
/*
* Update the on-disk extent count, the btree if necessary and log the
* inode.
*/
XFS_IFORK_NEXT_SET
(
ip
,
whichfork
,
XFS_IFORK_NEXTENTS
(
ip
,
whichfork
)
-
1
);
*
logflags
|=
XFS_ILOG_CORE
;
if
(
!
cur
)
{
*
logflags
|=
XFS_ILOG_DEXT
;
return
0
;
}
/* lookup and remove the extent to merge */
error
=
xfs_bmbt_lookup_eq
(
cur
,
got
.
br_startoff
,
got
.
br_startblock
,
got
.
br_blockcount
,
&
i
);
if
(
error
)
goto
out_error
;
XFS_WANT_CORRUPTED_GOTO
(
i
==
1
,
out_error
);
error
=
xfs_btree_delete
(
cur
,
&
i
);
if
(
error
)
goto
out_error
;
XFS_WANT_CORRUPTED_GOTO
(
i
==
1
,
out_error
);
/* lookup and update size of the previous extent */
error
=
xfs_bmbt_lookup_eq
(
cur
,
left
.
br_startoff
,
left
.
br_startblock
,
left
.
br_blockcount
,
&
i
);
if
(
error
)
goto
out_error
;
XFS_WANT_CORRUPTED_GOTO
(
i
==
1
,
out_error
);
left
.
br_blockcount
=
blockcount
;
error
=
xfs_bmbt_update
(
cur
,
left
.
br_startoff
,
left
.
br_startblock
,
left
.
br_blockcount
,
left
.
br_state
);
if
(
error
)
goto
out_error
;
return
0
;
out_error:
return
error
;
}
/*
* Shift a single extent.
*/
STATIC
int
xfs_bmse_shift_one
(
struct
xfs_inode
*
ip
,
int
whichfork
,
xfs_fileoff_t
offset_shift_fsb
,
int
*
current_ext
,
struct
xfs_bmbt_rec_host
*
gotp
,
struct
xfs_btree_cur
*
cur
,
int
*
logflags
)
{
struct
xfs_ifork
*
ifp
;
xfs_fileoff_t
startoff
;
struct
xfs_bmbt_rec_host
*
leftp
;
struct
xfs_bmbt_irec
got
;
struct
xfs_bmbt_irec
left
;
int
error
;
int
i
;
ifp
=
XFS_IFORK_PTR
(
ip
,
whichfork
);
xfs_bmbt_get_all
(
gotp
,
&
got
);
startoff
=
got
.
br_startoff
-
offset_shift_fsb
;
/* delalloc extents should be prevented by caller */
XFS_WANT_CORRUPTED_GOTO
(
!
isnullstartblock
(
got
.
br_startblock
),
out_error
);
/*
* If this is the first extent in the file, make sure there's enough
* room at the start of the file and jump right to the shift as there's
* no left extent to merge.
*/
if
(
*
current_ext
==
0
)
{
if
(
got
.
br_startoff
<
offset_shift_fsb
)
return
-
EINVAL
;
goto
shift_extent
;
}
/* grab the left extent and check for a large enough hole */
leftp
=
xfs_iext_get_ext
(
ifp
,
*
current_ext
-
1
);
xfs_bmbt_get_all
(
leftp
,
&
left
);
if
(
startoff
<
left
.
br_startoff
+
left
.
br_blockcount
)
return
-
EINVAL
;
/* check whether to merge the extent or shift it down */
if
(
!
xfs_bmse_can_merge
(
&
left
,
&
got
,
offset_shift_fsb
))
goto
shift_extent
;
return
xfs_bmse_merge
(
ip
,
whichfork
,
offset_shift_fsb
,
*
current_ext
,
gotp
,
leftp
,
cur
,
logflags
);
shift_extent:
/*
* Increment the extent index for the next iteration, update the start
* offset of the in-core extent and update the btree if applicable.
*/
(
*
current_ext
)
++
;
xfs_bmbt_set_startoff
(
gotp
,
startoff
);
*
logflags
|=
XFS_ILOG_CORE
;
if
(
!
cur
)
{
*
logflags
|=
XFS_ILOG_DEXT
;
return
0
;
}
error
=
xfs_bmbt_lookup_eq
(
cur
,
got
.
br_startoff
,
got
.
br_startblock
,
got
.
br_blockcount
,
&
i
);
if
(
error
)
return
error
;
XFS_WANT_CORRUPTED_GOTO
(
i
==
1
,
out_error
);
got
.
br_startoff
=
startoff
;
error
=
xfs_bmbt_update
(
cur
,
got
.
br_startoff
,
got
.
br_startblock
,
got
.
br_blockcount
,
got
.
br_state
);
if
(
error
)
return
error
;
return
0
;
out_error:
return
error
;
}
/*
* Shift extent records to the left to cover a hole.
*
* The maximum number of extents to be shifted in a single operation
* is @num_exts, and @current_ext keeps track of the current extent
* index we have shifted. @offset_shift_fsb is the length by which each
* extent is shifted. If there is no hole to shift the extents
* into, this will be considered invalid operation and we abort immediately.
* The maximum number of extents to be shifted in a single operation is
* @num_exts. @start_fsb specifies the file offset to start the shift and the
* file offset where we've left off is returned in @next_fsb. @offset_shift_fsb
* is the length by which each extent is shifted. If there is no hole to shift
* the extents into, this will be considered invalid operation and we abort
* immediately.
*/
int
xfs_bmap_shift_extents
(
struct
xfs_trans
*
tp
,
struct
xfs_inode
*
ip
,
int
*
done
,
xfs_fileoff_t
start_fsb
,
xfs_fileoff_t
offset_shift_fsb
,
xfs_extnum_t
*
current_ext
,
int
*
done
,
xfs_fileoff_t
*
next_fsb
,
xfs_fsblock_t
*
firstblock
,
struct
xfs_bmap_free
*
flist
,
int
num_exts
)
...
...
@@ -5427,16 +5628,13 @@ xfs_bmap_shift_extents(
struct
xfs_btree_cur
*
cur
=
NULL
;
struct
xfs_bmbt_rec_host
*
gotp
;
struct
xfs_bmbt_irec
got
;
struct
xfs_bmbt_irec
left
;
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
struct
xfs_ifork
*
ifp
;
xfs_extnum_t
nexts
=
0
;
xfs_
fileoff_t
startoff
;
xfs_
extnum_t
current_ext
;
int
error
=
0
;
int
i
;
int
whichfork
=
XFS_DATA_FORK
;
int
logflags
=
0
;
xfs_filblks_t
blockcount
=
0
;
int
total_extents
;
if
(
unlikely
(
XFS_TEST_ERROR
(
...
...
@@ -5451,7 +5649,8 @@ xfs_bmap_shift_extents(
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
-
EIO
;
ASSERT
(
current_ext
!=
NULL
);
ASSERT
(
xfs_isilocked
(
ip
,
XFS_IOLOCK_EXCL
));
ASSERT
(
xfs_isilocked
(
ip
,
XFS_ILOCK_EXCL
));
ifp
=
XFS_IFORK_PTR
(
ip
,
whichfork
);
if
(
!
(
ifp
->
if_flags
&
XFS_IFEXTENTS
))
{
...
...
@@ -5461,23 +5660,6 @@ xfs_bmap_shift_extents(
return
error
;
}
/*
* If *current_ext is 0, we would need to lookup the extent
* from where we would start shifting and store it in gotp.
*/
if
(
!*
current_ext
)
{
gotp
=
xfs_iext_bno_to_ext
(
ifp
,
start_fsb
,
current_ext
);
/*
* gotp can be null in 2 cases: 1) if there are no extents
* or 2) start_fsb lies in a hole beyond which there are
* no extents. Either way, we are done.
*/
if
(
!
gotp
)
{
*
done
=
1
;
return
0
;
}
}
if
(
ifp
->
if_flags
&
XFS_IFBROOT
)
{
cur
=
xfs_bmbt_init_cursor
(
mp
,
tp
,
ip
,
whichfork
);
cur
->
bc_private
.
b
.
firstblock
=
*
firstblock
;
...
...
@@ -5485,113 +5667,47 @@ xfs_bmap_shift_extents(
cur
->
bc_private
.
b
.
flags
=
0
;
}
/*
* Look up the extent index for the fsb where we start shifting. We can
* henceforth iterate with current_ext as extent list changes are locked
* out via ilock.
*
* gotp can be null in 2 cases: 1) if there are no extents or 2)
* start_fsb lies in a hole beyond which there are no extents. Either
* way, we are done.
*/
gotp
=
xfs_iext_bno_to_ext
(
ifp
,
start_fsb
,
&
current_ext
);
if
(
!
gotp
)
{
*
done
=
1
;
goto
del_cursor
;
}
/*
* There may be delalloc extents in the data fork before the range we
* are collapsing out, so we cannot
* use the count of real extents here. Instead we have to calculate it
* from the incore fork.
* are collapsing out, so we cannot use the count of real extents here.
* Instead we have to calculate it from the incore fork.
*/
total_extents
=
ifp
->
if_bytes
/
sizeof
(
xfs_bmbt_rec_t
);
while
(
nexts
++
<
num_exts
&&
*
current_ext
<
total_extents
)
{
gotp
=
xfs_iext_get_ext
(
ifp
,
*
current_ext
);
xfs_bmbt_get_all
(
gotp
,
&
got
);
startoff
=
got
.
br_startoff
-
offset_shift_fsb
;
/*
* Before shifting extent into hole, make sure that the hole
* is large enough to accomodate the shift.
*/
if
(
*
current_ext
)
{
xfs_bmbt_get_all
(
xfs_iext_get_ext
(
ifp
,
*
current_ext
-
1
),
&
left
);
if
(
startoff
<
left
.
br_startoff
+
left
.
br_blockcount
)
error
=
-
EINVAL
;
}
else
if
(
offset_shift_fsb
>
got
.
br_startoff
)
{
/*
* When first extent is shifted, offset_shift_fsb
* should be less than the stating offset of
* the first extent.
*/
error
=
-
EINVAL
;
}
while
(
nexts
++
<
num_exts
&&
current_ext
<
total_extents
)
{
error
=
xfs_bmse_shift_one
(
ip
,
whichfork
,
offset_shift_fsb
,
&
current_ext
,
gotp
,
cur
,
&
logflags
);
if
(
error
)
goto
del_cursor
;
if
(
cur
)
{
error
=
xfs_bmbt_lookup_eq
(
cur
,
got
.
br_startoff
,
got
.
br_startblock
,
got
.
br_blockcount
,
&
i
);
if
(
error
)
goto
del_cursor
;
XFS_WANT_CORRUPTED_GOTO
(
i
==
1
,
del_cursor
);
}
/* Check if we can merge 2 adjacent extents */
if
(
*
current_ext
&&
left
.
br_startoff
+
left
.
br_blockcount
==
startoff
&&
left
.
br_startblock
+
left
.
br_blockcount
==
got
.
br_startblock
&&
left
.
br_state
==
got
.
br_state
&&
left
.
br_blockcount
+
got
.
br_blockcount
<=
MAXEXTLEN
)
{
blockcount
=
left
.
br_blockcount
+
got
.
br_blockcount
;
xfs_iext_remove
(
ip
,
*
current_ext
,
1
,
0
);
logflags
|=
XFS_ILOG_CORE
;
if
(
cur
)
{
error
=
xfs_btree_delete
(
cur
,
&
i
);
if
(
error
)
goto
del_cursor
;
XFS_WANT_CORRUPTED_GOTO
(
i
==
1
,
del_cursor
);
}
else
{
logflags
|=
XFS_ILOG_DEXT
;
}
XFS_IFORK_NEXT_SET
(
ip
,
whichfork
,
XFS_IFORK_NEXTENTS
(
ip
,
whichfork
)
-
1
);
gotp
=
xfs_iext_get_ext
(
ifp
,
--*
current_ext
);
xfs_bmbt_get_all
(
gotp
,
&
got
);
/* Make cursor point to the extent we will update */
if
(
cur
)
{
error
=
xfs_bmbt_lookup_eq
(
cur
,
got
.
br_startoff
,
got
.
br_startblock
,
got
.
br_blockcount
,
&
i
);
if
(
error
)
goto
del_cursor
;
XFS_WANT_CORRUPTED_GOTO
(
i
==
1
,
del_cursor
);
}
xfs_bmbt_set_blockcount
(
gotp
,
blockcount
);
got
.
br_blockcount
=
blockcount
;
}
else
{
/* We have to update the startoff */
xfs_bmbt_set_startoff
(
gotp
,
startoff
);
got
.
br_startoff
=
startoff
;
}
logflags
|=
XFS_ILOG_CORE
;
if
(
cur
)
{
error
=
xfs_bmbt_update
(
cur
,
got
.
br_startoff
,
got
.
br_startblock
,
got
.
br_blockcount
,
got
.
br_state
);
if
(
error
)
goto
del_cursor
;
}
else
{
logflags
|=
XFS_ILOG_DEXT
;
}
(
*
current_ext
)
++
;
/* update total extent count and grab the next record */
total_extents
=
ifp
->
if_bytes
/
sizeof
(
xfs_bmbt_rec_t
);
if
(
current_ext
>=
total_extents
)
break
;
gotp
=
xfs_iext_get_ext
(
ifp
,
current_ext
);
}
/* Check if we are done */
if
(
*
current_ext
==
total_extents
)
if
(
current_ext
==
total_extents
)
{
*
done
=
1
;
}
else
if
(
next_fsb
)
{
xfs_bmbt_get_all
(
gotp
,
&
got
);
*
next_fsb
=
got
.
br_startoff
;
}
del_cursor:
if
(
cur
)
...
...
@@ -5600,5 +5716,6 @@ xfs_bmap_shift_extents(
if
(
logflags
)
xfs_trans_log_inode
(
tp
,
ip
,
logflags
);
return
error
;
}
fs/xfs/libxfs/xfs_bmap.h
View file @
f6d31f4b
...
...
@@ -178,9 +178,8 @@ int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
xfs_extnum_t
num
);
uint
xfs_default_attroffset
(
struct
xfs_inode
*
ip
);
int
xfs_bmap_shift_extents
(
struct
xfs_trans
*
tp
,
struct
xfs_inode
*
ip
,
int
*
done
,
xfs_fileoff_t
start_fsb
,
xfs_fileoff_t
offset_shift_fsb
,
xfs_extnum_t
*
current_ext
,
xfs_fsblock_t
*
firstblock
,
struct
xfs_bmap_free
*
flist
,
int
num_exts
);
xfs_fileoff_t
start_fsb
,
xfs_fileoff_t
offset_shift_fsb
,
int
*
done
,
xfs_fileoff_t
*
next_fsb
,
xfs_fsblock_t
*
firstblock
,
struct
xfs_bmap_free
*
flist
,
int
num_exts
);
#endif
/* __XFS_BMAP_H__ */
fs/xfs/xfs_aops.c
View file @
f6d31f4b
...
...
@@ -434,10 +434,22 @@ xfs_start_page_writeback(
{
ASSERT
(
PageLocked
(
page
));
ASSERT
(
!
PageWriteback
(
page
));
if
(
clear_dirty
)
/*
* if the page was not fully cleaned, we need to ensure that the higher
* layers come back to it correctly. That means we need to keep the page
* dirty, and for WB_SYNC_ALL writeback we need to ensure the
* PAGECACHE_TAG_TOWRITE index mark is not removed so another attempt to
* write this page in this writeback sweep will be made.
*/
if
(
clear_dirty
)
{
clear_page_dirty_for_io
(
page
);
set_page_writeback
(
page
);
set_page_writeback
(
page
);
}
else
set_page_writeback_keepwrite
(
page
);
unlock_page
(
page
);
/* If no buffers on the page are to be written, finish it here */
if
(
!
buffers
)
end_page_writeback
(
page
);
...
...
fs/xfs/xfs_bmap_util.c
View file @
f6d31f4b
...
...
@@ -1205,6 +1205,7 @@ xfs_free_file_space(
xfs_bmap_free_t
free_list
;
xfs_bmbt_irec_t
imap
;
xfs_off_t
ioffset
;
xfs_off_t
iendoffset
;
xfs_extlen_t
mod
=
0
;
xfs_mount_t
*
mp
;
int
nimap
;
...
...
@@ -1233,12 +1234,13 @@ xfs_free_file_space(
inode_dio_wait
(
VFS_I
(
ip
));
rounding
=
max_t
(
xfs_off_t
,
1
<<
mp
->
m_sb
.
sb_blocklog
,
PAGE_CACHE_SIZE
);
ioffset
=
offset
&
~
(
rounding
-
1
);
error
=
filemap_write_and_wait_range
(
VFS_I
(
ip
)
->
i_mapping
,
ioffset
,
-
1
);
ioffset
=
round_down
(
offset
,
rounding
);
iendoffset
=
round_up
(
offset
+
len
,
rounding
)
-
1
;
error
=
filemap_write_and_wait_range
(
VFS_I
(
ip
)
->
i_mapping
,
ioffset
,
iendoffset
);
if
(
error
)
goto
out
;
truncate_pagecache_range
(
VFS_I
(
ip
),
ioffset
,
-
1
);
truncate_pagecache_range
(
VFS_I
(
ip
),
ioffset
,
iendoffset
);
/*
* Need to zero the stuff we're not freeing, on disk.
...
...
@@ -1456,41 +1458,47 @@ xfs_collapse_file_space(
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
struct
xfs_trans
*
tp
;
int
error
;
xfs_extnum_t
current_ext
=
0
;
struct
xfs_bmap_free
free_list
;
xfs_fsblock_t
first_block
;
int
committed
;
xfs_fileoff_t
start_fsb
;
xfs_fileoff_t
next_fsb
;
xfs_fileoff_t
shift_fsb
;
ASSERT
(
xfs_isilocked
(
ip
,
XFS_IOLOCK_EXCL
));
trace_xfs_collapse_file_space
(
ip
);
star
t_fsb
=
XFS_B_TO_FSB
(
mp
,
offset
+
len
);
nex
t_fsb
=
XFS_B_TO_FSB
(
mp
,
offset
+
len
);
shift_fsb
=
XFS_B_TO_FSB
(
mp
,
len
);
/*
* Writeback the entire file and force remove any post-eof blocks. The
* writeback prevents changes to the extent list via concurrent
* writeback and the eofblocks trim prevents the extent shift algorithm
* from running into a post-eof delalloc extent.
*
* XXX: This is a temporary fix until the extent shift loop below is
* converted to use offsets and lookups within the ILOCK rather than
* carrying around the index into the extent list for the next
* iteration.
*/
error
=
filemap_write_and_wait
(
VFS_I
(
ip
)
->
i_mapping
);
error
=
xfs_free_file_space
(
ip
,
offset
,
len
);
if
(
error
)
return
error
;
/*
* Trim eofblocks to avoid shifting uninitialized post-eof preallocation
* into the accessible region of the file.
*/
if
(
xfs_can_free_eofblocks
(
ip
,
true
))
{
error
=
xfs_free_eofblocks
(
mp
,
ip
,
false
);
if
(
error
)
return
error
;
}
error
=
xfs_free_file_space
(
ip
,
offset
,
len
);
/*
* Writeback and invalidate cache for the remainder of the file as we're
* about to shift down every extent from the collapse range to EOF. The
* free of the collapse range above might have already done some of
* this, but we shouldn't rely on it to do anything outside of the range
* that was freed.
*/
error
=
filemap_write_and_wait_range
(
VFS_I
(
ip
)
->
i_mapping
,
offset
+
len
,
-
1
);
if
(
error
)
return
error
;
error
=
invalidate_inode_pages2_range
(
VFS_I
(
ip
)
->
i_mapping
,
(
offset
+
len
)
>>
PAGE_CACHE_SHIFT
,
-
1
);
if
(
error
)
return
error
;
...
...
@@ -1525,10 +1533,10 @@ xfs_collapse_file_space(
* We are using the write transaction in which max 2 bmbt
* updates are allowed
*/
error
=
xfs_bmap_shift_extents
(
tp
,
ip
,
&
done
,
start_fsb
,
shift_fsb
,
&
current_ext
,
&
first_block
,
&
free_list
,
XFS_BMAP_MAX_SHIFT_EXTENTS
);
start_fsb
=
next_fsb
;
error
=
xfs_bmap_shift_extents
(
tp
,
ip
,
start_fsb
,
shift_fsb
,
&
done
,
&
next_fsb
,
&
first_block
,
&
free_list
,
XFS_BMAP_MAX_SHIFT_EXTENTS
);
if
(
error
)
goto
out
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment