diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-01-22 11:02:36 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-01-22 11:02:36 -0500 |
commit | 6d45c042f35ea9b27bf946380f74ff75d32280c9 (patch) | |
tree | 065c108254a768aa12d145374b1b9f6f10591ac3 /fs | |
parent | 6272dcc6beebbc2d8cf4165b628169e878f143e0 (diff) | |
parent | 082fa37d1351a41afc491d44a1d095cb8d919aa2 (diff) |
Merge branch 'bugfixes'
* bugfixes:
pNFS/flexfiles: Fix an XDR encoding bug in layoutreturn
pNFS/flexfiles: Improve merging of errors in LAYOUTRETURN
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 6 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayoutdev.c | 99 |
2 files changed, 42 insertions, 63 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 6594e9f903a0..5bcd92d50e82 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -1948,11 +1948,9 @@ ff_layout_encode_layoutreturn(struct pnfs_layout_hdr *lo, | |||
1948 | start = xdr_reserve_space(xdr, 4); | 1948 | start = xdr_reserve_space(xdr, 4); |
1949 | BUG_ON(!start); | 1949 | BUG_ON(!start); |
1950 | 1950 | ||
1951 | if (ff_layout_encode_ioerr(flo, xdr, args)) | 1951 | ff_layout_encode_ioerr(flo, xdr, args); |
1952 | goto out; | ||
1953 | |||
1954 | ff_layout_encode_iostats(flo, xdr, args); | 1952 | ff_layout_encode_iostats(flo, xdr, args); |
1955 | out: | 1953 | |
1956 | *start = cpu_to_be32((xdr->p - start - 1) * 4); | 1954 | *start = cpu_to_be32((xdr->p - start - 1) * 4); |
1957 | dprintk("%s: Return\n", __func__); | 1955 | dprintk("%s: Return\n", __func__); |
1958 | } | 1956 | } |
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index bd0327541366..29898a9550fa 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c | |||
@@ -218,63 +218,55 @@ static void extend_ds_error(struct nfs4_ff_layout_ds_err *err, | |||
218 | err->length = end - err->offset; | 218 | err->length = end - err->offset; |
219 | } | 219 | } |
220 | 220 | ||
221 | static bool ds_error_can_merge(struct nfs4_ff_layout_ds_err *err, u64 offset, | 221 | static int |
222 | u64 length, int status, enum nfs_opnum4 opnum, | 222 | ff_ds_error_match(const struct nfs4_ff_layout_ds_err *e1, |
223 | nfs4_stateid *stateid, | 223 | const struct nfs4_ff_layout_ds_err *e2) |
224 | struct nfs4_deviceid *deviceid) | ||
225 | { | 224 | { |
226 | return err->status == status && err->opnum == opnum && | 225 | int ret; |
227 | nfs4_stateid_match(&err->stateid, stateid) && | 226 | |
228 | !memcmp(&err->deviceid, deviceid, sizeof(*deviceid)) && | 227 | if (e1->opnum != e2->opnum) |
229 | end_offset(err->offset, err->length) >= offset && | 228 | return e1->opnum < e2->opnum ? -1 : 1; |
230 | err->offset <= end_offset(offset, length); | 229 | if (e1->status != e2->status) |
231 | } | 230 | return e1->status < e2->status ? -1 : 1; |
232 | 231 | ret = memcmp(&e1->stateid, &e2->stateid, sizeof(e1->stateid)); | |
233 | static bool merge_ds_error(struct nfs4_ff_layout_ds_err *old, | 232 | if (ret != 0) |
234 | struct nfs4_ff_layout_ds_err *new) | 233 | return ret; |
235 | { | 234 | ret = memcmp(&e1->deviceid, &e2->deviceid, sizeof(e1->deviceid)); |
236 | if (!ds_error_can_merge(old, new->offset, new->length, new->status, | 235 | if (ret != 0) |
237 | new->opnum, &new->stateid, &new->deviceid)) | 236 | return ret; |
238 | return false; | 237 | if (end_offset(e1->offset, e1->length) < e2->offset) |
239 | 238 | return -1; | |
240 | extend_ds_error(old, new->offset, new->length); | 239 | if (e1->offset > end_offset(e2->offset, e2->length)) |
241 | return true; | 240 | return 1; |
241 | /* If ranges overlap or are contiguous, they are the same */ | ||
242 | return 0; | ||
242 | } | 243 | } |
243 | 244 | ||
244 | static bool | 245 | static void |
245 | ff_layout_add_ds_error_locked(struct nfs4_flexfile_layout *flo, | 246 | ff_layout_add_ds_error_locked(struct nfs4_flexfile_layout *flo, |
246 | struct nfs4_ff_layout_ds_err *dserr) | 247 | struct nfs4_ff_layout_ds_err *dserr) |
247 | { | 248 | { |
248 | struct nfs4_ff_layout_ds_err *err; | 249 | struct nfs4_ff_layout_ds_err *err, *tmp; |
249 | 250 | struct list_head *head = &flo->error_list; | |
250 | list_for_each_entry(err, &flo->error_list, list) { | 251 | int match; |
251 | if (merge_ds_error(err, dserr)) { | 252 | |
252 | return true; | 253 | /* Do insertion sort w/ merges */ |
253 | } | 254 | list_for_each_entry_safe(err, tmp, &flo->error_list, list) { |
254 | } | 255 | match = ff_ds_error_match(err, dserr); |
255 | 256 | if (match < 0) | |
256 | list_add(&dserr->list, &flo->error_list); | 257 | continue; |
257 | return false; | 258 | if (match > 0) { |
258 | } | 259 | /* Add entry "dserr" _before_ entry "err" */ |
259 | 260 | head = &err->list; | |
260 | static bool | ||
261 | ff_layout_update_ds_error(struct nfs4_flexfile_layout *flo, u64 offset, | ||
262 | u64 length, int status, enum nfs_opnum4 opnum, | ||
263 | nfs4_stateid *stateid, struct nfs4_deviceid *deviceid) | ||
264 | { | ||
265 | bool found = false; | ||
266 | struct nfs4_ff_layout_ds_err *err; | ||
267 | |||
268 | list_for_each_entry(err, &flo->error_list, list) { | ||
269 | if (ds_error_can_merge(err, offset, length, status, opnum, | ||
270 | stateid, deviceid)) { | ||
271 | found = true; | ||
272 | extend_ds_error(err, offset, length); | ||
273 | break; | 261 | break; |
274 | } | 262 | } |
263 | /* Entries match, so merge "err" into "dserr" */ | ||
264 | extend_ds_error(dserr, err->offset, err->length); | ||
265 | list_del(&err->list); | ||
266 | kfree(err); | ||
275 | } | 267 | } |
276 | 268 | ||
277 | return found; | 269 | list_add_tail(&dserr->list, head); |
278 | } | 270 | } |
279 | 271 | ||
280 | int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, | 272 | int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, |
@@ -283,7 +275,6 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, | |||
283 | gfp_t gfp_flags) | 275 | gfp_t gfp_flags) |
284 | { | 276 | { |
285 | struct nfs4_ff_layout_ds_err *dserr; | 277 | struct nfs4_ff_layout_ds_err *dserr; |
286 | bool needfree; | ||
287 | 278 | ||
288 | if (status == 0) | 279 | if (status == 0) |
289 | return 0; | 280 | return 0; |
@@ -291,14 +282,6 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, | |||
291 | if (mirror->mirror_ds == NULL) | 282 | if (mirror->mirror_ds == NULL) |
292 | return -EINVAL; | 283 | return -EINVAL; |
293 | 284 | ||
294 | spin_lock(&flo->generic_hdr.plh_inode->i_lock); | ||
295 | if (ff_layout_update_ds_error(flo, offset, length, status, opnum, | ||
296 | &mirror->stateid, | ||
297 | &mirror->mirror_ds->id_node.deviceid)) { | ||
298 | spin_unlock(&flo->generic_hdr.plh_inode->i_lock); | ||
299 | return 0; | ||
300 | } | ||
301 | spin_unlock(&flo->generic_hdr.plh_inode->i_lock); | ||
302 | dserr = kmalloc(sizeof(*dserr), gfp_flags); | 285 | dserr = kmalloc(sizeof(*dserr), gfp_flags); |
303 | if (!dserr) | 286 | if (!dserr) |
304 | return -ENOMEM; | 287 | return -ENOMEM; |
@@ -313,10 +296,8 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, | |||
313 | NFS4_DEVICEID4_SIZE); | 296 | NFS4_DEVICEID4_SIZE); |
314 | 297 | ||
315 | spin_lock(&flo->generic_hdr.plh_inode->i_lock); | 298 | spin_lock(&flo->generic_hdr.plh_inode->i_lock); |
316 | needfree = ff_layout_add_ds_error_locked(flo, dserr); | 299 | ff_layout_add_ds_error_locked(flo, dserr); |
317 | spin_unlock(&flo->generic_hdr.plh_inode->i_lock); | 300 | spin_unlock(&flo->generic_hdr.plh_inode->i_lock); |
318 | if (needfree) | ||
319 | kfree(dserr); | ||
320 | 301 | ||
321 | return 0; | 302 | return 0; |
322 | } | 303 | } |