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
Kirill Smelkov
linux
Commits
c2e95c3f
Commit
c2e95c3f
authored
Dec 20, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/home/hch/BK/xfs/linux-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
028d2f3e
b33cc8f7
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
814 additions
and
974 deletions
+814
-974
fs/buffer.c
fs/buffer.c
+3
-2
fs/xfs/Makefile
fs/xfs/Makefile
+11
-12
fs/xfs/linux/xfs_aops.c
fs/xfs/linux/xfs_aops.c
+66
-52
fs/xfs/linux/xfs_iomap.c
fs/xfs/linux/xfs_iomap.c
+496
-659
fs/xfs/linux/xfs_iops.c
fs/xfs/linux/xfs_iops.c
+8
-6
fs/xfs/linux/xfs_lrw.c
fs/xfs/linux/xfs_lrw.c
+19
-0
fs/xfs/linux/xfs_lrw.h
fs/xfs/linux/xfs_lrw.h
+12
-0
fs/xfs/linux/xfs_super.c
fs/xfs/linux/xfs_super.c
+9
-2
fs/xfs/linux/xfs_super.h
fs/xfs/linux/xfs_super.h
+9
-7
fs/xfs/pagebuf/page_buf.h
fs/xfs/pagebuf/page_buf.h
+7
-12
fs/xfs/xfs_alloc_btree.h
fs/xfs/xfs_alloc_btree.h
+2
-2
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf.h
+19
-13
fs/xfs/xfs_dmapi.h
fs/xfs/xfs_dmapi.h
+0
-17
fs/xfs/xfs_iget.c
fs/xfs/xfs_iget.c
+1
-3
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.c
+1
-1
fs/xfs/xfs_iocore.c
fs/xfs/xfs_iocore.c
+11
-2
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.c
+39
-17
fs/xfs/xfs_mount.h
fs/xfs/xfs_mount.h
+67
-21
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rtalloc.c
+1
-1
fs/xfs/xfs_rw.c
fs/xfs/xfs_rw.c
+1
-1
fs/xfs/xfs_trans_buf.c
fs/xfs/xfs_trans_buf.c
+1
-1
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vfsops.c
+8
-7
fs/xfs/xfs_vnodeops.c
fs/xfs/xfs_vnodeops.c
+19
-134
fs/xfs/xfsidbg.c
fs/xfs/xfsidbg.c
+2
-2
include/linux/buffer_head.h
include/linux/buffer_head.h
+2
-0
No files found.
fs/buffer.c
View file @
c2e95c3f
...
...
@@ -1453,6 +1453,7 @@ static inline void discard_buffer(struct buffer_head * bh)
clear_buffer_mapped
(
bh
);
clear_buffer_req
(
bh
);
clear_buffer_new
(
bh
);
clear_buffer_delay
(
bh
);
unlock_buffer
(
bh
);
}
...
...
@@ -1871,7 +1872,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
set_buffer_uptodate
(
bh
);
continue
;
}
if
(
!
buffer_uptodate
(
bh
)
&&
if
(
!
buffer_uptodate
(
bh
)
&&
!
buffer_delay
(
bh
)
&&
(
block_start
<
from
||
block_end
>
to
))
{
ll_rw_block
(
READ
,
1
,
&
bh
);
*
wait_bh
++=
bh
;
...
...
@@ -2457,7 +2458,7 @@ int block_truncate_page(struct address_space *mapping,
if
(
PageUptodate
(
page
))
set_buffer_uptodate
(
bh
);
if
(
!
buffer_uptodate
(
bh
))
{
if
(
!
buffer_uptodate
(
bh
)
&&
!
buffer_delay
(
bh
)
)
{
err
=
-
EIO
;
ll_rw_block
(
READ
,
1
,
&
bh
);
wait_on_buffer
(
bh
);
...
...
fs/xfs/Makefile
View file @
c2e95c3f
...
...
@@ -51,23 +51,22 @@ export-objs := pagebuf/page_buf.o support/ktrace.o \
obj-$(CONFIG_XFS_FS)
+=
xfs.o
xfs-
obj-$(CONFIG_XFS_RT)
+=
xfs_rtalloc.o
xfs-
$(CONFIG_XFS_RT)
+=
xfs_rtalloc.o
xfs-
obj-$(CONFIG_XFS_QUOTA)
+=
xfs_dquot.o
\
xfs-
$(CONFIG_XFS_QUOTA)
+=
xfs_dquot.o
\
xfs_dquot_item.o
\
xfs_trans_dquot.o
\
xfs_qm_syscalls.o
\
xfs_qm.o
xfs-
obj-
$(CONFIG_XFS_POSIX_ACL)
+=
xfs_acl.o
xfs-
obj-
$(CONFIG_FS_POSIX_CAP)
+=
xfs_cap.o
xfs-
obj-
$(CONFIG_FS_POSIX_MAC)
+=
xfs_mac.o
xfs-
obj-$(CONFIG_PROC_FS)
+=
linux/xfs_stats.o
xfs-
obj-$(CONFIG_SYSCTL)
+=
linux/xfs_sysctl.o
xfs-$(CONFIG_XFS_POSIX_ACL)
+=
xfs_acl.o
xfs-$(CONFIG_FS_POSIX_CAP)
+=
xfs_cap.o
xfs-$(CONFIG_FS_POSIX_MAC)
+=
xfs_mac.o
xfs-
$(CONFIG_PROC_FS)
+=
linux/xfs_stats.o
xfs-
$(CONFIG_SYSCTL)
+=
linux/xfs_sysctl.o
xfs-objs
+=
$
(
xfs-obj-y
)
\
xfs_alloc.o
\
xfs-y
+=
xfs_alloc.o
\
xfs_alloc_btree.o
\
xfs_attr.o
\
xfs_attr_fetch.o
\
...
...
@@ -115,12 +114,12 @@ xfs-objs += $(xfs-obj-y) \
xfs_rw.o
# Objects in pagebuf/
xfs-
objs
+=
$(
addprefix
pagebuf/,
\
xfs-
y
+=
$(
addprefix
pagebuf/,
\
page_buf.o
\
page_buf_locking.o
)
# Objects in linux/
xfs-
objs
+=
$(
addprefix
linux/,
\
xfs-
y
+=
$(
addprefix
linux/,
\
xfs_aops.o
\
xfs_behavior.o
\
xfs_file.o
\
...
...
@@ -134,7 +133,7 @@ xfs-objs += $(addprefix linux/, \
xfs_vnode.o
)
# Objects in support/
xfs-
objs
+=
$(
addprefix
support/,
\
xfs-
y
+=
$(
addprefix
support/,
\
debug.o
\
kmem.o
\
ktrace.o
\
...
...
fs/xfs/linux/xfs_aops.c
View file @
c2e95c3f
...
...
@@ -48,6 +48,9 @@ map_blocks(
vnode_t
*
vp
=
LINVFS_GET_VP
(
inode
);
int
error
,
nmaps
=
1
;
if
(((
flags
&
(
PBF_DIRECT
|
PBF_SYNC
))
==
PBF_DIRECT
)
&&
(
offset
>=
inode
->
i_size
))
count
=
max
(
count
,
XFS_WRITE_IO_LOG
);
retry:
VOP_BMAP
(
vp
,
offset
,
count
,
flags
,
pbmapp
,
&
nmaps
,
error
);
if
(
flags
&
PBF_WRITE
)
{
...
...
@@ -145,9 +148,8 @@ probe_unmapped_page(
struct
buffer_head
*
bh
,
*
head
;
bh
=
head
=
page_buffers
(
page
);
do
{
if
(
buffer_mapped
(
bh
)
||
!
buffer_uptodate
(
bh
))
{
if
(
buffer_mapped
(
bh
)
||
!
buffer_uptodate
(
bh
))
break
;
}
ret
+=
bh
->
b_size
;
if
(
ret
>=
pg_offset
)
break
;
...
...
@@ -289,7 +291,7 @@ convert_page(
bh
=
head
=
page_buffers
(
page
);
do
{
offset
=
i
<<
bbits
;
if
(
!
buffer_uptodate
(
bh
))
if
(
!
(
PageUptodate
(
page
)
||
buffer_uptodate
(
bh
)
))
continue
;
if
(
buffer_mapped
(
bh
)
&&
!
buffer_delay
(
bh
)
&&
all_bh
)
{
if
(
startio
&&
(
offset
<
end
))
{
...
...
@@ -372,7 +374,7 @@ delalloc_convert(
page_buf_bmap_t
*
mp
,
map
;
unsigned
long
p_offset
=
0
,
end_index
;
loff_t
offset
,
end_offset
;
int
len
,
err
,
i
,
cnt
=
0
;
int
len
,
err
,
i
,
cnt
=
0
,
uptodate
=
1
;
/* Are we off the end of the file ? */
end_index
=
inode
->
i_size
>>
PAGE_CACHE_SHIFT
;
...
...
@@ -396,7 +398,7 @@ delalloc_convert(
len
=
bh
->
b_size
;
do
{
if
(
!
buffer_uptodate
(
bh
)
&&
!
startio
)
{
if
(
!
(
PageUptodate
(
page
)
||
buffer_uptodate
(
bh
)
)
&&
!
startio
)
{
goto
next_bh
;
}
...
...
@@ -423,48 +425,57 @@ delalloc_convert(
unlock_buffer
(
bh
);
}
}
}
else
if
(
!
buffer_mapped
(
bh
)
&&
(
buffer_uptodate
(
bh
)
||
PageUptodate
(
page
))
&&
(
allocate_space
||
startio
))
{
int
size
;
/* Getting here implies an unmapped buffer was found,
* and we are in a path where we need to write the
* whole page out.
*/
if
(
!
mp
)
{
size
=
probe_unmapped_cluster
(
inode
,
page
,
bh
,
head
);
err
=
map_blocks
(
inode
,
offset
,
size
,
&
map
,
PBF_WRITE
|
PBF_DIRECT
);
if
(
err
)
{
goto
error
;
}
else
if
((
buffer_uptodate
(
bh
)
||
PageUptodate
(
page
))
&&
(
allocate_space
||
startio
))
{
if
(
!
buffer_mapped
(
bh
))
{
int
size
;
/*
* Getting here implies an unmapped buffer
* was found, and we are in a path where we
* need to write the whole page out.
*/
if
(
!
mp
)
{
size
=
probe_unmapped_cluster
(
inode
,
page
,
bh
,
head
);
err
=
map_blocks
(
inode
,
offset
,
size
,
&
map
,
PBF_WRITE
|
PBF_DIRECT
);
if
(
err
)
{
goto
error
;
}
mp
=
match_offset_to_mapping
(
page
,
&
map
,
p_offset
);
}
mp
=
match_offset_to_mapping
(
page
,
&
map
,
p_offset
);
}
if
(
mp
)
{
map_buffer_at_offset
(
page
,
bh
,
p_offset
,
inode
->
i_blkbits
,
mp
);
if
(
startio
)
{
if
(
mp
)
{
map_buffer_at_offset
(
page
,
bh
,
p_offset
,
inode
->
i_blkbits
,
mp
);
if
(
startio
)
{
bh_arr
[
cnt
++
]
=
bh
;
}
else
{
unlock_buffer
(
bh
);
}
}
}
else
if
(
startio
&&
buffer_mapped
(
bh
))
{
if
(
buffer_uptodate
(
bh
)
&&
allocate_space
)
{
lock_buffer
(
bh
);
bh_arr
[
cnt
++
]
=
bh
;
}
else
{
unlock_buffer
(
bh
);
}
}
}
else
if
(
startio
&&
buffer_mapped
(
bh
))
{
if
(
buffer_uptodate
(
bh
)
&&
allocate_space
)
{
lock_buffer
(
bh
);
bh_arr
[
cnt
++
]
=
bh
;
}
}
next_bh:
if
(
!
buffer_uptodate
(
bh
))
uptodate
=
0
;
offset
+=
len
;
p_offset
+=
len
;
bh
=
bh
->
b_this_page
;
}
while
(
offset
<
end_offset
);
if
(
uptodate
)
SetPageUptodate
(
page
);
if
(
startio
)
{
submit_page
(
page
,
bh_arr
,
cnt
);
}
...
...
@@ -509,17 +520,15 @@ linvfs_get_block_core(
ssize_t
size
;
loff_t
offset
=
(
loff_t
)
iblock
<<
inode
->
i_blkbits
;
if
(
blocks
)
{
/* If we are doing writes at the end of the file,
* allocate in chunks
*/
if
(
blocks
)
size
=
blocks
<<
inode
->
i_blkbits
;
}
else
{
/* If we are doing writes at the end of the file,
* allocate in chunks
*/
if
(
create
&&
(
offset
>=
inode
->
i_size
)
&&
!
(
flags
&
PBF_SYNC
))
size
=
1
<<
XFS_WRITE_IO_LOG
;
else
size
=
1
<<
inode
->
i_blkbits
;
}
else
if
(
create
&&
(
offset
>=
inode
->
i_size
))
size
=
1
<<
XFS_WRITE_IO_LOG
;
else
size
=
1
<<
inode
->
i_blkbits
;
VOP_BMAP
(
vp
,
offset
,
size
,
create
?
flags
:
PBF_READ
,
...
...
@@ -534,15 +543,20 @@ linvfs_get_block_core(
page_buf_daddr_t
bn
;
loff_t
delta
;
delta
=
offset
-
pbmap
.
pbm_offset
;
delta
>>=
inode
->
i_blkbits
;
/* For unwritten extents do not report a disk address on
* the read case.
*/
if
(
create
||
((
pbmap
.
pbm_flags
&
PBMF_UNWRITTEN
)
==
0
))
{
delta
=
offset
-
pbmap
.
pbm_offset
;
delta
>>=
inode
->
i_blkbits
;
bn
=
pbmap
.
pbm_bn
>>
(
inode
->
i_blkbits
-
9
);
bn
+=
delta
;
bn
=
pbmap
.
pbm_bn
>>
(
inode
->
i_blkbits
-
9
);
bn
+=
delta
;
bh_result
->
b_blocknr
=
bn
;
bh_result
->
b_bdev
=
pbmap
.
pbm_target
->
pbr_bdev
;
set_buffer_mapped
(
bh_result
);
bh_result
->
b_blocknr
=
bn
;
bh_result
->
b_bdev
=
pbmap
.
pbm_target
->
pbr_bdev
;
set_buffer_mapped
(
bh_result
);
}
}
/* If we previously allocated a block out beyond eof and
...
...
fs/xfs/linux/xfs_iomap.c
View file @
c2e95c3f
...
...
@@ -29,362 +29,13 @@
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
/*
* fs/xfs/linux/xfs_lrw.c (Linux Read Write stuff)
*
*/
#include <xfs.h>
#include <linux/pagemap.h>
#include <linux/capability.h>
#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \
<< mp->m_writeio_log)
#define XFS_STRAT_WRITE_IMAPS 2
STATIC
int
xfs_iomap_read
(
xfs_iocore_t
*
,
loff_t
,
size_t
,
int
,
page_buf_bmap_t
*
,
int
*
);
STATIC
int
xfs_iomap_write
(
xfs_iocore_t
*
,
loff_t
,
size_t
,
page_buf_bmap_t
*
,
int
*
,
int
);
STATIC
int
xfs_iomap_write_delay
(
xfs_iocore_t
*
,
loff_t
,
size_t
,
page_buf_bmap_t
*
,
int
*
,
int
,
int
);
STATIC
int
xfs_iomap_write_direct
(
xfs_iocore_t
*
,
loff_t
,
size_t
,
page_buf_bmap_t
*
,
int
*
,
int
,
int
);
STATIC
int
_xfs_imap_to_bmap
(
xfs_iocore_t
*
,
xfs_off_t
,
xfs_bmbt_irec_t
*
,
page_buf_bmap_t
*
,
int
,
int
);
int
xfs_strategy
(
xfs_inode_t
*
ip
,
xfs_off_t
offset
,
ssize_t
count
,
int
flags
,
page_buf_bmap_t
*
pbmapp
,
int
*
npbmaps
)
{
xfs_iocore_t
*
io
;
xfs_mount_t
*
mp
;
int
error
;
xfs_fileoff_t
offset_fsb
;
xfs_fileoff_t
end_fsb
;
xfs_fileoff_t
map_start_fsb
;
xfs_fileoff_t
last_block
;
xfs_fsblock_t
first_block
;
xfs_bmap_free_t
free_list
;
xfs_filblks_t
count_fsb
;
int
committed
,
i
,
loops
,
nimaps
;
int
is_xfs
;
xfs_bmbt_irec_t
imap
[
XFS_MAX_RW_NBMAPS
];
xfs_trans_t
*
tp
;
mp
=
ip
->
i_mount
;
io
=
&
ip
->
i_iocore
;
is_xfs
=
IO_IS_XFS
(
io
);
ASSERT
((
ip
->
i_d
.
di_mode
&
IFMT
)
==
IFREG
);
ASSERT
(((
ip
->
i_d
.
di_flags
&
XFS_DIFLAG_REALTIME
)
!=
0
)
==
((
io
->
io_flags
&
XFS_IOCORE_RT
)
!=
0
));
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
XFS_ERROR
(
EIO
);
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
nimaps
=
min
(
XFS_MAX_RW_NBMAPS
,
*
npbmaps
);
end_fsb
=
XFS_B_TO_FSB
(
mp
,
((
xfs_ufsize_t
)(
offset
+
count
)));
first_block
=
NULLFSBLOCK
;
XFS_ILOCK
(
mp
,
io
,
XFS_ILOCK_SHARED
|
XFS_EXTSIZE_RD
);
error
=
XFS_BMAPI
(
mp
,
NULL
,
io
,
offset_fsb
,
(
xfs_filblks_t
)(
end_fsb
-
offset_fsb
),
XFS_BMAPI_ENTIRE
,
&
first_block
,
0
,
imap
,
&
nimaps
,
NULL
);
XFS_IUNLOCK
(
mp
,
io
,
XFS_ILOCK_SHARED
|
XFS_EXTSIZE_RD
);
if
(
error
)
{
return
XFS_ERROR
(
error
);
}
if
(
nimaps
&&
!
ISNULLSTARTBLOCK
(
imap
[
0
].
br_startblock
))
{
*
npbmaps
=
_xfs_imap_to_bmap
(
&
ip
->
i_iocore
,
offset
,
imap
,
pbmapp
,
nimaps
,
*
npbmaps
);
return
0
;
}
/*
* Make sure that the dquots are there.
*/
if
(
XFS_IS_QUOTA_ON
(
mp
))
{
if
(
XFS_NOT_DQATTACHED
(
mp
,
ip
))
{
if
((
error
=
xfs_qm_dqattach
(
ip
,
0
)))
{
return
XFS_ERROR
(
error
);
}
}
}
XFS_STATS_ADD
(
xfsstats
.
xs_xstrat_bytes
,
XFS_FSB_TO_B
(
mp
,
imap
[
0
].
br_blockcount
));
offset_fsb
=
imap
[
0
].
br_startoff
;
count_fsb
=
imap
[
0
].
br_blockcount
;
map_start_fsb
=
offset_fsb
;
while
(
count_fsb
!=
0
)
{
/*
* Set up a transaction with which to allocate the
* backing store for the file. Do allocations in a
* loop until we get some space in the range we are
* interested in. The other space that might be allocated
* is in the delayed allocation extent on which we sit
* but before our buffer starts.
*/
nimaps
=
0
;
loops
=
0
;
while
(
nimaps
==
0
)
{
if
(
is_xfs
)
{
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_STRAT_WRITE
);
error
=
xfs_trans_reserve
(
tp
,
0
,
XFS_WRITE_LOG_RES
(
mp
),
0
,
XFS_TRANS_PERM_LOG_RES
,
XFS_WRITE_LOG_COUNT
);
if
(
error
)
{
xfs_trans_cancel
(
tp
,
0
);
goto
error0
;
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ijoin
(
tp
,
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
}
else
{
tp
=
NULL
;
XFS_ILOCK
(
mp
,
io
,
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
);
}
/*
* Allocate the backing store for the file.
*/
XFS_BMAP_INIT
(
&
(
free_list
),
&
(
first_block
));
nimaps
=
XFS_STRAT_WRITE_IMAPS
;
/*
* Ensure we don't go beyond eof - it is possible
* the extents changed since we did the read call,
* we dropped the ilock in the interim.
*/
end_fsb
=
XFS_B_TO_FSB
(
mp
,
XFS_SIZE
(
mp
,
io
));
xfs_bmap_last_offset
(
NULL
,
ip
,
&
last_block
,
XFS_DATA_FORK
);
last_block
=
XFS_FILEOFF_MAX
(
last_block
,
end_fsb
);
if
((
map_start_fsb
+
count_fsb
)
>
last_block
)
{
count_fsb
=
last_block
-
map_start_fsb
;
if
(
count_fsb
==
0
)
{
if
(
is_xfs
)
{
xfs_bmap_cancel
(
&
free_list
);
xfs_trans_cancel
(
tp
,
(
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
));
}
XFS_IUNLOCK
(
mp
,
io
,
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
);
return
XFS_ERROR
(
EAGAIN
);
}
}
error
=
XFS_BMAPI
(
mp
,
tp
,
io
,
map_start_fsb
,
count_fsb
,
XFS_BMAPI_WRITE
,
&
first_block
,
1
,
imap
,
&
nimaps
,
&
free_list
);
if
(
error
)
{
xfs_bmap_cancel
(
&
free_list
);
xfs_trans_cancel
(
tp
,
(
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
));
XFS_IUNLOCK
(
mp
,
io
,
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
);
goto
error0
;
}
if
(
is_xfs
)
{
error
=
xfs_bmap_finish
(
&
(
tp
),
&
(
free_list
),
first_block
,
&
committed
);
if
(
error
)
{
xfs_bmap_cancel
(
&
free_list
);
xfs_trans_cancel
(
tp
,
(
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
));
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
goto
error0
;
}
error
=
xfs_trans_commit
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
,
NULL
);
if
(
error
)
{
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
goto
error0
;
}
}
if
(
nimaps
==
0
)
{
XFS_IUNLOCK
(
mp
,
io
,
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
);
}
/* else hold 'till we maybe loop again below */
}
/*
* See if we were able to allocate an extent that
* covers at least part of the user's requested size.
*/
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
for
(
i
=
0
;
i
<
nimaps
;
i
++
)
{
int
maps
;
if
((
offset_fsb
>=
imap
[
i
].
br_startoff
)
&&
(
offset_fsb
<
(
imap
[
i
].
br_startoff
+
imap
[
i
].
br_blockcount
)))
{
XFS_IUNLOCK
(
mp
,
io
,
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
);
maps
=
min
(
nimaps
,
*
npbmaps
);
*
npbmaps
=
_xfs_imap_to_bmap
(
io
,
offset
,
&
imap
[
i
],
pbmapp
,
maps
,
*
npbmaps
);
XFS_STATS_INC
(
xfsstats
.
xs_xstrat_quick
);
return
0
;
}
count_fsb
-=
imap
[
i
].
br_blockcount
;
/* for next bmapi,
if needed. */
}
/*
* We didn't get an extent the caller can write into so
* loop around and try starting after the last imap we got back.
*/
nimaps
--
;
/* Index of last entry */
ASSERT
(
nimaps
>=
0
);
ASSERT
(
offset_fsb
>=
imap
[
nimaps
].
br_startoff
+
imap
[
nimaps
].
br_blockcount
);
ASSERT
(
count_fsb
);
offset_fsb
=
imap
[
nimaps
].
br_startoff
+
imap
[
nimaps
].
br_blockcount
;
map_start_fsb
=
offset_fsb
;
XFS_STATS_INC
(
xfsstats
.
xs_xstrat_split
);
XFS_IUNLOCK
(
mp
,
io
,
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
);
}
ASSERT
(
0
);
/* Should never get here */
error0:
if
(
error
)
{
ASSERT
(
count_fsb
!=
0
);
ASSERT
(
is_xfs
||
XFS_FORCED_SHUTDOWN
(
mp
));
}
return
XFS_ERROR
(
error
);
}
/*
* xfs_bmap() is the same as the irix xfs_bmap from xfs_rw.c
* execpt for slight changes to the params
*/
int
xfs_bmap
(
bhv_desc_t
*
bdp
,
xfs_off_t
offset
,
ssize_t
count
,
int
flags
,
page_buf_bmap_t
*
pbmapp
,
int
*
npbmaps
)
{
xfs_inode_t
*
ip
;
int
error
;
int
lockmode
;
int
fsynced
=
0
;
vnode_t
*
vp
;
ip
=
XFS_BHVTOI
(
bdp
);
ASSERT
((
ip
->
i_d
.
di_mode
&
IFMT
)
==
IFREG
);
ASSERT
(((
ip
->
i_d
.
di_flags
&
XFS_DIFLAG_REALTIME
)
!=
0
)
==
((
ip
->
i_iocore
.
io_flags
&
XFS_IOCORE_RT
)
!=
0
));
if
(
XFS_FORCED_SHUTDOWN
(
ip
->
i_iocore
.
io_mount
))
return
XFS_ERROR
(
EIO
);
if
(
flags
&
PBF_READ
)
{
lockmode
=
xfs_ilock_map_shared
(
ip
);
error
=
xfs_iomap_read
(
&
ip
->
i_iocore
,
offset
,
count
,
XFS_BMAPI_ENTIRE
,
pbmapp
,
npbmaps
);
xfs_iunlock_map_shared
(
ip
,
lockmode
);
}
else
if
(
flags
&
PBF_FILE_ALLOCATE
)
{
error
=
xfs_strategy
(
ip
,
offset
,
count
,
flags
,
pbmapp
,
npbmaps
);
}
else
{
/* PBF_WRITE */
ASSERT
(
flags
&
PBF_WRITE
);
vp
=
BHV_TO_VNODE
(
bdp
);
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
/*
* Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read.
*/
if
(
XFS_IS_QUOTA_ON
(
ip
->
i_mount
))
{
if
(
XFS_NOT_DQATTACHED
(
ip
->
i_mount
,
ip
))
{
if
((
error
=
xfs_qm_dqattach
(
ip
,
XFS_QMOPT_ILOCKED
)))
{
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
return
XFS_ERROR
(
error
);
}
}
}
retry:
error
=
xfs_iomap_write
(
&
ip
->
i_iocore
,
offset
,
count
,
pbmapp
,
npbmaps
,
flags
);
/* xfs_iomap_write unlocks/locks/unlocks */
if
(
error
==
ENOSPC
)
{
switch
(
fsynced
)
{
case
0
:
if
(
ip
->
i_delayed_blks
)
{
filemap_fdatawrite
(
LINVFS_GET_IP
(
vp
)
->
i_mapping
);
fsynced
=
1
;
}
else
{
fsynced
=
2
;
flags
|=
PBF_SYNC
;
}
error
=
0
;
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
goto
retry
;
case
1
:
fsynced
=
2
;
if
(
!
(
flags
&
PBF_SYNC
))
{
flags
|=
PBF_SYNC
;
error
=
0
;
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
goto
retry
;
}
case
2
:
sync_blockdev
(
vp
->
v_vfsp
->
vfs_super
->
s_bdev
);
xfs_log_force
(
ip
->
i_mount
,
(
xfs_lsn_t
)
0
,
XFS_LOG_FORCE
|
XFS_LOG_SYNC
);
error
=
0
;
/**
delay(HZ);
**/
fsynced
++
;
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
goto
retry
;
}
}
}
return
XFS_ERROR
(
error
);
}
#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP
STATIC
int
_xfs_imap_to_bmap
(
...
...
@@ -397,7 +48,7 @@ _xfs_imap_to_bmap(
{
xfs_mount_t
*
mp
;
xfs_fsize_t
nisize
;
int
im
,
pbm
;
int
pbm
;
xfs_fsblock_t
start_block
;
mp
=
io
->
io_mount
;
...
...
@@ -405,7 +56,7 @@ _xfs_imap_to_bmap(
if
(
io
->
io_new_size
>
nisize
)
nisize
=
io
->
io_new_size
;
for
(
im
=
pbm
=
0
;
im
<
imaps
&&
pbm
<
pbmaps
;
im
++
,
pbmapp
++
,
imap
++
,
pbm
++
)
{
for
(
pbm
=
0
;
imaps
&&
pbm
<
pbmaps
;
imaps
--
,
pbmapp
++
,
imap
++
,
pbm
++
)
{
pbmapp
->
pbm_target
=
io
->
io_flags
&
XFS_IOCORE_RT
?
mp
->
m_rtdev_targp
:
mp
->
m_ddev_targp
;
pbmapp
->
pbm_offset
=
XFS_FSB_TO_B
(
mp
,
imap
->
br_startoff
);
...
...
@@ -422,9 +73,8 @@ _xfs_imap_to_bmap(
pbmapp
->
pbm_flags
=
PBMF_DELAY
;
}
else
{
pbmapp
->
pbm_bn
=
XFS_FSB_TO_DB_IO
(
io
,
start_block
);
if
(
ISUNWRITTEN
(
imap
))
{
if
(
ISUNWRITTEN
(
imap
))
pbmapp
->
pbm_flags
|=
PBMF_UNWRITTEN
;
}
}
if
((
pbmapp
->
pbm_offset
+
pbmapp
->
pbm_bsize
)
>=
nisize
)
{
...
...
@@ -436,149 +86,344 @@ _xfs_imap_to_bmap(
return
pbm
;
/* Return the number filled */
}
STATIC
int
xfs_iomap
_read
(
int
xfs_iomap
(
xfs_iocore_t
*
io
,
loff_t
offset
,
size_t
count
,
xfs_off_t
offset
,
s
s
ize_t
count
,
int
flags
,
page_buf_bmap_t
*
pbmapp
,
int
*
npbmaps
)
{
xfs_fileoff_t
offset_fsb
;
xfs_fileoff_t
end_fsb
;
int
nimaps
;
xfs_mount_t
*
mp
=
io
->
io_mount
;
xfs_fileoff_t
offset_fsb
,
end_fsb
;
int
error
;
xfs_mount_t
*
mp
;
xfs_bmbt_irec_t
imap
[
XFS_MAX_RW_NBMAPS
];
int
lockmode
=
0
;
xfs_bmbt_irec_t
imap
;
int
nimaps
=
1
;
int
bmap_flags
=
0
;
ASSERT
(
ismrlocked
(
io
->
io_lock
,
MR_UPDATE
|
MR_ACCESS
)
!=
0
);
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
XFS_ERROR
(
EIO
);
switch
(
flags
&
(
PBF_READ
|
PBF_WRITE
|
PBF_FILE_ALLOCATE
|
PBF_FILE_UNWRITTEN
))
{
case
PBF_READ
:
lockmode
=
XFS_LCK_MAP_SHARED
(
mp
,
io
);
bmap_flags
=
XFS_BMAPI_ENTIRE
;
break
;
case
PBF_WRITE
:
lockmode
=
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
;
bmap_flags
=
0
;
XFS_ILOCK
(
mp
,
io
,
lockmode
);
break
;
case
PBF_FILE_ALLOCATE
:
lockmode
=
XFS_ILOCK_SHARED
|
XFS_EXTSIZE_RD
;
bmap_flags
=
XFS_BMAPI_ENTIRE
;
XFS_ILOCK
(
mp
,
io
,
lockmode
);
break
;
case
PBF_FILE_UNWRITTEN
:
lockmode
=
XFS_ILOCK_EXCL
|
XFS_EXTSIZE_WR
;
bmap_flags
=
XFS_BMAPI_ENTIRE
|
XFS_BMAPI_IGSTATE
;
XFS_ILOCK
(
mp
,
io
,
lockmode
);
break
;
default:
BUG
();
}
mp
=
io
->
io_mount
;
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
nimaps
=
sizeof
(
imap
)
/
sizeof
(
imap
[
0
]);
nimaps
=
min
(
nimaps
,
*
npbmaps
);
/* Don't ask for more than caller has */
end_fsb
=
XFS_B_TO_FSB
(
mp
,
((
xfs_ufsize_t
)(
offset
+
count
)));
error
=
XFS_BMAPI
(
mp
,
NULL
,
io
,
offset_fsb
,
(
xfs_filblks_t
)(
end_fsb
-
offset_fsb
),
flags
,
NULL
,
0
,
imap
,
&
nimaps
,
NULL
);
if
(
error
)
{
return
XFS_ERROR
(
error
);
(
xfs_filblks_t
)(
end_fsb
-
offset_fsb
)
,
bmap_flags
,
NULL
,
0
,
&
imap
,
&
nimaps
,
NULL
);
if
(
error
)
goto
out
;
switch
(
flags
&
(
PBF_WRITE
|
PBF_FILE_ALLOCATE
))
{
case
PBF_WRITE
:
/* If we found an extent, return it */
if
(
nimaps
&&
(
imap
.
br_startblock
!=
HOLESTARTBLOCK
))
break
;
if
(
flags
&
PBF_DIRECT
)
{
error
=
XFS_IOMAP_WRITE_DIRECT
(
mp
,
io
,
offset
,
count
,
flags
,
&
imap
,
&
nimaps
,
nimaps
);
}
else
{
error
=
XFS_IOMAP_WRITE_DELAY
(
mp
,
io
,
offset
,
count
,
flags
,
&
imap
,
&
nimaps
);
}
break
;
case
PBF_FILE_ALLOCATE
:
/* If we found an extent, return it */
XFS_IUNLOCK
(
mp
,
io
,
lockmode
);
lockmode
=
0
;
if
(
nimaps
&&
!
ISNULLSTARTBLOCK
(
imap
.
br_startblock
))
break
;
error
=
XFS_IOMAP_WRITE_ALLOCATE
(
mp
,
io
,
&
imap
,
&
nimaps
);
break
;
}
if
(
nimaps
)
{
*
npbmaps
=
_xfs_imap_to_bmap
(
io
,
offset
,
imap
,
pbmapp
,
nimaps
,
*
npbmaps
);
}
else
if
(
nimaps
)
{
*
npbmaps
=
_xfs_imap_to_bmap
(
io
,
offset
,
&
imap
,
pbmapp
,
nimaps
,
*
npbmaps
);
}
else
{
*
npbmaps
=
0
;
}
out:
if
(
lockmode
)
XFS_IUNLOCK
(
mp
,
io
,
lockmode
);
return
XFS_ERROR
(
error
);
}
/*
* xfs_iomap_write: return pagebuf_bmap_t's telling higher layers
* where to write.
* There are 2 main cases:
* 1 the extents already exist
* 2 must allocate.
* There are 3 cases when we allocate:
* delay allocation (doesn't really allocate or use transactions)
* direct allocation (no previous delay allocation)
* convert delay to real allocations
*/
STATIC
int
xfs_iomap_write
(
xfs_iocore_t
*
io
,
xfs_flush_space
(
xfs_inode_t
*
ip
,
int
*
fsynced
,
int
*
ioflags
)
{
vnode_t
*
vp
=
XFS_ITOV
(
ip
);
switch
(
*
fsynced
)
{
case
0
:
if
(
ip
->
i_delayed_blks
)
{
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
filemap_fdatawrite
(
LINVFS_GET_IP
(
vp
)
->
i_mapping
);
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
*
fsynced
=
1
;
}
else
{
*
ioflags
|=
PBF_SYNC
;
*
fsynced
=
2
;
}
return
0
;
case
1
:
*
fsynced
=
2
;
*
ioflags
|=
PBF_SYNC
;
return
0
;
case
2
:
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
sync_blockdev
(
vp
->
v_vfsp
->
vfs_super
->
s_bdev
);
xfs_log_force
(
ip
->
i_mount
,
(
xfs_lsn_t
)
0
,
XFS_LOG_FORCE
|
XFS_LOG_SYNC
);
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
*
fsynced
=
3
;
return
0
;
}
return
1
;
}
int
xfs_iomap_write_direct
(
xfs_inode_t
*
ip
,
loff_t
offset
,
size_t
count
,
page_buf_bmap_t
*
pbmapp
,
int
*
npbmaps
,
int
ioflag
)
int
ioflag
,
xfs_bmbt_irec_t
*
ret_imap
,
int
*
nmaps
,
int
found
)
{
int
maps
;
int
error
=
0
;
int
found
;
int
flags
=
0
;
xfs_mount_t
*
mp
=
ip
->
i_mount
;
xfs_iocore_t
*
io
=
&
ip
->
i_iocore
;
xfs_fileoff_t
offset_fsb
;
xfs_fileoff_t
last_fsb
;
xfs_filblks_t
count_fsb
;
xfs_fsize_t
isize
;
xfs_fsblock_t
firstfsb
;
int
nimaps
,
maps
;
int
error
;
int
bmapi_flag
;
int
rt
;
xfs_trans_t
*
tp
;
xfs_bmbt_irec_t
imap
[
XFS_WRITE_IMAPS
],
*
imapp
;
xfs_bmap_free_t
free_list
;
int
aeof
;
xfs_filblks_t
datablocks
;
int
committed
;
int
numrtextents
;
uint
resblks
;
maps
=
*
npbmaps
;
if
(
!
maps
)
goto
out
;
/*
* Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read.
*/
if
(
XFS_IS_QUOTA_ON
(
mp
)
&&
XFS_NOT_DQATTACHED
(
mp
,
ip
))
{
if
((
error
=
xfs_qm_dqattach
(
ip
,
XFS_QMOPT_ILOCKED
)))
{
return
XFS_ERROR
(
error
);
}
}
maps
=
min
(
XFS_WRITE_IMAPS
,
*
nmaps
);
nimaps
=
maps
;
isize
=
ip
->
i_d
.
di_size
;
aeof
=
(
offset
+
count
)
>
isize
;
if
(
io
->
io_new_size
>
isize
)
isize
=
io
->
io_new_size
;
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
last_fsb
=
XFS_B_TO_FSB
(
mp
,
((
xfs_ufsize_t
)(
offset
+
count
)));
count_fsb
=
last_fsb
-
offset_fsb
;
if
(
found
&&
(
ret_imap
->
br_startblock
==
HOLESTARTBLOCK
))
{
xfs_fileoff_t
map_last_fsb
;
map_last_fsb
=
ret_imap
->
br_blockcount
+
ret_imap
->
br_startoff
;
if
(
map_last_fsb
<
last_fsb
)
{
last_fsb
=
map_last_fsb
;
count_fsb
=
last_fsb
-
offset_fsb
;
}
ASSERT
(
count_fsb
>
0
);
}
/*
* determine if reserving space on
* the data or realtime partition.
*/
if
((
rt
=
ip
->
i_d
.
di_flags
&
XFS_DIFLAG_REALTIME
))
{
int
sbrtextsize
,
iprtextsize
;
sbrtextsize
=
mp
->
m_sb
.
sb_rextsize
;
iprtextsize
=
ip
->
i_d
.
di_extsize
?
ip
->
i_d
.
di_extsize
:
sbrtextsize
;
numrtextents
=
(
count_fsb
+
iprtextsize
-
1
);
do_div
(
numrtextents
,
sbrtextsize
);
datablocks
=
0
;
}
else
{
datablocks
=
count_fsb
;
numrtextents
=
0
;
}
/*
* allocate and setup the transaction
*/
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_DIOSTRAT
);
resblks
=
XFS_DIOSTRAT_SPACE_RES
(
mp
,
datablocks
);
error
=
xfs_trans_reserve
(
tp
,
resblks
,
XFS_WRITE_LOG_RES
(
mp
),
numrtextents
,
XFS_TRANS_PERM_LOG_RES
,
XFS_WRITE_LOG_COUNT
);
/*
* If we have extents that are allocated for this range,
* return them.
* check for running out of space
*/
if
(
error
)
/*
* Free the transaction structure.
*/
xfs_trans_cancel
(
tp
,
0
);
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
found
=
0
;
error
=
xfs_iomap_read
(
io
,
offset
,
count
,
flags
,
pbmapp
,
npbmaps
);
if
(
error
)
goto
out
;
goto
error_out
;
/* Don't return in above if .. trans ..,
need lock to return */
if
(
XFS_IS_QUOTA_ON
(
mp
))
{
if
(
xfs_trans_reserve_blkquota
(
tp
,
ip
,
resblks
))
{
error
=
(
EDQUOT
);
goto
error1
;
}
}
nimaps
=
1
;
bmapi_flag
=
XFS_BMAPI_WRITE
;
xfs_trans_ijoin
(
tp
,
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
if
(
offset
<
ip
->
i_d
.
di_size
||
rt
)
bmapi_flag
|=
XFS_BMAPI_PREALLOC
;
/*
* issue the bmapi() call to allocate the blocks
*/
XFS_BMAP_INIT
(
&
free_list
,
&
firstfsb
);
imapp
=
&
imap
[
0
];
error
=
xfs_bmapi
(
tp
,
ip
,
offset_fsb
,
count_fsb
,
bmapi_flag
,
&
firstfsb
,
0
,
imapp
,
&
nimaps
,
&
free_list
);
if
(
error
)
{
goto
error0
;
}
/*
* If we found mappings and they can just have data written
* without conversion,
* let the caller write these and call us again.
*
* If we have a HOLE or UNWRITTEN, proceed down lower to
* get the space or to convert to written.
* complete the transaction
*/
if
(
*
npbmaps
)
{
if
(
!
(
pbmapp
->
pbm_flags
&
PBMF_HOLE
))
{
*
npbmaps
=
1
;
/* Only checked the first one. */
/* We could check more, ... */
goto
out
;
}
error
=
xfs_bmap_finish
(
&
tp
,
&
free_list
,
firstfsb
,
&
committed
);
if
(
error
)
{
goto
error0
;
}
found
=
*
npbmaps
;
*
npbmaps
=
maps
;
/* Restore to original requested */
if
(
ioflag
&
PBF_DIRECT
)
{
error
=
xfs_iomap_write_direct
(
io
,
offset
,
count
,
pbmapp
,
npbmaps
,
ioflag
,
found
);
}
else
{
error
=
xfs_iomap_write_delay
(
io
,
offset
,
count
,
pbmapp
,
npbmaps
,
ioflag
,
found
);
error
=
xfs_trans_commit
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
,
NULL
);
if
(
error
)
{
goto
error_out
;
}
out:
XFS_IUNLOCK
(
io
->
io_mount
,
io
,
XFS_ILOCK_EXCL
);
/* copy any maps to caller's array and return any error. */
if
(
nimaps
==
0
)
{
error
=
(
ENOSPC
);
goto
error_out
;
}
*
ret_imap
=
imap
[
0
];
*
nmaps
=
1
;
return
0
;
error0:
/* Cancel bmap, unlock inode, and cancel trans */
xfs_bmap_cancel
(
&
free_list
);
error1:
/* Just cancel transaction */
xfs_trans_cancel
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
);
*
nmaps
=
0
;
/* nothing set-up here */
error_out:
return
XFS_ERROR
(
error
);
}
STATIC
int
int
xfs_iomap_write_delay
(
xfs_i
ocore_t
*
io
,
xfs_i
node_t
*
ip
,
loff_t
offset
,
size_t
count
,
page_buf_bmap_t
*
pbmapp
,
int
*
npbmaps
,
int
ioflag
,
int
found
)
xfs_bmbt_irec_t
*
ret_imap
,
int
*
nmaps
)
{
xfs_mount_t
*
mp
=
ip
->
i_mount
;
xfs_iocore_t
*
io
=
&
ip
->
i_iocore
;
xfs_fileoff_t
offset_fsb
;
xfs_fileoff_t
ioalign
;
xfs_fileoff_t
last_fsb
;
xfs_fileoff_t
start_fsb
;
xfs_filblks_t
count_fsb
;
xfs_off_t
aligned_offset
;
xfs_fsize_t
isize
;
xfs_fsblock_t
firstblock
;
int
nimaps
;
int
error
;
int
n
;
unsigned
int
iosize
;
xfs_mount_t
*
mp
;
#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP
xfs_bmbt_irec_t
imap
[
XFS_WRITE_IMAPS
];
int
aeof
;
int
fsynced
=
0
;
ASSERT
(
ismrlocked
(
io
->
io
_lock
,
MR_UPDATE
)
!=
0
);
ASSERT
(
ismrlocked
(
&
ip
->
i
_lock
,
MR_UPDATE
)
!=
0
);
mp
=
io
->
io_mount
;
/*
* Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read.
*/
if
(
XFS_IS_QUOTA_ON
(
mp
)
&&
XFS_NOT_DQATTACHED
(
mp
,
ip
))
{
if
((
error
=
xfs_qm_dqattach
(
ip
,
XFS_QMOPT_ILOCKED
)))
{
return
XFS_ERROR
(
error
);
}
}
isize
=
XFS_SIZE
(
mp
,
io
);
retry:
isize
=
ip
->
i_d
.
di_size
;
if
(
io
->
io_new_size
>
isize
)
{
isize
=
io
->
io_new_size
;
}
...
...
@@ -591,50 +436,22 @@ xfs_iomap_write_delay(
* then extend the allocation (and the buffer used for the write)
* out to the file system's write iosize. We clean up any extra
* space left over when the file is closed in xfs_inactive().
* We can only do this if we are sure that we will create buffers
* over all of the space we allocate beyond the end of the file.
* Not doing so would allow us to create delalloc blocks with
* no pages in memory covering them. So, we need to check that
* there are not any real blocks in the area beyond the end of
* the file which we are optimistically going to preallocate. If
* there are then our buffers will stop when they encounter them
* and we may accidentally create delalloc blocks beyond them
* that we never cover with a buffer. All of this is because
* we are not actually going to write the extra blocks preallocated
* at this point.
*
* We don't bother with this for sync writes, because we need
* to minimize the amount we write for good performance.
*/
if
(
!
(
ioflag
&
PBF_SYNC
)
&&
((
offset
+
count
)
>
XFS_SIZE
(
mp
,
io
)))
{
start_fsb
=
XFS_B_TO_FSBT
(
mp
,
((
xfs_ufsize_t
)(
offset
+
count
-
1
)));
count_fsb
=
mp
->
m_writeio_blocks
;
while
(
count_fsb
>
0
)
{
nimaps
=
XFS_WRITE_IMAPS
;
error
=
XFS_BMAPI
(
mp
,
NULL
,
io
,
start_fsb
,
count_fsb
,
0
,
NULL
,
0
,
imap
,
&
nimaps
,
NULL
);
if
(
error
)
{
return
error
;
}
for
(
n
=
0
;
n
<
nimaps
;
n
++
)
{
if
((
imap
[
n
].
br_startblock
!=
HOLESTARTBLOCK
)
&&
(
imap
[
n
].
br_startblock
!=
DELAYSTARTBLOCK
))
{
goto
write_map
;
}
start_fsb
+=
imap
[
n
].
br_blockcount
;
count_fsb
-=
imap
[
n
].
br_blockcount
;
ASSERT
(
count_fsb
<
0xffff000
);
}
}
if
(
!
(
ioflag
&
PBF_SYNC
)
&&
((
offset
+
count
)
>
ip
->
i_d
.
di_size
))
{
xfs_off_t
aligned_offset
;
unsigned
int
iosize
;
xfs_fileoff_t
ioalign
;
iosize
=
mp
->
m_writeio_blocks
;
aligned_offset
=
XFS_WRITEIO_ALIGN
(
mp
,
(
offset
+
count
-
1
));
ioalign
=
XFS_B_TO_FSBT
(
mp
,
aligned_offset
);
last_fsb
=
ioalign
+
iosize
;
aeof
=
1
;
}
write_map:
nimaps
=
XFS_WRITE_IMAPS
;
firstblock
=
NULLFSBLOCK
;
...
...
@@ -642,11 +459,11 @@ xfs_iomap_write_delay(
* roundup the allocation request to m_dalign boundary if file size
* is greater that 512K and we are allocating past the allocation eof
*/
if
(
mp
->
m_dalign
&&
(
XFS_SIZE
(
mp
,
io
)
>=
mp
->
m_dalign
)
&&
aeof
)
{
if
(
mp
->
m_dalign
&&
(
isize
>=
mp
->
m_dalign
)
&&
aeof
)
{
int
eof
;
xfs_fileoff_t
new_last_fsb
;
new_last_fsb
=
roundup_64
(
last_fsb
,
mp
->
m_dalign
);
error
=
XFS_BMAP_EOF
(
mp
,
io
,
new_last_fsb
,
XFS_DATA_FORK
,
&
eof
);
error
=
xfs_bmap_eof
(
ip
,
new_last_fsb
,
XFS_DATA_FORK
,
&
eof
);
if
(
error
)
{
return
error
;
}
...
...
@@ -655,7 +472,7 @@ xfs_iomap_write_delay(
}
}
error
=
XFS_BMAPI
(
mp
,
NULL
,
io
,
offset_fsb
,
error
=
xfs_bmapi
(
NULL
,
ip
,
offset_fsb
,
(
xfs_filblks_t
)(
last_fsb
-
offset_fsb
),
XFS_BMAPI_DELAY
|
XFS_BMAPI_WRITE
|
XFS_BMAPI_ENTIRE
,
&
firstblock
,
1
,
imap
,
...
...
@@ -663,235 +480,255 @@ xfs_iomap_write_delay(
/*
* This can be EDQUOT, if nimaps == 0
*/
if
(
error
)
{
if
(
error
&&
(
error
!=
ENOSPC
)
)
{
return
XFS_ERROR
(
error
);
}
/*
* If bmapi returned us nothing, and if we didn't get back EDQUOT,
* then we must have run out of space.
*/
if
(
nimaps
==
0
)
{
return
XFS_ERROR
(
ENOSPC
);
if
(
xfs_flush_space
(
ip
,
&
fsynced
,
&
ioflag
))
return
XFS_ERROR
(
ENOSPC
);
error
=
0
;
goto
retry
;
}
/*
* Now map our desired I/O size and alignment over the
* extents returned by xfs_bmapi().
*/
*
npbmaps
=
_xfs_imap_to_bmap
(
io
,
offset
,
imap
,
pbmapp
,
nimaps
,
*
npbmaps
);
*
ret_imap
=
imap
[
0
];
*
nmaps
=
1
;
return
0
;
}
STATIC
int
xfs_iomap_write_direct
(
xfs_iocore_t
*
io
,
loff_t
offset
,
size_t
count
,
page_buf_bmap_t
*
pbmapp
,
int
*
npbmaps
,
int
ioflag
,
int
found
)
/*
* Pass in a delayed allocate extent, convert it to real extents;
* return to the caller the extent we create which maps on top of
* the originating callers request.
*
* Called without a lock on the inode.
*/
int
xfs_iomap_write_allocate
(
xfs_inode_t
*
ip
,
xfs_bmbt_irec_t
*
map
,
int
*
retmap
)
{
xfs_inode_t
*
ip
=
XFS_IO_INODE
(
io
);
xfs_mount_t
*
mp
;
xfs_fileoff_t
offset_fsb
;
xfs_fileoff_t
last_fsb
;
xfs_mount_t
*
mp
=
ip
->
i_mount
;
xfs_fileoff_t
offset_fsb
,
last_block
;
xfs_fileoff_t
end_fsb
,
map_start_fsb
;
xfs_fsblock_t
first_block
;
xfs_bmap_free_t
free_list
;
xfs_filblks_t
count_fsb
;
xfs_fsize_t
isize
;
xfs_fsblock_t
firstfsb
;
int
nimaps
,
maps
;
int
error
;
xfs_bmbt_irec_t
imap
[
XFS_STRAT_WRITE_IMAPS
];
xfs_trans_t
*
tp
;
int
i
,
nimaps
,
committed
;
int
error
=
0
;
#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP
xfs_bmbt_irec_t
imap
[
XFS_WRITE_IMAPS
],
*
imapp
;
xfs_bmap_free_t
free_list
;
int
aeof
;
int
bmapi_flags
;
xfs_filblks_t
datablocks
;
int
rt
;
int
committed
;
int
numrtextents
;
uint
resblks
;
int
rtextsize
;
*
retmap
=
0
;
maps
=
min
(
XFS_WRITE_IMAPS
,
*
npbmaps
);
nimaps
=
maps
;
/*
* Make sure that the dquots are there.
*/
mp
=
io
->
io_mount
;
isize
=
XFS_SIZE
(
mp
,
io
);
if
(
io
->
io_new_size
>
isize
)
isize
=
io
->
io_new_size
;
if
(
XFS_IS_QUOTA_ON
(
mp
)
&&
XFS_NOT_DQATTACHED
(
mp
,
ip
))
{
if
((
error
=
xfs_qm_dqattach
(
ip
,
0
)))
{
return
XFS_ERROR
(
error
);
}
}
aeof
=
((
offset
+
count
)
>
isize
)
?
1
:
0
;
offset_fsb
=
map
->
br_startoff
;
count_fsb
=
map
->
br_blockcount
;
map_start_fsb
=
offset_fsb
;
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
last_fsb
=
XFS_B_TO_FSB
(
mp
,
((
xfs_ufsize_t
)(
offset
+
count
)));
count_fsb
=
last_fsb
-
offset_fsb
;
if
(
found
&&
(
pbmapp
->
pbm_flags
&
PBMF_HOLE
))
{
xfs_fileoff_t
map_last_fsb
;
XFS_STATS_ADD
(
xfsstats
.
xs_xstrat_bytes
,
XFS_FSB_TO_B
(
mp
,
count_fsb
));
map_last_fsb
=
XFS_B_TO_FSB
(
mp
,
(
pbmapp
->
pbm_bsize
+
pbmapp
->
pbm_offset
));
while
(
count_fsb
!=
0
)
{
/*
* Set up a transaction with which to allocate the
* backing store for the file. Do allocations in a
* loop until we get some space in the range we are
* interested in. The other space that might be allocated
* is in the delayed allocation extent on which we sit
* but before our buffer starts.
*/
if
(
map_last_fsb
<
last_fsb
)
{
last_fsb
=
map_last_fsb
;
count_fsb
=
last_fsb
-
offset_fsb
;
}
ASSERT
(
count_fsb
>
0
);
}
nimaps
=
0
;
while
(
nimaps
==
0
)
{
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_STRAT_WRITE
);
error
=
xfs_trans_reserve
(
tp
,
0
,
XFS_WRITE_LOG_RES
(
mp
),
0
,
XFS_TRANS_PERM_LOG_RES
,
XFS_WRITE_LOG_COUNT
);
if
(
error
)
{
xfs_trans_cancel
(
tp
,
0
);
return
XFS_ERROR
(
error
);
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ijoin
(
tp
,
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
/*
* roundup the allocation request to m_dalign boundary if file size
* is greater that 512K and we are allocating past the allocation eof
*/
if
(
!
found
&&
mp
->
m_dalign
&&
(
isize
>=
524288
)
&&
aeof
)
{
int
eof
;
xfs_fileoff_t
new_last_fsb
;
XFS_BMAP_INIT
(
&
free_list
,
&
first_block
);
new_last_fsb
=
roundup_64
(
last_fsb
,
mp
->
m_dalign
);
printk
(
"xfs_iomap_write_direct: about to XFS_BMAP_EOF %Ld
\n
"
,
new_last_fsb
);
error
=
XFS_BMAP_EOF
(
mp
,
io
,
new_last_fsb
,
XFS_DATA_FORK
,
&
eof
);
if
(
error
)
goto
error_out
;
if
(
eof
)
last_fsb
=
new_last_fsb
;
}
nimaps
=
XFS_STRAT_WRITE_IMAPS
;
/*
* Ensure we don't go beyond eof - it is possible
* the extents changed since we did the read call,
* we dropped the ilock in the interim.
*/
bmapi_flags
=
XFS_BMAPI_WRITE
|
XFS_BMAPI_DIRECT_IO
|
XFS_BMAPI_ENTIRE
;
bmapi_flags
&=
~
XFS_BMAPI_DIRECT_IO
;
end_fsb
=
XFS_B_TO_FSB
(
mp
,
ip
->
i_d
.
di_size
);
xfs_bmap_last_offset
(
NULL
,
ip
,
&
last_block
,
XFS_DATA_FORK
);
last_block
=
XFS_FILEOFF_MAX
(
last_block
,
end_fsb
);
if
((
map_start_fsb
+
count_fsb
)
>
last_block
)
{
count_fsb
=
last_block
-
map_start_fsb
;
if
(
count_fsb
==
0
)
{
error
=
EAGAIN
;
goto
trans_cancel
;
}
}
/*
* determine if this is a realtime file
*/
if
((
rt
=
(
ip
->
i_d
.
di_flags
&
XFS_DIFLAG_REALTIME
))
!=
0
)
{
rtextsize
=
mp
->
m_sb
.
sb_rextsize
;
}
else
rtextsize
=
0
;
/* Go get the actual blocks */
error
=
xfs_bmapi
(
tp
,
ip
,
map_start_fsb
,
count_fsb
,
XFS_BMAPI_WRITE
,
&
first_block
,
1
,
imap
,
&
nimaps
,
&
free_list
);
error
=
0
;
if
(
error
)
goto
trans_cancel
;
/*
* allocate file space for the bmapp entries passed in.
*/
error
=
xfs_bmap_finish
(
&
tp
,
&
free_list
,
first_block
,
&
committed
);
/*
* determine if reserving space on
* the data or realtime partition.
*/
if
(
rt
)
{
numrtextents
=
(
count_fsb
+
rtextsize
-
1
);
do_div
(
numrtextents
,
rtextsize
);
datablocks
=
0
;
}
else
{
datablocks
=
count_fsb
;
numrtextents
=
0
;
}
if
(
error
)
goto
trans_cancel
;
/*
* allocate and setup the transaction
*/
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_DIOSTRAT
);
resblks
=
XFS_DIOSTRAT_SPACE_RES
(
mp
,
datablocks
);
error
=
xfs_trans_commit
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
,
NULL
);
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
if
(
error
)
goto
error0
;
error
=
xfs_trans_reserve
(
tp
,
resblks
,
XFS_WRITE_LOG_RES
(
mp
),
numrtextents
,
XFS_TRANS_PERM_LOG_RES
,
XFS_WRITE_LOG_COUNT
);
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
}
/*
* check for running out of space
*/
if
(
error
)
{
/*
* Free the transaction structure.
* See if we were able to allocate an extent that
* covers at least part of the callers request
*/
xfs_trans_cancel
(
tp
,
0
);
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
for
(
i
=
0
;
i
<
nimaps
;
i
++
)
{
if
((
map
->
br_startoff
>=
imap
[
i
].
br_startoff
)
&&
(
map
->
br_startoff
<
(
imap
[
i
].
br_startoff
+
imap
[
i
].
br_blockcount
)))
{
*
map
=
imap
[
i
];
*
retmap
=
1
;
XFS_STATS_INC
(
xfsstats
.
xs_xstrat_quick
);
return
0
;
}
count_fsb
-=
imap
[
i
].
br_blockcount
;
}
if
(
error
)
{
goto
error_out
;
/* Don't return in above if .. trans ..,
need lock to return */
/* So far we have not mapped the requested part of the
* file, just surrounding data, try again.
*/
nimaps
--
;
offset_fsb
=
imap
[
nimaps
].
br_startoff
+
imap
[
nimaps
].
br_blockcount
;
map_start_fsb
=
offset_fsb
;
}
if
(
XFS_IS_QUOTA_ON
(
mp
))
{
if
(
xfs_trans_reserve_quota
(
tp
,
ip
->
i_udquot
,
ip
->
i_gdquot
,
resblks
,
0
,
0
))
{
error
=
(
EDQUOT
);
goto
error1
;
}
nimaps
=
1
;
}
else
{
nimaps
=
2
;
}
trans_cancel:
xfs_bmap_cancel
(
&
free_list
);
xfs_trans_cancel
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
);
error0:
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
return
XFS_ERROR
(
error
);
}
xfs_trans_ijoin
(
tp
,
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
int
xfs_iomap_write_unwritten
(
xfs_inode_t
*
ip
,
loff_t
offset
,
size_t
count
)
{
xfs_mount_t
*
mp
=
ip
->
i_mount
;
xfs_trans_t
*
tp
;
xfs_fileoff_t
offset_fsb
;
xfs_filblks_t
count_fsb
;
xfs_filblks_t
numblks_fsb
;
xfs_bmbt_irec_t
imap
;
int
committed
;
int
error
;
int
nres
;
int
nimaps
;
xfs_fsblock_t
firstfsb
;
xfs_bmap_free_t
free_list
;
/*
* issue the bmapi() call to allocate the blocks
*/
XFS_BMAP_INIT
(
&
free_list
,
&
firstfsb
);
imapp
=
&
imap
[
0
];
error
=
XFS_BMAPI
(
mp
,
tp
,
io
,
offset_fsb
,
count_fsb
,
bmapi_flags
,
&
firstfsb
,
1
,
imapp
,
&
nimaps
,
&
free_list
);
if
(
error
)
{
goto
error0
;
}
offset_fsb
=
XFS_B_TO_FSBT
(
mp
,
offset
);
count_fsb
=
XFS_B_TO_FSB
(
mp
,
count
);
/*
* complete the transaction
*/
do
{
nres
=
XFS_DIOSTRAT_SPACE_RES
(
mp
,
0
);
error
=
xfs_bmap_finish
(
&
tp
,
&
free_list
,
firstfsb
,
&
committed
);
if
(
error
)
{
goto
error0
;
}
/*
* set up a transaction to convert the range of extents
* from unwritten to real. Do allocations in a loop until
* we have covered the range passed in.
*/
error
=
xfs_trans_commit
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
,
NULL
);
if
(
error
)
{
goto
error_out
;
}
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_STRAT_WRITE
);
error
=
xfs_trans_reserve
(
tp
,
nres
,
XFS_WRITE_LOG_RES
(
mp
),
0
,
XFS_TRANS_PERM_LOG_RES
,
XFS_WRITE_LOG_COUNT
);
if
(
error
)
{
xfs_trans_cancel
(
tp
,
0
);
goto
error0
;
}
/* copy any maps to caller's array and return any error. */
if
(
nimaps
==
0
)
{
error
=
(
ENOSPC
);
goto
error_out
;
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ijoin
(
tp
,
ip
,
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
maps
=
min
(
nimaps
,
maps
);
*
npbmaps
=
_xfs_imap_to_bmap
(
io
,
offset
,
&
imap
[
0
],
pbmapp
,
maps
,
*
npbmaps
);
if
(
*
npbmaps
)
{
/*
* this is new since xfs_iomap_read
* didn't find it.
* Modify the unwritten extent state of the buffer.
*/
if
(
*
npbmaps
!=
1
)
{
/* NEED MORE WORK FOR MULTIPLE BMAPS (which are new) */
BUG
();
}
}
goto
out
;
XFS_BMAP_INIT
(
&
free_list
,
&
firstfsb
);
nimaps
=
1
;
error
=
xfs_bmapi
(
tp
,
ip
,
offset_fsb
,
count_fsb
,
XFS_BMAPI_WRITE
,
&
firstfsb
,
1
,
&
imap
,
&
nimaps
,
&
free_list
);
if
(
error
)
goto
error_on_bmapi_transaction
;
error0:
/* Cancel bmap, unlock inode, and cancel trans */
xfs_bmap_cancel
(
&
free_list
);
error
=
xfs_bmap_finish
(
&
(
tp
),
&
(
free_list
),
firstfsb
,
&
committed
);
if
(
error
)
goto
error_on_bmapi_transaction
;
error1:
/* Just cancel transaction */
xfs_trans_cancel
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
);
*
npbmaps
=
0
;
/* nothing set-up here */
error
=
xfs_trans_commit
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
,
NULL
);
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
if
(
error
)
goto
error0
;
error_out:
out:
/* Just return error and any tracing at end of routine */
if
((
numblks_fsb
=
imap
.
br_blockcount
)
==
0
)
{
/*
* The numblks_fsb value should always get
* smaller, otherwise the loop is stuck.
*/
ASSERT
(
imap
.
br_blockcount
);
break
;
}
offset_fsb
+=
numblks_fsb
;
count_fsb
-=
numblks_fsb
;
}
while
(
count_fsb
>
0
);
return
0
;
error_on_bmapi_transaction:
xfs_bmap_cancel
(
&
free_list
);
xfs_trans_cancel
(
tp
,
(
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
));
xfs_iunlock
(
ip
,
XFS_ILOCK_EXCL
);
error0:
return
XFS_ERROR
(
error
);
}
fs/xfs/linux/xfs_iops.c
View file @
c2e95c3f
...
...
@@ -575,7 +575,7 @@ STATIC int
linvfs_setxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
void
*
data
,
const
void
*
data
,
size_t
size
,
int
flags
)
{
...
...
@@ -593,13 +593,15 @@ linvfs_setxattr(
error
=
-
ENOATTR
;
p
+=
xfs_namespaces
[
SYSTEM_NAMES
].
namelen
;
if
(
strcmp
(
p
,
POSIXACL_ACCESS
)
==
0
)
{
error
=
xfs_acl_vset
(
vp
,
data
,
size
,
_ACL_TYPE_ACCESS
);
error
=
xfs_acl_vset
(
vp
,
(
void
*
)
data
,
size
,
_ACL_TYPE_ACCESS
);
}
else
if
(
strcmp
(
p
,
POSIXACL_DEFAULT
)
==
0
)
{
error
=
xfs_acl_vset
(
vp
,
data
,
size
,
_ACL_TYPE_DEFAULT
);
error
=
xfs_acl_vset
(
vp
,
(
void
*
)
data
,
size
,
_ACL_TYPE_DEFAULT
);
}
else
if
(
strcmp
(
p
,
POSIXCAP
)
==
0
)
{
error
=
xfs_cap_vset
(
vp
,
data
,
size
);
error
=
xfs_cap_vset
(
vp
,
(
void
*
)
data
,
size
);
}
if
(
!
error
)
{
error
=
vn_revalidate
(
vp
);
...
...
@@ -619,7 +621,7 @@ linvfs_setxattr(
return
-
EPERM
;
xflags
|=
ATTR_ROOT
;
p
+=
xfs_namespaces
[
ROOT_NAMES
].
namelen
;
VOP_ATTR_SET
(
vp
,
p
,
data
,
size
,
xflags
,
NULL
,
error
);
VOP_ATTR_SET
(
vp
,
p
,
(
void
*
)
data
,
size
,
xflags
,
NULL
,
error
);
return
-
error
;
}
if
(
strncmp
(
name
,
xfs_namespaces
[
USER_NAMES
].
name
,
...
...
@@ -627,7 +629,7 @@ linvfs_setxattr(
if
(
!
capable_user_xattr
(
inode
))
return
-
EPERM
;
p
+=
xfs_namespaces
[
USER_NAMES
].
namelen
;
VOP_ATTR_SET
(
vp
,
p
,
data
,
size
,
xflags
,
NULL
,
error
);
VOP_ATTR_SET
(
vp
,
p
,
(
void
*
)
data
,
size
,
xflags
,
NULL
,
error
);
return
-
error
;
}
return
-
ENOATTR
;
...
...
fs/xfs/linux/xfs_lrw.c
View file @
c2e95c3f
...
...
@@ -808,6 +808,25 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
}
}
int
xfs_bmap
(
bhv_desc_t
*
bdp
,
xfs_off_t
offset
,
ssize_t
count
,
int
flags
,
page_buf_bmap_t
*
pbmapp
,
int
*
npbmaps
)
{
xfs_inode_t
*
ip
=
XFS_BHVTOI
(
bdp
);
xfs_iocore_t
*
io
=
&
ip
->
i_iocore
;
ASSERT
((
ip
->
i_d
.
di_mode
&
IFMT
)
==
IFREG
);
ASSERT
(((
ip
->
i_d
.
di_flags
&
XFS_DIFLAG_REALTIME
)
!=
0
)
==
((
ip
->
i_iocore
.
io_flags
&
XFS_IOCORE_RT
)
!=
0
));
return
xfs_iomap
(
io
,
offset
,
count
,
flags
,
pbmapp
,
npbmaps
);
}
/*
* Wrapper around bdstrat so that we can stop data
* from going to disk in case we are shutting down the filesystem.
...
...
fs/xfs/linux/xfs_lrw.h
View file @
c2e95c3f
...
...
@@ -36,6 +36,8 @@ struct vnode;
struct
bhv_desc
;
struct
xfs_mount
;
struct
xfs_iocore
;
struct
xfs_inode
;
struct
xfs_bmbt_irec
;
struct
page_buf_s
;
struct
page_buf_bmap_s
;
...
...
@@ -62,6 +64,16 @@ extern ssize_t xfs_sendfile (struct bhv_desc *, struct file *,
loff_t
*
,
size_t
,
read_actor_t
,
void
*
,
struct
cred
*
);
extern
int
xfs_iomap
(
struct
xfs_iocore
*
,
xfs_off_t
,
ssize_t
,
int
,
struct
page_buf_bmap_s
*
,
int
*
);
extern
int
xfs_iomap_write_direct
(
struct
xfs_inode
*
,
loff_t
,
size_t
,
int
,
struct
xfs_bmbt_irec
*
,
int
*
,
int
);
extern
int
xfs_iomap_write_delay
(
struct
xfs_inode
*
,
loff_t
,
size_t
,
int
,
struct
xfs_bmbt_irec
*
,
int
*
);
extern
int
xfs_iomap_write_allocate
(
struct
xfs_inode
*
,
struct
xfs_bmbt_irec
*
,
int
*
);
extern
int
xfs_iomap_write_unwritten
(
struct
xfs_inode
*
,
loff_t
,
size_t
);
extern
int
xfs_dev_is_read_only
(
struct
xfs_mount
*
,
char
*
);
extern
void
XFS_log_write_unmount_ro
(
struct
bhv_desc
*
);
...
...
fs/xfs/linux/xfs_super.c
View file @
c2e95c3f
...
...
@@ -507,8 +507,15 @@ xfs_relse_buftarg(
truncate_inode_pages
(
btp
->
pbr_mapping
,
0LL
);
}
unsigned
int
xfs_getsize_buftarg
(
xfs_buftarg_t
*
btp
)
{
return
block_size
(
btp
->
pbr_bdev
);
}
void
xfs_size_buftarg
(
xfs_s
ets
ize_buftarg
(
xfs_buftarg_t
*
btp
,
unsigned
int
blocksize
,
unsigned
int
sectorsize
)
...
...
@@ -535,7 +542,7 @@ xfs_alloc_buftarg(
btp
->
pbr_dev
=
bdev
->
bd_dev
;
btp
->
pbr_bdev
=
bdev
;
btp
->
pbr_mapping
=
bdev
->
bd_inode
->
i_mapping
;
xfs_size_buftarg
(
btp
,
PAGE_CACHE_SIZE
,
bdev_hardsect_size
(
bdev
));
xfs_s
ets
ize_buftarg
(
btp
,
PAGE_CACHE_SIZE
,
bdev_hardsect_size
(
bdev
));
return
btp
;
}
...
...
fs/xfs/linux/xfs_super.h
View file @
c2e95c3f
...
...
@@ -82,15 +82,17 @@ struct xfs_mount;
struct
pb_target
;
struct
block_device
;
extern
void
xfs_initialize_vnode
(
bhv_desc_t
*
,
vnode_t
*
,
bhv_desc_t
*
,
int
);
extern
void
xfs_initialize_vnode
(
bhv_desc_t
*
,
vnode_t
*
,
bhv_desc_t
*
,
int
);
extern
int
xfs_blkdev_get
(
struct
xfs_mount
*
,
const
char
*
,
extern
int
xfs_blkdev_get
(
struct
xfs_mount
*
,
const
char
*
,
struct
block_device
**
);
extern
void
xfs_blkdev_put
(
struct
block_device
*
);
extern
void
xfs_blkdev_put
(
struct
block_device
*
);
extern
struct
pb_target
*
xfs_alloc_buftarg
(
struct
block_device
*
);
extern
void
xfs_size_buftarg
(
struct
pb_target
*
,
unsigned
int
,
unsigned
int
);
extern
void
xfs_relse_buftarg
(
struct
pb_target
*
);
extern
void
xfs_free_buftarg
(
struct
pb_target
*
);
extern
struct
pb_target
*
xfs_alloc_buftarg
(
struct
block_device
*
);
extern
void
xfs_relse_buftarg
(
struct
pb_target
*
);
extern
void
xfs_free_buftarg
(
struct
pb_target
*
);
extern
void
xfs_setsize_buftarg
(
struct
pb_target
*
,
unsigned
int
,
unsigned
int
);
extern
unsigned
int
xfs_getsize_buftarg
(
struct
pb_target
*
);
#endif
/* __XFS_SUPER_H__ */
fs/xfs/pagebuf/page_buf.h
View file @
c2e95c3f
...
...
@@ -48,9 +48,6 @@
#include <linux/buffer_head.h>
#include <linux/uio.h>
enum
xfs_buffer_state
{
BH_Delay
=
BH_PrivateStart
};
BUFFER_FNS
(
Delay
,
delay
);
/*
* Turn this on to get pagebuf lock ownership
#define PAGEBUF_LOCK_TRACKING
...
...
@@ -83,7 +80,7 @@ typedef enum { /* pbm_flags values */
PBMF_HOLE
=
0x02
,
/* mapping covers a hole */
PBMF_DELAY
=
0x04
,
/* mapping covers delalloc region */
PBMF_UNWRITTEN
=
0x20
/* mapping covers allocated */
/* but uninitialized
XFS
data */
/* but uninitialized
file
data */
}
bmap_flags_t
;
typedef
enum
page_buf_flags_e
{
/* pb_flags values */
...
...
@@ -105,19 +102,17 @@ typedef enum page_buf_flags_e { /* pb_flags values */
PBF_TRYLOCK
=
(
1
<<
14
),
/* lock requested, but do not wait */
PBF_FILE_ALLOCATE
=
(
1
<<
15
),
/* allocate all file space */
PBF_DONT_BLOCK
=
(
1
<<
16
),
/* do not block in current thread */
PBF_DIRECT
=
(
1
<<
17
),
/* direct I/O desired */
PBF_DIRECT
=
(
1
<<
17
),
/* direct I/O desired */
PBF_FILE_UNWRITTEN
=
(
1
<<
18
),
/* convert unwritten extent space */
/* flags used only internally */
_PBF_LOCKABLE
=
(
1
<<
19
),
/* page_buf_t may be locked */
_PBF_ALL_PAGES_MAPPED
=
(
1
<<
21
),
/* all pages in rage are mapped */
_PBF_ADDR_ALLOCATED
=
(
1
<<
22
),
/* pb_addr space was allocated */
_PBF_MEM_ALLOCATED
=
(
1
<<
23
),
/* pb_mem and underlying pages allocated */
_PBF_ALL_PAGES_MAPPED
=
(
1
<<
21
),
/* all pages in range mapped */
_PBF_ADDR_ALLOCATED
=
(
1
<<
22
),
/* pb_addr space was allocated */
_PBF_MEM_ALLOCATED
=
(
1
<<
23
),
/* pb_mem+underlying pages alloc'd */
PBF_FORCEIO
=
(
1
<<
24
),
PBF_FLUSH
=
(
1
<<
25
),
/* flush disk write cache */
PBF_FLUSH
=
(
1
<<
25
),
/* flush disk write cache
*/
PBF_READ_AHEAD
=
(
1
<<
26
),
}
page_buf_flags_t
;
...
...
fs/xfs/xfs_alloc_btree.h
View file @
c2e95c3f
...
...
@@ -104,8 +104,8 @@ int xfs_alloc_block_minrecs(int lev, struct xfs_btree_cur *cur);
#define XFS_MAX_BLOCKSIZE_LOG 16
/* i.e. 65536 bytes */
#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG)
#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG)
#define XFS_MIN_SECTORSIZE_LOG 9
/* i.e. 512 bytes */
#define XFS_MAX_SECTORSIZE_LOG 15
/* i.e. 32768 bytes */
#define XFS_MIN_SECTORSIZE_LOG 9
/* i.e. 512 bytes */
#define XFS_MAX_SECTORSIZE_LOG 15
/* i.e. 32768 bytes */
#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG)
#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG)
...
...
fs/xfs/xfs_buf.h
View file @
c2e95c3f
...
...
@@ -35,28 +35,34 @@
/* These are just for xfs_syncsub... it sets an internal variable
* then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t
*/
#define XFS_B_ASYNC PBF_ASYNC
#define XFS_B_DELWRI PBF_DELWRI
#define XFS_B_READ PBF_READ
#define XFS_B_WRITE PBF_WRITE
#define XFS_B_STALE PBF_STALE
#define XFS_B_ASYNC PBF_ASYNC
#define XFS_B_DELWRI PBF_DELWRI
#define XFS_B_READ PBF_READ
#define XFS_B_WRITE PBF_WRITE
#define XFS_B_STALE PBF_STALE
#define XFS_BUF_TRYLOCK PBF_TRYLOCK
#define XFS_INCORE_TRYLOCK PBF_TRYLOCK
#define XFS_BUF_LOCK PBF_LOCK
#define XFS_BUF_MAPPED PBF_MAPPED
#define BUF_BUSY PBF_DONT_BLOCK
#define BUF_BUSY
PBF_DONT_BLOCK
#define XFS_BUF_BFLAGS(x)
((x)->pb_flags)
/* debugging routines might need this */
#define XFS_BUF_BFLAGS(x)
((x)->pb_flags)
#define XFS_BUF_ZEROFLAGS(x) \
((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI))
#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE)
#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE)
#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE)
#define XFS_BUF_SUPER_STALE(x) (x)->pb_flags |= XFS_B_STALE;\
xfs_buf_undelay(x);\
(x)->pb_flags &= ~(PBF_PARTIAL|PBF_NONE)
#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE)
#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE)
#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE)
#define XFS_BUF_SUPER_STALE(x) do { \
XFS_BUF_STALE(x); \
xfs_buf_undelay(x); \
XFS_BUF_DONE(x); \
} while (0)
#define XFS_BUF_MANAGE PBF_FS_MANAGED
#define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED)
static
inline
void
xfs_buf_undelay
(
page_buf_t
*
pb
)
{
...
...
fs/xfs/xfs_dmapi.h
View file @
c2e95c3f
...
...
@@ -164,13 +164,6 @@ xfs_dm_send_data_event(
int
flags
,
vrwlock_t
*
locktype
);
extern
int
xfs_dm_send_create_event
(
bhv_desc_t
*
dir_bdp
,
char
*
name
,
mode_t
new_mode
,
int
*
good_event_sent
);
extern
int
xfs_dm_send_mmap_event
(
struct
vm_area_struct
*
vma
,
...
...
@@ -249,16 +242,6 @@ typedef enum {
* Stubs for XFS DMAPI utility routines.
*/
static
__inline
int
xfs_dm_send_create_event
(
bhv_desc_t
*
dir_bdp
,
char
*
name
,
mode_t
new_mode
,
int
*
good_event_sent
)
{
return
0
;
}
static
__inline
int
xfs_dm_send_data_event
(
dm_eventtype_t
event
,
...
...
fs/xfs/xfs_iget.c
View file @
c2e95c3f
...
...
@@ -246,9 +246,7 @@ xfs_iget_core(
/*
* Read the disk inode attributes into a new inode structure and get
* a new vnode for it. Initialize the inode lock so we can idestroy
* it soon if it's a dup. This should also initialize i_ino, i_bno,
* i_mount, and i_index.
* a new vnode for it. This should also initialize i_ino and i_mount.
*/
error
=
xfs_iread
(
mp
,
tp
,
ino
,
&
ip
,
bno
);
if
(
error
)
{
...
...
fs/xfs/xfs_inode.c
View file @
c2e95c3f
...
...
@@ -142,7 +142,7 @@ xfs_inobp_bwcheck(xfs_buf_t *bp)
}
if
(
INT_ISZERO
(
dip
->
di_next_unlinked
,
ARCH_CONVERT
))
{
cmn_err
(
CE_WARN
,
"Bad next_unlinked field (0) in XFS inode buffer 0x%
x
, starting blockno %Ld, offset 0x%x"
,
"Bad next_unlinked field (0) in XFS inode buffer 0x%
p
, starting blockno %Ld, offset 0x%x"
,
(
__uint64_t
)(
__psunsigned_t
)
bp
,
(
__int64_t
)
XFS_BUF_ADDR
(
bp
),
xfs_buf_offset
(
bp
,
i
*
mp
->
m_sb
.
sb_inodesize
));
...
...
fs/xfs/xfs_iocore.c
View file @
c2e95c3f
...
...
@@ -41,14 +41,24 @@ xfs_size_fn(
}
xfs_ioops_t
xfs_iocore_xfs
=
{
.
xfs_ioinit
=
(
xfs_ioinit_t
)
fs_noerr
,
.
xfs_bmapi_func
=
(
xfs_bmapi_t
)
xfs_bmapi
,
.
xfs_bmap_eof_func
=
(
xfs_bmap_eof_t
)
xfs_bmap_eof
,
.
xfs_iomap_write_direct
=
(
xfs_iomap_write_direct_t
)
xfs_iomap_write_direct
,
.
xfs_iomap_write_delay
=
(
xfs_iomap_write_delay_t
)
xfs_iomap_write_delay
,
.
xfs_iomap_write_allocate
=
(
xfs_iomap_write_allocate_t
)
xfs_iomap_write_allocate
,
.
xfs_iomap_write_unwritten
=
(
xfs_iomap_write_unwritten_t
)
xfs_iomap_write_unwritten
,
.
xfs_ilock
=
(
xfs_lock_t
)
xfs_ilock
,
.
xfs_lck_map_shared
=
(
xfs_lck_map_shared_t
)
xfs_ilock_map_shared
,
.
xfs_ilock_demote
=
(
xfs_lock_demote_t
)
xfs_ilock_demote
,
.
xfs_ilock_nowait
=
(
xfs_lock_nowait_t
)
xfs_ilock_nowait
,
.
xfs_unlock
=
(
xfs_unlk_t
)
xfs_iunlock
,
.
xfs_size_func
=
(
xfs_size_t
)
xfs_size_fn
,
.
xfs_
lastbyte
=
(
xfs_lastbyte_t
)
xfs_file_last_byte
,
.
xfs_
iodone
=
(
xfs_iodone_t
)
fs_noerr
,
};
void
...
...
@@ -83,4 +93,3 @@ xfs_iocore_inode_init(
xfs_iocore_inode_reinit
(
ip
);
}
fs/xfs/xfs_mount.c
View file @
c2e95c3f
...
...
@@ -419,42 +419,64 @@ xfs_xlatesb(
int
xfs_readsb
(
xfs_mount_t
*
mp
)
{
unsigned
int
sector_size
;
unsigned
int
extra_flags
;
xfs_buf_t
*
bp
;
xfs_sb_t
*
sbp
;
int
error
=
0
;
int
error
;
ASSERT
(
mp
->
m_sb_bp
==
0
);
ASSERT
(
mp
->
m_sb_bp
==
NULL
);
ASSERT
(
mp
->
m_ddev_targp
!=
NULL
);
/*
* Allocate a (locked) buffer to hold the superblock.
* This will be kept around at all time to optimize
* This will be kept around at all time
s
to optimize
* access to the superblock.
*/
bp
=
xfs_buf_read_flags
(
mp
->
m_ddev_targp
,
XFS_SB_DADDR
,
1
,
PBF_LOCK
|
PBF_READ
|
PBF_MAPPED
|
PBF_MAPPABLE
|
PBF_FS_MANAGED
);
ASSERT
(
bp
!=
NULL
);
ASSERT
(
XFS_BUF_ISBUSY
(
bp
)
&&
XFS_BUF_VALUSEMA
(
bp
)
<=
0
);
sector_size
=
xfs_getsize_buftarg
(
mp
->
m_ddev_targp
);
extra_flags
=
XFS_BUF_LOCK
|
XFS_BUF_MANAGE
|
XFS_BUF_MAPPED
;
bp
=
xfs_buf_read_flags
(
mp
->
m_ddev_targp
,
XFS_SB_DADDR
,
BTOBB
(
sector_size
),
extra_flags
);
ASSERT
(
bp
);
ASSERT
(
XFS_BUF_ISBUSY
(
bp
));
ASSERT
(
XFS_BUF_VALUSEMA
(
bp
)
<=
0
);
/*
* Initialize the mount structure from the superblock.
* But first do some basic consistency checking.
*/
sbp
=
XFS_BUF_TO_SBP
(
bp
);
xfs_xlatesb
(
XFS_BUF_PTR
(
bp
),
&
(
mp
->
m_sb
),
1
,
ARCH_CONVERT
,
XFS_SB_ALL_BITS
);
if
((
error
=
xfs_mount_validate_sb
(
mp
,
&
(
mp
->
m_sb
))))
{
xfs_xlatesb
(
XFS_BUF_PTR
(
bp
),
&
(
mp
->
m_sb
),
1
,
ARCH_CONVERT
,
XFS_SB_ALL_BITS
);
error
=
xfs_mount_validate_sb
(
mp
,
&
(
mp
->
m_sb
));
if
(
error
)
{
cmn_err
(
CE_WARN
,
"XFS: SB validate failed"
);
goto
err
;
XFS_BUF_UNMANAGE
(
bp
);
xfs_buf_relse
(
bp
);
return
error
;
}
/*
* Re-read the superblock so that our buffer is correctly sized.
* We only need to do this if sector size on-disk is different.
*/
if
(
sector_size
!=
mp
->
m_sb
.
sb_sectsize
)
{
XFS_BUF_UNMANAGE
(
bp
);
xfs_buf_relse
(
bp
);
sector_size
=
mp
->
m_sb
.
sb_sectsize
;
bp
=
xfs_buf_read_flags
(
mp
->
m_ddev_targp
,
XFS_SB_DADDR
,
BTOBB
(
sector_size
),
extra_flags
);
ASSERT
(
bp
);
ASSERT
(
XFS_BUF_ISBUSY
(
bp
));
ASSERT
(
XFS_BUF_VALUSEMA
(
bp
)
<=
0
);
}
mp
->
m_sb_bp
=
bp
;
xfs_buf_relse
(
bp
);
ASSERT
(
XFS_BUF_VALUSEMA
(
bp
)
>
0
);
return
0
;
err:
bp
->
pb_flags
&=
~
PBF_FS_MANAGED
;
xfs_buf_relse
(
bp
);
return
error
;
}
...
...
@@ -1531,10 +1553,10 @@ xfs_freesb(
/*
* Use xfs_getsb() so that the buffer will be locked
* when we call
nfreerbuf
().
* when we call
xfs_buf_relse
().
*/
bp
=
xfs_getsb
(
mp
,
0
);
bp
->
pb_flags
&=
~
PBF_FS_MANAGED
;
XFS_BUF_UNMANAGE
(
bp
)
;
xfs_buf_relse
(
bp
);
mp
->
m_sb_bp
=
NULL
;
}
...
...
fs/xfs/xfs_mount.h
View file @
c2e95c3f
...
...
@@ -87,41 +87,60 @@ struct xfs_bmap_free;
#define AIL_LOCK(mp,s) s=mutex_spinlock(&(mp)->m_ail_lock)
#define AIL_UNLOCK(mp,s) mutex_spinunlock(&(mp)->m_ail_lock, s)
/* Prototypes and functions for I/O core modularization, a vector
* of functions is used to indirect from xfs/cxfs independent code
* to the xfs/cxfs dependent code.
* The vector is placed in the mount structure so that we can
* minimize the number of memory indirections involved.
/*
* Prototypes and functions for I/O core modularization.
*/
struct
flid
;
struct
buf
;
typedef
int
(
*
xfs_ioinit_t
)(
struct
vfs
*
,
struct
xfs_mount_args
*
,
int
*
);
typedef
int
(
*
xfs_bmapi_t
)(
struct
xfs_trans
*
,
void
*
,
xfs_fileoff_t
,
xfs_filblks_t
,
int
,
xfs_fsblock_t
*
,
xfs_extlen_t
,
struct
xfs_bmbt_irec
*
,
int
*
,
struct
xfs_bmap_free
*
);
typedef
int
(
*
xfs_bmap_eof_t
)(
void
*
,
xfs_fileoff_t
,
int
,
int
*
);
typedef
int
(
*
xfs_iomap_write_direct_t
)(
void
*
,
loff_t
,
size_t
,
int
,
struct
xfs_bmbt_irec
*
,
int
*
,
int
);
typedef
int
(
*
xfs_iomap_write_delay_t
)(
void
*
,
loff_t
,
size_t
,
int
,
struct
xfs_bmbt_irec
*
,
int
*
);
typedef
int
(
*
xfs_iomap_write_allocate_t
)(
void
*
,
struct
xfs_bmbt_irec
*
,
int
*
);
typedef
int
(
*
xfs_iomap_write_unwritten_t
)(
void
*
,
loff_t
,
size_t
);
typedef
uint
(
*
xfs_lck_map_shared_t
)(
void
*
);
typedef
void
(
*
xfs_lock_t
)(
void
*
,
uint
);
typedef
void
(
*
xfs_lock_demote_t
)(
void
*
,
uint
);
typedef
int
(
*
xfs_lock_nowait_t
)(
void
*
,
uint
);
typedef
void
(
*
xfs_unlk_t
)(
void
*
,
unsigned
int
);
typedef
void
(
*
xfs_chgtime_t
)(
void
*
,
int
);
typedef
xfs_fsize_t
(
*
xfs_size_t
)(
void
*
);
typedef
xfs_fsize_t
(
*
xfs_
lastbyte_t
)(
void
*
);
typedef
xfs_fsize_t
(
*
xfs_
iodone_t
)(
struct
vfs
*
);
typedef
struct
xfs_ioops
{
xfs_bmapi_t
xfs_bmapi_func
;
xfs_bmap_eof_t
xfs_bmap_eof_func
;
xfs_lock_t
xfs_ilock
;
xfs_lock_demote_t
xfs_ilock_demote
;
xfs_lock_nowait_t
xfs_ilock_nowait
;
xfs_unlk_t
xfs_unlock
;
xfs_chgtime_t
xfs_chgtime
;
xfs_size_t
xfs_size_func
;
xfs_lastbyte_t
xfs_lastbyte
;
xfs_ioinit_t
xfs_ioinit
;
xfs_bmapi_t
xfs_bmapi_func
;
xfs_bmap_eof_t
xfs_bmap_eof_func
;
xfs_iomap_write_direct_t
xfs_iomap_write_direct
;
xfs_iomap_write_delay_t
xfs_iomap_write_delay
;
xfs_iomap_write_allocate_t
xfs_iomap_write_allocate
;
xfs_iomap_write_unwritten_t
xfs_iomap_write_unwritten
;
xfs_lock_t
xfs_ilock
;
xfs_lck_map_shared_t
xfs_lck_map_shared
;
xfs_lock_demote_t
xfs_ilock_demote
;
xfs_lock_nowait_t
xfs_ilock_nowait
;
xfs_unlk_t
xfs_unlock
;
xfs_size_t
xfs_size_func
;
xfs_iodone_t
xfs_iodone
;
}
xfs_ioops_t
;
#define XFS_IOINIT(vfsp, args, flags) \
(*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags)
#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist) \
(*(mp)->m_io_ops.xfs_bmapi_func) \
(trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist)
...
...
@@ -130,9 +149,31 @@ typedef struct xfs_ioops {
(*(mp)->m_io_ops.xfs_bmap_eof_func) \
((io)->io_obj, endoff, whichfork, eof)
#define XFS_IOMAP_WRITE_DIRECT(mp, io, offset, count, flags, mval, nmap, found)\
(*(mp)->m_io_ops.xfs_iomap_write_direct) \
((io)->io_obj, offset, count, flags, mval, nmap, found)
#define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \
(*(mp)->m_io_ops.xfs_iomap_write_delay) \
((io)->io_obj, offset, count, flags, mval, nmap)
#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, mval, nmap) \
(*(mp)->m_io_ops.xfs_iomap_write_allocate) \
((io)->io_obj, mval, nmap)
#define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \
(*(mp)->m_io_ops.xfs_iomap_write_unwritten) \
((io)->io_obj, offset, count)
#define XFS_LCK_MAP_SHARED(mp, io) \
(*(mp)->m_io_ops.xfs_lck_map_shared)((io)->io_obj)
#define XFS_ILOCK(mp, io, mode) \
(*(mp)->m_io_ops.xfs_ilock)((io)->io_obj, mode)
#define XFS_ILOCK_NOWAIT(mp, io, mode) \
(*(mp)->m_io_ops.xfs_ilock_nowait)((io)->io_obj, mode)
#define XFS_IUNLOCK(mp, io, mode) \
(*(mp)->m_io_ops.xfs_unlock)((io)->io_obj, mode)
...
...
@@ -142,8 +183,13 @@ typedef struct xfs_ioops {
#define XFS_SIZE(mp, io) \
(*(mp)->m_io_ops.xfs_size_func)((io)->io_obj)
#define XFS_LASTBYTE(mp, io) \
(*(mp)->m_io_ops.xfs_lastbyte)((io)->io_obj)
#define XFS_IODONE(vfsp) \
(*(mp)->m_io_ops.xfs_iodone)(vfsp)
/*
* Prototypes and functions for the XFS realtime subsystem.
*/
typedef
struct
xfs_mount
{
...
...
@@ -303,8 +349,8 @@ typedef struct xfs_mount {
/*
* Default minimum read and write sizes.
*/
#define XFS_READIO_LOG_LARGE 1
2
#define XFS_WRITEIO_LOG_LARGE 1
2
#define XFS_READIO_LOG_LARGE 1
6
#define XFS_WRITEIO_LOG_LARGE 1
6
/*
* Default allocation size
*/
...
...
fs/xfs/xfs_rtalloc.c
View file @
c2e95c3f
...
...
@@ -2287,7 +2287,7 @@ xfs_rtmount_init(
return
XFS_ERROR
(
E2BIG
);
}
error
=
xfs_read_buf
(
mp
,
mp
->
m_rtdev_targp
,
XFS_FSB_TO_BB
(
mp
,
d
-
1
),
d
-
XFS_FSB_TO_BB
(
mp
,
1
),
XFS_FSB_TO_BB
(
mp
,
1
),
0
,
&
bp
);
if
(
error
)
{
cmn_err
(
CE_WARN
,
...
...
fs/xfs/xfs_rw.c
View file @
c2e95c3f
...
...
@@ -97,7 +97,7 @@ xfs_do_force_shutdown(
if
(
!
(
flags
&
XFS_FORCE_UMOUNT
))
{
cmn_err
(
CE_NOTE
,
"xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%
x
"
,
"xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%
p
"
,
mp
->
m_fsname
,
flags
,
lnnum
,
fname
,
__return_address
);
}
/*
...
...
fs/xfs/xfs_trans_buf.c
View file @
c2e95c3f
...
...
@@ -472,7 +472,7 @@ xfs_trans_read_buf(
*/
#if defined(DEBUG)
if
(
XFS_BUF_ISSTALE
(
bp
)
&&
XFS_BUF_ISDELAYWRITE
(
bp
))
cmn_err
(
CE_NOTE
,
"about to pop assert, bp == 0x%
x
"
,
bp
);
cmn_err
(
CE_NOTE
,
"about to pop assert, bp == 0x%
p
"
,
bp
);
#endif
ASSERT
((
XFS_BUF_BFLAGS
(
bp
)
&
(
XFS_B_STALE
|
XFS_B_DELWRI
))
!=
(
XFS_B_STALE
|
XFS_B_DELWRI
));
...
...
fs/xfs/xfs_vfsops.c
View file @
c2e95c3f
...
...
@@ -451,18 +451,19 @@ xfs_mount(
goto
error
;
}
xfs_size_buftarg
(
mp
->
m_ddev_targp
,
mp
->
m_sb
.
sb_blocksize
,
mp
->
m_sb
.
sb_sectsize
);
xfs_s
ets
ize_buftarg
(
mp
->
m_ddev_targp
,
mp
->
m_sb
.
sb_blocksize
,
mp
->
m_sb
.
sb_sectsize
);
if
(
logdev
&&
logdev
!=
ddev
)
{
unsigned
int
ss
=
BBSIZE
;
unsigned
int
log_sector_size
=
BBSIZE
;
if
(
XFS_SB_VERSION_HASSECTOR
(
&
mp
->
m_sb
))
ss
=
mp
->
m_sb
.
sb_logsectsize
;
xfs_size_buftarg
(
mp
->
m_logdev_targp
,
mp
->
m_sb
.
sb_blocksize
,
ss
);
log_sector_size
=
mp
->
m_sb
.
sb_logsectsize
;
xfs_setsize_buftarg
(
mp
->
m_logdev_targp
,
mp
->
m_sb
.
sb_blocksize
,
log_sector_size
);
}
if
(
rtdev
)
xfs_size_buftarg
(
mp
->
m_rtdev_targp
,
mp
->
m_sb
.
sb_blocksize
,
mp
->
m_sb
.
sb_blocksize
);
xfs_s
ets
ize_buftarg
(
mp
->
m_rtdev_targp
,
mp
->
m_sb
.
sb_blocksize
,
mp
->
m_sb
.
sb_blocksize
);
error
=
xfs_mountfs
(
vfsp
,
mp
,
ddev
->
bd_dev
,
flags
);
if
(
error
)
...
...
fs/xfs/xfs_vnodeops.c
View file @
c2e95c3f
...
...
@@ -44,15 +44,6 @@ extern int xfs_ioctl(bhv_desc_t *, struct inode *, struct file *,
unsigned
int
,
unsigned
long
);
#ifdef XFS_RW_TRACE
STATIC
void
xfs_ctrunc_trace
(
int
tag
,
xfs_inode_t
*
ip
);
#else
#define xfs_ctrunc_trace(tag, ip)
#endif
/* DEBUG */
/*
* For xfs, we check that the file isn't too big to be opened by this kernel.
* No other open action is required for regular files. Devices are handled
...
...
@@ -1880,7 +1871,6 @@ xfs_lookup(
cred_t
*
credp
)
{
xfs_inode_t
*
dp
,
*
ip
;
struct
vnode
*
vp
;
xfs_ino_t
e_inum
;
int
error
;
uint
lock_mode
;
...
...
@@ -1896,58 +1886,19 @@ xfs_lookup(
lock_mode
=
xfs_ilock_map_shared
(
dp
);
error
=
xfs_dir_lookup_int
(
dir_bdp
,
lock_mode
,
dentry
,
&
e_inum
,
&
ip
);
if
(
error
)
{
xfs_iunlock_map_shared
(
dp
,
lock_mode
);
return
error
;
if
(
!
error
)
{
*
vpp
=
XFS_ITOV
(
ip
);
ITRACE
(
ip
)
;
}
vp
=
XFS_ITOV
(
ip
);
ITRACE
(
ip
);
xfs_iunlock_map_shared
(
dp
,
lock_mode
);
*
vpp
=
vp
;
return
0
;
return
error
;
}
#ifdef XFS_RW_TRACE
STATIC
void
xfs_ctrunc_trace
(
int
tag
,
xfs_inode_t
*
ip
)
{
if
(
ip
->
i_rwtrace
==
NULL
)
{
return
;
}
ktrace_enter
(
ip
->
i_rwtrace
,
(
void
*
)((
long
)
tag
),
(
void
*
)
ip
,
(
void
*
)((
long
)
private
.
p_cpuid
),
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
,
(
void
*
)
0
);
}
#endif
/* XFS_RW_TRACE */
#define XFS_CREATE_NEW_MAXTRIES 10000
/*
* xfs_create (create a new file).
* It might still find name exists out there, though.
* But vpp, doens't point at a vnode.
*/
STATIC
int
xfs_create
(
...
...
@@ -1968,7 +1919,6 @@ xfs_create(
xfs_bmap_free_t
free_list
;
xfs_fsblock_t
first_block
;
boolean_t
dp_joined_to_trans
;
int
dm_event_sent
=
0
;
uint
cancel_flags
;
int
committed
;
xfs_prid_t
prid
;
...
...
@@ -1989,8 +1939,10 @@ xfs_create(
return
XFS_ERROR
(
ENAMETOOLONG
);
if
(
DM_EVENT_ENABLED
(
dir_vp
->
v_vfsp
,
dp
,
DM_EVENT_CREATE
))
{
error
=
xfs_dm_send_create_event
(
dir_bdp
,
name
,
dm_di_mode
,
&
dm_event_sent
);
error
=
dm_send_namesp_event
(
DM_EVENT_CREATE
,
dir_bdp
,
DM_RIGHT_NULL
,
NULL
,
DM_RIGHT_NULL
,
name
,
NULL
,
dm_di_mode
,
0
,
0
);
if
(
error
)
return
error
;
}
...
...
@@ -2161,7 +2113,7 @@ xfs_create(
/* Fallthrough to std_return with error = 0 */
std_return:
if
((
error
!=
0
&&
dm_event_sent
!=
0
)
&&
if
((
error
!=
0
)
&&
DM_EVENT_ENABLED
(
dir_vp
->
v_vfsp
,
XFS_BHVTOI
(
dir_bdp
),
DM_EVENT_POSTCREATE
))
{
(
void
)
dm_send_namesp_event
(
DM_EVENT_POSTCREATE
,
...
...
@@ -2227,16 +2179,7 @@ int xfs_rm_attempts;
* vnode ref count will still include that from the .. entry in
* this case.
*
* The inode passed in will have been looked up using xfs_get_dir_entry().
* Since that lookup the directory lock will have been dropped, so
* we need to validate that the inode given is still pointed to by the
* directory. We use the directory inode in memory generation count
* as an optimization to tell if a new lookup is necessary. If the
* directory no longer points to the given inode with the given name,
* then we drop the directory lock, set the entry_changed parameter to 1,
* and return. It is up to the caller to drop the reference to the inode.
*
* There is a dealock we need to worry about. If the locked directory is
* There is a deadlock we need to worry about. If the locked directory is
* in the AIL, it might be blocking up the log. The next inode we lock
* could be already locked by another thread waiting for log space (e.g
* a permanent log reservation with a long running transaction (see
...
...
@@ -2249,8 +2192,7 @@ STATIC int
xfs_lock_dir_and_entry
(
xfs_inode_t
*
dp
,
vname_t
*
dentry
,
xfs_inode_t
*
ip
,
/* inode of entry 'name' */
int
*
entry_changed
)
xfs_inode_t
*
ip
)
/* inode of entry 'name' */
{
int
attempts
;
xfs_ino_t
e_inum
;
...
...
@@ -2263,7 +2205,6 @@ xfs_lock_dir_and_entry(
attempts
=
0
;
again:
*
entry_changed
=
0
;
xfs_ilock
(
dp
,
XFS_ILOCK_EXCL
);
e_inum
=
ip
->
i_ino
;
...
...
@@ -2477,7 +2418,6 @@ xfs_remove(
xfs_fsblock_t
first_block
;
int
cancel_flags
;
int
committed
;
int
entry_changed
;
int
dm_di_mode
=
0
;
int
link_zero
;
uint
resblks
;
...
...
@@ -2504,7 +2444,6 @@ xfs_remove(
}
/* From this point on, return through std_return */
retry:
ip
=
NULL
;
/*
...
...
@@ -2571,7 +2510,7 @@ xfs_remove(
return
error
;
}
error
=
xfs_lock_dir_and_entry
(
dp
,
dentry
,
ip
,
&
entry_changed
);
error
=
xfs_lock_dir_and_entry
(
dp
,
dentry
,
ip
);
if
(
error
)
{
REMOVE_DEBUG_TRACE
(
__LINE__
);
xfs_trans_cancel
(
tp
,
cancel_flags
);
...
...
@@ -2579,17 +2518,6 @@ xfs_remove(
goto
std_return
;
}
/*
* If the inode we found in the first pass is no longer
* the entry with the given name, then drop our transaction and
* inode reference and start over.
*/
if
(
entry_changed
)
{
xfs_trans_cancel
(
tp
,
cancel_flags
);
IRELE
(
ip
);
goto
retry
;
}
/*
* At this point, we've gotten both the directory and the entry
* inodes locked.
...
...
@@ -2610,28 +2538,6 @@ xfs_remove(
goto
error_return
;
}
if
((
ip
->
i_d
.
di_mode
&
IFMT
)
==
IFDIR
)
{
error
=
XFS_ERROR
(
EPERM
);
REMOVE_DEBUG_TRACE
(
__LINE__
);
goto
error_return
;
}
/*
* Return error when removing . and ..
*/
if
(
name
[
0
]
==
'.'
)
{
if
(
name
[
1
]
==
'\0'
)
{
error
=
XFS_ERROR
(
EINVAL
);
REMOVE_DEBUG_TRACE
(
__LINE__
);
goto
error_return
;
}
else
if
(
name
[
1
]
==
'.'
&&
name
[
2
]
==
'\0'
)
{
error
=
XFS_ERROR
(
EEXIST
);
REMOVE_DEBUG_TRACE
(
__LINE__
);
goto
error_return
;
}
}
/*
* Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
*/
...
...
@@ -2696,8 +2602,7 @@ xfs_remove(
IRELE
(
ip
);
/* Fall through to std_return with error = 0 */
std_return:
std_return:
if
(
DM_EVENT_ENABLED
(
dir_vp
->
v_vfsp
,
dp
,
DM_EVENT_POSTREMOVE
))
{
(
void
)
dm_send_namesp_event
(
DM_EVENT_POSTREMOVE
,
...
...
@@ -2938,7 +2843,6 @@ xfs_mkdir(
vnode_t
*
dir_vp
;
boolean_t
dp_joined_to_trans
;
boolean_t
created
=
B_FALSE
;
int
dm_event_sent
=
0
;
xfs_prid_t
prid
;
xfs_dquot_t
*
udqp
,
*
gdqp
;
uint
resblks
;
...
...
@@ -2961,8 +2865,10 @@ xfs_mkdir(
dm_di_mode
=
vap
->
va_mode
|
VTTOIF
(
vap
->
va_type
);
if
(
DM_EVENT_ENABLED
(
dir_vp
->
v_vfsp
,
dp
,
DM_EVENT_CREATE
))
{
error
=
xfs_dm_send_create_event
(
dir_bdp
,
dir_name
,
dm_di_mode
,
&
dm_event_sent
);
error
=
dm_send_namesp_event
(
DM_EVENT_CREATE
,
dir_bdp
,
DM_RIGHT_NULL
,
NULL
,
DM_RIGHT_NULL
,
dir_name
,
NULL
,
dm_di_mode
,
0
,
0
);
if
(
error
)
return
error
;
}
...
...
@@ -3127,7 +3033,7 @@ xfs_mkdir(
* xfs_trans_commit. */
std_return:
if
(
(
created
||
(
error
!=
0
&&
dm_event_sent
!=
0
))
&&
if
(
(
created
||
(
error
!=
0
))
&&
DM_EVENT_ENABLED
(
dir_vp
->
v_vfsp
,
XFS_BHVTOI
(
dir_bdp
),
DM_EVENT_POSTCREATE
))
{
(
void
)
dm_send_namesp_event
(
DM_EVENT_POSTCREATE
,
...
...
@@ -3180,7 +3086,6 @@ xfs_rmdir(
xfs_fsblock_t
first_block
;
int
cancel_flags
;
int
committed
;
int
entry_changed
;
vnode_t
*
dir_vp
;
int
dm_di_mode
=
0
;
int
last_cdp_link
;
...
...
@@ -3209,7 +3114,6 @@ xfs_rmdir(
/* Return through std_return after this point. */
retry:
cdp
=
NULL
;
/*
...
...
@@ -3281,24 +3185,13 @@ xfs_rmdir(
* that the directory entry for the child directory inode has
* not changed while we were obtaining a log reservation.
*/
error
=
xfs_lock_dir_and_entry
(
dp
,
dentry
,
cdp
,
&
entry_changed
);
error
=
xfs_lock_dir_and_entry
(
dp
,
dentry
,
cdp
);
if
(
error
)
{
xfs_trans_cancel
(
tp
,
cancel_flags
);
IRELE
(
cdp
);
goto
std_return
;
}
/*
* If the inode we found in the first pass is no longer
* the entry with the given name, then drop our transaction and
* inode reference and start over.
*/
if
(
entry_changed
)
{
xfs_trans_cancel
(
tp
,
cancel_flags
);
IRELE
(
cdp
);
goto
retry
;
}
xfs_trans_ijoin
(
tp
,
dp
,
XFS_ILOCK_EXCL
);
if
(
dp
!=
cdp
)
{
/*
...
...
@@ -3455,20 +3348,12 @@ xfs_readdir(
}
lock_mode
=
xfs_ilock_map_shared
(
dp
);
if
((
dp
->
i_d
.
di_mode
&
IFMT
)
!=
IFDIR
)
{
xfs_iunlock_map_shared
(
dp
,
lock_mode
);
return
XFS_ERROR
(
ENOTDIR
);
}
start_offset
=
uiop
->
uio_offset
;
error
=
XFS_DIR_GETDENTS
(
dp
->
i_mount
,
tp
,
dp
,
uiop
,
eofp
);
if
(
start_offset
!=
uiop
->
uio_offset
)
{
xfs_ichgtime
(
dp
,
XFS_ICHGTIME_ACC
);
}
xfs_iunlock_map_shared
(
dp
,
lock_mode
);
return
error
;
}
...
...
fs/xfs/xfsidbg.c
View file @
c2e95c3f
...
...
@@ -1637,9 +1637,9 @@ static void printinode(struct inode *ip)
if
(
ip
==
NULL
)
return
;
kdb_printf
(
" i_ino = %lu i_count = %u i_
dev = 0x%x i_
size %Ld
\n
"
,
kdb_printf
(
" i_ino = %lu i_count = %u i_size %Ld
\n
"
,
ip
->
i_ino
,
atomic_read
(
&
ip
->
i_count
),
ip
->
i_s
b
->
s_dev
,
ip
->
i_s
ize
);
ip
->
i_size
);
kdb_printf
(
" i_mode = 0x%x i_nlink = %d i_rdev = 0x%x i_state = 0x%lx
\n
"
,
...
...
include/linux/buffer_head.h
View file @
c2e95c3f
...
...
@@ -22,6 +22,7 @@ enum bh_state_bits {
BH_New
,
/* Disk mapping was newly created by get_block */
BH_Async_Read
,
/* Is under end_buffer_async_read I/O */
BH_Async_Write
,
/* Is under end_buffer_async_write I/O */
BH_Delay
,
/* Buffer is not yet allocated on disk */
BH_Boundary
,
/* Block is followed by a discontiguity */
BH_PrivateStart
,
/* not a state bit, but the first bit available
...
...
@@ -105,6 +106,7 @@ BUFFER_FNS(Mapped, mapped)
BUFFER_FNS
(
New
,
new
)
BUFFER_FNS
(
Async_Read
,
async_read
)
BUFFER_FNS
(
Async_Write
,
async_write
)
BUFFER_FNS
(
Delay
,
delay
);
BUFFER_FNS
(
Boundary
,
boundary
)
#define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)
...
...
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