Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
668f455d
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
668f455d
编写于
7月 24, 2016
作者:
T
Trond Myklebust
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'pnfs'
上级
36274526
01d7b29f
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
218 addition
and
136 deletion
+218
-136
fs/nfs/blocklayout/dev.c
fs/nfs/blocklayout/dev.c
+75
-35
fs/nfs/callback_proc.c
fs/nfs/callback_proc.c
+44
-20
fs/nfs/nfs42proc.c
fs/nfs/nfs42proc.c
+1
-2
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+2
-4
fs/nfs/pnfs.c
fs/nfs/pnfs.c
+89
-62
fs/nfs/pnfs.h
fs/nfs/pnfs.h
+7
-13
未找到文件。
fs/nfs/blocklayout/dev.c
浏览文件 @
668f455d
...
...
@@ -65,8 +65,8 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
if
(
!
p
)
return
-
EIO
;
b
->
simple
.
nr_sigs
=
be32_to_cpup
(
p
++
);
if
(
!
b
->
simple
.
nr_sigs
)
{
dprintk
(
"
no signature
\n
"
);
if
(
!
b
->
simple
.
nr_sigs
||
b
->
simple
.
nr_sigs
>
PNFS_BLOCK_MAX_UUIDS
)
{
dprintk
(
"
Bad signature count: %d
\n
"
,
b
->
simple
.
nr_sigs
);
return
-
EIO
;
}
...
...
@@ -89,7 +89,8 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
memcpy
(
&
b
->
simple
.
sigs
[
i
].
sig
,
p
,
b
->
simple
.
sigs
[
i
].
sig_len
);
b
->
simple
.
len
+=
8
+
4
+
b
->
simple
.
sigs
[
i
].
sig_len
;
b
->
simple
.
len
+=
8
+
4
+
\
(
XDR_QUADLEN
(
b
->
simple
.
sigs
[
i
].
sig_len
)
<<
2
);
}
break
;
case
PNFS_BLOCK_VOLUME_SLICE
:
...
...
@@ -104,7 +105,12 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
p
=
xdr_inline_decode
(
xdr
,
4
);
if
(
!
p
)
return
-
EIO
;
b
->
concat
.
volumes_count
=
be32_to_cpup
(
p
++
);
if
(
b
->
concat
.
volumes_count
>
PNFS_BLOCK_MAX_DEVICES
)
{
dprintk
(
"Too many volumes: %d
\n
"
,
b
->
concat
.
volumes_count
);
return
-
EIO
;
}
p
=
xdr_inline_decode
(
xdr
,
b
->
concat
.
volumes_count
*
4
);
if
(
!
p
)
...
...
@@ -116,8 +122,13 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
p
=
xdr_inline_decode
(
xdr
,
8
+
4
);
if
(
!
p
)
return
-
EIO
;
p
=
xdr_decode_hyper
(
p
,
&
b
->
stripe
.
chunk_size
);
b
->
stripe
.
volumes_count
=
be32_to_cpup
(
p
++
);
if
(
b
->
stripe
.
volumes_count
>
PNFS_BLOCK_MAX_DEVICES
)
{
dprintk
(
"Too many volumes: %d
\n
"
,
b
->
stripe
.
volumes_count
);
return
-
EIO
;
}
p
=
xdr_inline_decode
(
xdr
,
b
->
stripe
.
volumes_count
*
4
);
if
(
!
p
)
...
...
@@ -224,18 +235,20 @@ bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d,
struct
pnfs_block_volume
*
volumes
,
int
idx
,
gfp_t
gfp_mask
)
{
struct
pnfs_block_volume
*
v
=
&
volumes
[
idx
];
struct
block_device
*
bdev
;
dev_t
dev
;
dev
=
bl_resolve_deviceid
(
server
,
v
,
gfp_mask
);
if
(
!
dev
)
return
-
EIO
;
d
->
bdev
=
blkdev_get_by_dev
(
dev
,
FMODE_READ
|
FMODE_WRITE
,
NULL
);
if
(
IS_ERR
(
d
->
bdev
))
{
bdev
=
blkdev_get_by_dev
(
dev
,
FMODE_READ
|
FMODE_WRITE
,
NULL
);
if
(
IS_ERR
(
bdev
))
{
printk
(
KERN_WARNING
"pNFS: failed to open device %d:%d (%ld)
\n
"
,
MAJOR
(
dev
),
MINOR
(
dev
),
PTR_ERR
(
d
->
bdev
));
return
PTR_ERR
(
d
->
bdev
);
MAJOR
(
dev
),
MINOR
(
dev
),
PTR_ERR
(
bdev
));
return
PTR_ERR
(
bdev
);
}
d
->
bdev
=
bdev
;
d
->
len
=
i_size_read
(
d
->
bdev
->
bd_inode
);
...
...
@@ -287,44 +300,71 @@ bl_validate_designator(struct pnfs_block_volume *v)
}
}
/*
* Try to open the udev path for the WWN. At least on Debian the udev
* by-id path will always point to the dm-multipath device if one exists.
*/
static
struct
block_device
*
bl_open_udev_path
(
struct
pnfs_block_volume
*
v
)
{
struct
block_device
*
bdev
;
const
char
*
devname
;
devname
=
kasprintf
(
GFP_KERNEL
,
"/dev/disk/by-id/wwn-0x%*phN"
,
v
->
scsi
.
designator_len
,
v
->
scsi
.
designator
);
if
(
!
devname
)
return
ERR_PTR
(
-
ENOMEM
);
bdev
=
blkdev_get_by_path
(
devname
,
FMODE_READ
|
FMODE_WRITE
,
NULL
);
if
(
IS_ERR
(
bdev
))
{
pr_warn
(
"pNFS: failed to open device %s (%ld)
\n
"
,
devname
,
PTR_ERR
(
bdev
));
}
kfree
(
devname
);
return
bdev
;
}
/*
* Try to open the RH/Fedora specific dm-mpath udev path for this WWN, as the
* wwn- links will only point to the first discovered SCSI device there.
*/
static
struct
block_device
*
bl_open_dm_mpath_udev_path
(
struct
pnfs_block_volume
*
v
)
{
struct
block_device
*
bdev
;
const
char
*
devname
;
devname
=
kasprintf
(
GFP_KERNEL
,
"/dev/disk/by-id/dm-uuid-mpath-%d%*phN"
,
v
->
scsi
.
designator_type
,
v
->
scsi
.
designator_len
,
v
->
scsi
.
designator
);
if
(
!
devname
)
return
ERR_PTR
(
-
ENOMEM
);
bdev
=
blkdev_get_by_path
(
devname
,
FMODE_READ
|
FMODE_WRITE
,
NULL
);
kfree
(
devname
);
return
bdev
;
}
static
int
bl_parse_scsi
(
struct
nfs_server
*
server
,
struct
pnfs_block_dev
*
d
,
struct
pnfs_block_volume
*
volumes
,
int
idx
,
gfp_t
gfp_mask
)
{
struct
pnfs_block_volume
*
v
=
&
volumes
[
idx
];
struct
block_device
*
bdev
;
const
struct
pr_ops
*
ops
;
const
char
*
devname
;
int
error
;
if
(
!
bl_validate_designator
(
v
))
return
-
EINVAL
;
switch
(
v
->
scsi
.
designator_len
)
{
case
8
:
devname
=
kasprintf
(
GFP_KERNEL
,
"/dev/disk/by-id/wwn-0x%8phN"
,
v
->
scsi
.
designator
);
break
;
case
12
:
devname
=
kasprintf
(
GFP_KERNEL
,
"/dev/disk/by-id/wwn-0x%12phN"
,
v
->
scsi
.
designator
);
break
;
case
16
:
devname
=
kasprintf
(
GFP_KERNEL
,
"/dev/disk/by-id/wwn-0x%16phN"
,
v
->
scsi
.
designator
);
break
;
default:
return
-
EINVAL
;
}
d
->
bdev
=
blkdev_get_by_path
(
devname
,
FMODE_READ
,
NULL
);
if
(
IS_ERR
(
d
->
bdev
))
{
pr_warn
(
"pNFS: failed to open device %s (%ld)
\n
"
,
devname
,
PTR_ERR
(
d
->
bdev
));
kfree
(
devname
);
return
PTR_ERR
(
d
->
bdev
);
}
kfree
(
devname
);
bdev
=
bl_open_dm_mpath_udev_path
(
v
);
if
(
IS_ERR
(
bdev
))
bdev
=
bl_open_udev_path
(
v
);
if
(
IS_ERR
(
bdev
))
return
PTR_ERR
(
bdev
);
d
->
bdev
=
bdev
;
d
->
len
=
i_size_read
(
d
->
bdev
->
bd_inode
);
d
->
map
=
bl_map_simple
;
...
...
@@ -352,7 +392,7 @@ bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
return
0
;
out_blkdev_put:
blkdev_put
(
d
->
bdev
,
FMODE_READ
);
blkdev_put
(
d
->
bdev
,
FMODE_READ
|
FMODE_WRITE
);
return
error
;
}
...
...
fs/nfs/callback_proc.c
浏览文件 @
668f455d
...
...
@@ -119,27 +119,30 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
* hashed by filehandle.
*/
static
struct
pnfs_layout_hdr
*
get_layout_by_fh_locked
(
struct
nfs_client
*
clp
,
struct
nfs_fh
*
fh
,
nfs4_stateid
*
stateid
)
struct
nfs_fh
*
fh
)
{
struct
nfs_server
*
server
;
struct
nfs_inode
*
nfsi
;
struct
inode
*
ino
;
struct
pnfs_layout_hdr
*
lo
;
restart:
list_for_each_entry_rcu
(
server
,
&
clp
->
cl_superblocks
,
client_link
)
{
list_for_each_entry
(
lo
,
&
server
->
layouts
,
plh_layouts
)
{
if
(
!
nfs4_stateid_match_other
(
&
lo
->
plh_stateid
,
stateid
))
nfsi
=
NFS_I
(
lo
->
plh_inode
);
if
(
nfs_compare_fh
(
fh
,
&
nfsi
->
fh
))
continue
;
if
(
nfs
_compare_fh
(
fh
,
&
NFS_I
(
lo
->
plh_inode
)
->
fh
)
)
if
(
nfs
i
->
layout
!=
lo
)
continue
;
ino
=
igrab
(
lo
->
plh_inode
);
if
(
!
ino
)
break
;
spin_lock
(
&
ino
->
i_lock
);
/* Is this layout in the process of being freed? */
if
(
NFS_I
(
ino
)
->
layout
!=
lo
)
{
if
(
nfsi
->
layout
!=
lo
)
{
spin_unlock
(
&
ino
->
i_lock
);
iput
(
ino
);
break
;
goto
restart
;
}
pnfs_get_layout_hdr
(
lo
);
spin_unlock
(
&
ino
->
i_lock
);
...
...
@@ -151,13 +154,13 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
}
static
struct
pnfs_layout_hdr
*
get_layout_by_fh
(
struct
nfs_client
*
clp
,
struct
nfs_fh
*
fh
,
nfs4_stateid
*
stateid
)
struct
nfs_fh
*
fh
)
{
struct
pnfs_layout_hdr
*
lo
;
spin_lock
(
&
clp
->
cl_lock
);
rcu_read_lock
();
lo
=
get_layout_by_fh_locked
(
clp
,
fh
,
stateid
);
lo
=
get_layout_by_fh_locked
(
clp
,
fh
);
rcu_read_unlock
();
spin_unlock
(
&
clp
->
cl_lock
);
...
...
@@ -167,17 +170,39 @@ static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
/*
* Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing)
*/
static
bool
pnfs_check_stateid_sequence
(
struct
pnfs_layout_hdr
*
lo
,
static
u32
pnfs_check_callback_stateid
(
struct
pnfs_layout_hdr
*
lo
,
const
nfs4_stateid
*
new
)
{
u32
oldseq
,
newseq
;
oldseq
=
be32_to_cpu
(
lo
->
plh_stateid
.
seqid
);
/* Is the stateid still not initialised? */
if
(
!
pnfs_layout_is_valid
(
lo
))
return
NFS4ERR_DELAY
;
/* Mismatched stateid? */
if
(
!
nfs4_stateid_match_other
(
&
lo
->
plh_stateid
,
new
))
return
NFS4ERR_BAD_STATEID
;
newseq
=
be32_to_cpu
(
new
->
seqid
);
/* Are we already in a layout recall situation? */
if
(
test_bit
(
NFS_LAYOUT_RETURN_REQUESTED
,
&
lo
->
plh_flags
)
&&
lo
->
plh_return_seq
!=
0
)
{
if
(
newseq
<
lo
->
plh_return_seq
)
return
NFS4ERR_OLD_STATEID
;
if
(
newseq
>
lo
->
plh_return_seq
)
return
NFS4ERR_DELAY
;
goto
out
;
}
/* Check that the stateid matches what we think it should be. */
oldseq
=
be32_to_cpu
(
lo
->
plh_stateid
.
seqid
);
if
(
newseq
>
oldseq
+
1
)
return
false
;
return
true
;
return
NFS4ERR_DELAY
;
/* Crazy server! */
if
(
newseq
<=
oldseq
)
return
NFS4ERR_OLD_STATEID
;
out:
return
NFS_OK
;
}
static
u32
initiate_file_draining
(
struct
nfs_client
*
clp
,
...
...
@@ -188,7 +213,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
u32
rv
=
NFS4ERR_NOMATCHING_LAYOUT
;
LIST_HEAD
(
free_me_list
);
lo
=
get_layout_by_fh
(
clp
,
&
args
->
cbl_fh
,
&
args
->
cbl_stateid
);
lo
=
get_layout_by_fh
(
clp
,
&
args
->
cbl_fh
);
if
(
!
lo
)
{
trace_nfs4_cb_layoutrecall_file
(
clp
,
&
args
->
cbl_fh
,
NULL
,
&
args
->
cbl_stateid
,
-
rv
);
...
...
@@ -196,18 +221,15 @@ static u32 initiate_file_draining(struct nfs_client *clp,
}
ino
=
lo
->
plh_inode
;
pnfs_layoutcommit_inode
(
ino
,
false
);
spin_lock
(
&
ino
->
i_lock
);
if
(
!
pnfs_check_stateid_sequence
(
lo
,
&
args
->
cbl_stateid
))
{
rv
=
NFS4ERR_DELAY
;
rv
=
pnfs_check_callback_stateid
(
lo
,
&
args
->
cbl_stateid
);
if
(
rv
!=
NFS_OK
)
goto
unlock
;
}
pnfs_set_layout_stateid
(
lo
,
&
args
->
cbl_stateid
,
true
);
spin_unlock
(
&
ino
->
i_lock
);
pnfs_layoutcommit_inode
(
ino
,
false
);
spin_lock
(
&
ino
->
i_lock
);
/*
* Enforce RFC5661 Section 12.5.5.2.1.5 (Bulk Recall and Return)
*/
...
...
@@ -223,11 +245,13 @@ static u32 initiate_file_draining(struct nfs_client *clp,
goto
unlock
;
}
/* Embrace your forgetfulness! */
rv
=
NFS4ERR_NOMATCHING_LAYOUT
;
if
(
NFS_SERVER
(
ino
)
->
pnfs_curr_ld
->
return_range
)
{
NFS_SERVER
(
ino
)
->
pnfs_curr_ld
->
return_range
(
lo
,
&
args
->
cbl_range
);
}
pnfs_mark_layout_returned_if_empty
(
lo
);
unlock:
spin_unlock
(
&
ino
->
i_lock
);
pnfs_free_lseg_list
(
&
free_me_list
);
...
...
fs/nfs/nfs42proc.c
浏览文件 @
668f455d
...
...
@@ -351,8 +351,7 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
* Mark the bad layout state as invalid, then retry
* with the current stateid.
*/
set_bit
(
NFS_LAYOUT_INVALID_STID
,
&
lo
->
plh_flags
);
pnfs_mark_matching_lsegs_invalid
(
lo
,
&
head
,
NULL
,
0
);
pnfs_mark_layout_stateid_invalid
(
lo
,
&
head
);
spin_unlock
(
&
inode
->
i_lock
);
pnfs_free_lseg_list
(
&
head
);
}
else
...
...
fs/nfs/nfs4proc.c
浏览文件 @
668f455d
...
...
@@ -7944,8 +7944,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
/*
* Mark the bad layout state as invalid, then retry
*/
set_bit
(
NFS_LAYOUT_INVALID_STID
,
&
lo
->
plh_flags
);
pnfs_mark_matching_lsegs_invalid
(
lo
,
&
head
,
NULL
,
0
);
pnfs_mark_layout_stateid_invalid
(
lo
,
&
head
);
spin_unlock
(
&
inode
->
i_lock
);
pnfs_free_lseg_list
(
&
head
);
status
=
-
EAGAIN
;
...
...
@@ -8144,8 +8143,7 @@ static void nfs4_layoutreturn_release(void *calldata)
spin_lock
(
&
lo
->
plh_inode
->
i_lock
);
pnfs_mark_matching_lsegs_invalid
(
lo
,
&
freeme
,
&
lrp
->
args
.
range
,
be32_to_cpu
(
lrp
->
args
.
stateid
.
seqid
));
pnfs_mark_layout_returned_if_empty
(
lo
);
if
(
lrp
->
res
.
lrs_present
)
if
(
lrp
->
res
.
lrs_present
&&
pnfs_layout_is_valid
(
lo
))
pnfs_set_layout_stateid
(
lo
,
&
lrp
->
res
.
stateid
,
true
);
pnfs_clear_layoutreturn_waitbit
(
lo
);
spin_unlock
(
&
lo
->
plh_inode
->
i_lock
);
...
...
fs/nfs/pnfs.c
浏览文件 @
668f455d
...
...
@@ -259,7 +259,7 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
* is required.
* Note that caller must hold inode->i_lock.
*/
static
int
int
pnfs_mark_layout_stateid_invalid
(
struct
pnfs_layout_hdr
*
lo
,
struct
list_head
*
lseg_list
)
{
...
...
@@ -334,14 +334,17 @@ pnfs_layout_io_test_failed(struct pnfs_layout_hdr *lo, u32 iomode)
}
static
void
init_lseg
(
struct
pnfs_layout_hdr
*
lo
,
struct
pnfs_layout_segment
*
lseg
)
pnfs_init_lseg
(
struct
pnfs_layout_hdr
*
lo
,
struct
pnfs_layout_segment
*
lseg
,
const
struct
pnfs_layout_range
*
range
,
const
nfs4_stateid
*
stateid
)
{
INIT_LIST_HEAD
(
&
lseg
->
pls_list
);
INIT_LIST_HEAD
(
&
lseg
->
pls_lc_list
);
atomic_set
(
&
lseg
->
pls_refcount
,
1
);
smp_mb
();
set_bit
(
NFS_LSEG_VALID
,
&
lseg
->
pls_flags
);
lseg
->
pls_layout
=
lo
;
lseg
->
pls_range
=
*
range
;
lseg
->
pls_seq
=
be32_to_cpu
(
stateid
->
seqid
);
}
static
void
pnfs_free_lseg
(
struct
pnfs_layout_segment
*
lseg
)
...
...
@@ -486,15 +489,6 @@ pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1,
(
end2
==
NFS4_MAX_UINT64
||
end2
>
start1
);
}
static
bool
should_free_lseg
(
const
struct
pnfs_layout_range
*
lseg_range
,
const
struct
pnfs_layout_range
*
recall_range
)
{
return
(
recall_range
->
iomode
==
IOMODE_ANY
||
lseg_range
->
iomode
==
recall_range
->
iomode
)
&&
pnfs_lseg_range_intersecting
(
lseg_range
,
recall_range
);
}
static
bool
pnfs_lseg_dec_and_remove_zero
(
struct
pnfs_layout_segment
*
lseg
,
struct
list_head
*
tmp_list
)
{
...
...
@@ -533,6 +527,27 @@ static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
return
(
s32
)(
s1
-
s2
)
>
0
;
}
static
bool
pnfs_should_free_range
(
const
struct
pnfs_layout_range
*
lseg_range
,
const
struct
pnfs_layout_range
*
recall_range
)
{
return
(
recall_range
->
iomode
==
IOMODE_ANY
||
lseg_range
->
iomode
==
recall_range
->
iomode
)
&&
pnfs_lseg_range_intersecting
(
lseg_range
,
recall_range
);
}
static
bool
pnfs_match_lseg_recall
(
const
struct
pnfs_layout_segment
*
lseg
,
const
struct
pnfs_layout_range
*
recall_range
,
u32
seq
)
{
if
(
seq
!=
0
&&
pnfs_seqid_is_newer
(
lseg
->
pls_seq
,
seq
))
return
false
;
if
(
recall_range
==
NULL
)
return
true
;
return
pnfs_should_free_range
(
&
lseg
->
pls_range
,
recall_range
);
}
/**
* pnfs_mark_matching_lsegs_invalid - tear down lsegs or mark them for later
* @lo: layout header containing the lsegs
...
...
@@ -562,10 +577,7 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
if
(
list_empty
(
&
lo
->
plh_segs
))
return
0
;
list_for_each_entry_safe
(
lseg
,
next
,
&
lo
->
plh_segs
,
pls_list
)
if
(
!
recall_range
||
should_free_lseg
(
&
lseg
->
pls_range
,
recall_range
))
{
if
(
seq
&&
pnfs_seqid_is_newer
(
lseg
->
pls_seq
,
seq
))
continue
;
if
(
pnfs_match_lseg_recall
(
lseg
,
recall_range
,
seq
))
{
dprintk
(
"%s: freeing lseg %p iomode %d seq %u"
"offset %llu length %llu
\n
"
,
__func__
,
lseg
,
lseg
->
pls_range
.
iomode
,
lseg
->
pls_seq
,
...
...
@@ -761,24 +773,25 @@ void
pnfs_set_layout_stateid
(
struct
pnfs_layout_hdr
*
lo
,
const
nfs4_stateid
*
new
,
bool
update_barrier
)
{
u32
oldseq
,
newseq
,
new_barrier
;
int
empty
=
list_empty
(
&
lo
->
plh_segs
);
u32
oldseq
,
newseq
,
new_barrier
=
0
;
bool
invalid
=
!
pnfs_layout_is_valid
(
lo
);
oldseq
=
be32_to_cpu
(
lo
->
plh_stateid
.
seqid
);
newseq
=
be32_to_cpu
(
new
->
seqid
);
if
(
empty
||
pnfs_seqid_is_newer
(
newseq
,
oldseq
))
{
if
(
invalid
||
pnfs_seqid_is_newer
(
newseq
,
oldseq
))
{
nfs4_stateid_copy
(
&
lo
->
plh_stateid
,
new
);
if
(
update_barrier
)
{
new_barrier
=
be32_to_cpu
(
new
->
seqid
);
}
else
{
/* Because of wraparound, we want to keep the barrier
* "close" to the current seqids.
*/
new_barrier
=
newseq
-
atomic_read
(
&
lo
->
plh_outstanding
);
}
if
(
empty
||
pnfs_seqid_is_newer
(
new_barrier
,
lo
->
plh_barrier
))
lo
->
plh_barrier
=
new_barrier
;
/*
* Because of wraparound, we want to keep the barrier
* "close" to the current seqids.
*/
new_barrier
=
newseq
-
atomic_read
(
&
lo
->
plh_outstanding
);
}
if
(
update_barrier
)
new_barrier
=
be32_to_cpu
(
new
->
seqid
);
else
if
(
new_barrier
==
0
)
return
;
if
(
invalid
||
pnfs_seqid_is_newer
(
new_barrier
,
lo
->
plh_barrier
))
lo
->
plh_barrier
=
new_barrier
;
}
static
bool
...
...
@@ -873,15 +886,37 @@ void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo)
rpc_wake_up
(
&
NFS_SERVER
(
lo
->
plh_inode
)
->
roc_rpcwaitq
);
}
static
void
pnfs_clear_layoutreturn_info
(
struct
pnfs_layout_hdr
*
lo
)
{
lo
->
plh_return_iomode
=
0
;
lo
->
plh_return_seq
=
0
;
clear_bit
(
NFS_LAYOUT_RETURN_REQUESTED
,
&
lo
->
plh_flags
);
}
static
bool
pnfs_prepare_layoutreturn
(
struct
pnfs_layout_hdr
*
lo
)
pnfs_prepare_layoutreturn
(
struct
pnfs_layout_hdr
*
lo
,
nfs4_stateid
*
stateid
,
enum
pnfs_iomode
*
iomode
)
{
if
(
test_and_set_bit
(
NFS_LAYOUT_RETURN
,
&
lo
->
plh_flags
))
return
false
;
lo
->
plh_return_iomode
=
0
;
lo
->
plh_return_seq
=
0
;
pnfs_get_layout_hdr
(
lo
);
clear_bit
(
NFS_LAYOUT_RETURN_REQUESTED
,
&
lo
->
plh_flags
);
if
(
test_bit
(
NFS_LAYOUT_RETURN_REQUESTED
,
&
lo
->
plh_flags
))
{
if
(
stateid
!=
NULL
)
{
nfs4_stateid_copy
(
stateid
,
&
lo
->
plh_stateid
);
if
(
lo
->
plh_return_seq
!=
0
)
stateid
->
seqid
=
cpu_to_be32
(
lo
->
plh_return_seq
);
}
if
(
iomode
!=
NULL
)
*
iomode
=
lo
->
plh_return_iomode
;
pnfs_clear_layoutreturn_info
(
lo
);
return
true
;
}
if
(
stateid
!=
NULL
)
nfs4_stateid_copy
(
stateid
,
&
lo
->
plh_stateid
);
if
(
iomode
!=
NULL
)
*
iomode
=
IOMODE_ANY
;
return
true
;
}
...
...
@@ -949,10 +984,7 @@ static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo)
enum
pnfs_iomode
iomode
;
bool
send
;
nfs4_stateid_copy
(
&
stateid
,
&
lo
->
plh_stateid
);
stateid
.
seqid
=
cpu_to_be32
(
lo
->
plh_return_seq
);
iomode
=
lo
->
plh_return_iomode
;
send
=
pnfs_prepare_layoutreturn
(
lo
);
send
=
pnfs_prepare_layoutreturn
(
lo
,
&
stateid
,
&
iomode
);
spin_unlock
(
&
inode
->
i_lock
);
if
(
send
)
{
/* Send an async layoutreturn so we dont deadlock */
...
...
@@ -989,7 +1021,6 @@ _pnfs_return_layout(struct inode *ino)
dprintk
(
"NFS: %s no layout to return
\n
"
,
__func__
);
goto
out
;
}
nfs4_stateid_copy
(
&
stateid
,
&
nfsi
->
layout
->
plh_stateid
);
/* Reference matched in nfs4_layoutreturn_release */
pnfs_get_layout_hdr
(
lo
);
empty
=
list_empty
(
&
lo
->
plh_segs
);
...
...
@@ -1012,8 +1043,7 @@ _pnfs_return_layout(struct inode *ino)
goto
out_put_layout_hdr
;
}
set_bit
(
NFS_LAYOUT_INVALID_STID
,
&
lo
->
plh_flags
);
send
=
pnfs_prepare_layoutreturn
(
lo
);
send
=
pnfs_prepare_layoutreturn
(
lo
,
&
stateid
,
NULL
);
spin_unlock
(
&
ino
->
i_lock
);
pnfs_free_lseg_list
(
&
tmp_list
);
if
(
send
)
...
...
@@ -1080,11 +1110,10 @@ bool pnfs_roc(struct inode *ino)
goto
out_noroc
;
}
nfs4_stateid_copy
(
&
stateid
,
&
lo
->
plh_stateid
);
/* always send layoutreturn if being marked so */
if
(
test_
and_clear_bit
(
NFS_LAYOUT_RETURN_REQUESTED
,
&
lo
->
plh_flags
))
layoutreturn
=
pnfs_prepare_layoutreturn
(
lo
);
if
(
test_
bit
(
NFS_LAYOUT_RETURN_REQUESTED
,
&
lo
->
plh_flags
))
layoutreturn
=
pnfs_prepare_layoutreturn
(
lo
,
&
stateid
,
NULL
);
list_for_each_entry_safe
(
lseg
,
tmp
,
&
lo
->
plh_segs
,
pls_list
)
/* If we are sending layoutreturn, invalidate all valid lsegs */
...
...
@@ -1132,7 +1161,6 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier)
spin_lock
(
&
ino
->
i_lock
);
lo
=
NFS_I
(
ino
)
->
layout
;
pnfs_mark_layout_returned_if_empty
(
lo
);
if
(
pnfs_seqid_is_newer
(
barrier
,
lo
->
plh_barrier
))
lo
->
plh_barrier
=
barrier
;
spin_unlock
(
&
ino
->
i_lock
);
...
...
@@ -1746,9 +1774,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
return
lseg
;
}
init_lseg
(
lo
,
lseg
);
lseg
->
pls_range
=
res
->
range
;
lseg
->
pls_seq
=
be32_to_cpu
(
res
->
stateid
.
seqid
);
pnfs_init_lseg
(
lo
,
lseg
,
&
res
->
range
,
&
res
->
stateid
);
spin_lock
(
&
ino
->
i_lock
);
if
(
pnfs_layoutgets_blocked
(
lo
))
{
...
...
@@ -1769,16 +1795,19 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
* inode invalid, and don't bother validating the stateid
* sequence number.
*/
pnfs_mark_
matching_lsegs_invalid
(
lo
,
&
free_me
,
NULL
,
0
);
pnfs_mark_
layout_stateid_invalid
(
lo
,
&
free_me
);
nfs4_stateid_copy
(
&
lo
->
plh_stateid
,
&
res
->
stateid
);
lo
->
plh_barrier
=
be32_to_cpu
(
res
->
stateid
.
seqid
);
}
clear_bit
(
NFS_LAYOUT_INVALID_STID
,
&
lo
->
plh_flags
);
pnfs_get_lseg
(
lseg
);
pnfs_layout_insert_lseg
(
lo
,
lseg
,
&
free_me
);
if
(
!
pnfs_layout_is_valid
(
lo
))
{
pnfs_clear_layoutreturn_info
(
lo
);
clear_bit
(
NFS_LAYOUT_INVALID_STID
,
&
lo
->
plh_flags
);
}
if
(
res
->
return_on_close
)
set_bit
(
NFS_LSEG_ROC
,
&
lseg
->
pls_flags
);
...
...
@@ -1798,14 +1827,14 @@ static void
pnfs_set_plh_return_info
(
struct
pnfs_layout_hdr
*
lo
,
enum
pnfs_iomode
iomode
,
u32
seq
)
{
if
(
lo
->
plh_return_iomode
==
iomode
)
return
;
if
(
lo
->
plh_return_iomode
!=
0
)
if
(
lo
->
plh_return_iomode
!=
0
&&
lo
->
plh_return_iomode
!=
iomode
)
iomode
=
IOMODE_ANY
;
lo
->
plh_return_iomode
=
iomode
;
set_bit
(
NFS_LAYOUT_RETURN_REQUESTED
,
&
lo
->
plh_flags
);
if
(
!
lo
->
plh_return_seq
||
pnfs_seqid_is_newer
(
seq
,
lo
->
plh_return_seq
))
if
(
seq
!=
0
)
{
WARN_ON_ONCE
(
lo
->
plh_return_seq
!=
0
&&
lo
->
plh_return_seq
!=
seq
);
lo
->
plh_return_seq
=
seq
;
}
}
/**
...
...
@@ -1835,7 +1864,7 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
assert_spin_locked
(
&
lo
->
plh_inode
->
i_lock
);
list_for_each_entry_safe
(
lseg
,
next
,
&
lo
->
plh_segs
,
pls_list
)
if
(
should_free_lseg
(
&
lseg
->
pls_range
,
return_range
))
{
if
(
pnfs_match_lseg_recall
(
lseg
,
return_range
,
seq
))
{
dprintk
(
"%s: marking lseg %p iomode %d "
"offset %llu length %llu
\n
"
,
__func__
,
lseg
,
lseg
->
pls_range
.
iomode
,
...
...
@@ -1866,19 +1895,17 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
bool
return_now
=
false
;
spin_lock
(
&
inode
->
i_lock
);
pnfs_set_plh_return_info
(
lo
,
range
.
iomode
,
lseg
->
pls_seq
);
pnfs_set_plh_return_info
(
lo
,
range
.
iomode
,
0
);
/*
* mark all matching lsegs so that we are sure to have no live
* segments at hand when sending layoutreturn. See pnfs_put_lseg()
* for how it works.
*/
if
(
!
pnfs_mark_matching_lsegs_return
(
lo
,
&
free_me
,
&
range
,
lseg
->
pls_seq
))
{
if
(
!
pnfs_mark_matching_lsegs_return
(
lo
,
&
free_me
,
&
range
,
0
))
{
nfs4_stateid
stateid
;
enum
pnfs_iomode
iomode
=
lo
->
plh_return_iomode
;
enum
pnfs_iomode
iomode
;
nfs4_stateid_copy
(
&
stateid
,
&
lo
->
plh_stateid
);
return_now
=
pnfs_prepare_layoutreturn
(
lo
);
return_now
=
pnfs_prepare_layoutreturn
(
lo
,
&
stateid
,
&
iomode
);
spin_unlock
(
&
inode
->
i_lock
);
if
(
return_now
)
pnfs_send_layoutreturn
(
lo
,
&
stateid
,
iomode
,
false
);
...
...
fs/nfs/pnfs.h
浏览文件 @
668f455d
...
...
@@ -268,6 +268,8 @@ int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
struct
list_head
*
tmp_list
,
const
struct
pnfs_layout_range
*
recall_range
,
u32
seq
);
int
pnfs_mark_layout_stateid_invalid
(
struct
pnfs_layout_hdr
*
lo
,
struct
list_head
*
lseg_list
);
bool
pnfs_roc
(
struct
inode
*
ino
);
void
pnfs_roc_release
(
struct
inode
*
ino
);
void
pnfs_roc_set_barrier
(
struct
inode
*
ino
,
u32
barrier
);
...
...
@@ -375,6 +377,11 @@ static inline bool nfs_have_layout(struct inode *inode)
return
NFS_I
(
inode
)
->
layout
!=
NULL
;
}
static
inline
bool
pnfs_layout_is_valid
(
const
struct
pnfs_layout_hdr
*
lo
)
{
return
test_bit
(
NFS_LAYOUT_INVALID_STID
,
&
lo
->
plh_flags
)
==
0
;
}
static
inline
struct
nfs4_deviceid_node
*
nfs4_get_deviceid
(
struct
nfs4_deviceid_node
*
d
)
{
...
...
@@ -545,19 +552,6 @@ pnfs_calc_offset_length(u64 offset, u64 end)
return
1
+
end
-
offset
;
}
/**
* pnfs_mark_layout_returned_if_empty - marks the layout as returned
* @lo: layout header
*
* Note: Caller must hold inode->i_lock
*/
static
inline
void
pnfs_mark_layout_returned_if_empty
(
struct
pnfs_layout_hdr
*
lo
)
{
if
(
list_empty
(
&
lo
->
plh_segs
))
set_bit
(
NFS_LAYOUT_INVALID_STID
,
&
lo
->
plh_flags
);
}
static
inline
void
pnfs_copy_range
(
struct
pnfs_layout_range
*
dst
,
const
struct
pnfs_layout_range
*
src
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录