diff options
-rw-r--r-- | fs/nfs/callback_proc.c | 57 | ||||
-rw-r--r-- | fs/nfs/client.c | 4 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 13 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 2 |
4 files changed, 48 insertions, 28 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index d4d1954e9bb9..74780f9f852c 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -111,6 +111,7 @@ int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nf | |||
111 | static u32 initiate_file_draining(struct nfs_client *clp, | 111 | static u32 initiate_file_draining(struct nfs_client *clp, |
112 | struct cb_layoutrecallargs *args) | 112 | struct cb_layoutrecallargs *args) |
113 | { | 113 | { |
114 | struct nfs_server *server; | ||
114 | struct pnfs_layout_hdr *lo; | 115 | struct pnfs_layout_hdr *lo; |
115 | struct inode *ino; | 116 | struct inode *ino; |
116 | bool found = false; | 117 | bool found = false; |
@@ -118,21 +119,28 @@ static u32 initiate_file_draining(struct nfs_client *clp, | |||
118 | LIST_HEAD(free_me_list); | 119 | LIST_HEAD(free_me_list); |
119 | 120 | ||
120 | spin_lock(&clp->cl_lock); | 121 | spin_lock(&clp->cl_lock); |
121 | list_for_each_entry(lo, &clp->cl_layouts, plh_layouts) { | 122 | rcu_read_lock(); |
122 | if (nfs_compare_fh(&args->cbl_fh, | 123 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
123 | &NFS_I(lo->plh_inode)->fh)) | 124 | list_for_each_entry(lo, &server->layouts, plh_layouts) { |
124 | continue; | 125 | if (nfs_compare_fh(&args->cbl_fh, |
125 | ino = igrab(lo->plh_inode); | 126 | &NFS_I(lo->plh_inode)->fh)) |
126 | if (!ino) | 127 | continue; |
127 | continue; | 128 | ino = igrab(lo->plh_inode); |
128 | found = true; | 129 | if (!ino) |
129 | /* Without this, layout can be freed as soon | 130 | continue; |
130 | * as we release cl_lock. | 131 | found = true; |
131 | */ | 132 | /* Without this, layout can be freed as soon |
132 | get_layout_hdr(lo); | 133 | * as we release cl_lock. |
133 | break; | 134 | */ |
135 | get_layout_hdr(lo); | ||
136 | break; | ||
137 | } | ||
138 | if (found) | ||
139 | break; | ||
134 | } | 140 | } |
141 | rcu_read_unlock(); | ||
135 | spin_unlock(&clp->cl_lock); | 142 | spin_unlock(&clp->cl_lock); |
143 | |||
136 | if (!found) | 144 | if (!found) |
137 | return NFS4ERR_NOMATCHING_LAYOUT; | 145 | return NFS4ERR_NOMATCHING_LAYOUT; |
138 | 146 | ||
@@ -154,6 +162,7 @@ static u32 initiate_file_draining(struct nfs_client *clp, | |||
154 | static u32 initiate_bulk_draining(struct nfs_client *clp, | 162 | static u32 initiate_bulk_draining(struct nfs_client *clp, |
155 | struct cb_layoutrecallargs *args) | 163 | struct cb_layoutrecallargs *args) |
156 | { | 164 | { |
165 | struct nfs_server *server; | ||
157 | struct pnfs_layout_hdr *lo; | 166 | struct pnfs_layout_hdr *lo; |
158 | struct inode *ino; | 167 | struct inode *ino; |
159 | u32 rv = NFS4ERR_NOMATCHING_LAYOUT; | 168 | u32 rv = NFS4ERR_NOMATCHING_LAYOUT; |
@@ -167,18 +176,24 @@ static u32 initiate_bulk_draining(struct nfs_client *clp, | |||
167 | }; | 176 | }; |
168 | 177 | ||
169 | spin_lock(&clp->cl_lock); | 178 | spin_lock(&clp->cl_lock); |
170 | list_for_each_entry(lo, &clp->cl_layouts, plh_layouts) { | 179 | rcu_read_lock(); |
180 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { | ||
171 | if ((args->cbl_recall_type == RETURN_FSID) && | 181 | if ((args->cbl_recall_type == RETURN_FSID) && |
172 | memcmp(&NFS_SERVER(lo->plh_inode)->fsid, | 182 | memcmp(&server->fsid, &args->cbl_fsid, |
173 | &args->cbl_fsid, sizeof(struct nfs_fsid))) | 183 | sizeof(struct nfs_fsid))) |
174 | continue; | ||
175 | if (!igrab(lo->plh_inode)) | ||
176 | continue; | 184 | continue; |
177 | get_layout_hdr(lo); | 185 | |
178 | BUG_ON(!list_empty(&lo->plh_bulk_recall)); | 186 | list_for_each_entry(lo, &server->layouts, plh_layouts) { |
179 | list_add(&lo->plh_bulk_recall, &recall_list); | 187 | if (!igrab(lo->plh_inode)) |
188 | continue; | ||
189 | get_layout_hdr(lo); | ||
190 | BUG_ON(!list_empty(&lo->plh_bulk_recall)); | ||
191 | list_add(&lo->plh_bulk_recall, &recall_list); | ||
192 | } | ||
180 | } | 193 | } |
194 | rcu_read_unlock(); | ||
181 | spin_unlock(&clp->cl_lock); | 195 | spin_unlock(&clp->cl_lock); |
196 | |||
182 | list_for_each_entry_safe(lo, tmp, | 197 | list_for_each_entry_safe(lo, tmp, |
183 | &recall_list, plh_bulk_recall) { | 198 | &recall_list, plh_bulk_recall) { |
184 | ino = lo->plh_inode; | 199 | ino = lo->plh_inode; |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 006f8ff0a3c0..5452ada59461 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -188,9 +188,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
188 | cred = rpc_lookup_machine_cred(); | 188 | cred = rpc_lookup_machine_cred(); |
189 | if (!IS_ERR(cred)) | 189 | if (!IS_ERR(cred)) |
190 | clp->cl_machine_cred = cred; | 190 | clp->cl_machine_cred = cred; |
191 | #if defined(CONFIG_NFS_V4_1) | ||
192 | INIT_LIST_HEAD(&clp->cl_layouts); | ||
193 | #endif | ||
194 | nfs_fscache_get_client_cookie(clp); | 191 | nfs_fscache_get_client_cookie(clp); |
195 | 192 | ||
196 | return clp; | 193 | return clp; |
@@ -1063,6 +1060,7 @@ static struct nfs_server *nfs_alloc_server(void) | |||
1063 | INIT_LIST_HEAD(&server->client_link); | 1060 | INIT_LIST_HEAD(&server->client_link); |
1064 | INIT_LIST_HEAD(&server->master_link); | 1061 | INIT_LIST_HEAD(&server->master_link); |
1065 | INIT_LIST_HEAD(&server->delegations); | 1062 | INIT_LIST_HEAD(&server->delegations); |
1063 | INIT_LIST_HEAD(&server->layouts); | ||
1066 | 1064 | ||
1067 | atomic_set(&server->active, 0); | 1065 | atomic_set(&server->active, 0); |
1068 | 1066 | ||
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 29c0ca7fc347..ff8200772377 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -448,11 +448,17 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) | |||
448 | void | 448 | void |
449 | pnfs_destroy_all_layouts(struct nfs_client *clp) | 449 | pnfs_destroy_all_layouts(struct nfs_client *clp) |
450 | { | 450 | { |
451 | struct nfs_server *server; | ||
451 | struct pnfs_layout_hdr *lo; | 452 | struct pnfs_layout_hdr *lo; |
452 | LIST_HEAD(tmp_list); | 453 | LIST_HEAD(tmp_list); |
453 | 454 | ||
454 | spin_lock(&clp->cl_lock); | 455 | spin_lock(&clp->cl_lock); |
455 | list_splice_init(&clp->cl_layouts, &tmp_list); | 456 | rcu_read_lock(); |
457 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { | ||
458 | if (!list_empty(&server->layouts)) | ||
459 | list_splice_init(&server->layouts, &tmp_list); | ||
460 | } | ||
461 | rcu_read_unlock(); | ||
456 | spin_unlock(&clp->cl_lock); | 462 | spin_unlock(&clp->cl_lock); |
457 | 463 | ||
458 | while (!list_empty(&tmp_list)) { | 464 | while (!list_empty(&tmp_list)) { |
@@ -920,7 +926,8 @@ pnfs_update_layout(struct inode *ino, | |||
920 | }; | 926 | }; |
921 | unsigned pg_offset; | 927 | unsigned pg_offset; |
922 | struct nfs_inode *nfsi = NFS_I(ino); | 928 | struct nfs_inode *nfsi = NFS_I(ino); |
923 | struct nfs_client *clp = NFS_SERVER(ino)->nfs_client; | 929 | struct nfs_server *server = NFS_SERVER(ino); |
930 | struct nfs_client *clp = server->nfs_client; | ||
924 | struct pnfs_layout_hdr *lo; | 931 | struct pnfs_layout_hdr *lo; |
925 | struct pnfs_layout_segment *lseg = NULL; | 932 | struct pnfs_layout_segment *lseg = NULL; |
926 | bool first = false; | 933 | bool first = false; |
@@ -964,7 +971,7 @@ pnfs_update_layout(struct inode *ino, | |||
964 | */ | 971 | */ |
965 | spin_lock(&clp->cl_lock); | 972 | spin_lock(&clp->cl_lock); |
966 | BUG_ON(!list_empty(&lo->plh_layouts)); | 973 | BUG_ON(!list_empty(&lo->plh_layouts)); |
967 | list_add_tail(&lo->plh_layouts, &clp->cl_layouts); | 974 | list_add_tail(&lo->plh_layouts, &server->layouts); |
968 | spin_unlock(&clp->cl_lock); | 975 | spin_unlock(&clp->cl_lock); |
969 | } | 976 | } |
970 | 977 | ||
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index f23b18831559..4faeac8f448a 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -78,7 +78,6 @@ struct nfs_client { | |||
78 | /* The flags used for obtaining the clientid during EXCHANGE_ID */ | 78 | /* The flags used for obtaining the clientid during EXCHANGE_ID */ |
79 | u32 cl_exchange_flags; | 79 | u32 cl_exchange_flags; |
80 | struct nfs4_session *cl_session; /* sharred session */ | 80 | struct nfs4_session *cl_session; /* sharred session */ |
81 | struct list_head cl_layouts; | ||
82 | #endif /* CONFIG_NFS_V4 */ | 81 | #endif /* CONFIG_NFS_V4 */ |
83 | 82 | ||
84 | #ifdef CONFIG_NFS_FSCACHE | 83 | #ifdef CONFIG_NFS_FSCACHE |
@@ -152,6 +151,7 @@ struct nfs_server { | |||
152 | struct rb_root openowner_id; | 151 | struct rb_root openowner_id; |
153 | struct rb_root lockowner_id; | 152 | struct rb_root lockowner_id; |
154 | #endif | 153 | #endif |
154 | struct list_head layouts; | ||
155 | struct list_head delegations; | 155 | struct list_head delegations; |
156 | void (*destroy)(struct nfs_server *); | 156 | void (*destroy)(struct nfs_server *); |
157 | 157 | ||