Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
fdba8dd2
Commit
fdba8dd2
authored
Sep 25, 2002
by
Christoph Hellwig
Browse files
Options
Browse Files
Download
Plain Diff
Merge
parents
463b2b8d
919dc9e2
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
508 additions
and
734 deletions
+508
-734
fs/xfs/linux/xfs_aops.c
fs/xfs/linux/xfs_aops.c
+40
-153
fs/xfs/linux/xfs_file.c
fs/xfs/linux/xfs_file.c
+55
-47
fs/xfs/linux/xfs_lrw.c
fs/xfs/linux/xfs_lrw.c
+97
-49
fs/xfs/linux/xfs_lrw.h
fs/xfs/linux/xfs_lrw.h
+10
-10
fs/xfs/linux/xfs_vnode.h
fs/xfs/linux/xfs_vnode.h
+11
-17
fs/xfs/pagebuf/page_buf.c
fs/xfs/pagebuf/page_buf.c
+7
-6
fs/xfs/pagebuf/page_buf.h
fs/xfs/pagebuf/page_buf.h
+0
-7
fs/xfs/pagebuf/page_buf_internal.h
fs/xfs/pagebuf/page_buf_internal.h
+0
-12
fs/xfs/pagebuf/page_buf_locking.c
fs/xfs/pagebuf/page_buf_locking.c
+6
-4
fs/xfs/support/time.h
fs/xfs/support/time.h
+6
-2
fs/xfs/xfs_iget.c
fs/xfs/xfs_iget.c
+0
-20
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode.h
+0
-1
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.c
+0
-10
fs/xfs/xfs_rename.c
fs/xfs/xfs_rename.c
+1
-6
fs/xfs/xfs_utils.c
fs/xfs/xfs_utils.c
+5
-52
fs/xfs/xfs_utils.h
fs/xfs/xfs_utils.h
+1
-4
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vfsops.c
+211
-202
fs/xfs/xfs_vnodeops.c
fs/xfs/xfs_vnodeops.c
+58
-132
No files found.
fs/xfs/linux/xfs_aops.c
View file @
fdba8dd2
...
...
@@ -37,10 +37,38 @@
#include <linux/iobuf.h>
STATIC
int
linvfs_pb_bmap
(
struct
inode
*
,
loff_t
,
ssize_t
,
struct
page_buf_bmap_s
*
,
int
);
STATIC
int
delalloc_convert
(
struct
inode
*
,
struct
page
*
,
int
,
int
);
STATIC
int
map_blocks
(
struct
inode
*
inode
,
loff_t
offset
,
ssize_t
count
,
page_buf_bmap_t
*
pbmapp
,
int
flags
)
{
vnode_t
*
vp
=
LINVFS_GET_VP
(
inode
);
int
error
,
nmaps
=
1
;
retry:
if
(
flags
&
PBF_FILE_ALLOCATE
)
{
VOP_STRATEGY
(
vp
,
offset
,
count
,
flags
,
NULL
,
pbmapp
,
&
nmaps
,
error
);
}
else
{
VOP_BMAP
(
vp
,
offset
,
count
,
flags
,
NULL
,
pbmapp
,
&
nmaps
,
error
);
}
if
(
flags
&
PBF_WRITE
)
{
if
(
unlikely
((
flags
&
PBF_DIRECT
)
&&
nmaps
&&
(
pbmapp
->
pbm_flags
&
PBMF_DELAY
)))
{
flags
=
PBF_WRITE
|
PBF_FILE_ALLOCATE
;
goto
retry
;
}
VMODIFY
(
vp
);
}
return
-
error
;
}
/*
* match_offset_to_mapping
* Finds the corresponding mapping in block @map array of the
...
...
@@ -195,7 +223,7 @@ probe_unmapped_page(
page
=
find_get_page
(
mapping
,
index
);
if
(
!
page
)
return
0
;
if
(
TestSetPageLocked
(
page
))
{
if
(
PageWriteback
(
page
)
||
TestSetPageLocked
(
page
))
{
page_cache_release
(
page
);
return
0
;
}
...
...
@@ -274,7 +302,7 @@ probe_page(
page
=
find_get_page
(
inode
->
i_mapping
,
index
);
if
(
!
page
)
return
NULL
;
if
(
TestSetPageLocked
(
page
))
{
if
(
PageWriteback
(
page
)
||
TestSetPageLocked
(
page
))
{
page_cache_release
(
page
);
return
NULL
;
}
...
...
@@ -303,6 +331,7 @@ submit_page(
BUG_ON
(
PageWriteback
(
page
));
SetPageWriteback
(
page
);
clear_page_dirty
(
page
);
unlock_page
(
page
);
if
(
cnt
)
{
...
...
@@ -461,7 +490,7 @@ delalloc_convert(
if
(
buffer_delay
(
bh
))
{
if
(
!
mp
)
{
err
=
linvfs_pb_bmap
(
inode
,
offset
,
len
,
&
map
,
err
=
map_blocks
(
inode
,
offset
,
len
,
&
map
,
PBF_WRITE
|
PBF_FILE_ALLOCATE
);
if
(
err
)
goto
error
;
...
...
@@ -487,7 +516,7 @@ delalloc_convert(
if
(
!
mp
)
{
size
=
probe_unmapped_cluster
(
inode
,
page
,
bh
,
head
);
err
=
linvfs_pb_bmap
(
inode
,
offset
,
size
,
&
map
,
err
=
map_blocks
(
inode
,
offset
,
size
,
&
map
,
PBF_WRITE
|
PBF_DIRECT
);
if
(
err
)
goto
error
;
...
...
@@ -661,36 +690,6 @@ linvfs_direct_IO(
linvfs_get_blocks_direct
);
}
STATIC
int
linvfs_pb_bmap
(
struct
inode
*
inode
,
loff_t
offset
,
ssize_t
count
,
page_buf_bmap_t
*
pbmapp
,
int
flags
)
{
vnode_t
*
vp
=
LINVFS_GET_VP
(
inode
);
int
error
,
nmaps
=
1
;
retry:
if
(
flags
&
PBF_FILE_ALLOCATE
)
{
VOP_STRATEGY
(
vp
,
offset
,
count
,
flags
,
NULL
,
pbmapp
,
&
nmaps
,
error
);
}
else
{
VOP_BMAP
(
vp
,
offset
,
count
,
flags
,
NULL
,
pbmapp
,
&
nmaps
,
error
);
}
if
(
flags
&
PBF_WRITE
)
{
if
(
unlikely
((
flags
&
PBF_DIRECT
)
&&
nmaps
&&
(
pbmapp
->
pbm_flags
&
PBMF_DELAY
)))
{
flags
=
PBF_WRITE
|
PBF_FILE_ALLOCATE
;
goto
retry
;
}
VMODIFY
(
vp
);
}
return
-
error
;
}
STATIC
int
linvfs_bmap
(
struct
address_space
*
mapping
,
...
...
@@ -714,11 +713,11 @@ linvfs_bmap(
}
STATIC
int
linvfs_read
_full_
page
(
linvfs_readpage
(
struct
file
*
unused
,
struct
page
*
page
)
{
return
block_read_full_
page
(
page
,
linvfs_get_block
);
return
mpage_read
page
(
page
,
linvfs_get_block
);
}
STATIC
int
...
...
@@ -759,7 +758,7 @@ count_page_state(
}
STATIC
int
linvfs_write
_full_
page
(
linvfs_writepage
(
struct
page
*
page
)
{
int
error
;
...
...
@@ -801,118 +800,6 @@ linvfs_prepare_write(
}
}
#if 0
/* Keeping this for now as an example of a better way of
* doing O_DIRECT for XFS - the generic path has more
* overhead than we want.
*/
/*
* Initiate I/O on a kiobuf of user memory
*/
STATIC int
linvfs_direct_IO(
int rw,
struct inode *inode,
struct kiobuf *iobuf,
unsigned long blocknr,
int blocksize)
{
struct page **maplist;
size_t page_offset;
page_buf_t *pb;
page_buf_bmap_t map;
int error = 0;
int pb_flags, map_flags, pg_index = 0;
size_t length, total;
loff_t offset;
size_t map_size, size;
total = length = iobuf->length;
offset = blocknr;
offset <<= inode->i_blkbits;
maplist = iobuf->maplist;
page_offset = iobuf->offset;
map_flags = (rw ? PBF_WRITE : PBF_READ) | PBF_DIRECT;
pb_flags = (rw ? PBF_WRITE : PBF_READ) | PBF_FORCEIO | _PBF_LOCKABLE;
while (length) {
error = linvfs_pb_bmap(inode, offset, length, &map, map_flags);
if (error)
break;
map_size = map.pbm_bsize - map.pbm_delta;
size = min(map_size, length);
if (map.pbm_flags & PBMF_HOLE) {
size_t zero_len = size;
if (rw == WRITE)
break;
/* Need to zero it all */
while (zero_len) {
struct page *page;
size_t pg_len;
pg_len = min((size_t)
(PAGE_CACHE_SIZE - page_offset),
zero_len);
page = maplist[pg_index];
memset(kmap(page) + page_offset, 0, pg_len);
flush_dcache_page(page);
kunmap(page);
zero_len -= pg_len;
if ((pg_len + page_offset) == PAGE_CACHE_SIZE) {
pg_index++;
page_offset = 0;
} else {
page_offset = (page_offset + pg_len) &
~PAGE_CACHE_MASK;
}
}
} else {
int pg_count;
pg_count = (size + page_offset + PAGE_CACHE_SIZE - 1)
>> PAGE_CACHE_SHIFT;
if ((pb = pagebuf_lookup(map.pbm_target, inode, offset,
size, pb_flags)) == NULL) {
error = -ENOMEM;
break;
}
/* Need to hook up pagebuf to kiobuf pages */
pb->pb_pages = &maplist[pg_index];
pb->pb_offset = page_offset;
pb->pb_page_count = pg_count;
pb->pb_bn = map.pbm_bn + (map.pbm_delta >> 9);
error = pagebuf_iostart(pb, pb_flags);
pb->pb_flags &= ~_PBF_LOCKABLE;
pagebuf_rele(pb);
if (error != 0) {
if (error > 0)
error = -error;
break;
}
page_offset = (page_offset + size) & ~PAGE_CACHE_MASK;
if (page_offset)
pg_count--;
pg_index += pg_count;
}
offset += size;
length -= size;
}
return (error ? error : (int)(total - length));
}
#endif
/*
* This gets a page into cleanable state - page locked on entry
* kept locked on exit. If the page is marked dirty we should
...
...
@@ -945,9 +832,9 @@ linvfs_release_page(
struct
address_space_operations
linvfs_aops
=
{
.
readpage
=
linvfs_read
_full_
page
,
.
readpage
=
linvfs_readpage
,
.
readpages
=
linvfs_readpages
,
.
writepage
=
linvfs_write
_full_
page
,
.
writepage
=
linvfs_writepage
,
.
sync_page
=
block_sync_page
,
.
releasepage
=
linvfs_release_page
,
.
prepare_write
=
linvfs_prepare_write
,
...
...
fs/xfs/linux/xfs_file.c
View file @
fdba8dd2
...
...
@@ -40,70 +40,76 @@ static struct vm_operations_struct linvfs_file_vm_ops;
STATIC
ssize_t
linvfs_read
(
struct
file
*
filp
,
c
har
*
buf
,
size_t
size
,
loff_t
*
offset
)
linvfs_read
v
(
struct
file
*
filp
,
c
onst
struct
iovec
*
iovp
,
unsigned
long
nr_segs
,
loff_t
*
ppos
)
{
vnode_t
*
vp
;
int
error
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
filp
->
f_dentry
->
d_inode
)
;
int
error
;
vp
=
LINVFS_GET_VP
(
filp
->
f_dentry
->
d_inode
);
ASSERT
(
vp
);
VOP_READ
(
vp
,
filp
,
iovp
,
nr_segs
,
ppos
,
NULL
,
error
);
VOP_READ
(
vp
,
filp
,
buf
,
size
,
offset
,
NULL
,
error
);
return
(
error
);
return
error
;
}
STATIC
ssize_t
linvfs_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
linvfs_write
v
(
struct
file
*
filp
,
const
struct
iovec
*
iovp
,
unsigned
long
nr_segs
,
loff_t
*
ppos
)
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
loff_t
pos
;
vnode_t
*
vp
;
int
err
;
/* Use negative errors in this f'n */
if
((
ssize_t
)
count
<
0
)
return
-
EINVAL
;
if
(
!
access_ok
(
VERIFY_READ
,
buf
,
count
))
return
-
EFAULT
;
struct
inode
*
inode
=
filp
->
f_dentry
->
d_inode
;
vnode_t
*
vp
=
LINVFS_GET_VP
(
inode
);
int
error
=
filp
->
f_error
;
pos
=
*
ppos
;
err
=
-
EINVAL
;
if
(
pos
<
0
)
goto
out
;
err
=
file
->
f_error
;
if
(
err
)
{
file
->
f_error
=
0
;
goto
out
;
if
(
unlikely
(
error
))
{
filp
->
f_error
=
0
;
return
error
;
}
vp
=
LINVFS_GET_VP
(
inode
);
ASSERT
(
vp
);
/* We allow multiple direct writers in, there is no
/*
* We allow multiple direct writers in, there is no
* potential call to vmtruncate in that path.
*/
if
(
!
(
file
->
f_flags
&
O_DIRECT
))
if
(
filp
->
f_flags
&
O_DIRECT
)
{
VOP_WRITE
(
vp
,
filp
,
iovp
,
nr_segs
,
ppos
,
NULL
,
error
);
}
else
{
down
(
&
inode
->
i_sem
);
VOP_WRITE
(
vp
,
filp
,
iovp
,
nr_segs
,
ppos
,
NULL
,
error
);
up
(
&
inode
->
i_sem
);
}
VOP_WRITE
(
vp
,
file
,
buf
,
count
,
&
pos
,
NULL
,
err
)
;
*
ppos
=
pos
;
return
error
;
}
if
(
!
(
file
->
f_flags
&
O_DIRECT
))
up
(
&
inode
->
i_sem
);
out:
return
(
err
);
STATIC
ssize_t
linvfs_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
iovec
iov
=
{
buf
,
count
};
return
linvfs_readv
(
filp
,
&
iov
,
1
,
ppos
);
}
STATIC
ssize_t
linvfs_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
iovec
iov
=
{(
void
*
)
buf
,
count
};
return
linvfs_writev
(
file
,
&
iov
,
1
,
ppos
);
}
...
...
@@ -312,6 +318,8 @@ struct file_operations linvfs_file_operations = {
.
llseek
=
generic_file_llseek
,
.
read
=
linvfs_read
,
.
write
=
linvfs_write
,
.
readv
=
linvfs_readv
,
.
writev
=
linvfs_writev
,
.
ioctl
=
linvfs_ioctl
,
.
mmap
=
linvfs_file_mmap
,
.
open
=
linvfs_open
,
...
...
fs/xfs/linux/xfs_lrw.c
View file @
fdba8dd2
...
...
@@ -124,36 +124,64 @@ xfs_iozero(
ssize_t
/* bytes read, or (-) error */
xfs_read
(
bhv_desc_t
*
bdp
,
struct
file
*
file
,
c
har
*
buf
,
size_t
size
,
loff_t
*
offset
,
cred_t
*
credp
)
bhv_desc_t
*
bdp
,
struct
file
*
filp
,
c
onst
struct
iovec
*
iovp
,
unsigned
long
segs
,
loff_t
*
offp
,
cred_t
*
credp
)
{
ssize_t
ret
;
xfs_fsize_t
n
;
xfs_inode_t
*
ip
;
xfs_mount_t
*
mp
;
size_t
size
=
0
;
ssize_t
ret
;
xfs_fsize_t
n
;
xfs_inode_t
*
ip
;
xfs_mount_t
*
mp
;
unsigned
long
seg
;
int
direct
=
filp
->
f_flags
&
O_DIRECT
;
ip
=
XFS_BHVTOI
(
bdp
);
mp
=
ip
->
i_mount
;
XFS_STATS_INC
(
xfsstats
.
xs_read_calls
);
if
(
file
->
f_flags
&
O_DIRECT
)
{
if
(((
__psint_t
)
buf
&
BBMASK
)
||
(
*
offset
&
mp
->
m_blockmask
)
||
/* START copy & waste from filemap.c */
for
(
seg
=
0
;
seg
<
segs
;
seg
++
)
{
const
struct
iovec
*
iv
=
&
iovp
[
seg
];
/*
* If any segment has a negative length, or the cumulative
* length ever wraps negative then return -EINVAL.
*/
size
+=
iv
->
iov_len
;
if
(
unlikely
((
ssize_t
)(
size
|
iv
->
iov_len
)
<
0
))
return
XFS_ERROR
(
-
EINVAL
);
if
(
direct
)
{
/* XFS specific check */
if
((
__psint_t
)
iv
->
iov_base
&
BBMASK
)
{
if
(
*
offp
==
ip
->
i_d
.
di_size
)
return
0
;
return
XFS_ERROR
(
-
EINVAL
);
}
}
if
(
access_ok
(
VERIFY_WRITE
,
iv
->
iov_base
,
iv
->
iov_len
))
continue
;
if
(
seg
==
0
)
return
XFS_ERROR
(
-
EFAULT
);
segs
=
seg
;
break
;
}
/* END copy & waste from filemap.c */
if
(
direct
)
{
if
((
*
offp
&
mp
->
m_blockmask
)
||
(
size
&
mp
->
m_blockmask
))
{
if
(
*
off
set
==
ip
->
i_d
.
di_size
)
{
if
(
*
off
p
==
ip
->
i_d
.
di_size
)
{
return
(
0
);
}
return
-
XFS_ERROR
(
EINVAL
);
}
}
n
=
XFS_MAX_FILE_OFFSET
-
*
offset
;
n
=
XFS_MAX_FILE_OFFSET
-
*
offp
;
if
((
n
<=
0
)
||
(
size
==
0
))
return
0
;
...
...
@@ -167,26 +195,24 @@ xfs_read(
xfs_ilock
(
ip
,
XFS_IOLOCK_SHARED
);
if
(
DM_EVENT_ENABLED
(
BHV_TO_VNODE
(
bdp
)
->
v_vfsp
,
ip
,
DM_EVENT_READ
)
&&
!
(
fil
e
->
f_mode
&
FINVIS
))
{
!
(
fil
p
->
f_mode
&
FINVIS
))
{
int
error
;
vrwlock_t
locktype
=
VRWLOCK_READ
;
error
=
xfs_dm_send_data_event
(
DM_EVENT_READ
,
bdp
,
*
offset
,
size
,
FILP_DELAY_FLAG
(
file
),
&
locktype
);
error
=
xfs_dm_send_data_event
(
DM_EVENT_READ
,
bdp
,
*
offp
,
size
,
FILP_DELAY_FLAG
(
filp
),
&
locktype
);
if
(
error
)
{
xfs_iunlock
(
ip
,
XFS_IOLOCK_SHARED
);
return
-
error
;
}
}
ret
=
generic_file_read
(
file
,
buf
,
size
,
offset
);
ret
=
generic_file_read
v
(
filp
,
iovp
,
segs
,
offp
);
xfs_iunlock
(
ip
,
XFS_IOLOCK_SHARED
);
XFS_STATS_ADD
(
xfsstats
.
xs_read_bytes
,
ret
);
if
(
!
(
fil
e
->
f_mode
&
FINVIS
))
if
(
!
(
fil
p
->
f_mode
&
FINVIS
))
xfs_ichgtime
(
ip
,
XFS_ICHGTIME_ACC
);
return
ret
;
...
...
@@ -418,32 +444,57 @@ xfs_zero_eof(
ssize_t
/* bytes written, or (-) error */
xfs_write
(
bhv_desc_t
*
bdp
,
struct
file
*
file
,
const
char
*
buf
,
size_t
size
,
loff_t
*
offset
,
cred_t
*
credp
)
bhv_desc_t
*
bdp
,
struct
file
*
file
,
const
struct
iovec
*
iovp
,
unsigned
long
segs
,
loff_t
*
offset
,
cred_t
*
credp
)
{
xfs_inode_t
*
xip
;
xfs_mount_t
*
mp
;
ssize_t
ret
;
int
error
=
0
;
xfs_fsize_t
isize
,
new_size
;
xfs_fsize_t
n
,
limit
=
XFS_MAX_FILE_OFFSET
;
xfs_iocore_t
*
io
;
vnode_t
*
vp
;
struct
iovec
iov
;
int
iolock
;
int
direct
=
file
->
f_flags
&
O_DIRECT
;
int
eventsent
=
0
;
vrwlock_t
locktype
;
size_t
size
=
0
;
xfs_inode_t
*
xip
;
xfs_mount_t
*
mp
;
ssize_t
ret
;
int
error
=
0
;
xfs_fsize_t
isize
,
new_size
;
xfs_fsize_t
n
,
limit
=
XFS_MAX_FILE_OFFSET
;
xfs_iocore_t
*
io
;
vnode_t
*
vp
;
unsigned
long
seg
;
int
iolock
;
int
direct
=
file
->
f_flags
&
O_DIRECT
;
int
eventsent
=
0
;
vrwlock_t
locktype
;
XFS_STATS_INC
(
xfsstats
.
xs_write_calls
);
vp
=
BHV_TO_VNODE
(
bdp
);
xip
=
XFS_BHVTOI
(
bdp
);
/* START copy & waste from filemap.c */
for
(
seg
=
0
;
seg
<
segs
;
seg
++
)
{
const
struct
iovec
*
iv
=
&
iovp
[
seg
];
/*
* If any segment has a negative length, or the cumulative
* length ever wraps negative then return -EINVAL.
*/
size
+=
iv
->
iov_len
;
if
(
unlikely
((
ssize_t
)(
size
|
iv
->
iov_len
)
<
0
))
return
XFS_ERROR
(
-
EINVAL
);
if
(
direct
)
{
/* XFS specific check */
if
((
__psint_t
)
iv
->
iov_base
&
BBMASK
)
return
XFS_ERROR
(
-
EINVAL
);
}
if
(
access_ok
(
VERIFY_READ
,
iv
->
iov_base
,
iv
->
iov_len
))
continue
;
if
(
seg
==
0
)
return
XFS_ERROR
(
-
EFAULT
);
segs
=
seg
;
break
;
}
/* END copy & waste from filemap.c */
if
(
size
==
0
)
return
0
;
...
...
@@ -457,9 +508,8 @@ xfs_write(
}
if
(
direct
)
{
if
(((
__psint_t
)
buf
&
BBMASK
)
||
(
*
offset
&
mp
->
m_blockmask
)
||
(
size
&
mp
->
m_blockmask
))
{
if
((
*
offset
&
mp
->
m_blockmask
)
||
(
size
&
mp
->
m_blockmask
))
{
return
XFS_ERROR
(
-
EINVAL
);
}
iolock
=
XFS_IOLOCK_SHARED
;
...
...
@@ -481,6 +531,7 @@ xfs_write(
xfs_iunlock
(
xip
,
XFS_ILOCK_EXCL
|
iolock
);
return
-
EFBIG
;
}
if
(
n
<
size
)
size
=
n
;
...
...
@@ -572,10 +623,7 @@ xfs_write(
xfs_inval_cached_pages
(
vp
,
&
xip
->
i_iocore
,
*
offset
,
1
,
1
);
}
iov
.
iov_base
=
(
void
*
)
buf
;
iov
.
iov_len
=
size
;
ret
=
generic_file_write_nolock
(
file
,
&
iov
,
1
,
offset
);
ret
=
generic_file_write_nolock
(
file
,
iovp
,
segs
,
offset
);
if
((
ret
==
-
ENOSPC
)
&&
DM_EVENT_ENABLED
(
vp
->
v_vfsp
,
xip
,
DM_EVENT_NOSPACE
)
&&
...
...
fs/xfs/linux/xfs_lrw.h
View file @
fdba8dd2
...
...
@@ -47,19 +47,19 @@ extern int xfs_bdstrat_cb (struct xfs_buf *);
extern
int
xfs_zero_eof
(
vnode_t
*
,
struct
xfs_iocore
*
,
xfs_off_t
,
xfs_fsize_t
,
xfs_fsize_t
,
struct
pm
*
);
extern
ssize_t
xfs_read
(
struct
bhv_desc
*
bdp
,
struct
file
*
fil
e
,
c
har
*
buf
,
size_t
size
,
loff_t
*
off
set
,
struct
cred
*
credp
);
struct
bhv_desc
*
bdp
,
struct
file
*
fil
p
,
c
onst
struct
iovec
*
iovp
,
unsigned
long
segs
,
loff_t
*
off
p
,
struct
cred
*
credp
);
extern
ssize_t
xfs_write
(
struct
bhv_desc
*
bdp
,
struct
file
*
fil
e
,
const
char
*
buf
,
size_t
size
,
loff_t
*
off
set
,
struct
file
*
fil
p
,
const
struct
iovec
*
iovp
,
unsigned
long
segs
,
loff_t
*
off
p
,
struct
cred
*
credp
);
extern
int
xfs_recover_read_only
(
xlog_t
*
);
...
...
fs/xfs/linux/xfs_vnode.h
View file @
fdba8dd2
...
...
@@ -56,10 +56,8 @@ typedef __u64 vnumber_t;
/*
* MP locking protocols:
* v_flag, v_count VN_LOCK/VN_UNLOCK
* v_vfsp VN_LOCK/VN_UNLOCK
* v_flag, v_vfsp VN_LOCK/VN_UNLOCK
* v_type read-only or fs-dependent
* v_list, v_hashp, v_hashn freelist lock
*/
typedef
struct
vnode
{
__u32
v_flag
;
/* vnode flags (see below) */
...
...
@@ -70,9 +68,9 @@ typedef struct vnode {
spinlock_t
v_lock
;
/* don't use VLOCK on Linux */
struct
inode
v_inode
;
/* linux inode */
#ifdef
CONFIG_XFS_VNODE_TRACING
#ifdef
CONFIG_XFS_VNODE_TRACING
struct
ktrace
*
v_trace
;
/* trace header structure */
#endif
/* CONFIG_XFS_VNODE_TRACING */
#endif
}
vnode_t
;
/*
...
...
@@ -170,7 +168,6 @@ typedef enum vchange {
#define v_fops v_bh.bh_first->bd_ops
/* ops for first behavior */
union
rval
;
struct
uio
;
struct
file
;
struct
vattr
;
...
...
@@ -178,9 +175,11 @@ struct page_buf_bmap_s;
struct
attrlist_cursor_kern
;
typedef
int
(
*
vop_open_t
)(
bhv_desc_t
*
,
struct
cred
*
);
typedef
ssize_t
(
*
vop_read_t
)(
bhv_desc_t
*
,
struct
file
*
,
char
*
,
size_t
,
typedef
ssize_t
(
*
vop_read_t
)(
bhv_desc_t
*
,
struct
file
*
,
const
struct
iovec
*
,
unsigned
long
,
loff_t
*
,
struct
cred
*
);
typedef
ssize_t
(
*
vop_write_t
)(
bhv_desc_t
*
,
struct
file
*
,
const
char
*
,
size_t
,
typedef
ssize_t
(
*
vop_write_t
)(
bhv_desc_t
*
,
struct
file
*
,
const
struct
iovec
*
,
unsigned
long
,
loff_t
*
,
struct
cred
*
);
typedef
int
(
*
vop_ioctl_t
)(
bhv_desc_t
*
,
struct
inode
*
,
struct
file
*
,
unsigned
int
,
unsigned
long
);
typedef
int
(
*
vop_getattr_t
)(
bhv_desc_t
*
,
struct
vattr
*
,
int
,
...
...
@@ -275,21 +274,16 @@ typedef struct vnodeops {
*/
#define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op)
/*
* Be careful with VOP_OPEN, since we're holding the chain lock on the
* original vnode and VOP_OPEN semantic allows the new vnode to be returned
* in vpp. The practice of passing &vp for vpp just doesn't work.
*/
#define VOP_READ(vp,file,buf,size,offset,cr,rv) \
#define VOP_READ(vp,file,iov,segs,offset,cr,rv) \
{ \
VN_BHV_READ_LOCK(&(vp)->v_bh); \
rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,
buf,size
,offset,cr); \
rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,
iov,segs
,offset,cr); \
VN_BHV_READ_UNLOCK(&(vp)->v_bh); \
}
#define VOP_WRITE(vp,file,
buf,size
,offset,cr,rv) \
#define VOP_WRITE(vp,file,
iov,segs
,offset,cr,rv) \
{ \
VN_BHV_READ_LOCK(&(vp)->v_bh); \
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,
buf,size
,offset,cr);\
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,
iov,segs
,offset,cr);\
VN_BHV_READ_UNLOCK(&(vp)->v_bh); \
}
#define VOP_BMAP(vp,of,sz,rw,cr,b,n,rv) \
...
...
fs/xfs/pagebuf/page_buf.c
View file @
fdba8dd2
...
...
@@ -55,11 +55,12 @@
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <linux/bio.h>
#include <asm/softirq.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <support/debug.h>
#include <support/kmem.h>
#include "page_buf_internal.h"
#define SECTOR_SHIFT 9
...
...
@@ -548,8 +549,8 @@ _pagebuf_lookup_pages(
}
else
if
(
!
PagePrivate
(
page
))
{
unsigned
long
i
,
range
=
(
offset
+
nbytes
)
>>
SECTOR_SHIFT
;
assert
(
blocksize
<
PAGE_CACHE_SIZE
);
assert
(
!
(
pb
->
pb_flags
&
_PBF_PRIVATE_BH
));
ASSERT
(
blocksize
<
PAGE_CACHE_SIZE
);
ASSERT
(
!
(
pb
->
pb_flags
&
_PBF_PRIVATE_BH
));
/*
* In this case page->private holds a bitmap
* of uptodate sectors (512) within the page
...
...
@@ -1317,8 +1318,8 @@ bio_end_io_pagebuf(
}
else
if
(
!
PagePrivate
(
page
))
{
unsigned
int
j
,
range
;
assert
(
blocksize
<
PAGE_CACHE_SIZE
);
assert
(
!
(
pb
->
pb_flags
&
_PBF_PRIVATE_BH
));
ASSERT
(
blocksize
<
PAGE_CACHE_SIZE
);
ASSERT
(
!
(
pb
->
pb_flags
&
_PBF_PRIVATE_BH
));
range
=
(
bvec
->
bv_offset
+
bvec
->
bv_len
)
>>
SECTOR_SHIFT
;
for
(
j
=
bvec
->
bv_offset
>>
SECTOR_SHIFT
;
j
<
range
;
j
++
)
...
...
@@ -1607,7 +1608,7 @@ pagebuf_iomove(
while
(
cboff
<
boff
)
{
pagebuf_segment
(
pb
,
&
cboff
,
&
page
,
&
cpoff
,
&
csize
);
assert
(((
csize
+
cpoff
)
<=
PAGE_CACHE_SIZE
));
ASSERT
(((
csize
+
cpoff
)
<=
PAGE_CACHE_SIZE
));
switch
(
mode
)
{
case
PBRW_ZERO
:
...
...
fs/xfs/pagebuf/page_buf.h
View file @
fdba8dd2
...
...
@@ -378,13 +378,6 @@ extern int pagebuf_ispin( page_buf_t *); /* check if pagebuf is pinned */
/* Reading and writing pages */
extern
int
pagebuf_write_full_page
(
/* write a page via pagebuf */
struct
page
*
,
/* page to write */
int
delalloc
);
/* delalloc bh present */
extern
int
pagebuf_release_page
(
/* Attempt to convert a delalloc page */
struct
page
*
);
/* page to release */
extern
void
pagebuf_delwri_queue
(
page_buf_t
*
,
int
);
extern
void
pagebuf_delwri_dequeue
(
page_buf_t
*
);
...
...
fs/xfs/pagebuf/page_buf_internal.h
View file @
fdba8dd2
...
...
@@ -151,18 +151,6 @@ extern struct pbstats pbstats;
#define PB_STATS_INC(count) ( count ++ )
#undef assert
#ifdef PAGEBUF_DEBUG
# define assert(expr) \
if (!(expr)) { \
printk("Assertion failed: %s\n%s::%s line %d\n",\
#expr,__FILE__,__FUNCTION__,__LINE__); \
BUG(); \
}
#else
# define assert(x) do { } while (0)
#endif
#ifndef STATIC
# define STATIC static
#endif
...
...
fs/xfs/pagebuf/page_buf_locking.c
View file @
fdba8dd2
...
...
@@ -54,6 +54,8 @@
#include <linux/init.h>
#include <linux/major.h>
#include <support/debug.h>
#include "page_buf_internal.h"
#ifndef EVMS_MAJOR
...
...
@@ -76,7 +78,7 @@ pagebuf_cond_lock( /* lock buffer, if not locked */
{
int
locked
;
assert
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
ASSERT
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
locked
=
down_trylock
(
&
PBP
(
pb
)
->
pb_sema
)
==
0
;
if
(
locked
)
{
...
...
@@ -97,7 +99,7 @@ int
pagebuf_lock_value
(
page_buf_t
*
pb
)
{
assert
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
ASSERT
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
return
(
atomic_read
(
&
PBP
(
pb
)
->
pb_sema
.
count
));
}
...
...
@@ -113,7 +115,7 @@ int
pagebuf_lock
(
page_buf_t
*
pb
)
{
assert
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
ASSERT
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
PB_TRACE
(
pb
,
PB_TRACE_REC
(
lock
),
0
);
if
(
atomic_read
(
&
PBP
(
pb
)
->
pb_io_remaining
))
...
...
@@ -219,7 +221,7 @@ void
pagebuf_unlock
(
/* unlock buffer */
page_buf_t
*
pb
)
/* buffer to unlock */
{
assert
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
ASSERT
(
pb
->
pb_flags
&
_PBF_LOCKABLE
);
PB_CLEAR_OWNER
(
pb
);
up
(
&
PBP
(
pb
)
->
pb_sema
);
PB_TRACE
(
pb
,
PB_TRACE_REC
(
unlock
),
0
);
...
...
fs/xfs/support/time.h
View file @
fdba8dd2
...
...
@@ -33,6 +33,7 @@
#define __XFS_SUPPORT_TIME_H__
#include <linux/sched.h>
#include <linux/time.h>
static
inline
void
delay
(
long
ticks
)
{
...
...
@@ -42,8 +43,11 @@ static inline void delay(long ticks)
static
inline
void
nanotime
(
struct
timespec
*
tvp
)
{
tvp
->
tv_sec
=
xtime
.
tv_sec
;
tvp
->
tv_nsec
=
xtime
.
tv_nsec
;
struct
timeval
tv
;
do_gettimeofday
(
&
tv
);
tvp
->
tv_sec
=
tv
.
tv_sec
;
tvp
->
tv_nsec
=
tv
.
tv_usec
*
1000
;
}
#endif
/* __XFS_SUPPORT_TIME_H__ */
fs/xfs/xfs_iget.c
View file @
fdba8dd2
...
...
@@ -507,26 +507,6 @@ xfs_iget(
}
/*
* A 'special' interface to xfs_iget, where the
* vnode is already allocated.
*/
int
xfs_vn_iget
(
vfs_t
*
vfsp
,
struct
vnode
*
vp
,
xfs_ino_t
ino
)
{
xfs_inode_t
*
ip
;
xfs_mount_t
*
mp
=
XFS_BHVTOM
(
vfsp
->
vfs_fbhv
);
int
error
;
error
=
xfs_iget_core
(
vp
,
mp
,
NULL
,
ino
,
0
,
&
ip
,
0
);
return
error
;
}
/*
* Do the setup for the various locks within the incore inode.
*/
...
...
fs/xfs/xfs_inode.h
View file @
fdba8dd2
...
...
@@ -490,7 +490,6 @@ xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
void
xfs_inode_lock_init
(
xfs_inode_t
*
,
struct
vnode
*
);
int
xfs_iget
(
struct
xfs_mount
*
,
struct
xfs_trans
*
,
xfs_ino_t
,
uint
,
xfs_inode_t
**
,
xfs_daddr_t
);
int
xfs_vn_iget
(
vfs_t
*
,
struct
vnode
*
,
xfs_ino_t
);
void
xfs_iput
(
xfs_inode_t
*
,
uint
);
void
xfs_iput_new
(
xfs_inode_t
*
,
uint
);
void
xfs_ilock
(
xfs_inode_t
*
,
uint
);
...
...
fs/xfs/xfs_mount.c
View file @
fdba8dd2
...
...
@@ -788,16 +788,6 @@ xfs_mountfs(
}
}
/*
* Disallow mount attempts with (IRIX) project quota enabled
*/
if
(
XFS_SB_VERSION_HASQUOTA
(
&
mp
->
m_sb
)
&&
(
mp
->
m_sb
.
sb_qflags
&
XFS_PQUOTA_ACCT
))
{
cmn_err
(
CE_WARN
,
"XFS: IRIX project quota are enabled"
);
error
=
XFS_ERROR
(
ENOSYS
);
goto
error1
;
}
/*
* Initialize realtime fields in the mount structure
*/
...
...
fs/xfs/xfs_rename.c
View file @
fdba8dd2
...
...
@@ -91,7 +91,6 @@ xfs_lock_for_rename(
int
error
;
int
i
,
j
;
uint
lock_mode
;
uint
lookup_flags
;
int
diff_dirs
=
(
dp1
!=
dp2
);
ip2
=
NULL
;
...
...
@@ -123,11 +122,7 @@ xfs_lock_for_rename(
lock_mode
=
xfs_ilock_map_shared
(
dp2
);
}
lookup_flags
=
DLF_IGET
;
if
(
lock_mode
==
XFS_ILOCK_SHARED
)
{
lookup_flags
|=
DLF_LOCK_SHARED
;
}
error
=
xfs_dir_lookup_int
(
XFS_ITOBHV
(
dp2
),
lookup_flags
,
error
=
xfs_dir_lookup_int
(
XFS_ITOBHV
(
dp2
),
lock_mode
,
dentry2
,
&
inum2
,
&
ip2
);
if
(
error
==
ENOENT
)
{
/* target does not need to exist. */
inum2
=
0
;
...
...
fs/xfs/xfs_utils.c
View file @
fdba8dd2
...
...
@@ -64,52 +64,27 @@ xfs_get_dir_entry(
return
0
;
}
/*
* Wrapper around xfs_dir_lookup.
*
* If DLF_IGET is set, then this routine will also return the inode.
* Note that the inode will not be locked. Note, however, that the
* vnode will have an additional reference in this case.
*/
int
xfs_dir_lookup_int
(
bhv_desc_t
*
dir_bdp
,
int
flags
,
uint
lock_mode
,
struct
dentry
*
dentry
,
xfs_ino_t
*
inum
,
xfs_inode_t
**
ipp
)
{
vnode_t
*
dir_vp
;
xfs_inode_t
*
dp
;
char
*
name
=
(
char
*
)
dentry
->
d_name
.
name
;
int
name_len
=
dentry
->
d_name
.
len
;
int
error
;
int
do_iget
;
uint
lock_mode
;
bhv_desc_t
*
bdp
;
dir_vp
=
BHV_TO_VNODE
(
dir_bdp
);
vn_trace_entry
(
dir_vp
,
"xfs_dir_lookup_int"
,
(
inst_t
*
)
__return_address
);
do_iget
=
flags
&
DLF_IGET
;
error
=
0
;
if
(
flags
&
DLF_LOCK_SHARED
)
{
lock_mode
=
XFS_ILOCK_SHARED
;
}
else
{
lock_mode
=
XFS_ILOCK_EXCL
;
}
dp
=
XFS_BHVTOI
(
dir_bdp
);
bdp
=
NULL
;
/*
* If all else fails, call the directory code.
*/
error
=
XFS_DIR_LOOKUP
(
dp
->
i_mount
,
NULL
,
dp
,
name
,
name_len
,
inum
);
if
(
!
error
&&
do_iget
)
{
error
=
XFS_DIR_LOOKUP
(
dp
->
i_mount
,
NULL
,
dp
,
(
char
*
)
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
inum
);
if
(
!
error
)
{
/*
* Unlock the directory. We do this because we can't
* hold the directory lock while doing the vn_get()
...
...
@@ -119,22 +94,12 @@ xfs_dir_lookup_int(
* reservation in the inactive routine.
*/
xfs_iunlock
(
dp
,
lock_mode
);
if
(
bdp
)
{
VN_RELE
(
BHV_TO_VNODE
(
bdp
));
bdp
=
NULL
;
}
error
=
xfs_iget
(
dp
->
i_mount
,
NULL
,
*
inum
,
0
,
ipp
,
0
);
xfs_ilock
(
dp
,
lock_mode
);
if
(
error
)
{
*
ipp
=
NULL
;
return
error
;
}
if
((
*
ipp
)
->
i_d
.
di_mode
==
0
)
{
}
else
if
((
*
ipp
)
->
i_d
.
di_mode
==
0
)
{
/*
* The inode has been freed. Something is
* wrong so just get out of here.
...
...
@@ -144,20 +109,8 @@ xfs_dir_lookup_int(
*
ipp
=
NULL
;
xfs_ilock
(
dp
,
lock_mode
);
error
=
XFS_ERROR
(
ENOENT
);
}
else
{
bdp
=
XFS_ITOBHV
(
*
ipp
);
bdp
=
NULL
;
}
}
if
(
bdp
)
{
/* The only time we should get here is if the dir_lookup
* failed.
*/
ASSERT
(
error
);
xfs_iunlock
(
dp
,
lock_mode
);
VN_RELE
(
BHV_TO_VNODE
(
bdp
));
xfs_ilock
(
dp
,
lock_mode
);
}
return
error
;
}
...
...
fs/xfs/xfs_utils.h
View file @
fdba8dd2
...
...
@@ -37,9 +37,6 @@
#define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \
(inst_t *)__return_address)
#define DLF_IGET 0x01
/* get entry inode if name lookup succeeds */
#define DLF_LOCK_SHARED 0x02
/* directory locked shared */
struct
bhv_desc
;
struct
cred
;
struct
vnode
;
...
...
@@ -63,7 +60,7 @@ xfs_get_dir_entry(
extern
int
xfs_dir_lookup_int
(
struct
bhv_desc
*
dir_bdp
,
int
flags
,
uint
lock_mode
,
struct
dentry
*
dentry
,
xfs_ino_t
*
inum
,
struct
xfs_inode
**
ipp
);
...
...
fs/xfs/xfs_vfsops.c
View file @
fdba8dd2
This diff is collapsed.
Click to expand it.
fs/xfs/xfs_vnodeops.c
View file @
fdba8dd2
...
...
@@ -1144,138 +1144,70 @@ xfs_fsync(
* (Note that xfs_inode_item_format() called at commit clears
* the update_* fields.)
*/
if
(
!
(
flag
&
FSYNC_DATA
))
{
xfs_ilock
(
ip
,
XFS_ILOCK_SHARED
);
xfs_ilock
(
ip
,
XFS_ILOCK_SHARED
);
if
(
ip
->
i_update_core
==
0
)
{
/*
* Timestamps/size haven't changed since last inode
* flush or inode transaction commit. That means
* either nothing got written or a transaction
* committed which caught the updates. If the
* latter happened and the transaction hasn't
* hit the disk yet, the inode will be still
* be pinned. If it is, force the log.
*/
if
(
xfs_ipincount
(
ip
)
==
0
)
{
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_SHARED
);
}
else
{
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_SHARED
);
xfs_log_force
(
ip
->
i_mount
,
(
xfs_lsn_t
)
0
,
XFS_LOG_FORCE
|
((
flag
&
FSYNC_WAIT
)
?
XFS_LOG_SYNC
:
0
));
}
error
=
0
;
}
else
{
/*
* Kick off a transaction to log the inode
* core to get the updates. Make it
* sync if FSYNC_WAIT is passed in (which
* is done by everybody but specfs). The
* sync transaction will also force the log.
*/
xfs_iunlock
(
ip
,
XFS_ILOCK_SHARED
);
tp
=
xfs_trans_alloc
(
ip
->
i_mount
,
XFS_TRANS_FSYNC_TS
);
if
((
error
=
xfs_trans_reserve
(
tp
,
0
,
XFS_FSYNC_TS_LOG_RES
(
ip
->
i_mount
),
0
,
0
,
0
)))
{
xfs_trans_cancel
(
tp
,
0
);
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
);
return
error
;
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
/* If we are flushing data then we care about update_size
* being set, otherwise we care about update_core
*/
if
((
flag
&
FSYNC_DATA
)
?
(
ip
->
i_update_size
==
0
)
:
(
ip
->
i_update_core
==
0
))
{
/*
* Timestamps/size haven't changed since last inode
* flush or inode transaction commit. That means
* either nothing got written or a transaction
* committed which caught the updates. If the
* latter happened and the transaction hasn't
* hit the disk yet, the inode will be still
* be pinned. If it is, force the log.
*/
/*
* Note - it's possible that we might have pushed
* ourselves out of the way during trans_reserve
* which would flush the inode. But there's no
* guarantee that the inode buffer has actually
* gone out yet (it's delwri). Plus the buffer
* could be pinned anyway if it's part of an
* inode in another recent transaction. So we
* play it safe and fire off the transaction anyway.
*/
xfs_trans_ijoin
(
tp
,
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
xfs_trans_log_inode
(
tp
,
ip
,
XFS_ILOG_CORE
);
if
(
flag
&
FSYNC_WAIT
)
xfs_trans_set_sync
(
tp
);
error
=
xfs_trans_commit
(
tp
,
0
,
NULL
);
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_EXCL
);
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_SHARED
);
if
(
xfs_ipincount
(
ip
))
{
xfs_log_force
(
ip
->
i_mount
,
(
xfs_lsn_t
)
0
,
XFS_LOG_FORCE
|
((
flag
&
FSYNC_WAIT
)
?
XFS_LOG_SYNC
:
0
));
}
}
else
{
error
=
0
;
}
else
{
/*
* We don't care about the timestamps here. We
* only care about the size field growing on us
* and forcing any space allocation transactions.
* We have to flush changes to the size fields
* otherwise we could write out data that
* becomes inaccessible after a crash.
* Kick off a transaction to log the inode
* core to get the updates. Make it
* sync if FSYNC_WAIT is passed in (which
* is done by everybody but specfs). The
* sync transaction will also force the log.
*/
xfs_ilock
(
ip
,
XFS_ILOCK_SHARED
);
if
(
ip
->
i_update_size
==
0
)
{
/*
* Force the log if the inode is pinned.
* That ensures that all transactions committed
* against the inode hit the disk. This may do
* too much work but it's safe.
*/
if
(
xfs_ipincount
(
ip
)
==
0
)
{
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_SHARED
);
}
else
{
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_SHARED
);
xfs_log_force
(
ip
->
i_mount
,
(
xfs_lsn_t
)
0
,
XFS_LOG_FORCE
|
((
flag
&
FSYNC_WAIT
)
?
XFS_LOG_SYNC
:
0
));
}
error
=
0
;
}
else
{
/*
* Kick off a sync transaction to log the inode
* core. The transaction has to be sync since
* we need these updates to guarantee that the
* data written will be seen. The sync
* transaction will also force the log.
*/
xfs_iunlock
(
ip
,
XFS_ILOCK_SHARED
);
xfs_iunlock
(
ip
,
XFS_ILOCK_SHARED
);
tp
=
xfs_trans_alloc
(
ip
->
i_mount
,
XFS_TRANS_FSYNC_TS
);
if
((
error
=
xfs_trans_reserve
(
tp
,
0
,
XFS_FSYNC_TS_LOG_RES
(
ip
->
i_mount
),
0
,
0
,
0
)))
{
xfs_trans_cancel
(
tp
,
0
);
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
);
return
error
;
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
tp
=
xfs_trans_alloc
(
ip
->
i_mount
,
XFS_TRANS_FSYNC_TS
);
if
((
error
=
xfs_trans_reserve
(
tp
,
0
,
XFS_FSYNC_TS_LOG_RES
(
ip
->
i_mount
),
0
,
0
,
0
)))
{
xfs_trans_cancel
(
tp
,
0
);
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
);
return
error
;
}
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
/*
* Note - it's possible that we might have pushed
* ourselves out of the way during trans_reserve
* which would flush the inode. But there's no
* guarantee that the inode buffer has actually
* gone out yet (it's delwri). Plus the buffer
* could be pinned anyway if it's part of an
* inode in another recent transaction. So we
* play it safe and fire off the transaction anyway.
*/
xfs_trans_ijoin
(
tp
,
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
xfs_trans_log_inode
(
tp
,
ip
,
XFS_ILOG_CORE
);
if
(
flag
&
FSYNC_WAIT
)
xfs_trans_set_sync
(
tp
);
error
=
xfs_trans_commit
(
tp
,
0
,
NULL
);
/*
* Note - it's possible that we might have pushed
* ourselves out of the way during trans_reserve
* which would flush the inode. But there's no
* guarantee that the inode buffer has actually
* gone out yet (it's delwri). Plus the buffer
* could be pinned anyway if it's part of an
* inode in another recent transaction. So we
* play it safe and fire off the transaction anyway.
*/
xfs_trans_ijoin
(
tp
,
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_EXCL
);
xfs_trans_ihold
(
tp
,
ip
);
xfs_trans_log_inode
(
tp
,
ip
,
XFS_ILOG_CORE
);
if
(
flag
&
FSYNC_WAIT
)
xfs_trans_set_sync
(
tp
);
error
=
xfs_trans_commit
(
tp
,
0
,
NULL
);
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_EXCL
);
}
xfs_iunlock
(
ip
,
XFS_IOLOCK_EXCL
|
XFS_ILOCK_EXCL
);
}
return
error
;
}
...
...
@@ -1958,7 +1890,6 @@ xfs_lookup(
xfs_ino_t
e_inum
;
int
error
;
uint
lock_mode
;
uint
lookup_flags
;
vnode_t
*
dir_vp
;
dir_vp
=
BHV_TO_VNODE
(
dir_bdp
);
...
...
@@ -1971,12 +1902,7 @@ xfs_lookup(
return
XFS_ERROR
(
EIO
);
lock_mode
=
xfs_ilock_map_shared
(
dp
);
lookup_flags
=
DLF_IGET
;
if
(
lock_mode
==
XFS_ILOCK_SHARED
)
{
lookup_flags
|=
DLF_LOCK_SHARED
;
}
error
=
xfs_dir_lookup_int
(
dir_bdp
,
lookup_flags
,
dentry
,
&
e_inum
,
&
ip
);
error
=
xfs_dir_lookup_int
(
dir_bdp
,
lock_mode
,
dentry
,
&
e_inum
,
&
ip
);
if
(
error
)
{
xfs_iunlock_map_shared
(
dp
,
lock_mode
);
return
error
;
...
...
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