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
f477cedc
Commit
f477cedc
authored
Jun 21, 2016
by
Dave Chinner
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'xfs-4.8-misc-fixes-2' into for-next
parents
9b7fad20
19b54ee6
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
246 additions
and
166 deletions
+246
-166
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.c
+56
-43
fs/xfs/libxfs/xfs_alloc.h
fs/xfs/libxfs/xfs_alloc.h
+2
-0
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.c
+17
-34
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_bmap.h
+10
-8
fs/xfs/libxfs/xfs_bmap_btree.c
fs/xfs/libxfs/xfs_bmap_btree.c
+1
-1
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_btree.c
+19
-0
fs/xfs/libxfs/xfs_btree.h
fs/xfs/libxfs/xfs_btree.h
+2
-0
fs/xfs/libxfs/xfs_ialloc.c
fs/xfs/libxfs/xfs_ialloc.c
+9
-19
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_bmap_util.c
+25
-7
fs/xfs/xfs_bmap_util.h
fs/xfs/xfs_bmap_util.h
+0
-1
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.c
+5
-3
fs/xfs/xfs_error.c
fs/xfs/xfs_error.c
+3
-0
fs/xfs/xfs_fsops.c
fs/xfs/xfs_fsops.c
+60
-45
fs/xfs/xfs_icache.c
fs/xfs/xfs_icache.c
+1
-1
fs/xfs/xfs_icache.h
fs/xfs/xfs_icache.h
+1
-0
fs/xfs/xfs_ondisk.h
fs/xfs/xfs_ondisk.h
+23
-2
fs/xfs/xfs_super.c
fs/xfs/xfs_super.c
+11
-2
fs/xfs/xfs_trace.h
fs/xfs/xfs_trace.h
+1
-0
No files found.
fs/xfs/libxfs/xfs_alloc.c
View file @
f477cedc
...
...
@@ -1839,19 +1839,8 @@ void
xfs_alloc_compute_maxlevels
(
xfs_mount_t
*
mp
)
/* file system mount structure */
{
int
level
;
uint
maxblocks
;
uint
maxleafents
;
int
minleafrecs
;
int
minnoderecs
;
maxleafents
=
(
mp
->
m_sb
.
sb_agblocks
+
1
)
/
2
;
minleafrecs
=
mp
->
m_alloc_mnr
[
0
];
minnoderecs
=
mp
->
m_alloc_mnr
[
1
];
maxblocks
=
(
maxleafents
+
minleafrecs
-
1
)
/
minleafrecs
;
for
(
level
=
1
;
maxblocks
>
1
;
level
++
)
maxblocks
=
(
maxblocks
+
minnoderecs
-
1
)
/
minnoderecs
;
mp
->
m_ag_maxlevels
=
level
;
mp
->
m_ag_maxlevels
=
xfs_btree_compute_maxlevels
(
mp
,
mp
->
m_alloc_mnr
,
(
mp
->
m_sb
.
sb_agblocks
+
1
)
/
2
);
}
/*
...
...
@@ -2658,55 +2647,79 @@ xfs_alloc_vextent(
return
error
;
}
/*
* Free an extent.
* Just break up the extent address and hand off to xfs_free_ag_extent
* after fixing up the freelist.
*/
int
/* error */
xfs_free_extent
(
xfs_trans_t
*
tp
,
/* transaction pointer */
xfs_fsblock_t
bno
,
/* starting block number of extent */
xfs_extlen_t
len
)
/* length of extent */
/* Ensure that the freelist is at full capacity. */
int
xfs_free_extent_fix_freelist
(
struct
xfs_trans
*
tp
,
xfs_agnumber_t
agno
,
struct
xfs_buf
**
agbp
)
{
xfs_alloc_arg_t
args
;
int
error
;
struct
xfs_alloc_arg
args
;
int
error
;
ASSERT
(
len
!=
0
);
memset
(
&
args
,
0
,
sizeof
(
xfs_alloc_arg_t
));
memset
(
&
args
,
0
,
sizeof
(
struct
xfs_alloc_arg
));
args
.
tp
=
tp
;
args
.
mp
=
tp
->
t_mountp
;
args
.
agno
=
agno
;
/*
* validate that the block number is legal - the enables us to detect
* and handle a silent filesystem corruption rather than crashing.
*/
args
.
agno
=
XFS_FSB_TO_AGNO
(
args
.
mp
,
bno
);
if
(
args
.
agno
>=
args
.
mp
->
m_sb
.
sb_agcount
)
return
-
EFSCORRUPTED
;
args
.
agbno
=
XFS_FSB_TO_AGBNO
(
args
.
mp
,
bno
);
if
(
args
.
agbno
>=
args
.
mp
->
m_sb
.
sb_agblocks
)
return
-
EFSCORRUPTED
;
args
.
pag
=
xfs_perag_get
(
args
.
mp
,
args
.
agno
);
ASSERT
(
args
.
pag
);
error
=
xfs_alloc_fix_freelist
(
&
args
,
XFS_ALLOC_FLAG_FREEING
);
if
(
error
)
goto
error0
;
goto
out
;
*
agbp
=
args
.
agbp
;
out:
xfs_perag_put
(
args
.
pag
);
return
error
;
}
/*
* Free an extent.
* Just break up the extent address and hand off to xfs_free_ag_extent
* after fixing up the freelist.
*/
int
/* error */
xfs_free_extent
(
struct
xfs_trans
*
tp
,
/* transaction pointer */
xfs_fsblock_t
bno
,
/* starting block number of extent */
xfs_extlen_t
len
)
/* length of extent */
{
struct
xfs_mount
*
mp
=
tp
->
t_mountp
;
struct
xfs_buf
*
agbp
;
xfs_agnumber_t
agno
=
XFS_FSB_TO_AGNO
(
mp
,
bno
);
xfs_agblock_t
agbno
=
XFS_FSB_TO_AGBNO
(
mp
,
bno
);
int
error
;
ASSERT
(
len
!=
0
);
error
=
xfs_free_extent_fix_freelist
(
tp
,
agno
,
&
agbp
);
if
(
error
)
return
error
;
XFS_WANT_CORRUPTED_GOTO
(
mp
,
agbno
<
mp
->
m_sb
.
sb_agblocks
,
err
);
/* validate the extent size is legal now we have the agf locked */
if
(
args
.
agbno
+
len
>
be32_to_cpu
(
XFS_BUF_TO_AGF
(
args
.
agbp
)
->
agf_length
))
{
error
=
-
EFSCORRUPTED
;
goto
error0
;
}
XFS_WANT_CORRUPTED_GOTO
(
mp
,
agbno
+
len
<=
be32_to_cpu
(
XFS_BUF_TO_AGF
(
agbp
)
->
agf_length
),
err
);
error
=
xfs_free_ag_extent
(
tp
,
args
.
agbp
,
args
.
agno
,
args
.
agbno
,
len
,
0
);
if
(
!
error
)
xfs_extent_busy_insert
(
tp
,
args
.
agno
,
args
.
agbno
,
len
,
0
);
error0:
xfs_perag_put
(
args
.
pag
);
error
=
xfs_free_ag_extent
(
tp
,
agbp
,
agno
,
agbno
,
len
,
0
);
if
(
error
)
goto
err
;
xfs_extent_busy_insert
(
tp
,
agno
,
agbno
,
len
,
0
);
return
0
;
err:
xfs_trans_brelse
(
tp
,
agbp
);
return
error
;
}
fs/xfs/libxfs/xfs_alloc.h
View file @
f477cedc
...
...
@@ -229,5 +229,7 @@ xfs_alloc_get_rec(
int
xfs_read_agf
(
struct
xfs_mount
*
mp
,
struct
xfs_trans
*
tp
,
xfs_agnumber_t
agno
,
int
flags
,
struct
xfs_buf
**
bpp
);
int
xfs_alloc_fix_freelist
(
struct
xfs_alloc_arg
*
args
,
int
flags
);
int
xfs_free_extent_fix_freelist
(
struct
xfs_trans
*
tp
,
xfs_agnumber_t
agno
,
struct
xfs_buf
**
agbp
);
#endif
/* __XFS_ALLOC_H__ */
fs/xfs/libxfs/xfs_bmap.c
View file @
f477cedc
...
...
@@ -570,14 +570,12 @@ xfs_bmap_validate_ret(
*/
void
xfs_bmap_add_free
(
struct
xfs_mount
*
mp
,
/* mount point structure */
struct
xfs_bmap_free
*
flist
,
/* list of extents */
xfs_fsblock_t
bno
,
/* fs block number of extent */
xfs_filblks_t
len
,
/* length of extent */
xfs_bmap_free_t
*
flist
,
/* list of extents */
xfs_mount_t
*
mp
)
/* mount point structure */
xfs_filblks_t
len
)
/* length of extent */
{
xfs_bmap_free_item_t
*
cur
;
/* current (next) element */
xfs_bmap_free_item_t
*
new
;
/* new element */
xfs_bmap_free_item_t
*
prev
;
/* previous element */
struct
xfs_bmap_free_item
*
new
;
/* new element */
#ifdef DEBUG
xfs_agnumber_t
agno
;
xfs_agblock_t
agbno
;
...
...
@@ -597,17 +595,7 @@ xfs_bmap_add_free(
new
=
kmem_zone_alloc
(
xfs_bmap_free_item_zone
,
KM_SLEEP
);
new
->
xbfi_startblock
=
bno
;
new
->
xbfi_blockcount
=
(
xfs_extlen_t
)
len
;
for
(
prev
=
NULL
,
cur
=
flist
->
xbf_first
;
cur
!=
NULL
;
prev
=
cur
,
cur
=
cur
->
xbfi_next
)
{
if
(
cur
->
xbfi_startblock
>=
bno
)
break
;
}
if
(
prev
)
prev
->
xbfi_next
=
new
;
else
flist
->
xbf_first
=
new
;
new
->
xbfi_next
=
cur
;
list_add
(
&
new
->
xbfi_list
,
&
flist
->
xbf_flist
);
flist
->
xbf_count
++
;
}
...
...
@@ -617,14 +605,10 @@ xfs_bmap_add_free(
*/
void
xfs_bmap_del_free
(
xfs_bmap_free_t
*
flist
,
/* free item list header */
xfs_bmap_free_item_t
*
prev
,
/* previous item on list, if any */
xfs_bmap_free_item_t
*
free
)
/* list item to be freed */
struct
xfs_bmap_free
*
flist
,
/* free item list header */
struct
xfs_bmap_free_item
*
free
)
/* list item to be freed */
{
if
(
prev
)
prev
->
xbfi_next
=
free
->
xbfi_next
;
else
flist
->
xbf_first
=
free
->
xbfi_next
;
list_del
(
&
free
->
xbfi_list
);
flist
->
xbf_count
--
;
kmem_zone_free
(
xfs_bmap_free_item_zone
,
free
);
}
...
...
@@ -634,17 +618,16 @@ xfs_bmap_del_free(
*/
void
xfs_bmap_cancel
(
xfs_bmap_free_t
*
flist
)
/* list of bmap_free_items */
struct
xfs_bmap_free
*
flist
)
/* list of bmap_free_items */
{
xfs_bmap_free_item_t
*
free
;
/* free list item */
xfs_bmap_free_item_t
*
next
;
struct
xfs_bmap_free_item
*
free
;
/* free list item */
if
(
flist
->
xbf_count
==
0
)
return
;
ASSERT
(
flist
->
xbf_first
!=
NULL
);
for
(
free
=
flist
->
xbf_first
;
free
;
free
=
next
)
{
next
=
free
->
xbfi_next
;
xfs_bmap_del_free
(
flist
,
NULL
,
free
);
while
(
!
list_empty
(
&
flist
->
xbf_flist
))
{
free
=
list_first_entry
(
&
flist
->
xbf_flist
,
struct
xfs_bmap_free_item
,
xbfi_list
)
;
xfs_bmap_del_free
(
flist
,
free
);
}
ASSERT
(
flist
->
xbf_count
==
0
);
}
...
...
@@ -699,7 +682,7 @@ xfs_bmap_btree_to_extents(
cblock
=
XFS_BUF_TO_BLOCK
(
cbp
);
if
((
error
=
xfs_btree_check_block
(
cur
,
cblock
,
0
,
cbp
)))
return
error
;
xfs_bmap_add_free
(
cbno
,
1
,
cur
->
bc_private
.
b
.
flist
,
mp
);
xfs_bmap_add_free
(
mp
,
cur
->
bc_private
.
b
.
flist
,
cbno
,
1
);
ip
->
i_d
.
di_nblocks
--
;
xfs_trans_mod_dquot_byino
(
tp
,
ip
,
XFS_TRANS_DQ_BCOUNT
,
-
1L
);
xfs_trans_binval
(
tp
,
cbp
);
...
...
@@ -5073,8 +5056,8 @@ xfs_bmap_del_extent(
* If we need to, add to list of extents to delete.
*/
if
(
do_fx
)
xfs_bmap_add_free
(
del
->
br_startblock
,
del
->
br_blockcount
,
flist
,
mp
);
xfs_bmap_add_free
(
mp
,
flist
,
del
->
br_startblock
,
del
->
br_blockcount
);
/*
* Adjust inode # blocks in the file.
*/
...
...
fs/xfs/libxfs/xfs_bmap.h
View file @
f477cedc
...
...
@@ -62,12 +62,12 @@ struct xfs_bmalloca {
* List of extents to be free "later".
* The list is kept sorted on xbf_startblock.
*/
typedef
struct
xfs_bmap_free_item
struct
xfs_bmap_free_item
{
xfs_fsblock_t
xbfi_startblock
;
/* starting fs block number */
xfs_extlen_t
xbfi_blockcount
;
/* number of blocks in extent */
struct
xfs_bmap_free_item
*
xbfi_next
;
/* link to next entry */
}
xfs_bmap_free_item_t
;
struct
list_head
xbfi_list
;
};
/*
* Header for free extent list.
...
...
@@ -85,7 +85,7 @@ typedef struct xfs_bmap_free_item
*/
typedef
struct
xfs_bmap_free
{
xfs_bmap_free_item_t
*
xbf_fir
st
;
/* list of to-be-free extents */
struct
list_head
xbf_fli
st
;
/* list of to-be-free extents */
int
xbf_count
;
/* count of items on list */
int
xbf_low
;
/* alloc in low mode */
}
xfs_bmap_free_t
;
...
...
@@ -141,8 +141,10 @@ static inline int xfs_bmapi_aflag(int w)
static
inline
void
xfs_bmap_init
(
xfs_bmap_free_t
*
flp
,
xfs_fsblock_t
*
fbp
)
{
((
flp
)
->
xbf_first
=
NULL
,
(
flp
)
->
xbf_count
=
0
,
\
(
flp
)
->
xbf_low
=
0
,
*
(
fbp
)
=
NULLFSBLOCK
);
INIT_LIST_HEAD
(
&
flp
->
xbf_flist
);
flp
->
xbf_count
=
0
;
flp
->
xbf_low
=
0
;
*
fbp
=
NULLFSBLOCK
;
}
/*
...
...
@@ -191,8 +193,8 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
int
xfs_bmap_add_attrfork
(
struct
xfs_inode
*
ip
,
int
size
,
int
rsvd
);
void
xfs_bmap_local_to_extents_empty
(
struct
xfs_inode
*
ip
,
int
whichfork
);
void
xfs_bmap_add_free
(
xfs_fsblock_t
bno
,
xfs_filblks_t
len
,
struct
xfs_bmap_free
*
flist
,
struct
xfs_mount
*
mp
);
void
xfs_bmap_add_free
(
struct
xfs_mount
*
mp
,
struct
xfs_bmap_free
*
flist
,
xfs_fsblock_t
bno
,
xfs_filblks_t
len
);
void
xfs_bmap_cancel
(
struct
xfs_bmap_free
*
flist
);
int
xfs_bmap_finish
(
struct
xfs_trans
**
tp
,
struct
xfs_bmap_free
*
flist
,
struct
xfs_inode
*
ip
);
...
...
fs/xfs/libxfs/xfs_bmap_btree.c
View file @
f477cedc
...
...
@@ -526,7 +526,7 @@ xfs_bmbt_free_block(
struct
xfs_trans
*
tp
=
cur
->
bc_tp
;
xfs_fsblock_t
fsbno
=
XFS_DADDR_TO_FSB
(
mp
,
XFS_BUF_ADDR
(
bp
));
xfs_bmap_add_free
(
fsbno
,
1
,
cur
->
bc_private
.
b
.
flist
,
mp
);
xfs_bmap_add_free
(
mp
,
cur
->
bc_private
.
b
.
flist
,
fsbno
,
1
);
ip
->
i_d
.
di_nblocks
--
;
xfs_trans_log_inode
(
tp
,
ip
,
XFS_ILOG_CORE
);
...
...
fs/xfs/libxfs/xfs_btree.c
View file @
f477cedc
...
...
@@ -4152,3 +4152,22 @@ xfs_btree_sblock_verify(
return
true
;
}
/*
* Calculate the number of btree levels needed to store a given number of
* records in a short-format btree.
*/
uint
xfs_btree_compute_maxlevels
(
struct
xfs_mount
*
mp
,
uint
*
limits
,
unsigned
long
len
)
{
uint
level
;
unsigned
long
maxblocks
;
maxblocks
=
(
len
+
limits
[
0
]
-
1
)
/
limits
[
0
];
for
(
level
=
1
;
maxblocks
>
1
;
level
++
)
maxblocks
=
(
maxblocks
+
limits
[
1
]
-
1
)
/
limits
[
1
];
return
level
;
}
fs/xfs/libxfs/xfs_btree.h
View file @
f477cedc
...
...
@@ -474,5 +474,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block)
bool
xfs_btree_sblock_v5hdr_verify
(
struct
xfs_buf
*
bp
);
bool
xfs_btree_sblock_verify
(
struct
xfs_buf
*
bp
,
unsigned
int
max_recs
);
uint
xfs_btree_compute_maxlevels
(
struct
xfs_mount
*
mp
,
uint
*
limits
,
unsigned
long
len
);
#endif
/* __XFS_BTREE_H__ */
fs/xfs/libxfs/xfs_ialloc.c
View file @
f477cedc
...
...
@@ -1828,9 +1828,8 @@ xfs_difree_inode_chunk(
if
(
!
xfs_inobt_issparse
(
rec
->
ir_holemask
))
{
/* not sparse, calculate extent info directly */
xfs_bmap_add_free
(
XFS_AGB_TO_FSB
(
mp
,
agno
,
XFS_AGINO_TO_AGBNO
(
mp
,
rec
->
ir_startino
)),
mp
->
m_ialloc_blks
,
flist
,
mp
);
xfs_bmap_add_free
(
mp
,
flist
,
XFS_AGB_TO_FSB
(
mp
,
agno
,
sagbno
),
mp
->
m_ialloc_blks
);
return
;
}
...
...
@@ -1873,8 +1872,8 @@ xfs_difree_inode_chunk(
ASSERT
(
agbno
%
mp
->
m_sb
.
sb_spino_align
==
0
);
ASSERT
(
contigblk
%
mp
->
m_sb
.
sb_spino_align
==
0
);
xfs_bmap_add_free
(
XFS_AGB_TO_FSB
(
mp
,
agno
,
agbno
),
contigblk
,
flist
,
mp
);
xfs_bmap_add_free
(
mp
,
flist
,
XFS_AGB_TO_FSB
(
mp
,
agno
,
agbno
)
,
contigblk
);
/* reset range to current bit and carry on... */
startidx
=
endidx
=
nextbit
;
...
...
@@ -2395,20 +2394,11 @@ void
xfs_ialloc_compute_maxlevels
(
xfs_mount_t
*
mp
)
/* file system mount structure */
{
int
level
;
uint
maxblocks
;
uint
maxleafents
;
int
minleafrecs
;
int
minnoderecs
;
maxleafents
=
(
1LL
<<
XFS_INO_AGINO_BITS
(
mp
))
>>
XFS_INODES_PER_CHUNK_LOG
;
minleafrecs
=
mp
->
m_inobt_mnr
[
0
];
minnoderecs
=
mp
->
m_inobt_mnr
[
1
];
maxblocks
=
(
maxleafents
+
minleafrecs
-
1
)
/
minleafrecs
;
for
(
level
=
1
;
maxblocks
>
1
;
level
++
)
maxblocks
=
(
maxblocks
+
minnoderecs
-
1
)
/
minnoderecs
;
mp
->
m_in_maxlevels
=
level
;
uint
inodes
;
inodes
=
(
1LL
<<
XFS_INO_AGINO_BITS
(
mp
))
>>
XFS_INODES_PER_CHUNK_LOG
;
mp
->
m_in_maxlevels
=
xfs_btree_compute_maxlevels
(
mp
,
mp
->
m_inobt_mnr
,
inodes
);
}
/*
...
...
fs/xfs/xfs_bmap_util.c
View file @
f477cedc
...
...
@@ -79,6 +79,23 @@ xfs_zero_extent(
GFP_NOFS
,
true
);
}
/* Sort bmap items by AG. */
static
int
xfs_bmap_free_list_cmp
(
void
*
priv
,
struct
list_head
*
a
,
struct
list_head
*
b
)
{
struct
xfs_mount
*
mp
=
priv
;
struct
xfs_bmap_free_item
*
ra
;
struct
xfs_bmap_free_item
*
rb
;
ra
=
container_of
(
a
,
struct
xfs_bmap_free_item
,
xbfi_list
);
rb
=
container_of
(
b
,
struct
xfs_bmap_free_item
,
xbfi_list
);
return
XFS_FSB_TO_AGNO
(
mp
,
ra
->
xbfi_startblock
)
-
XFS_FSB_TO_AGNO
(
mp
,
rb
->
xbfi_startblock
);
}
/*
* Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
* caller. Frees all the extents that need freeing, which must be done
...
...
@@ -99,14 +116,15 @@ xfs_bmap_finish(
int
error
;
/* error return value */
int
committed
;
/* xact committed or not */
struct
xfs_bmap_free_item
*
free
;
/* free extent item */
struct
xfs_bmap_free_item
*
next
;
/* next item on free list */
ASSERT
((
*
tp
)
->
t_flags
&
XFS_TRANS_PERM_LOG_RES
);
if
(
flist
->
xbf_count
==
0
)
return
0
;
list_sort
((
*
tp
)
->
t_mountp
,
&
flist
->
xbf_flist
,
xfs_bmap_free_list_cmp
);
efi
=
xfs_trans_get_efi
(
*
tp
,
flist
->
xbf_count
);
for
(
free
=
flist
->
xbf_first
;
free
;
free
=
free
->
xbfi_nex
t
)
list_for_each_entry
(
free
,
&
flist
->
xbf_flist
,
xbfi_lis
t
)
xfs_trans_log_efi_extent
(
*
tp
,
efi
,
free
->
xbfi_startblock
,
free
->
xbfi_blockcount
);
...
...
@@ -136,15 +154,15 @@ xfs_bmap_finish(
* on error.
*/
efd
=
xfs_trans_get_efd
(
*
tp
,
efi
,
flist
->
xbf_count
);
for
(
free
=
flist
->
xbf_first
;
free
!=
NULL
;
free
=
next
)
{
next
=
free
->
xbfi_next
;
while
(
!
list_empty
(
&
flist
->
xbf_flist
)
)
{
free
=
list_first_entry
(
&
flist
->
xbf_flist
,
struct
xfs_bmap_free_item
,
xbfi_list
);
error
=
xfs_trans_free_extent
(
*
tp
,
efd
,
free
->
xbfi_startblock
,
free
->
xbfi_blockcount
);
if
(
error
)
return
error
;
xfs_bmap_del_free
(
flist
,
NULL
,
free
);
xfs_bmap_del_free
(
flist
,
free
);
}
return
0
;
...
...
@@ -797,7 +815,7 @@ xfs_bmap_punch_delalloc_range(
if
(
error
)
break
;
ASSERT
(
!
flist
.
xbf_count
&&
!
flist
.
xbf_first
);
ASSERT
(
!
flist
.
xbf_count
&&
list_empty
(
&
flist
.
xbf_flist
)
);
next_block:
start_fsb
++
;
remaining
--
;
...
...
fs/xfs/xfs_bmap_util.h
View file @
f477cedc
...
...
@@ -41,7 +41,6 @@ int xfs_getbmap(struct xfs_inode *ip, struct getbmapx *bmv,
/* functions in xfs_bmap.c that are only needed by xfs_bmap_util.c */
void
xfs_bmap_del_free
(
struct
xfs_bmap_free
*
flist
,
struct
xfs_bmap_free_item
*
prev
,
struct
xfs_bmap_free_item
*
free
);
int
xfs_bmap_extsize_align
(
struct
xfs_mount
*
mp
,
struct
xfs_bmbt_irec
*
gotp
,
struct
xfs_bmbt_irec
*
prevp
,
xfs_extlen_t
extsz
,
...
...
fs/xfs/xfs_buf.c
View file @
f477cedc
...
...
@@ -944,10 +944,12 @@ xfs_buf_trylock(
int
locked
;
locked
=
down_trylock
(
&
bp
->
b_sema
)
==
0
;
if
(
locked
)
if
(
locked
)
{
XB_SET_OWNER
(
bp
);
trace_xfs_buf_trylock
(
bp
,
_RET_IP_
);
trace_xfs_buf_trylock
(
bp
,
_RET_IP_
);
}
else
{
trace_xfs_buf_trylock_fail
(
bp
,
_RET_IP_
);
}
return
locked
;
}
...
...
fs/xfs/xfs_error.c
View file @
f477cedc
...
...
@@ -61,6 +61,9 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
int
len
;
int64_t
fsid
;
if
(
error_tag
>=
XFS_ERRTAG_MAX
)
return
-
EINVAL
;
memcpy
(
&
fsid
,
mp
->
m_fixedfsid
,
sizeof
(
xfs_fsid_t
));
for
(
i
=
0
;
i
<
XFS_NUM_INJECT_ERROR
;
i
++
)
{
...
...
fs/xfs/xfs_fsops.c
View file @
f477cedc
...
...
@@ -667,8 +667,11 @@ xfs_reserve_blocks(
__uint64_t
*
inval
,
xfs_fsop_resblks_t
*
outval
)
{
__int64_t
lcounter
,
delta
,
fdblks_delta
;
__int64_t
lcounter
,
delta
;
__int64_t
fdblks_delta
=
0
;
__uint64_t
request
;
__int64_t
free
;
int
error
=
0
;
/* If inval is null, report current values and return */
if
(
inval
==
(
__uint64_t
*
)
NULL
)
{
...
...
@@ -682,24 +685,23 @@ xfs_reserve_blocks(
request
=
*
inval
;
/*
* With per-cpu counters, this becomes an interesting
*
problem. we needto work out if we are freeing or allocatio
n
*
blocks first, then we can
do the modification as necessary.
* With per-cpu counters, this becomes an interesting
problem. we need
*
to work out if we are freeing or allocation blocks first, then we ca
n
* do the modification as necessary.
*
* We do this under the m_sb_lock so that if we are near
* ENOSPC, we will hold out any changes while we work out
* what to do. This means that the amount of free space can
* change while we do this, so we need to retry if we end up
* trying to reserve more space than is available.
* We do this under the m_sb_lock so that if we are near ENOSPC, we will
* hold out any changes while we work out what to do. This means that
* the amount of free space can change while we do this, so we need to
* retry if we end up trying to reserve more space than is available.
*/
retry:
spin_lock
(
&
mp
->
m_sb_lock
);
/*
* If our previous reservation was larger than the current value,
* then move any unused blocks back to the free pool.
* then move any unused blocks back to the free pool. Modify the resblks
* counters directly since we shouldn't have any problems unreserving
* space.
*/
fdblks_delta
=
0
;
if
(
mp
->
m_resblks
>
request
)
{
lcounter
=
mp
->
m_resblks_avail
-
request
;
if
(
lcounter
>
0
)
{
/* release unused blocks */
...
...
@@ -707,54 +709,67 @@ xfs_reserve_blocks(
mp
->
m_resblks_avail
-=
lcounter
;
}
mp
->
m_resblks
=
request
;
}
else
{
__int64_t
free
;
if
(
fdblks_delta
)
{
spin_unlock
(
&
mp
->
m_sb_lock
);
error
=
xfs_mod_fdblocks
(
mp
,
fdblks_delta
,
0
);
spin_lock
(
&
mp
->
m_sb_lock
);
}
goto
out
;
}
/*
* If the request is larger than the current reservation, reserve the
* blocks before we update the reserve counters. Sample m_fdblocks and
* perform a partial reservation if the request exceeds free space.
*/
error
=
-
ENOSPC
;
do
{
free
=
percpu_counter_sum
(
&
mp
->
m_fdblocks
)
-
XFS_ALLOC_SET_ASIDE
(
mp
);
if
(
!
free
)
goto
out
;
/* ENOSPC and fdblks_delta = 0 */
break
;
delta
=
request
-
mp
->
m_resblks
;
lcounter
=
free
-
delta
;
if
(
lcounter
<
0
)
{
if
(
lcounter
<
0
)
/* We can't satisfy the request, just get what we can */
mp
->
m_resblks
+=
free
;
mp
->
m_resblks_avail
+=
free
;
fdblks_delta
=
-
free
;
}
else
{
fdblks_delta
=
-
delta
;
mp
->
m_resblks
=
request
;
mp
->
m_resblks_avail
+=
delta
;
}
}
out:
if
(
outval
)
{
outval
->
resblks
=
mp
->
m_resblks
;
outval
->
resblks_avail
=
mp
->
m_resblks_avail
;
}
spin_unlock
(
&
mp
->
m_sb_lock
);
fdblks_delta
=
free
;
else
fdblks_delta
=
delta
;
if
(
fdblks_delta
)
{
/*
* If we are putting blocks back here, m_resblks_avail is
* already at its max so this will put it in the free pool.
*
* If we need space, we'll either succeed in getting it
* from the free block count or we'll get an enospc. If
* we get a ENOSPC, it means things changed while we were
* calculating fdblks_delta and so we should try again to
* see if there is anything left to reserve.
* We'll either succeed in getting space from the free block
* count or we'll get an ENOSPC. If we get a ENOSPC, it means
* things changed while we were calculating fdblks_delta and so
* we should try again to see if there is anything left to
* reserve.
*
* Don't set the reserved flag here - we don't want to reserve
* the extra reserve blocks from the reserve.....
*/
int
error
;
error
=
xfs_mod_fdblocks
(
mp
,
fdblks_delta
,
0
);
if
(
error
==
-
ENOSPC
)
goto
retry
;
spin_unlock
(
&
mp
->
m_sb_lock
);
error
=
xfs_mod_fdblocks
(
mp
,
-
fdblks_delta
,
0
);
spin_lock
(
&
mp
->
m_sb_lock
);
}
while
(
error
==
-
ENOSPC
);
/*
* Update the reserve counters if blocks have been successfully
* allocated.
*/
if
(
!
error
&&
fdblks_delta
)
{
mp
->
m_resblks
+=
fdblks_delta
;
mp
->
m_resblks_avail
+=
fdblks_delta
;
}
return
0
;
out:
if
(
outval
)
{
outval
->
resblks
=
mp
->
m_resblks
;
outval
->
resblks_avail
=
mp
->
m_resblks_avail
;
}
spin_unlock
(
&
mp
->
m_sb_lock
);
return
error
;
}
int
...
...
fs/xfs/xfs_icache.c
View file @
f477cedc
...
...
@@ -765,7 +765,7 @@ xfs_inode_ag_walk(
* Background scanning to trim post-EOF preallocated space. This is queued
* based on the 'speculative_prealloc_lifetime' tunable (5m by default).
*/
STATIC
void
void
xfs_queue_eofblocks
(
struct
xfs_mount
*
mp
)
{
...
...
fs/xfs/xfs_icache.h
View file @
f477cedc
...
...
@@ -68,6 +68,7 @@ void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
int
xfs_icache_free_eofblocks
(
struct
xfs_mount
*
,
struct
xfs_eofblocks
*
);
int
xfs_inode_free_quota_eofblocks
(
struct
xfs_inode
*
ip
);
void
xfs_eofblocks_worker
(
struct
work_struct
*
);
void
xfs_queue_eofblocks
(
struct
xfs_mount
*
);
int
xfs_inode_ag_iterator
(
struct
xfs_mount
*
mp
,
int
(
*
execute
)(
struct
xfs_inode
*
ip
,
int
flags
,
void
*
args
),
...
...
fs/xfs/xfs_ondisk.h
View file @
f477cedc
...
...
@@ -22,6 +22,11 @@
BUILD_BUG_ON_MSG(sizeof(structname) != (size), "XFS: sizeof(" \
#structname ") is wrong, expected " #size)
#define XFS_CHECK_OFFSET(structname, member, off) \
BUILD_BUG_ON_MSG(offsetof(structname, member) != (off), \
"XFS: offsetof(" #structname ", " #member ") is wrong, " \
"expected " #off)
static
inline
void
__init
xfs_check_ondisk_structs
(
void
)
{
...
...
@@ -75,15 +80,28 @@ xfs_check_ondisk_structs(void)
XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_remote_t, 12);
*/
XFS_CHECK_OFFSET
(
xfs_attr_leaf_name_local_t
,
valuelen
,
0
);
XFS_CHECK_OFFSET
(
xfs_attr_leaf_name_local_t
,
namelen
,
2
);
XFS_CHECK_OFFSET
(
xfs_attr_leaf_name_local_t
,
nameval
,
3
);
XFS_CHECK_OFFSET
(
xfs_attr_leaf_name_remote_t
,
valueblk
,
0
);
XFS_CHECK_OFFSET
(
xfs_attr_leaf_name_remote_t
,
valuelen
,
4
);
XFS_CHECK_OFFSET
(
xfs_attr_leaf_name_remote_t
,
namelen
,
8
);
XFS_CHECK_OFFSET
(
xfs_attr_leaf_name_remote_t
,
name
,
9
);
XFS_CHECK_STRUCT_SIZE
(
xfs_attr_leafblock_t
,
40
);
XFS_CHECK_STRUCT_SIZE
(
xfs_attr_shortform_t
,
8
);
XFS_CHECK_OFFSET
(
xfs_attr_shortform_t
,
hdr
.
totsize
,
0
);
XFS_CHECK_OFFSET
(
xfs_attr_shortform_t
,
hdr
.
count
,
2
);
XFS_CHECK_OFFSET
(
xfs_attr_shortform_t
,
list
[
0
].
namelen
,
4
);
XFS_CHECK_OFFSET
(
xfs_attr_shortform_t
,
list
[
0
].
valuelen
,
5
);
XFS_CHECK_OFFSET
(
xfs_attr_shortform_t
,
list
[
0
].
flags
,
6
);
XFS_CHECK_OFFSET
(
xfs_attr_shortform_t
,
list
[
0
].
nameval
,
7
);
XFS_CHECK_STRUCT_SIZE
(
xfs_da_blkinfo_t
,
12
);
XFS_CHECK_STRUCT_SIZE
(
xfs_da_intnode_t
,
16
);
XFS_CHECK_STRUCT_SIZE
(
xfs_da_node_entry_t
,
8
);
XFS_CHECK_STRUCT_SIZE
(
xfs_da_node_hdr_t
,
16
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_data_free_t
,
4
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_data_hdr_t
,
16
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_data_unused_t
,
6
);
XFS_CHECK_OFFSET
(
xfs_dir2_data_unused_t
,
freetag
,
0
);
XFS_CHECK_OFFSET
(
xfs_dir2_data_unused_t
,
length
,
2
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_free_hdr_t
,
16
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_free_t
,
16
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_ino4_t
,
4
);
...
...
@@ -94,6 +112,9 @@ xfs_check_ondisk_structs(void)
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_leaf_t
,
16
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_leaf_tail_t
,
4
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_sf_entry_t
,
3
);
XFS_CHECK_OFFSET
(
xfs_dir2_sf_entry_t
,
namelen
,
0
);
XFS_CHECK_OFFSET
(
xfs_dir2_sf_entry_t
,
offset
,
1
);
XFS_CHECK_OFFSET
(
xfs_dir2_sf_entry_t
,
name
,
3
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_sf_hdr_t
,
10
);
XFS_CHECK_STRUCT_SIZE
(
xfs_dir2_sf_off_t
,
2
);
...
...
fs/xfs/xfs_super.c
View file @
f477cedc
...
...
@@ -1294,6 +1294,7 @@ xfs_fs_remount(
*/
xfs_restore_resvblks
(
mp
);
xfs_log_work_queue
(
mp
);
xfs_queue_eofblocks
(
mp
);
}
/* rw -> ro */
...
...
@@ -1306,6 +1307,13 @@ xfs_fs_remount(
* return it to the same size.
*/
xfs_save_resvblks
(
mp
);
/*
* Cancel background eofb scanning so it cannot race with the
* final log force+buftarg wait and deadlock the remount.
*/
cancel_delayed_work_sync
(
&
mp
->
m_eofblocks_work
);
xfs_quiesce_attr
(
mp
);
mp
->
m_flags
|=
XFS_MOUNT_RDONLY
;
}
...
...
@@ -1692,8 +1700,9 @@ xfs_init_zones(void)
if
(
!
xfs_log_ticket_zone
)
goto
out_free_ioend_bioset
;
xfs_bmap_free_item_zone
=
kmem_zone_init
(
sizeof
(
xfs_bmap_free_item_t
),
"xfs_bmap_free_item"
);
xfs_bmap_free_item_zone
=
kmem_zone_init
(
sizeof
(
struct
xfs_bmap_free_item
),
"xfs_bmap_free_item"
);
if
(
!
xfs_bmap_free_item_zone
)
goto
out_destroy_log_ticket_zone
;
...
...
fs/xfs/xfs_trace.h
View file @
f477cedc
...
...
@@ -354,6 +354,7 @@ DEFINE_BUF_EVENT(xfs_buf_submit_wait);
DEFINE_BUF_EVENT
(
xfs_buf_bawrite
);
DEFINE_BUF_EVENT
(
xfs_buf_lock
);
DEFINE_BUF_EVENT
(
xfs_buf_lock_done
);
DEFINE_BUF_EVENT
(
xfs_buf_trylock_fail
);
DEFINE_BUF_EVENT
(
xfs_buf_trylock
);
DEFINE_BUF_EVENT
(
xfs_buf_unlock
);
DEFINE_BUF_EVENT
(
xfs_buf_iowait
);
...
...
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