diff options
Diffstat (limited to 'fs/nfs/objlayout/objlayout.c')
-rw-r--r-- | fs/nfs/objlayout/objlayout.c | 209 |
1 files changed, 73 insertions, 136 deletions
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index 1d06f8e2adea..72074e3a04f9 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -156,77 +156,39 @@ last_byte_offset(u64 start, u64 len) | |||
156 | return end > start ? end - 1 : NFS4_MAX_UINT64; | 156 | return end > start ? end - 1 : NFS4_MAX_UINT64; |
157 | } | 157 | } |
158 | 158 | ||
159 | static struct objlayout_io_state * | 159 | void _fix_verify_io_params(struct pnfs_layout_segment *lseg, |
160 | objlayout_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type, | 160 | struct page ***p_pages, unsigned *p_pgbase, |
161 | struct page **pages, | 161 | u64 offset, unsigned long count) |
162 | unsigned pgbase, | ||
163 | loff_t offset, | ||
164 | size_t count, | ||
165 | struct pnfs_layout_segment *lseg, | ||
166 | void *rpcdata, | ||
167 | gfp_t gfp_flags) | ||
168 | { | 162 | { |
169 | struct objlayout_io_state *state; | ||
170 | u64 lseg_end_offset; | 163 | u64 lseg_end_offset; |
171 | 164 | ||
172 | dprintk("%s: allocating io_state\n", __func__); | ||
173 | if (objio_alloc_io_state(lseg, &state, gfp_flags)) | ||
174 | return NULL; | ||
175 | |||
176 | BUG_ON(offset < lseg->pls_range.offset); | 165 | BUG_ON(offset < lseg->pls_range.offset); |
177 | lseg_end_offset = end_offset(lseg->pls_range.offset, | 166 | lseg_end_offset = end_offset(lseg->pls_range.offset, |
178 | lseg->pls_range.length); | 167 | lseg->pls_range.length); |
179 | BUG_ON(offset >= lseg_end_offset); | 168 | BUG_ON(offset >= lseg_end_offset); |
180 | if (offset + count > lseg_end_offset) { | 169 | WARN_ON(offset + count > lseg_end_offset); |
181 | count = lseg->pls_range.length - | ||
182 | (offset - lseg->pls_range.offset); | ||
183 | dprintk("%s: truncated count %Zd\n", __func__, count); | ||
184 | } | ||
185 | 170 | ||
186 | if (pgbase > PAGE_SIZE) { | 171 | if (*p_pgbase > PAGE_SIZE) { |
187 | pages += pgbase >> PAGE_SHIFT; | 172 | dprintk("%s: pgbase(0x%x) > PAGE_SIZE\n", __func__, *p_pgbase); |
188 | pgbase &= ~PAGE_MASK; | 173 | *p_pages += *p_pgbase >> PAGE_SHIFT; |
174 | *p_pgbase &= ~PAGE_MASK; | ||
189 | } | 175 | } |
190 | |||
191 | INIT_LIST_HEAD(&state->err_list); | ||
192 | state->lseg = lseg; | ||
193 | state->rpcdata = rpcdata; | ||
194 | state->pages = pages; | ||
195 | state->pgbase = pgbase; | ||
196 | state->nr_pages = (pgbase + count + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
197 | state->offset = offset; | ||
198 | state->count = count; | ||
199 | state->sync = 0; | ||
200 | |||
201 | return state; | ||
202 | } | ||
203 | |||
204 | static void | ||
205 | objlayout_free_io_state(struct objlayout_io_state *state) | ||
206 | { | ||
207 | dprintk("%s: freeing io_state\n", __func__); | ||
208 | if (unlikely(!state)) | ||
209 | return; | ||
210 | |||
211 | objio_free_io_state(state); | ||
212 | } | 176 | } |
213 | 177 | ||
214 | /* | 178 | /* |
215 | * I/O done common code | 179 | * I/O done common code |
216 | */ | 180 | */ |
217 | static void | 181 | static void |
218 | objlayout_iodone(struct objlayout_io_state *state) | 182 | objlayout_iodone(struct objlayout_io_res *oir) |
219 | { | 183 | { |
220 | dprintk("%s: state %p status\n", __func__, state); | 184 | if (likely(oir->status >= 0)) { |
221 | 185 | objio_free_result(oir); | |
222 | if (likely(state->status >= 0)) { | ||
223 | objlayout_free_io_state(state); | ||
224 | } else { | 186 | } else { |
225 | struct objlayout *objlay = OBJLAYOUT(state->lseg->pls_layout); | 187 | struct objlayout *objlay = oir->objlay; |
226 | 188 | ||
227 | spin_lock(&objlay->lock); | 189 | spin_lock(&objlay->lock); |
228 | objlay->delta_space_valid = OBJ_DSU_INVALID; | 190 | objlay->delta_space_valid = OBJ_DSU_INVALID; |
229 | list_add(&objlay->err_list, &state->err_list); | 191 | list_add(&objlay->err_list, &oir->err_list); |
230 | spin_unlock(&objlay->lock); | 192 | spin_unlock(&objlay->lock); |
231 | } | 193 | } |
232 | } | 194 | } |
@@ -238,13 +200,13 @@ objlayout_iodone(struct objlayout_io_state *state) | |||
238 | * the error for later reporting at layout-return. | 200 | * the error for later reporting at layout-return. |
239 | */ | 201 | */ |
240 | void | 202 | void |
241 | objlayout_io_set_result(struct objlayout_io_state *state, unsigned index, | 203 | objlayout_io_set_result(struct objlayout_io_res *oir, unsigned index, |
242 | struct pnfs_osd_objid *pooid, int osd_error, | 204 | struct pnfs_osd_objid *pooid, int osd_error, |
243 | u64 offset, u64 length, bool is_write) | 205 | u64 offset, u64 length, bool is_write) |
244 | { | 206 | { |
245 | struct pnfs_osd_ioerr *ioerr = &state->ioerrs[index]; | 207 | struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[index]; |
246 | 208 | ||
247 | BUG_ON(index >= state->num_comps); | 209 | BUG_ON(index >= oir->num_comps); |
248 | if (osd_error) { | 210 | if (osd_error) { |
249 | ioerr->oer_component = *pooid; | 211 | ioerr->oer_component = *pooid; |
250 | ioerr->oer_comp_offset = offset; | 212 | ioerr->oer_comp_offset = offset; |
@@ -285,21 +247,18 @@ static void _rpc_read_complete(struct work_struct *work) | |||
285 | } | 247 | } |
286 | 248 | ||
287 | void | 249 | void |
288 | objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync) | 250 | objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync) |
289 | { | 251 | { |
290 | int eof = state->eof; | 252 | struct nfs_read_data *rdata = oir->rpcdata; |
291 | struct nfs_read_data *rdata; | ||
292 | 253 | ||
293 | state->status = status; | 254 | oir->status = rdata->task.tk_status = status; |
294 | dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof); | 255 | if (status >= 0) |
295 | rdata = state->rpcdata; | ||
296 | rdata->task.tk_status = status; | ||
297 | if (status >= 0) { | ||
298 | rdata->res.count = status; | 256 | rdata->res.count = status; |
299 | rdata->res.eof = eof; | 257 | objlayout_iodone(oir); |
300 | } | 258 | /* must not use oir after this point */ |
301 | objlayout_iodone(state); | 259 | |
302 | /* must not use state after this point */ | 260 | dprintk("%s: Return status=%zd eof=%d sync=%d\n", __func__, |
261 | status, rdata->res.eof, sync); | ||
303 | 262 | ||
304 | if (sync) | 263 | if (sync) |
305 | pnfs_ld_read_done(rdata); | 264 | pnfs_ld_read_done(rdata); |
@@ -317,40 +276,36 @@ objlayout_read_pagelist(struct nfs_read_data *rdata) | |||
317 | { | 276 | { |
318 | loff_t offset = rdata->args.offset; | 277 | loff_t offset = rdata->args.offset; |
319 | size_t count = rdata->args.count; | 278 | size_t count = rdata->args.count; |
320 | struct objlayout_io_state *state; | 279 | int err; |
321 | ssize_t status = 0; | ||
322 | loff_t eof; | 280 | loff_t eof; |
323 | 281 | ||
324 | dprintk("%s: Begin inode %p offset %llu count %d\n", | ||
325 | __func__, rdata->inode, offset, (int)count); | ||
326 | |||
327 | eof = i_size_read(rdata->inode); | 282 | eof = i_size_read(rdata->inode); |
328 | if (unlikely(offset + count > eof)) { | 283 | if (unlikely(offset + count > eof)) { |
329 | if (offset >= eof) { | 284 | if (offset >= eof) { |
330 | status = 0; | 285 | err = 0; |
331 | rdata->res.count = 0; | 286 | rdata->res.count = 0; |
332 | rdata->res.eof = 1; | 287 | rdata->res.eof = 1; |
288 | /*FIXME: do we need to call pnfs_ld_read_done() */ | ||
333 | goto out; | 289 | goto out; |
334 | } | 290 | } |
335 | count = eof - offset; | 291 | count = eof - offset; |
336 | } | 292 | } |
337 | 293 | ||
338 | state = objlayout_alloc_io_state(NFS_I(rdata->inode)->layout, | 294 | rdata->res.eof = (offset + count) >= eof; |
339 | rdata->args.pages, rdata->args.pgbase, | 295 | _fix_verify_io_params(rdata->lseg, &rdata->args.pages, |
340 | offset, count, | 296 | &rdata->args.pgbase, |
341 | rdata->lseg, rdata, | 297 | rdata->args.offset, rdata->args.count); |
342 | GFP_KERNEL); | ||
343 | if (unlikely(!state)) { | ||
344 | status = -ENOMEM; | ||
345 | goto out; | ||
346 | } | ||
347 | 298 | ||
348 | state->eof = state->offset + state->count >= eof; | 299 | dprintk("%s: inode(%lx) offset 0x%llx count 0x%Zx eof=%d\n", |
300 | __func__, rdata->inode->i_ino, offset, count, rdata->res.eof); | ||
349 | 301 | ||
350 | status = objio_read_pagelist(state); | 302 | err = objio_read_pagelist(rdata); |
351 | out: | 303 | out: |
352 | dprintk("%s: Return status %Zd\n", __func__, status); | 304 | if (unlikely(err)) { |
353 | rdata->pnfs_error = status; | 305 | rdata->pnfs_error = err; |
306 | dprintk("%s: Returned Error %d\n", __func__, err); | ||
307 | return PNFS_NOT_ATTEMPTED; | ||
308 | } | ||
354 | return PNFS_ATTEMPTED; | 309 | return PNFS_ATTEMPTED; |
355 | } | 310 | } |
356 | 311 | ||
@@ -371,26 +326,20 @@ static void _rpc_write_complete(struct work_struct *work) | |||
371 | } | 326 | } |
372 | 327 | ||
373 | void | 328 | void |
374 | objlayout_write_done(struct objlayout_io_state *state, ssize_t status, | 329 | objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync) |
375 | bool sync) | ||
376 | { | 330 | { |
377 | struct nfs_write_data *wdata; | 331 | struct nfs_write_data *wdata = oir->rpcdata; |
378 | 332 | ||
379 | dprintk("%s: Begin\n", __func__); | 333 | oir->status = wdata->task.tk_status = status; |
380 | wdata = state->rpcdata; | ||
381 | state->status = status; | ||
382 | wdata->task.tk_status = status; | ||
383 | if (status >= 0) { | 334 | if (status >= 0) { |
384 | wdata->res.count = status; | 335 | wdata->res.count = status; |
385 | wdata->verf.committed = state->committed; | 336 | wdata->verf.committed = oir->committed; |
386 | dprintk("%s: Return status %d committed %d\n", | 337 | } |
387 | __func__, wdata->task.tk_status, | 338 | objlayout_iodone(oir); |
388 | wdata->verf.committed); | 339 | /* must not use oir after this point */ |
389 | } else | 340 | |
390 | dprintk("%s: Return status %d\n", | 341 | dprintk("%s: Return status %zd committed %d sync=%d\n", __func__, |
391 | __func__, wdata->task.tk_status); | 342 | status, wdata->verf.committed, sync); |
392 | objlayout_iodone(state); | ||
393 | /* must not use state after this point */ | ||
394 | 343 | ||
395 | if (sync) | 344 | if (sync) |
396 | pnfs_ld_write_done(wdata); | 345 | pnfs_ld_write_done(wdata); |
@@ -407,30 +356,18 @@ enum pnfs_try_status | |||
407 | objlayout_write_pagelist(struct nfs_write_data *wdata, | 356 | objlayout_write_pagelist(struct nfs_write_data *wdata, |
408 | int how) | 357 | int how) |
409 | { | 358 | { |
410 | struct objlayout_io_state *state; | 359 | int err; |
411 | ssize_t status; | ||
412 | |||
413 | dprintk("%s: Begin inode %p offset %llu count %u\n", | ||
414 | __func__, wdata->inode, wdata->args.offset, wdata->args.count); | ||
415 | |||
416 | state = objlayout_alloc_io_state(NFS_I(wdata->inode)->layout, | ||
417 | wdata->args.pages, | ||
418 | wdata->args.pgbase, | ||
419 | wdata->args.offset, | ||
420 | wdata->args.count, | ||
421 | wdata->lseg, wdata, | ||
422 | GFP_NOFS); | ||
423 | if (unlikely(!state)) { | ||
424 | status = -ENOMEM; | ||
425 | goto out; | ||
426 | } | ||
427 | 360 | ||
428 | state->sync = how & FLUSH_SYNC; | 361 | _fix_verify_io_params(wdata->lseg, &wdata->args.pages, |
362 | &wdata->args.pgbase, | ||
363 | wdata->args.offset, wdata->args.count); | ||
429 | 364 | ||
430 | status = objio_write_pagelist(state, how & FLUSH_STABLE); | 365 | err = objio_write_pagelist(wdata, how); |
431 | out: | 366 | if (unlikely(err)) { |
432 | dprintk("%s: Return status %Zd\n", __func__, status); | 367 | wdata->pnfs_error = err; |
433 | wdata->pnfs_error = status; | 368 | dprintk("%s: Returned Error %d\n", __func__, err); |
369 | return PNFS_NOT_ATTEMPTED; | ||
370 | } | ||
434 | return PNFS_ATTEMPTED; | 371 | return PNFS_ATTEMPTED; |
435 | } | 372 | } |
436 | 373 | ||
@@ -537,14 +474,14 @@ merge_ioerr(struct pnfs_osd_ioerr *dest_err, | |||
537 | static void | 474 | static void |
538 | encode_accumulated_error(struct objlayout *objlay, __be32 *p) | 475 | encode_accumulated_error(struct objlayout *objlay, __be32 *p) |
539 | { | 476 | { |
540 | struct objlayout_io_state *state, *tmp; | 477 | struct objlayout_io_res *oir, *tmp; |
541 | struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0}; | 478 | struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0}; |
542 | 479 | ||
543 | list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) { | 480 | list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) { |
544 | unsigned i; | 481 | unsigned i; |
545 | 482 | ||
546 | for (i = 0; i < state->num_comps; i++) { | 483 | for (i = 0; i < oir->num_comps; i++) { |
547 | struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i]; | 484 | struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i]; |
548 | 485 | ||
549 | if (!ioerr->oer_errno) | 486 | if (!ioerr->oer_errno) |
550 | continue; | 487 | continue; |
@@ -563,8 +500,8 @@ encode_accumulated_error(struct objlayout *objlay, __be32 *p) | |||
563 | 500 | ||
564 | merge_ioerr(&accumulated_err, ioerr); | 501 | merge_ioerr(&accumulated_err, ioerr); |
565 | } | 502 | } |
566 | list_del(&state->err_list); | 503 | list_del(&oir->err_list); |
567 | objlayout_free_io_state(state); | 504 | objio_free_result(oir); |
568 | } | 505 | } |
569 | 506 | ||
570 | pnfs_osd_xdr_encode_ioerr(p, &accumulated_err); | 507 | pnfs_osd_xdr_encode_ioerr(p, &accumulated_err); |
@@ -576,7 +513,7 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay, | |||
576 | const struct nfs4_layoutreturn_args *args) | 513 | const struct nfs4_layoutreturn_args *args) |
577 | { | 514 | { |
578 | struct objlayout *objlay = OBJLAYOUT(pnfslay); | 515 | struct objlayout *objlay = OBJLAYOUT(pnfslay); |
579 | struct objlayout_io_state *state, *tmp; | 516 | struct objlayout_io_res *oir, *tmp; |
580 | __be32 *start; | 517 | __be32 *start; |
581 | 518 | ||
582 | dprintk("%s: Begin\n", __func__); | 519 | dprintk("%s: Begin\n", __func__); |
@@ -585,13 +522,13 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay, | |||
585 | 522 | ||
586 | spin_lock(&objlay->lock); | 523 | spin_lock(&objlay->lock); |
587 | 524 | ||
588 | list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) { | 525 | list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) { |
589 | __be32 *last_xdr = NULL, *p; | 526 | __be32 *last_xdr = NULL, *p; |
590 | unsigned i; | 527 | unsigned i; |
591 | int res = 0; | 528 | int res = 0; |
592 | 529 | ||
593 | for (i = 0; i < state->num_comps; i++) { | 530 | for (i = 0; i < oir->num_comps; i++) { |
594 | struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i]; | 531 | struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i]; |
595 | 532 | ||
596 | if (!ioerr->oer_errno) | 533 | if (!ioerr->oer_errno) |
597 | continue; | 534 | continue; |
@@ -615,7 +552,7 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay, | |||
615 | } | 552 | } |
616 | 553 | ||
617 | last_xdr = p; | 554 | last_xdr = p; |
618 | pnfs_osd_xdr_encode_ioerr(p, &state->ioerrs[i]); | 555 | pnfs_osd_xdr_encode_ioerr(p, &oir->ioerrs[i]); |
619 | } | 556 | } |
620 | 557 | ||
621 | /* TODO: use xdr_write_pages */ | 558 | /* TODO: use xdr_write_pages */ |
@@ -631,8 +568,8 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay, | |||
631 | encode_accumulated_error(objlay, last_xdr); | 568 | encode_accumulated_error(objlay, last_xdr); |
632 | goto loop_done; | 569 | goto loop_done; |
633 | } | 570 | } |
634 | list_del(&state->err_list); | 571 | list_del(&oir->err_list); |
635 | objlayout_free_io_state(state); | 572 | objio_free_result(oir); |
636 | } | 573 | } |
637 | loop_done: | 574 | loop_done: |
638 | spin_unlock(&objlay->lock); | 575 | spin_unlock(&objlay->lock); |