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
a4241aeb
Commit
a4241aeb
authored
Sep 09, 2014
by
Dave Chinner
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'xfs-misc-fixes-for-3.18-1' into for-next
parents
41b9d726
ab6978c2
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
290 additions
and
325 deletions
+290
-325
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.c
+4
-0
fs/xfs/libxfs/xfs_dir2.c
fs/xfs/libxfs/xfs_dir2.c
+12
-55
fs/xfs/libxfs/xfs_dir2.h
fs/xfs/libxfs/xfs_dir2.h
+1
-1
fs/xfs/libxfs/xfs_ialloc.c
fs/xfs/libxfs/xfs_ialloc.c
+2
-0
fs/xfs/libxfs/xfs_rtbitmap.c
fs/xfs/libxfs/xfs_rtbitmap.c
+35
-14
fs/xfs/libxfs/xfs_sb.c
fs/xfs/libxfs/xfs_sb.c
+2
-0
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.c
+1
-1
fs/xfs/xfs_file.c
fs/xfs/xfs_file.c
+53
-125
fs/xfs/xfs_globals.c
fs/xfs/xfs_globals.c
+4
-0
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.c
+15
-9
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_log_recover.c
+39
-54
fs/xfs/xfs_mru_cache.c
fs/xfs/xfs_mru_cache.c
+2
-1
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rtalloc.c
+2
-53
fs/xfs/xfs_rtalloc.h
fs/xfs/xfs_rtalloc.h
+4
-0
fs/xfs/xfs_super.c
fs/xfs/xfs_super.c
+29
-9
fs/xfs/xfs_symlink.c
fs/xfs/xfs_symlink.c
+5
-3
fs/xfs/xfs_sysctl.h
fs/xfs/xfs_sysctl.h
+5
-0
fs/xfs/xfs_sysfs.c
fs/xfs/xfs_sysfs.c
+74
-0
fs/xfs/xfs_sysfs.h
fs/xfs/xfs_sysfs.h
+1
-0
No files found.
fs/xfs/libxfs/xfs_alloc.c
View file @
a4241aeb
...
...
@@ -2209,6 +2209,10 @@ xfs_agf_verify(
be32_to_cpu
(
agf
->
agf_flcount
)
<=
XFS_AGFL_SIZE
(
mp
)))
return
false
;
if
(
be32_to_cpu
(
agf
->
agf_levels
[
XFS_BTNUM_BNO
])
>
XFS_BTREE_MAXLEVELS
||
be32_to_cpu
(
agf
->
agf_levels
[
XFS_BTNUM_CNT
])
>
XFS_BTREE_MAXLEVELS
)
return
false
;
/*
* during growfs operations, the perag is not fully initialised,
* so we can't use it for any useful checking. growfs ensures we can't
...
...
fs/xfs/libxfs/xfs_dir2.c
View file @
a4241aeb
...
...
@@ -237,7 +237,8 @@ xfs_dir_init(
}
/*
Enter a name in a directory.
* Enter a name in a directory, or check for available space.
* If inum is 0, only the available space test is performed.
*/
int
xfs_dir_createname
(
...
...
@@ -254,10 +255,12 @@ xfs_dir_createname(
int
v
;
/* type-checking value */
ASSERT
(
S_ISDIR
(
dp
->
i_d
.
di_mode
));
rval
=
xfs_dir_ino_validate
(
tp
->
t_mountp
,
inum
);
if
(
rval
)
return
rval
;
XFS_STATS_INC
(
xs_dir_create
);
if
(
inum
)
{
rval
=
xfs_dir_ino_validate
(
tp
->
t_mountp
,
inum
);
if
(
rval
)
return
rval
;
XFS_STATS_INC
(
xs_dir_create
);
}
args
=
kmem_zalloc
(
sizeof
(
*
args
),
KM_SLEEP
|
KM_NOFS
);
if
(
!
args
)
...
...
@@ -276,6 +279,8 @@ xfs_dir_createname(
args
->
whichfork
=
XFS_DATA_FORK
;
args
->
trans
=
tp
;
args
->
op_flags
=
XFS_DA_OP_ADDNAME
|
XFS_DA_OP_OKNOENT
;
if
(
!
inum
)
args
->
op_flags
|=
XFS_DA_OP_JUSTCHECK
;
if
(
dp
->
i_d
.
di_format
==
XFS_DINODE_FMT_LOCAL
)
{
rval
=
xfs_dir2_sf_addname
(
args
);
...
...
@@ -535,62 +540,14 @@ xfs_dir_replace(
/*
* See if this entry can be added to the directory without allocating space.
* First checks that the caller couldn't reserve enough space (resblks = 0).
*/
int
xfs_dir_canenter
(
xfs_trans_t
*
tp
,
xfs_inode_t
*
dp
,
struct
xfs_name
*
name
,
/* name of entry to add */
uint
resblks
)
struct
xfs_name
*
name
)
/* name of entry to add */
{
struct
xfs_da_args
*
args
;
int
rval
;
int
v
;
/* type-checking value */
if
(
resblks
)
return
0
;
ASSERT
(
S_ISDIR
(
dp
->
i_d
.
di_mode
));
args
=
kmem_zalloc
(
sizeof
(
*
args
),
KM_SLEEP
|
KM_NOFS
);
if
(
!
args
)
return
-
ENOMEM
;
args
->
geo
=
dp
->
i_mount
->
m_dir_geo
;
args
->
name
=
name
->
name
;
args
->
namelen
=
name
->
len
;
args
->
filetype
=
name
->
type
;
args
->
hashval
=
dp
->
i_mount
->
m_dirnameops
->
hashname
(
name
);
args
->
dp
=
dp
;
args
->
whichfork
=
XFS_DATA_FORK
;
args
->
trans
=
tp
;
args
->
op_flags
=
XFS_DA_OP_JUSTCHECK
|
XFS_DA_OP_ADDNAME
|
XFS_DA_OP_OKNOENT
;
if
(
dp
->
i_d
.
di_format
==
XFS_DINODE_FMT_LOCAL
)
{
rval
=
xfs_dir2_sf_addname
(
args
);
goto
out_free
;
}
rval
=
xfs_dir2_isblock
(
args
,
&
v
);
if
(
rval
)
goto
out_free
;
if
(
v
)
{
rval
=
xfs_dir2_block_addname
(
args
);
goto
out_free
;
}
rval
=
xfs_dir2_isleaf
(
args
,
&
v
);
if
(
rval
)
goto
out_free
;
if
(
v
)
rval
=
xfs_dir2_leaf_addname
(
args
);
else
rval
=
xfs_dir2_node_addname
(
args
);
out_free:
kmem_free
(
args
);
return
rval
;
return
xfs_dir_createname
(
tp
,
dp
,
name
,
0
,
NULL
,
NULL
,
0
);
}
/*
...
...
fs/xfs/libxfs/xfs_dir2.h
View file @
a4241aeb
...
...
@@ -136,7 +136,7 @@ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
xfs_fsblock_t
*
first
,
struct
xfs_bmap_free
*
flist
,
xfs_extlen_t
tot
);
extern
int
xfs_dir_canenter
(
struct
xfs_trans
*
tp
,
struct
xfs_inode
*
dp
,
struct
xfs_name
*
name
,
uint
resblks
);
struct
xfs_name
*
name
);
/*
* Direct call from the bmap code, bypassing the generic directory layer.
...
...
fs/xfs/libxfs/xfs_ialloc.c
View file @
a4241aeb
...
...
@@ -2051,6 +2051,8 @@ xfs_agi_verify(
if
(
!
XFS_AGI_GOOD_VERSION
(
be32_to_cpu
(
agi
->
agi_versionnum
)))
return
false
;
if
(
be32_to_cpu
(
agi
->
agi_level
)
>
XFS_BTREE_MAXLEVELS
)
return
false
;
/*
* during growfs operations, the perag is not fully initialised,
* so we can't use it for any useful checking. growfs ensures we can't
...
...
fs/xfs/libxfs/xfs_rtbitmap.c
View file @
a4241aeb
...
...
@@ -424,20 +424,24 @@ xfs_rtfind_forw(
}
/*
* Read and modify the summary information for a given extent size,
* Read and
/or
modify the summary information for a given extent size,
* bitmap block combination.
* Keeps track of a current summary block, so we don't keep reading
* it from the buffer cache.
*
* Summary information is returned in *sum if specified.
* If no delta is specified, returns summary only.
*/
int
xfs_rtmodify_summary
(
xfs_mount_t
*
mp
,
/* file system mount
point
*/
xfs_rtmodify_summary
_int
(
xfs_mount_t
*
mp
,
/* file system mount
structure
*/
xfs_trans_t
*
tp
,
/* transaction pointer */
int
log
,
/* log2 of extent size */
xfs_rtblock_t
bbno
,
/* bitmap block number */
int
delta
,
/* change to make to summary info */
xfs_buf_t
**
rbpp
,
/* in/out: summary block buffer */
xfs_fsblock_t
*
rsb
)
/* in/out: summary block number */
xfs_fsblock_t
*
rsb
,
/* in/out: summary block number */
xfs_suminfo_t
*
sum
)
/* out: summary info for this block */
{
xfs_buf_t
*
bp
;
/* buffer for the summary block */
int
error
;
/* error value */
...
...
@@ -456,7 +460,7 @@ xfs_rtmodify_summary(
/*
* If we have an old buffer, and the block number matches, use that.
*/
if
(
rbpp
&&
*
rbpp
&&
*
rsb
==
sb
)
if
(
*
rbpp
&&
*
rsb
==
sb
)
bp
=
*
rbpp
;
/*
* Otherwise we have to get the buffer.
...
...
@@ -465,7 +469,7 @@ xfs_rtmodify_summary(
/*
* If there was an old one, get rid of it first.
*/
if
(
rbpp
&&
*
rbpp
)
if
(
*
rbpp
)
xfs_trans_brelse
(
tp
,
*
rbpp
);
error
=
xfs_rtbuf_get
(
mp
,
tp
,
sb
,
1
,
&
bp
);
if
(
error
)
{
...
...
@@ -474,21 +478,38 @@ xfs_rtmodify_summary(
/*
* Remember this buffer and block for the next call.
*/
if
(
rbpp
)
{
*
rbpp
=
bp
;
*
rsb
=
sb
;
}
*
rbpp
=
bp
;
*
rsb
=
sb
;
}
/*
* Point to the summary information, modify
and log i
t.
* Point to the summary information, modify
/log it, and/or copy it ou
t.
*/
sp
=
XFS_SUMPTR
(
mp
,
bp
,
so
);
*
sp
+=
delta
;
xfs_trans_log_buf
(
tp
,
bp
,
(
uint
)((
char
*
)
sp
-
(
char
*
)
bp
->
b_addr
),
(
uint
)((
char
*
)
sp
-
(
char
*
)
bp
->
b_addr
+
sizeof
(
*
sp
)
-
1
));
if
(
delta
)
{
uint
first
=
(
uint
)((
char
*
)
sp
-
(
char
*
)
bp
->
b_addr
);
*
sp
+=
delta
;
xfs_trans_log_buf
(
tp
,
bp
,
first
,
first
+
sizeof
(
*
sp
)
-
1
);
}
if
(
sum
)
*
sum
=
*
sp
;
return
0
;
}
int
xfs_rtmodify_summary
(
xfs_mount_t
*
mp
,
/* file system mount structure */
xfs_trans_t
*
tp
,
/* transaction pointer */
int
log
,
/* log2 of extent size */
xfs_rtblock_t
bbno
,
/* bitmap block number */
int
delta
,
/* change to make to summary info */
xfs_buf_t
**
rbpp
,
/* in/out: summary block buffer */
xfs_fsblock_t
*
rsb
)
/* in/out: summary block number */
{
return
xfs_rtmodify_summary_int
(
mp
,
tp
,
log
,
bbno
,
delta
,
rbpp
,
rsb
,
NULL
);
}
/*
* Set the given range of bitmap bits to the given value.
* Do whatever I/O and logging is required.
...
...
fs/xfs/libxfs/xfs_sb.c
View file @
a4241aeb
...
...
@@ -279,11 +279,13 @@ xfs_mount_validate_sb(
sbp
->
sb_blocklog
<
XFS_MIN_BLOCKSIZE_LOG
||
sbp
->
sb_blocklog
>
XFS_MAX_BLOCKSIZE_LOG
||
sbp
->
sb_blocksize
!=
(
1
<<
sbp
->
sb_blocklog
)
||
sbp
->
sb_dirblklog
>
XFS_MAX_BLOCKSIZE_LOG
||
sbp
->
sb_inodesize
<
XFS_DINODE_MIN_SIZE
||
sbp
->
sb_inodesize
>
XFS_DINODE_MAX_SIZE
||
sbp
->
sb_inodelog
<
XFS_DINODE_MIN_LOG
||
sbp
->
sb_inodelog
>
XFS_DINODE_MAX_LOG
||
sbp
->
sb_inodesize
!=
(
1
<<
sbp
->
sb_inodelog
)
||
sbp
->
sb_logsunit
>
XLOG_MAX_RECORD_BSIZE
||
sbp
->
sb_inopblock
!=
howmany
(
sbp
->
sb_blocksize
,
sbp
->
sb_inodesize
)
||
(
sbp
->
sb_blocklog
-
sbp
->
sb_inodelog
!=
sbp
->
sb_inopblog
)
||
(
sbp
->
sb_rextsize
*
sbp
->
sb_blocksize
>
XFS_MAX_RTEXTSIZE
)
||
...
...
fs/xfs/xfs_buf.c
View file @
a4241aeb
...
...
@@ -1884,7 +1884,7 @@ xfs_buf_init(void)
goto
out
;
xfslogd_workqueue
=
alloc_workqueue
(
"xfslogd"
,
WQ_MEM_RECLAIM
|
WQ_HIGHPRI
,
1
);
WQ_MEM_RECLAIM
|
WQ_HIGHPRI
|
WQ_FREEZABLE
,
1
);
if
(
!
xfslogd_workqueue
)
goto
out_free_buf_zone
;
...
...
fs/xfs/xfs_file.c
View file @
a4241aeb
...
...
@@ -983,7 +983,7 @@ xfs_vm_page_mkwrite(
/*
* This type is designed to indicate the type of offset we would like
* to search from page cache for
either xfs_seek_data() or xfs_seek_hole
().
* to search from page cache for
xfs_seek_hole_data
().
*/
enum
{
HOLE_OFF
=
0
,
...
...
@@ -1040,7 +1040,7 @@ xfs_lookup_buffer_offset(
/*
* This routine is called to find out and return a data or hole offset
* from the page cache for unwritten extents according to the desired
* type for xfs_seek_
data() or xfs_seek_hole
().
* type for xfs_seek_
hole_data
().
*
* The argument offset is used to tell where we start to search from the
* page cache. Map is used to figure out the end points of the range to
...
...
@@ -1200,9 +1200,10 @@ xfs_find_get_desired_pgoff(
}
STATIC
loff_t
xfs_seek_data
(
xfs_seek_
hole_
data
(
struct
file
*
file
,
loff_t
start
)
loff_t
start
,
int
whence
)
{
struct
inode
*
inode
=
file
->
f_mapping
->
host
;
struct
xfs_inode
*
ip
=
XFS_I
(
inode
);
...
...
@@ -1214,6 +1215,9 @@ xfs_seek_data(
uint
lock
;
int
error
;
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
-
EIO
;
lock
=
xfs_ilock_data_map_shared
(
ip
);
isize
=
i_size_read
(
inode
);
...
...
@@ -1228,6 +1232,7 @@ xfs_seek_data(
*/
fsbno
=
XFS_B_TO_FSBT
(
mp
,
start
);
end
=
XFS_B_TO_FSB
(
mp
,
isize
);
for
(;;)
{
struct
xfs_bmbt_irec
map
[
2
];
int
nmap
=
2
;
...
...
@@ -1248,29 +1253,48 @@ xfs_seek_data(
offset
=
max_t
(
loff_t
,
start
,
XFS_FSB_TO_B
(
mp
,
map
[
i
].
br_startoff
));
/* Landed in a data extent */
if
(
map
[
i
].
br_startblock
==
DELAYSTARTBLOCK
||
(
map
[
i
].
br_state
==
XFS_EXT_NORM
&&
!
isnullstartblock
(
map
[
i
].
br_startblock
)))
/* Landed in the hole we wanted? */
if
(
whence
==
SEEK_HOLE
&&
map
[
i
].
br_startblock
==
HOLESTARTBLOCK
)
goto
out
;
/* Landed in the data extent we wanted? */
if
(
whence
==
SEEK_DATA
&&
(
map
[
i
].
br_startblock
==
DELAYSTARTBLOCK
||
(
map
[
i
].
br_state
==
XFS_EXT_NORM
&&
!
isnullstartblock
(
map
[
i
].
br_startblock
))))
goto
out
;
/*
* Landed in an unwritten extent, try to search
data
* from page cache.
* Landed in an unwritten extent, try to search
* f
or hole or data f
rom page cache.
*/
if
(
map
[
i
].
br_state
==
XFS_EXT_UNWRITTEN
)
{
if
(
xfs_find_get_desired_pgoff
(
inode
,
&
map
[
i
],
DATA_OFF
,
&
offset
))
whence
==
SEEK_HOLE
?
HOLE_OFF
:
DATA_OFF
,
&
offset
))
goto
out
;
}
}
/*
* map[0] is hole or its an unwritten extent but
* without data in page cache. Probably means that
* we are reading after EOF if nothing in map[1].
* We only received one extent out of the two requested. This
* means we've hit EOF and didn't find what we are looking for.
*/
if
(
nmap
==
1
)
{
/*
* If we were looking for a hole, set offset to
* the end of the file (i.e., there is an implicit
* hole at the end of any file).
*/
if
(
whence
==
SEEK_HOLE
)
{
offset
=
isize
;
break
;
}
/*
* If we were looking for data, it's nowhere to be found
*/
ASSERT
(
whence
==
SEEK_DATA
);
error
=
-
ENXIO
;
goto
out_unlock
;
}
...
...
@@ -1279,125 +1303,30 @@ xfs_seek_data(
/*
* Nothing was found, proceed to the next round of search
* if
reading offset not beyond or hit
EOF.
* if
the next reading offset is not at or beyond
EOF.
*/
fsbno
=
map
[
i
-
1
].
br_startoff
+
map
[
i
-
1
].
br_blockcount
;
start
=
XFS_FSB_TO_B
(
mp
,
fsbno
);
if
(
start
>=
isize
)
{
if
(
whence
==
SEEK_HOLE
)
{
offset
=
isize
;
break
;
}
ASSERT
(
whence
==
SEEK_DATA
);
error
=
-
ENXIO
;
goto
out_unlock
;
}
}
out:
offset
=
vfs_setpos
(
file
,
offset
,
inode
->
i_sb
->
s_maxbytes
);
out_unlock:
xfs_iunlock
(
ip
,
lock
);
if
(
error
)
return
error
;
return
offset
;
}
STATIC
loff_t
xfs_seek_hole
(
struct
file
*
file
,
loff_t
start
)
{
struct
inode
*
inode
=
file
->
f_mapping
->
host
;
struct
xfs_inode
*
ip
=
XFS_I
(
inode
);
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
loff_t
uninitialized_var
(
offset
);
xfs_fsize_t
isize
;
xfs_fileoff_t
fsbno
;
xfs_filblks_t
end
;
uint
lock
;
int
error
;
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
-
EIO
;
lock
=
xfs_ilock_data_map_shared
(
ip
);
isize
=
i_size_read
(
inode
);
if
(
start
>=
isize
)
{
error
=
-
ENXIO
;
goto
out_unlock
;
}
fsbno
=
XFS_B_TO_FSBT
(
mp
,
start
);
end
=
XFS_B_TO_FSB
(
mp
,
isize
);
for
(;;)
{
struct
xfs_bmbt_irec
map
[
2
];
int
nmap
=
2
;
unsigned
int
i
;
error
=
xfs_bmapi_read
(
ip
,
fsbno
,
end
-
fsbno
,
map
,
&
nmap
,
XFS_BMAPI_ENTIRE
);
if
(
error
)
goto
out_unlock
;
/* No extents at given offset, must be beyond EOF */
if
(
nmap
==
0
)
{
error
=
-
ENXIO
;
goto
out_unlock
;
}
for
(
i
=
0
;
i
<
nmap
;
i
++
)
{
offset
=
max_t
(
loff_t
,
start
,
XFS_FSB_TO_B
(
mp
,
map
[
i
].
br_startoff
));
/* Landed in a hole */
if
(
map
[
i
].
br_startblock
==
HOLESTARTBLOCK
)
goto
out
;
/*
* Landed in an unwritten extent, try to search hole
* from page cache.
*/
if
(
map
[
i
].
br_state
==
XFS_EXT_UNWRITTEN
)
{
if
(
xfs_find_get_desired_pgoff
(
inode
,
&
map
[
i
],
HOLE_OFF
,
&
offset
))
goto
out
;
}
}
/*
* map[0] contains data or its unwritten but contains
* data in page cache, probably means that we are
* reading after EOF. We should fix offset to point
* to the end of the file(i.e., there is an implicit
* hole at the end of any file).
*/
if
(
nmap
==
1
)
{
offset
=
isize
;
break
;
}
ASSERT
(
i
>
1
);
/*
* Both mappings contains data, proceed to the next round of
* search if the current reading offset not beyond or hit EOF.
*/
fsbno
=
map
[
i
-
1
].
br_startoff
+
map
[
i
-
1
].
br_blockcount
;
start
=
XFS_FSB_TO_B
(
mp
,
fsbno
);
if
(
start
>=
isize
)
{
offset
=
isize
;
break
;
}
}
out:
/*
*
At this point, we must have found a hole. However
, the returned
*
If at this point we have found the hole we wanted
, the returned
* offset may be bigger than the file size as it may be aligned to
* page boundary for unwritten extents
, w
e need to deal with this
* page boundary for unwritten extents
. W
e need to deal with this
* situation in particular.
*/
offset
=
min_t
(
loff_t
,
offset
,
isize
);
if
(
whence
==
SEEK_HOLE
)
offset
=
min_t
(
loff_t
,
offset
,
isize
);
offset
=
vfs_setpos
(
file
,
offset
,
inode
->
i_sb
->
s_maxbytes
);
out_unlock:
...
...
@@ -1412,17 +1341,16 @@ STATIC loff_t
xfs_file_llseek
(
struct
file
*
file
,
loff_t
offset
,
int
origin
)
int
whence
)
{
switch
(
origin
)
{
switch
(
whence
)
{
case
SEEK_END
:
case
SEEK_CUR
:
case
SEEK_SET
:
return
generic_file_llseek
(
file
,
offset
,
origin
);
case
SEEK_DATA
:
return
xfs_seek_data
(
file
,
offset
);
return
generic_file_llseek
(
file
,
offset
,
whence
);
case
SEEK_HOLE
:
return
xfs_seek_hole
(
file
,
offset
);
case
SEEK_DATA
:
return
xfs_seek_hole_data
(
file
,
offset
,
whence
);
default:
return
-
EINVAL
;
}
...
...
fs/xfs/xfs_globals.c
View file @
a4241aeb
...
...
@@ -43,3 +43,7 @@ xfs_param_t xfs_params = {
.
fstrm_timer
=
{
1
,
30
*
100
,
3600
*
100
},
.
eofb_timer
=
{
1
,
300
,
3600
*
24
},
};
struct
xfs_globals
xfs_globals
=
{
.
log_recovery_delay
=
0
,
/* no delay by default */
};
fs/xfs/xfs_inode.c
View file @
a4241aeb
...
...
@@ -1153,9 +1153,11 @@ xfs_create(
if
(
error
)
goto
out_trans_cancel
;
error
=
xfs_dir_canenter
(
tp
,
dp
,
name
,
resblks
);
if
(
error
)
goto
out_trans_cancel
;
if
(
!
resblks
)
{
error
=
xfs_dir_canenter
(
tp
,
dp
,
name
);
if
(
error
)
goto
out_trans_cancel
;
}
/*
* A newly created regular or special file just has one directory
...
...
@@ -1421,9 +1423,11 @@ xfs_link(
goto
error_return
;
}
error
=
xfs_dir_canenter
(
tp
,
tdp
,
target_name
,
resblks
);
if
(
error
)
goto
error_return
;
if
(
!
resblks
)
{
error
=
xfs_dir_canenter
(
tp
,
tdp
,
target_name
);
if
(
error
)
goto
error_return
;
}
xfs_bmap_init
(
&
free_list
,
&
first_block
);
...
...
@@ -2759,9 +2763,11 @@ xfs_rename(
* If there's no space reservation, check the entry will
* fit before actually inserting it.
*/
error
=
xfs_dir_canenter
(
tp
,
target_dp
,
target_name
,
spaceres
);
if
(
error
)
goto
error_return
;
if
(
!
spaceres
)
{
error
=
xfs_dir_canenter
(
tp
,
target_dp
,
target_name
);
if
(
error
)
goto
error_return
;
}
/*
* If target does not exist and the rename crosses
* directories, adjust the target directory link count
...
...
fs/xfs/xfs_log_recover.c
View file @
a4241aeb
...
...
@@ -4132,41 +4132,13 @@ xlog_do_recovery_pass(
}
memset
(
rhash
,
0
,
sizeof
(
rhash
));
if
(
tail_blk
<=
head_blk
)
{
for
(
blk_no
=
tail_blk
;
blk_no
<
head_blk
;
)
{
error
=
xlog_bread
(
log
,
blk_no
,
hblks
,
hbp
,
&
offset
);
if
(
error
)
goto
bread_err2
;
rhead
=
(
xlog_rec_header_t
*
)
offset
;
error
=
xlog_valid_rec_header
(
log
,
rhead
,
blk_no
);
if
(
error
)
goto
bread_err2
;
/* blocks in data section */
bblks
=
(
int
)
BTOBB
(
be32_to_cpu
(
rhead
->
h_len
));
error
=
xlog_bread
(
log
,
blk_no
+
hblks
,
bblks
,
dbp
,
&
offset
);
if
(
error
)
goto
bread_err2
;
error
=
xlog_unpack_data
(
rhead
,
offset
,
log
);
if
(
error
)
goto
bread_err2
;
error
=
xlog_recover_process_data
(
log
,
rhash
,
rhead
,
offset
,
pass
);
if
(
error
)
goto
bread_err2
;
blk_no
+=
bblks
+
hblks
;
}
}
else
{
blk_no
=
tail_blk
;
if
(
tail_blk
>
head_blk
)
{
/*
* Perform recovery around the end of the physical log.
* When the head is not on the same cycle number as the tail,
* we can't do a sequential recovery
as above
.
* we can't do a sequential recovery.
*/
blk_no
=
tail_blk
;
while
(
blk_no
<
log
->
l_logBBsize
)
{
/*
* Check for header wrapping around physical end-of-log
...
...
@@ -4280,34 +4252,35 @@ xlog_do_recovery_pass(
ASSERT
(
blk_no
>=
log
->
l_logBBsize
);
blk_no
-=
log
->
l_logBBsize
;
}
/* read first part of physical log */
while
(
blk_no
<
head_blk
)
{
error
=
xlog_bread
(
log
,
blk_no
,
hblks
,
hbp
,
&
offset
);
if
(
error
)
goto
bread_err2
;
/* read first part of physical log */
while
(
blk_no
<
head_blk
)
{
error
=
xlog_bread
(
log
,
blk_no
,
hblks
,
hbp
,
&
offset
);
if
(
error
)
goto
bread_err2
;
rhead
=
(
xlog_rec_header_t
*
)
offset
;
error
=
xlog_valid_rec_header
(
log
,
rhead
,
blk_no
);
if
(
error
)
goto
bread_err2
;
rhead
=
(
xlog_rec_header_t
*
)
offset
;
error
=
xlog_valid_rec_header
(
log
,
rhead
,
blk_no
);
if
(
error
)
goto
bread_err2
;
bblks
=
(
int
)
BTOBB
(
be32_to_cpu
(
rhead
->
h_len
));
error
=
xlog_bread
(
log
,
blk_no
+
hblks
,
bblks
,
dbp
,
&
offset
);
if
(
error
)
goto
bread_err2
;
/* blocks in data section */
bblks
=
(
int
)
BTOBB
(
be32_to_cpu
(
rhead
->
h_len
));
error
=
xlog_bread
(
log
,
blk_no
+
hblks
,
bblks
,
dbp
,
&
offset
);
if
(
error
)
goto
bread_err2
;
error
=
xlog_unpack_data
(
rhead
,
offset
,
log
);
if
(
error
)
goto
bread_err2
;
error
=
xlog_unpack_data
(
rhead
,
offset
,
log
);
if
(
error
)
goto
bread_err2
;
error
=
xlog_recover_process_data
(
log
,
rhash
,
rhead
,
offset
,
pass
);
if
(
error
)
goto
bread_err2
;
blk_no
+=
bblks
+
hblks
;
}
error
=
xlog_recover_process_data
(
log
,
rhash
,
rhead
,
offset
,
pass
);
if
(
error
)
goto
bread_err2
;
blk_no
+=
bblks
+
hblks
;
}
bread_err2:
...
...
@@ -4509,6 +4482,18 @@ xlog_recover(
return
-
EINVAL
;
}
/*
* Delay log recovery if the debug hook is set. This is debug
* instrumention to coordinate simulation of I/O failures with
* log recovery.
*/
if
(
xfs_globals
.
log_recovery_delay
)
{
xfs_notice
(
log
->
l_mp
,
"Delaying log recovery for %d seconds."
,
xfs_globals
.
log_recovery_delay
);
msleep
(
xfs_globals
.
log_recovery_delay
*
1000
);
}
xfs_notice
(
log
->
l_mp
,
"Starting recovery (logdev: %s)"
,
log
->
l_mp
->
m_logname
?
log
->
l_mp
->
m_logname
:
"internal"
);
...
...
fs/xfs/xfs_mru_cache.c
View file @
a4241aeb
...
...
@@ -304,7 +304,8 @@ _xfs_mru_cache_reap(
int
xfs_mru_cache_init
(
void
)
{
xfs_mru_reap_wq
=
alloc_workqueue
(
"xfs_mru_cache"
,
WQ_MEM_RECLAIM
,
1
);
xfs_mru_reap_wq
=
alloc_workqueue
(
"xfs_mru_cache"
,
WQ_MEM_RECLAIM
|
WQ_FREEZABLE
,
1
);
if
(
!
xfs_mru_reap_wq
)
return
-
ENOMEM
;
return
0
;
...
...
fs/xfs/xfs_rtalloc.c
View file @
a4241aeb
...
...
@@ -46,7 +46,7 @@
* Keeps track of a current summary block, so we don't keep reading
* it from the buffer cache.
*/
STATIC
int
/* error */
int
xfs_rtget_summary
(
xfs_mount_t
*
mp
,
/* file system mount structure */
xfs_trans_t
*
tp
,
/* transaction pointer */
...
...
@@ -56,60 +56,9 @@ xfs_rtget_summary(
xfs_fsblock_t
*
rsb
,
/* in/out: summary block number */
xfs_suminfo_t
*
sum
)
/* out: summary info for this block */
{
xfs_buf_t
*
bp
;
/* buffer for summary block */
int
error
;
/* error value */
xfs_fsblock_t
sb
;
/* summary fsblock */
int
so
;
/* index into the summary file */
xfs_suminfo_t
*
sp
;
/* pointer to returned data */
/*
* Compute entry number in the summary file.
*/
so
=
XFS_SUMOFFS
(
mp
,
log
,
bbno
);
/*
* Compute the block number in the summary file.
*/
sb
=
XFS_SUMOFFSTOBLOCK
(
mp
,
so
);
/*
* If we have an old buffer, and the block number matches, use that.
*/
if
(
rbpp
&&
*
rbpp
&&
*
rsb
==
sb
)
bp
=
*
rbpp
;
/*
* Otherwise we have to get the buffer.
*/
else
{
/*
* If there was an old one, get rid of it first.
*/
if
(
rbpp
&&
*
rbpp
)
xfs_trans_brelse
(
tp
,
*
rbpp
);
error
=
xfs_rtbuf_get
(
mp
,
tp
,
sb
,
1
,
&
bp
);
if
(
error
)
{
return
error
;
}
/*
* Remember this buffer and block for the next call.
*/
if
(
rbpp
)
{
*
rbpp
=
bp
;
*
rsb
=
sb
;
}
}
/*
* Point to the summary information & copy it out.
*/
sp
=
XFS_SUMPTR
(
mp
,
bp
,
so
);
*
sum
=
*
sp
;
/*
* Drop the buffer if we're not asked to remember it.
*/
if
(
!
rbpp
)
xfs_trans_brelse
(
tp
,
bp
);
return
0
;
return
xfs_rtmodify_summary_int
(
mp
,
tp
,
log
,
bbno
,
0
,
rbpp
,
rsb
,
sum
);
}
/*
* Return whether there are any free extents in the size range given
* by low and high, for the bitmap block bbno.
...
...
fs/xfs/xfs_rtalloc.h
View file @
a4241aeb
...
...
@@ -111,6 +111,10 @@ int xfs_rtfind_forw(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t
*
rtblock
);
int
xfs_rtmodify_range
(
struct
xfs_mount
*
mp
,
struct
xfs_trans
*
tp
,
xfs_rtblock_t
start
,
xfs_extlen_t
len
,
int
val
);
int
xfs_rtmodify_summary_int
(
struct
xfs_mount
*
mp
,
struct
xfs_trans
*
tp
,
int
log
,
xfs_rtblock_t
bbno
,
int
delta
,
xfs_buf_t
**
rbpp
,
xfs_fsblock_t
*
rsb
,
xfs_suminfo_t
*
sum
);
int
xfs_rtmodify_summary
(
struct
xfs_mount
*
mp
,
struct
xfs_trans
*
tp
,
int
log
,
xfs_rtblock_t
bbno
,
int
delta
,
xfs_buf_t
**
rbpp
,
xfs_fsblock_t
*
rsb
);
...
...
fs/xfs/xfs_super.c
View file @
a4241aeb
...
...
@@ -47,6 +47,7 @@
#include "xfs_dinode.h"
#include "xfs_filestream.h"
#include "xfs_quota.h"
#include "xfs_sysfs.h"
#include <linux/namei.h>
#include <linux/init.h>
...
...
@@ -61,7 +62,11 @@
static
const
struct
super_operations
xfs_super_operations
;
static
kmem_zone_t
*
xfs_ioend_zone
;
mempool_t
*
xfs_ioend_pool
;
struct
kset
*
xfs_kset
;
struct
kset
*
xfs_kset
;
/* top-level xfs sysfs dir */
#ifdef DEBUG
static
struct
xfs_kobj
xfs_dbg_kobj
;
/* global debug sysfs attrs */
#endif
#define MNTOPT_LOGBUFS "logbufs"
/* number of XFS log buffers */
#define MNTOPT_LOGBSIZE "logbsize"
/* size of XFS log buffers */
...
...
@@ -838,32 +843,32 @@ xfs_init_mount_workqueues(
struct
xfs_mount
*
mp
)
{
mp
->
m_data_workqueue
=
alloc_workqueue
(
"xfs-data/%s"
,
WQ_MEM_RECLAIM
,
0
,
mp
->
m_fsname
);
WQ_MEM_RECLAIM
|
WQ_FREEZABLE
,
0
,
mp
->
m_fsname
);
if
(
!
mp
->
m_data_workqueue
)
goto
out
;
mp
->
m_unwritten_workqueue
=
alloc_workqueue
(
"xfs-conv/%s"
,
WQ_MEM_RECLAIM
,
0
,
mp
->
m_fsname
);
WQ_MEM_RECLAIM
|
WQ_FREEZABLE
,
0
,
mp
->
m_fsname
);
if
(
!
mp
->
m_unwritten_workqueue
)
goto
out_destroy_data_iodone_queue
;
mp
->
m_cil_workqueue
=
alloc_workqueue
(
"xfs-cil/%s"
,
WQ_MEM_RECLAIM
,
0
,
mp
->
m_fsname
);
WQ_MEM_RECLAIM
|
WQ_FREEZABLE
,
0
,
mp
->
m_fsname
);
if
(
!
mp
->
m_cil_workqueue
)
goto
out_destroy_unwritten
;
mp
->
m_reclaim_workqueue
=
alloc_workqueue
(
"xfs-reclaim/%s"
,
0
,
0
,
mp
->
m_fsname
);
WQ_FREEZABLE
,
0
,
mp
->
m_fsname
);
if
(
!
mp
->
m_reclaim_workqueue
)
goto
out_destroy_cil
;
mp
->
m_log_workqueue
=
alloc_workqueue
(
"xfs-log/%s"
,
0
,
0
,
mp
->
m_fsname
);
WQ_FREEZABLE
,
0
,
mp
->
m_fsname
);
if
(
!
mp
->
m_log_workqueue
)
goto
out_destroy_reclaim
;
mp
->
m_eofblocks_workqueue
=
alloc_workqueue
(
"xfs-eofblocks/%s"
,
0
,
0
,
mp
->
m_fsname
);
WQ_FREEZABLE
,
0
,
mp
->
m_fsname
);
if
(
!
mp
->
m_eofblocks_workqueue
)
goto
out_destroy_log
;
...
...
@@ -1715,7 +1720,8 @@ xfs_init_workqueues(void)
* AGs in all the filesystems mounted. Hence use the default large
* max_active value for this workqueue.
*/
xfs_alloc_wq
=
alloc_workqueue
(
"xfsalloc"
,
WQ_MEM_RECLAIM
,
0
);
xfs_alloc_wq
=
alloc_workqueue
(
"xfsalloc"
,
WQ_MEM_RECLAIM
|
WQ_FREEZABLE
,
0
);
if
(
!
xfs_alloc_wq
)
return
-
ENOMEM
;
...
...
@@ -1768,9 +1774,16 @@ init_xfs_fs(void)
goto
out_sysctl_unregister
;;
}
error
=
xfs_qm_init
();
#ifdef DEBUG
xfs_dbg_kobj
.
kobject
.
kset
=
xfs_kset
;
error
=
xfs_sysfs_init
(
&
xfs_dbg_kobj
,
&
xfs_dbg_ktype
,
NULL
,
"debug"
);
if
(
error
)
goto
out_kset_unregister
;
#endif
error
=
xfs_qm_init
();
if
(
error
)
goto
out_remove_kobj
;
error
=
register_filesystem
(
&
xfs_fs_type
);
if
(
error
)
...
...
@@ -1779,7 +1792,11 @@ init_xfs_fs(void)
out_qm_exit:
xfs_qm_exit
();
out_remove_kobj:
#ifdef DEBUG
xfs_sysfs_del
(
&
xfs_dbg_kobj
);
out_kset_unregister:
#endif
kset_unregister
(
xfs_kset
);
out_sysctl_unregister:
xfs_sysctl_unregister
();
...
...
@@ -1802,6 +1819,9 @@ exit_xfs_fs(void)
{
xfs_qm_exit
();
unregister_filesystem
(
&
xfs_fs_type
);
#ifdef DEBUG
xfs_sysfs_del
(
&
xfs_dbg_kobj
);
#endif
kset_unregister
(
xfs_kset
);
xfs_sysctl_unregister
();
xfs_cleanup_procfs
();
...
...
fs/xfs/xfs_symlink.c
View file @
a4241aeb
...
...
@@ -269,9 +269,11 @@ xfs_symlink(
/*
* Check for ability to enter directory entry, if no space reserved.
*/
error
=
xfs_dir_canenter
(
tp
,
dp
,
link_name
,
resblks
);
if
(
error
)
goto
error_return
;
if
(
!
resblks
)
{
error
=
xfs_dir_canenter
(
tp
,
dp
,
link_name
);
if
(
error
)
goto
error_return
;
}
/*
* Initialize the bmap freelist prior to calling either
* bmapi or the directory create code.
...
...
fs/xfs/xfs_sysctl.h
View file @
a4241aeb
...
...
@@ -92,6 +92,11 @@ enum {
extern
xfs_param_t
xfs_params
;
struct
xfs_globals
{
int
log_recovery_delay
;
/* log recovery delay (secs) */
};
extern
struct
xfs_globals
xfs_globals
;
#ifdef CONFIG_SYSCTL
extern
int
xfs_sysctl_register
(
void
);
extern
void
xfs_sysctl_unregister
(
void
);
...
...
fs/xfs/xfs_sysfs.c
View file @
a4241aeb
...
...
@@ -51,6 +51,80 @@ struct kobj_type xfs_mp_ktype = {
.
release
=
xfs_sysfs_release
,
};
#ifdef DEBUG
/* debug */
STATIC
ssize_t
log_recovery_delay_store
(
const
char
*
buf
,
size_t
count
,
void
*
data
)
{
int
ret
;
int
val
;
ret
=
kstrtoint
(
buf
,
0
,
&
val
);
if
(
ret
)
return
ret
;
if
(
val
<
0
||
val
>
60
)
return
-
EINVAL
;
xfs_globals
.
log_recovery_delay
=
val
;
return
count
;
}
STATIC
ssize_t
log_recovery_delay_show
(
char
*
buf
,
void
*
data
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
xfs_globals
.
log_recovery_delay
);
}
XFS_SYSFS_ATTR_RW
(
log_recovery_delay
);
static
struct
attribute
*
xfs_dbg_attrs
[]
=
{
ATTR_LIST
(
log_recovery_delay
),
NULL
,
};
STATIC
ssize_t
xfs_dbg_show
(
struct
kobject
*
kobject
,
struct
attribute
*
attr
,
char
*
buf
)
{
struct
xfs_sysfs_attr
*
xfs_attr
=
to_attr
(
attr
);
return
xfs_attr
->
show
?
xfs_attr
->
show
(
buf
,
NULL
)
:
0
;
}
STATIC
ssize_t
xfs_dbg_store
(
struct
kobject
*
kobject
,
struct
attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
xfs_sysfs_attr
*
xfs_attr
=
to_attr
(
attr
);
return
xfs_attr
->
store
?
xfs_attr
->
store
(
buf
,
count
,
NULL
)
:
0
;
}
static
struct
sysfs_ops
xfs_dbg_ops
=
{
.
show
=
xfs_dbg_show
,
.
store
=
xfs_dbg_store
,
};
struct
kobj_type
xfs_dbg_ktype
=
{
.
release
=
xfs_sysfs_release
,
.
sysfs_ops
=
&
xfs_dbg_ops
,
.
default_attrs
=
xfs_dbg_attrs
,
};
#endif
/* DEBUG */
/* xlog */
STATIC
ssize_t
...
...
fs/xfs/xfs_sysfs.h
View file @
a4241aeb
...
...
@@ -20,6 +20,7 @@
#define __XFS_SYSFS_H__
extern
struct
kobj_type
xfs_mp_ktype
;
/* xfs_mount */
extern
struct
kobj_type
xfs_dbg_ktype
;
/* debug */
extern
struct
kobj_type
xfs_log_ktype
;
/* xlog */
static
inline
struct
xfs_kobj
*
...
...
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