Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
a89b3f97
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
a89b3f97
编写于
10月 03, 2016
作者:
D
Dave Chinner
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'xfs-4.9-delalloc-rework' into for-next
上级
79ad5761
51446f5b
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
242 addition
and
350 deletion
+242
-350
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.c
+2
-87
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_bmap.h
+7
-3
fs/xfs/xfs_icache.c
fs/xfs/xfs_icache.c
+14
-0
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode.h
+1
-0
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iomap.c
+218
-258
fs/xfs/xfs_iomap.h
fs/xfs/xfs_iomap.h
+0
-2
未找到文件。
fs/xfs/libxfs/xfs_bmap.c
浏览文件 @
a89b3f97
...
...
@@ -1389,7 +1389,7 @@ xfs_bmap_search_multi_extents(
* Else, *lastxp will be set to the index of the found
* entry; *gotp will contain the entry.
*/
STATIC
xfs_bmbt_rec_host_t
*
/* pointer to found extent entry */
xfs_bmbt_rec_host_t
*
/* pointer to found extent entry */
xfs_bmap_search_extents
(
xfs_inode_t
*
ip
,
/* incore inode pointer */
xfs_fileoff_t
bno
,
/* block number searched for */
...
...
@@ -4076,7 +4076,7 @@ xfs_bmapi_read(
return
0
;
}
STATIC
int
int
xfs_bmapi_reserve_delalloc
(
struct
xfs_inode
*
ip
,
xfs_fileoff_t
aoff
,
...
...
@@ -4172,91 +4172,6 @@ xfs_bmapi_reserve_delalloc(
return
error
;
}
/*
* Map file blocks to filesystem blocks, adding delayed allocations as needed.
*/
int
xfs_bmapi_delay
(
struct
xfs_inode
*
ip
,
/* incore inode */
xfs_fileoff_t
bno
,
/* starting file offs. mapped */
xfs_filblks_t
len
,
/* length to map in file */
struct
xfs_bmbt_irec
*
mval
,
/* output: map values */
int
*
nmap
,
/* i/o: mval size/count */
int
flags
)
/* XFS_BMAPI_... */
{
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
struct
xfs_ifork
*
ifp
=
XFS_IFORK_PTR
(
ip
,
XFS_DATA_FORK
);
struct
xfs_bmbt_irec
got
;
/* current file extent record */
struct
xfs_bmbt_irec
prev
;
/* previous file extent record */
xfs_fileoff_t
obno
;
/* old block number (offset) */
xfs_fileoff_t
end
;
/* end of mapped file region */
xfs_extnum_t
lastx
;
/* last useful extent number */
int
eof
;
/* we've hit the end of extents */
int
n
=
0
;
/* current extent index */
int
error
=
0
;
ASSERT
(
*
nmap
>=
1
);
ASSERT
(
*
nmap
<=
XFS_BMAP_MAX_NMAP
);
ASSERT
(
!
(
flags
&
~
XFS_BMAPI_ENTIRE
));
ASSERT
(
xfs_isilocked
(
ip
,
XFS_ILOCK_EXCL
));
if
(
unlikely
(
XFS_TEST_ERROR
(
(
XFS_IFORK_FORMAT
(
ip
,
XFS_DATA_FORK
)
!=
XFS_DINODE_FMT_EXTENTS
&&
XFS_IFORK_FORMAT
(
ip
,
XFS_DATA_FORK
)
!=
XFS_DINODE_FMT_BTREE
),
mp
,
XFS_ERRTAG_BMAPIFORMAT
,
XFS_RANDOM_BMAPIFORMAT
)))
{
XFS_ERROR_REPORT
(
"xfs_bmapi_delay"
,
XFS_ERRLEVEL_LOW
,
mp
);
return
-
EFSCORRUPTED
;
}
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
-
EIO
;
XFS_STATS_INC
(
mp
,
xs_blk_mapw
);
if
(
!
(
ifp
->
if_flags
&
XFS_IFEXTENTS
))
{
error
=
xfs_iread_extents
(
NULL
,
ip
,
XFS_DATA_FORK
);
if
(
error
)
return
error
;
}
xfs_bmap_search_extents
(
ip
,
bno
,
XFS_DATA_FORK
,
&
eof
,
&
lastx
,
&
got
,
&
prev
);
end
=
bno
+
len
;
obno
=
bno
;
while
(
bno
<
end
&&
n
<
*
nmap
)
{
if
(
eof
||
got
.
br_startoff
>
bno
)
{
error
=
xfs_bmapi_reserve_delalloc
(
ip
,
bno
,
len
,
&
got
,
&
prev
,
&
lastx
,
eof
);
if
(
error
)
{
if
(
n
==
0
)
{
*
nmap
=
0
;
return
error
;
}
break
;
}
}
/* set up the extent map to return. */
xfs_bmapi_trim_map
(
mval
,
&
got
,
&
bno
,
len
,
obno
,
end
,
n
,
flags
);
xfs_bmapi_update_map
(
&
mval
,
&
bno
,
&
len
,
obno
,
end
,
&
n
,
flags
);
/* If we're done, stop now. */
if
(
bno
>=
end
||
n
>=
*
nmap
)
break
;
/* Else go on to the next record. */
prev
=
got
;
if
(
++
lastx
<
ifp
->
if_bytes
/
sizeof
(
xfs_bmbt_rec_t
))
xfs_bmbt_get_all
(
xfs_iext_get_ext
(
ifp
,
lastx
),
&
got
);
else
eof
=
1
;
}
*
nmap
=
n
;
return
0
;
}
static
int
xfs_bmapi_allocate
(
struct
xfs_bmalloca
*
bma
)
...
...
fs/xfs/libxfs/xfs_bmap.h
浏览文件 @
a89b3f97
...
...
@@ -181,9 +181,6 @@ int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip,
int
xfs_bmapi_read
(
struct
xfs_inode
*
ip
,
xfs_fileoff_t
bno
,
xfs_filblks_t
len
,
struct
xfs_bmbt_irec
*
mval
,
int
*
nmap
,
int
flags
);
int
xfs_bmapi_delay
(
struct
xfs_inode
*
ip
,
xfs_fileoff_t
bno
,
xfs_filblks_t
len
,
struct
xfs_bmbt_irec
*
mval
,
int
*
nmap
,
int
flags
);
int
xfs_bmapi_write
(
struct
xfs_trans
*
tp
,
struct
xfs_inode
*
ip
,
xfs_fileoff_t
bno
,
xfs_filblks_t
len
,
int
flags
,
xfs_fsblock_t
*
firstblock
,
xfs_extlen_t
total
,
...
...
@@ -202,5 +199,12 @@ int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
struct
xfs_defer_ops
*
dfops
,
enum
shift_direction
direction
,
int
num_exts
);
int
xfs_bmap_split_extent
(
struct
xfs_inode
*
ip
,
xfs_fileoff_t
split_offset
);
struct
xfs_bmbt_rec_host
*
xfs_bmap_search_extents
(
struct
xfs_inode
*
ip
,
xfs_fileoff_t
bno
,
int
fork
,
int
*
eofp
,
xfs_extnum_t
*
lastxp
,
struct
xfs_bmbt_irec
*
gotp
,
struct
xfs_bmbt_irec
*
prevp
);
int
xfs_bmapi_reserve_delalloc
(
struct
xfs_inode
*
ip
,
xfs_fileoff_t
aoff
,
xfs_filblks_t
len
,
struct
xfs_bmbt_irec
*
got
,
struct
xfs_bmbt_irec
*
prev
,
xfs_extnum_t
*
lastx
,
int
eof
);
#endif
/* __XFS_BMAP_H__ */
fs/xfs/xfs_icache.c
浏览文件 @
a89b3f97
...
...
@@ -1414,6 +1414,16 @@ xfs_inode_set_eofblocks_tag(
struct
xfs_perag
*
pag
;
int
tagged
;
/*
* Don't bother locking the AG and looking up in the radix trees
* if we already know that we have the tag set.
*/
if
(
ip
->
i_flags
&
XFS_IEOFBLOCKS
)
return
;
spin_lock
(
&
ip
->
i_flags_lock
);
ip
->
i_flags
|=
XFS_IEOFBLOCKS
;
spin_unlock
(
&
ip
->
i_flags_lock
);
pag
=
xfs_perag_get
(
mp
,
XFS_INO_TO_AGNO
(
mp
,
ip
->
i_ino
));
spin_lock
(
&
pag
->
pag_ici_lock
);
trace_xfs_inode_set_eofblocks_tag
(
ip
);
...
...
@@ -1449,6 +1459,10 @@ xfs_inode_clear_eofblocks_tag(
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
struct
xfs_perag
*
pag
;
spin_lock
(
&
ip
->
i_flags_lock
);
ip
->
i_flags
&=
~
XFS_IEOFBLOCKS
;
spin_unlock
(
&
ip
->
i_flags_lock
);
pag
=
xfs_perag_get
(
mp
,
XFS_INO_TO_AGNO
(
mp
,
ip
->
i_ino
));
spin_lock
(
&
pag
->
pag_ici_lock
);
trace_xfs_inode_clear_eofblocks_tag
(
ip
);
...
...
fs/xfs/xfs_inode.h
浏览文件 @
a89b3f97
...
...
@@ -216,6 +216,7 @@ xfs_get_initial_prid(struct xfs_inode *dp)
#define __XFS_IPINNED_BIT 8
/* wakeup key for zero pin count */
#define XFS_IPINNED (1 << __XFS_IPINNED_BIT)
#define XFS_IDONTCACHE (1 << 9)
/* don't cache the inode long term */
#define XFS_IEOFBLOCKS (1 << 10)
/* has the preallocblocks tag set */
/*
* Per-lifetime flags need to be reset when re-using a reclaimable inode during
...
...
fs/xfs/xfs_iomap.c
浏览文件 @
a89b3f97
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2016 Christoph Hellwig.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
...
...
@@ -42,17 +43,40 @@
#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \
<< mp->m_writeio_log)
#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP
STATIC
int
xfs_iomap_eof_align_last_fsb
(
xfs_mount_t
*
mp
,
xfs_inode_t
*
ip
,
xfs_extlen_t
extsize
,
xfs_fileoff_t
*
last_fsb
)
void
xfs_bmbt_to_iomap
(
struct
xfs_inode
*
ip
,
struct
iomap
*
iomap
,
struct
xfs_bmbt_irec
*
imap
)
{
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
if
(
imap
->
br_startblock
==
HOLESTARTBLOCK
)
{
iomap
->
blkno
=
IOMAP_NULL_BLOCK
;
iomap
->
type
=
IOMAP_HOLE
;
}
else
if
(
imap
->
br_startblock
==
DELAYSTARTBLOCK
)
{
iomap
->
blkno
=
IOMAP_NULL_BLOCK
;
iomap
->
type
=
IOMAP_DELALLOC
;
}
else
{
iomap
->
blkno
=
xfs_fsb_to_db
(
ip
,
imap
->
br_startblock
);
if
(
imap
->
br_state
==
XFS_EXT_UNWRITTEN
)
iomap
->
type
=
IOMAP_UNWRITTEN
;
else
iomap
->
type
=
IOMAP_MAPPED
;
}
iomap
->
offset
=
XFS_FSB_TO_B
(
mp
,
imap
->
br_startoff
);
iomap
->
length
=
XFS_FSB_TO_B
(
mp
,
imap
->
br_blockcount
);
iomap
->
bdev
=
xfs_find_bdev_for_inode
(
VFS_I
(
ip
));
}
static
xfs_extlen_t
xfs_eof_alignment
(
struct
xfs_inode
*
ip
,
xfs_extlen_t
extsize
)
{
xfs_extlen_t
align
=
0
;
int
eof
,
error
;
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
xfs_extlen_t
align
=
0
;
if
(
!
XFS_IS_REALTIME_INODE
(
ip
))
{
/*
...
...
@@ -83,8 +107,21 @@ xfs_iomap_eof_align_last_fsb(
align
=
extsize
;
}
return
align
;
}
STATIC
int
xfs_iomap_eof_align_last_fsb
(
struct
xfs_inode
*
ip
,
xfs_extlen_t
extsize
,
xfs_fileoff_t
*
last_fsb
)
{
xfs_extlen_t
align
=
xfs_eof_alignment
(
ip
,
extsize
);
if
(
align
)
{
xfs_fileoff_t
new_last_fsb
=
roundup_64
(
*
last_fsb
,
align
);
int
eof
,
error
;
error
=
xfs_bmap_eof
(
ip
,
new_last_fsb
,
XFS_DATA_FORK
,
&
eof
);
if
(
error
)
return
error
;
...
...
@@ -154,7 +191,7 @@ xfs_iomap_write_direct(
*/
ASSERT
(
XFS_IFORK_PTR
(
ip
,
XFS_DATA_FORK
)
->
if_flags
&
XFS_IFEXTENTS
);
error
=
xfs_iomap_eof_align_last_fsb
(
mp
,
ip
,
extsz
,
&
last_fsb
);
error
=
xfs_iomap_eof_align_last_fsb
(
ip
,
extsz
,
&
last_fsb
);
if
(
error
)
goto
out_unlock
;
}
else
{
...
...
@@ -274,130 +311,6 @@ xfs_iomap_write_direct(
goto
out_unlock
;
}
/*
* If the caller is doing a write at the end of the file, then extend the
* allocation out to the file system's write iosize. We clean up any extra
* space left over when the file is closed in xfs_inactive().
*
* If we find we already have delalloc preallocation beyond EOF, don't do more
* preallocation as it it not needed.
*/
STATIC
int
xfs_iomap_eof_want_preallocate
(
xfs_mount_t
*
mp
,
xfs_inode_t
*
ip
,
xfs_off_t
offset
,
size_t
count
,
xfs_bmbt_irec_t
*
imap
,
int
nimaps
,
int
*
prealloc
)
{
xfs_fileoff_t
start_fsb
;
xfs_filblks_t
count_fsb
;
int
n
,
error
,
imaps
;
int
found_delalloc
=
0
;
*
prealloc
=
0
;
if
(
offset
+
count
<=
XFS_ISIZE
(
ip
))
return
0
;
/*
* If the file is smaller than the minimum prealloc and we are using
* dynamic preallocation, don't do any preallocation at all as it is
* likely this is the only write to the file that is going to be done.
*/
if
(
!
(
mp
->
m_flags
&
XFS_MOUNT_DFLT_IOSIZE
)
&&
XFS_ISIZE
(
ip
)
<
XFS_FSB_TO_B
(
mp
,
mp
->
m_writeio_blocks
))
return
0
;
/*
* If there are any real blocks past eof, then don't
* do any speculative allocation.
*/
start_fsb
=
XFS_B_TO_FSBT
(
mp
,
((
xfs_ufsize_t
)(
offset
+
count
-
1
)));
count_fsb
=
XFS_B_TO_FSB
(
mp
,
mp
->
m_super
->
s_maxbytes
);
while
(
count_fsb
>
0
)
{
imaps
=
nimaps
;
error
=
xfs_bmapi_read
(
ip
,
start_fsb
,
count_fsb
,
imap
,
&
imaps
,
0
);
if
(
error
)
return
error
;
for
(
n
=
0
;
n
<
imaps
;
n
++
)
{
if
((
imap
[
n
].
br_startblock
!=
HOLESTARTBLOCK
)
&&
(
imap
[
n
].
br_startblock
!=
DELAYSTARTBLOCK
))
return
0
;
start_fsb
+=
imap
[
n
].
br_blockcount
;
count_fsb
-=
imap
[
n
].
br_blockcount
;
if
(
imap
[
n
].
br_startblock
==
DELAYSTARTBLOCK
)
found_delalloc
=
1
;
}
}
if
(
!
found_delalloc
)
*
prealloc
=
1
;
return
0
;
}
/*
* Determine the initial size of the preallocation. We are beyond the current
* EOF here, but we need to take into account whether this is a sparse write or
* an extending write when determining the preallocation size. Hence we need to
* look up the extent that ends at the current write offset and use the result
* to determine the preallocation size.
*
* If the extent is a hole, then preallocation is essentially disabled.
* Otherwise we take the size of the preceeding data extent as the basis for the
* preallocation size. If the size of the extent is greater than half the
* maximum extent length, then use the current offset as the basis. This ensures
* that for large files the preallocation size always extends to MAXEXTLEN
* rather than falling short due to things like stripe unit/width alignment of
* real extents.
*/
STATIC
xfs_fsblock_t
xfs_iomap_eof_prealloc_initial_size
(
struct
xfs_mount
*
mp
,
struct
xfs_inode
*
ip
,
xfs_off_t
offset
,
xfs_bmbt_irec_t
*
imap
,
int
nimaps
)
{
xfs_fileoff_t
start_fsb
;
int
imaps
=
1
;
int
error
;
ASSERT
(
nimaps
>=
imaps
);
/* if we are using a specific prealloc size, return now */
if
(
mp
->
m_flags
&
XFS_MOUNT_DFLT_IOSIZE
)
return
0
;
/* If the file is small, then use the minimum prealloc */
if
(
XFS_ISIZE
(
ip
)
<
XFS_FSB_TO_B
(
mp
,
mp
->
m_dalign
))
return
0
;
/*
* As we write multiple pages, the offset will always align to the
* start of a page and hence point to a hole at EOF. i.e. if the size is
* 4096 bytes, we only have one block at FSB 0, but XFS_B_TO_FSB(4096)
* will return FSB 1. Hence if there are blocks in the file, we want to
* point to the block prior to the EOF block and not the hole that maps
* directly at @offset.
*/
start_fsb
=
XFS_B_TO_FSB
(
mp
,
offset
);
if
(
start_fsb
)
start_fsb
--
;
error
=
xfs_bmapi_read
(
ip
,
start_fsb
,
1
,
imap
,
&
imaps
,
XFS_BMAPI_ENTIRE
);
if
(
error
)
return
0
;
ASSERT
(
imaps
==
1
);
if
(
imap
[
0
].
br_startblock
==
HOLESTARTBLOCK
)
return
0
;
if
(
imap
[
0
].
br_blockcount
<=
(
MAXEXTLEN
>>
1
))
return
imap
[
0
].
br_blockcount
<<
1
;
return
XFS_B_TO_FSB
(
mp
,
offset
);
}
STATIC
bool
xfs_quota_need_throttle
(
struct
xfs_inode
*
ip
,
...
...
@@ -459,27 +372,76 @@ xfs_quota_calc_throttle(
}
/*
* If we are doing a write at the end of the file and there are no allocations
* past this one, then extend the allocation out to the file system's write
* iosize.
*
* If we don't have a user specified preallocation size, dynamically increase
* the preallocation size as the size of the file grows. Cap the maximum size
* the preallocation size as the size of the file grows.
Cap the maximum size
* at a single extent or less if the filesystem is near full. The closer the
* filesystem is to full, the smaller the maximum prealocation.
*
* As an exception we don't do any preallocation at all if the file is smaller
* than the minimum preallocation and we are using the default dynamic
* preallocation scheme, as it is likely this is the only write to the file that
* is going to be done.
*
* We clean up any extra space left over when the file is closed in
* xfs_inactive().
*/
STATIC
xfs_fsblock_t
xfs_iomap_prealloc_size
(
struct
xfs_mount
*
mp
,
struct
xfs_inode
*
ip
,
xfs_off_t
offset
,
struct
xfs_bmbt_irec
*
imap
,
int
nimaps
)
loff_t
offset
,
loff_t
count
,
xfs_extnum_t
idx
,
struct
xfs_bmbt_irec
*
prev
)
{
xfs_fsblock_t
alloc_blocks
=
0
;
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
xfs_fileoff_t
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
int
shift
=
0
;
int64_t
freesp
;
xfs_fsblock_t
qblocks
;
int
qshift
=
0
;
xfs_fsblock_t
alloc_blocks
=
0
;
alloc_blocks
=
xfs_iomap_eof_prealloc_initial_size
(
mp
,
ip
,
offset
,
imap
,
nimaps
);
if
(
offset
+
count
<=
XFS_ISIZE
(
ip
))
return
0
;
if
(
!
(
mp
->
m_flags
&
XFS_MOUNT_DFLT_IOSIZE
)
&&
(
XFS_ISIZE
(
ip
)
<
XFS_FSB_TO_B
(
mp
,
mp
->
m_writeio_blocks
)))
return
0
;
/*
* If an explicit allocsize is set, the file is small, or we
* are writing behind a hole, then use the minimum prealloc:
*/
if
((
mp
->
m_flags
&
XFS_MOUNT_DFLT_IOSIZE
)
||
XFS_ISIZE
(
ip
)
<
XFS_FSB_TO_B
(
mp
,
mp
->
m_dalign
)
||
idx
==
0
||
prev
->
br_startoff
+
prev
->
br_blockcount
<
offset_fsb
)
return
mp
->
m_writeio_blocks
;
/*
* Determine the initial size of the preallocation. We are beyond the
* current EOF here, but we need to take into account whether this is
* a sparse write or an extending write when determining the
* preallocation size. Hence we need to look up the extent that ends
* at the current write offset and use the result to determine the
* preallocation size.
*
* If the extent is a hole, then preallocation is essentially disabled.
* Otherwise we take the size of the preceding data extent as the basis
* for the preallocation size. If the size of the extent is greater than
* half the maximum extent length, then use the current offset as the
* basis. This ensures that for large files the preallocation size
* always extends to MAXEXTLEN rather than falling short due to things
* like stripe unit/width alignment of real extents.
*/
if
(
prev
->
br_blockcount
<=
(
MAXEXTLEN
>>
1
))
alloc_blocks
=
prev
->
br_blockcount
<<
1
;
else
alloc_blocks
=
XFS_B_TO_FSB
(
mp
,
offset
);
if
(
!
alloc_blocks
)
goto
check_writeio
;
qblocks
=
alloc_blocks
;
...
...
@@ -550,120 +512,145 @@ xfs_iomap_prealloc_size(
*/
while
(
alloc_blocks
&&
alloc_blocks
>=
freesp
)
alloc_blocks
>>=
4
;
check_writeio:
if
(
alloc_blocks
<
mp
->
m_writeio_blocks
)
alloc_blocks
=
mp
->
m_writeio_blocks
;
trace_xfs_iomap_prealloc_size
(
ip
,
alloc_blocks
,
shift
,
mp
->
m_writeio_blocks
);
return
alloc_blocks
;
}
int
xfs_iomap_write_delay
(
xfs_inode_t
*
ip
,
xfs_off_t
offset
,
size_t
count
,
xfs_bmbt_irec_t
*
ret_imap
)
static
int
xfs_file_iomap_begin_delay
(
struct
inode
*
inode
,
loff_t
offset
,
loff_t
count
,
unsigned
flags
,
struct
iomap
*
iomap
)
{
xfs_mount_t
*
mp
=
ip
->
i_mount
;
xfs_fileoff_t
offset_fsb
;
xfs_fileoff_t
last_fsb
;
xfs_off_t
aligned_offset
;
xfs_fileoff_t
ioalign
;
xfs_extlen_t
extsz
;
int
nimaps
;
xfs_bmbt_irec_t
imap
[
XFS_WRITE_IMAPS
];
int
prealloc
;
int
error
;
ASSERT
(
xfs_isilocked
(
ip
,
XFS_ILOCK_EXCL
));
/*
* Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read.
*/
error
=
xfs_qm_dqattach_locked
(
ip
,
0
);
if
(
error
)
return
error
;
struct
xfs_inode
*
ip
=
XFS_I
(
inode
);
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
struct
xfs_ifork
*
ifp
=
XFS_IFORK_PTR
(
ip
,
XFS_DATA_FORK
);
xfs_fileoff_t
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
xfs_fileoff_t
maxbytes_fsb
=
XFS_B_TO_FSB
(
mp
,
mp
->
m_super
->
s_maxbytes
);
xfs_fileoff_t
end_fsb
,
orig_end_fsb
;
int
error
=
0
,
eof
=
0
;
struct
xfs_bmbt_irec
got
;
struct
xfs_bmbt_irec
prev
;
xfs_extnum_t
idx
;
extsz
=
xfs_get_extsz_hint
(
ip
);
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
ASSERT
(
!
XFS_IS_REALTIME_INODE
(
ip
)
);
ASSERT
(
!
xfs_get_extsz_hint
(
ip
)
);
error
=
xfs_iomap_eof_want_preallocate
(
mp
,
ip
,
offset
,
count
,
imap
,
XFS_WRITE_IMAPS
,
&
prealloc
);
if
(
error
)
return
error
;
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
retry:
if
(
prealloc
)
{
xfs_fsblock_t
alloc_blocks
;
if
(
unlikely
(
XFS_TEST_ERROR
(
(
XFS_IFORK_FORMAT
(
ip
,
XFS_DATA_FORK
)
!=
XFS_DINODE_FMT_EXTENTS
&&
XFS_IFORK_FORMAT
(
ip
,
XFS_DATA_FORK
)
!=
XFS_DINODE_FMT_BTREE
),
mp
,
XFS_ERRTAG_BMAPIFORMAT
,
XFS_RANDOM_BMAPIFORMAT
)))
{
XFS_ERROR_REPORT
(
__func__
,
XFS_ERRLEVEL_LOW
,
mp
);
error
=
-
EFSCORRUPTED
;
goto
out_unlock
;
}
alloc_blocks
=
xfs_iomap_prealloc_size
(
mp
,
ip
,
offset
,
imap
,
XFS_WRITE_IMAPS
);
XFS_STATS_INC
(
mp
,
xs_blk_mapw
);
aligned_offset
=
XFS_WRITEIO_ALIGN
(
mp
,
(
offset
+
count
-
1
));
ioalign
=
XFS_B_TO_FSBT
(
mp
,
aligned_offset
);
last_fsb
=
ioalign
+
alloc_blocks
;
}
else
{
last_fsb
=
XFS_B_TO_FSB
(
mp
,
((
xfs_ufsize_t
)(
offset
+
count
)));
if
(
!
(
ifp
->
if_flags
&
XFS_IFEXTENTS
))
{
error
=
xfs_iread_extents
(
NULL
,
ip
,
XFS_DATA_FORK
);
if
(
error
)
goto
out_unlock
;
}
if
(
prealloc
||
extsz
)
{
error
=
xfs_iomap_eof_align_last_fsb
(
mp
,
ip
,
extsz
,
&
last_fsb
);
if
(
error
)
return
error
;
xfs_bmap_search_extents
(
ip
,
offset_fsb
,
XFS_DATA_FORK
,
&
eof
,
&
idx
,
&
got
,
&
prev
);
if
(
!
eof
&&
got
.
br_startoff
<=
offset_fsb
)
{
trace_xfs_iomap_found
(
ip
,
offset
,
count
,
0
,
&
got
);
goto
done
;
}
error
=
xfs_qm_dqattach_locked
(
ip
,
0
);
if
(
error
)
goto
out_unlock
;
/*
* Make sure preallocation does not create extents beyond the range we
* actually support in this filesystem.
* We cap the maximum length we map here to MAX_WRITEBACK_PAGES pages
* to keep the chunks of work done where somewhat symmetric with the
* work writeback does. This is a completely arbitrary number pulled
* out of thin air as a best guess for initial testing.
*
* Note that the values needs to be less than 32-bits wide until
* the lower level functions are updated.
*/
if
(
last_fsb
>
XFS_B_TO_FSB
(
mp
,
mp
->
m_super
->
s_maxbytes
))
last_fsb
=
XFS_B_TO_FSB
(
mp
,
mp
->
m_super
->
s_maxbytes
);
count
=
min_t
(
loff_t
,
count
,
1024
*
PAGE_SIZE
);
end_fsb
=
orig_end_fsb
=
min
(
XFS_B_TO_FSB
(
mp
,
offset
+
count
),
maxbytes_fsb
);
if
(
eof
)
{
xfs_fsblock_t
prealloc_blocks
;
ASSERT
(
last_fsb
>
offset_fsb
);
prealloc_blocks
=
xfs_iomap_prealloc_size
(
ip
,
offset
,
count
,
idx
,
&
prev
);
if
(
prealloc_blocks
)
{
xfs_extlen_t
align
;
xfs_off_t
end_offset
;
nimaps
=
XFS_WRITE_IMAPS
;
error
=
xfs_bmapi_delay
(
ip
,
offset_fsb
,
last_fsb
-
offset_fsb
,
imap
,
&
nimaps
,
XFS_BMAPI_ENTIRE
);
end_offset
=
XFS_WRITEIO_ALIGN
(
mp
,
offset
+
count
-
1
);
end_fsb
=
XFS_B_TO_FSBT
(
mp
,
end_offset
)
+
prealloc_blocks
;
align
=
xfs_eof_alignment
(
ip
,
0
);
if
(
align
)
end_fsb
=
roundup_64
(
end_fsb
,
align
);
end_fsb
=
min
(
end_fsb
,
maxbytes_fsb
);
ASSERT
(
end_fsb
>
offset_fsb
);
}
}
retry:
error
=
xfs_bmapi_reserve_delalloc
(
ip
,
offset_fsb
,
end_fsb
-
offset_fsb
,
&
got
,
&
prev
,
&
idx
,
eof
);
switch
(
error
)
{
case
0
:
break
;
case
-
ENOSPC
:
case
-
EDQUOT
:
break
;
default:
return
error
;
}
/*
* If bmapi returned us nothing, we got either ENOSPC or EDQUOT. Retry
* without EOF preallocation.
*/
if
(
nimaps
==
0
)
{
/* retry without any preallocation */
trace_xfs_delalloc_enospc
(
ip
,
offset
,
count
);
if
(
prealloc
)
{
prealloc
=
0
;
error
=
0
;
if
(
end_fsb
!=
orig_end_fsb
)
{
end_fsb
=
orig_end_fsb
;
goto
retry
;
}
return
error
?
error
:
-
ENOSPC
;
/*FALLTHRU*/
default:
goto
out_unlock
;
}
if
(
!
(
imap
[
0
].
br_startblock
||
XFS_IS_REALTIME_INODE
(
ip
)))
return
xfs_alert_fsblock_zero
(
ip
,
&
imap
[
0
]);
/*
* Tag the inode as speculatively preallocated so we can reclaim this
* space on demand, if necessary.
*/
if
(
prealloc
)
if
(
end_fsb
!=
orig_end_fsb
)
xfs_inode_set_eofblocks_tag
(
ip
);
*
ret_imap
=
imap
[
0
];
return
0
;
trace_xfs_iomap_alloc
(
ip
,
offset
,
count
,
0
,
&
got
);
done:
if
(
isnullstartblock
(
got
.
br_startblock
))
got
.
br_startblock
=
DELAYSTARTBLOCK
;
if
(
!
got
.
br_startblock
)
{
error
=
xfs_alert_fsblock_zero
(
ip
,
&
got
);
if
(
error
)
goto
out_unlock
;
}
xfs_bmbt_to_iomap
(
ip
,
iomap
,
&
got
);
out_unlock:
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
return
error
;
}
/*
...
...
@@ -947,32 +934,6 @@ xfs_iomap_write_unwritten(
return
error
;
}
void
xfs_bmbt_to_iomap
(
struct
xfs_inode
*
ip
,
struct
iomap
*
iomap
,
struct
xfs_bmbt_irec
*
imap
)
{
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
if
(
imap
->
br_startblock
==
HOLESTARTBLOCK
)
{
iomap
->
blkno
=
IOMAP_NULL_BLOCK
;
iomap
->
type
=
IOMAP_HOLE
;
}
else
if
(
imap
->
br_startblock
==
DELAYSTARTBLOCK
)
{
iomap
->
blkno
=
IOMAP_NULL_BLOCK
;
iomap
->
type
=
IOMAP_DELALLOC
;
}
else
{
iomap
->
blkno
=
xfs_fsb_to_db
(
ip
,
imap
->
br_startblock
);
if
(
imap
->
br_state
==
XFS_EXT_UNWRITTEN
)
iomap
->
type
=
IOMAP_UNWRITTEN
;
else
iomap
->
type
=
IOMAP_MAPPED
;
}
iomap
->
offset
=
XFS_FSB_TO_B
(
mp
,
imap
->
br_startoff
);
iomap
->
length
=
XFS_FSB_TO_B
(
mp
,
imap
->
br_blockcount
);
iomap
->
bdev
=
xfs_find_bdev_for_inode
(
VFS_I
(
ip
));
}
static
inline
bool
imap_needs_alloc
(
struct
xfs_bmbt_irec
*
imap
,
int
nimaps
)
{
return
!
nimaps
||
...
...
@@ -997,6 +958,11 @@ xfs_file_iomap_begin(
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
-
EIO
;
if
((
flags
&
IOMAP_WRITE
)
&&
!
xfs_get_extsz_hint
(
ip
))
{
return
xfs_file_iomap_begin_delay
(
inode
,
offset
,
length
,
flags
,
iomap
);
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
ASSERT
(
offset
<=
mp
->
m_super
->
s_maxbytes
);
...
...
@@ -1024,19 +990,13 @@ xfs_file_iomap_begin(
* the lower level functions are updated.
*/
length
=
min_t
(
loff_t
,
length
,
1024
*
PAGE_SIZE
);
if
(
xfs_get_extsz_hint
(
ip
))
{
/*
* xfs_iomap_write_direct() expects the shared lock. It
* is unlocked on return.
*/
xfs_ilock_demote
(
ip
,
XFS_ILOCK_EXCL
);
error
=
xfs_iomap_write_direct
(
ip
,
offset
,
length
,
&
imap
,
nimaps
);
}
else
{
error
=
xfs_iomap_write_delay
(
ip
,
offset
,
length
,
&
imap
);
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
}
/*
* xfs_iomap_write_direct() expects the shared lock. It
* is unlocked on return.
*/
xfs_ilock_demote
(
ip
,
XFS_ILOCK_EXCL
);
error
=
xfs_iomap_write_direct
(
ip
,
offset
,
length
,
&
imap
,
nimaps
);
if
(
error
)
return
error
;
...
...
fs/xfs/xfs_iomap.h
浏览文件 @
a89b3f97
...
...
@@ -25,8 +25,6 @@ struct xfs_bmbt_irec;
int
xfs_iomap_write_direct
(
struct
xfs_inode
*
,
xfs_off_t
,
size_t
,
struct
xfs_bmbt_irec
*
,
int
);
int
xfs_iomap_write_delay
(
struct
xfs_inode
*
,
xfs_off_t
,
size_t
,
struct
xfs_bmbt_irec
*
);
int
xfs_iomap_write_allocate
(
struct
xfs_inode
*
,
xfs_off_t
,
struct
xfs_bmbt_irec
*
);
int
xfs_iomap_write_unwritten
(
struct
xfs_inode
*
,
xfs_off_t
,
xfs_off_t
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录