objlayout.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /*
  2. * pNFS Objects layout driver high level definitions
  3. *
  4. * Copyright (C) 2007 Panasas Inc. [year of first publication]
  5. * All rights reserved.
  6. *
  7. * Benny Halevy <bhalevy@panasas.com>
  8. * Boaz Harrosh <bharrosh@panasas.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2
  12. * See the file COPYING included with this distribution for more details.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions
  16. * are met:
  17. *
  18. * 1. Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. * 2. Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in the
  22. * documentation and/or other materials provided with the distribution.
  23. * 3. Neither the name of the Panasas company nor the names of its
  24. * contributors may be used to endorse or promote products derived
  25. * from this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  28. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  29. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  30. * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  34. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  35. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  36. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  37. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. */
  39. #include <scsi/osd_initiator.h>
  40. #include "objlayout.h"
  41. #define NFSDBG_FACILITY NFSDBG_PNFS_LD
  42. /*
  43. * Create a objlayout layout structure for the given inode and return it.
  44. */
  45. struct pnfs_layout_hdr *
  46. objlayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
  47. {
  48. struct objlayout *objlay;
  49. objlay = kzalloc(sizeof(struct objlayout), gfp_flags);
  50. if (objlay) {
  51. spin_lock_init(&objlay->lock);
  52. INIT_LIST_HEAD(&objlay->err_list);
  53. }
  54. dprintk("%s: Return %p\n", __func__, objlay);
  55. return &objlay->pnfs_layout;
  56. }
  57. /*
  58. * Free an objlayout layout structure
  59. */
  60. void
  61. objlayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
  62. {
  63. struct objlayout *objlay = OBJLAYOUT(lo);
  64. dprintk("%s: objlay %p\n", __func__, objlay);
  65. WARN_ON(!list_empty(&objlay->err_list));
  66. kfree(objlay);
  67. }
  68. /*
  69. * Unmarshall layout and store it in pnfslay.
  70. */
  71. struct pnfs_layout_segment *
  72. objlayout_alloc_lseg(struct pnfs_layout_hdr *pnfslay,
  73. struct nfs4_layoutget_res *lgr,
  74. gfp_t gfp_flags)
  75. {
  76. int status = -ENOMEM;
  77. struct xdr_stream stream;
  78. struct xdr_buf buf = {
  79. .pages = lgr->layoutp->pages,
  80. .page_len = lgr->layoutp->len,
  81. .buflen = lgr->layoutp->len,
  82. .len = lgr->layoutp->len,
  83. };
  84. struct page *scratch;
  85. struct pnfs_layout_segment *lseg;
  86. dprintk("%s: Begin pnfslay %p\n", __func__, pnfslay);
  87. scratch = alloc_page(gfp_flags);
  88. if (!scratch)
  89. goto err_nofree;
  90. xdr_init_decode(&stream, &buf, NULL);
  91. xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
  92. status = objio_alloc_lseg(&lseg, pnfslay, &lgr->range, &stream, gfp_flags);
  93. if (unlikely(status)) {
  94. dprintk("%s: objio_alloc_lseg Return err %d\n", __func__,
  95. status);
  96. goto err;
  97. }
  98. __free_page(scratch);
  99. dprintk("%s: Return %p\n", __func__, lseg);
  100. return lseg;
  101. err:
  102. __free_page(scratch);
  103. err_nofree:
  104. dprintk("%s: Err Return=>%d\n", __func__, status);
  105. return ERR_PTR(status);
  106. }
  107. /*
  108. * Free a layout segement
  109. */
  110. void
  111. objlayout_free_lseg(struct pnfs_layout_segment *lseg)
  112. {
  113. dprintk("%s: freeing layout segment %p\n", __func__, lseg);
  114. if (unlikely(!lseg))
  115. return;
  116. objio_free_lseg(lseg);
  117. }
  118. /*
  119. * I/O Operations
  120. */
  121. static inline u64
  122. end_offset(u64 start, u64 len)
  123. {
  124. u64 end;
  125. end = start + len;
  126. return end >= start ? end : NFS4_MAX_UINT64;
  127. }
  128. /* last octet in a range */
  129. static inline u64
  130. last_byte_offset(u64 start, u64 len)
  131. {
  132. u64 end;
  133. BUG_ON(!len);
  134. end = start + len;
  135. return end > start ? end - 1 : NFS4_MAX_UINT64;
  136. }
  137. static struct objlayout_io_state *
  138. objlayout_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type,
  139. struct page **pages,
  140. unsigned pgbase,
  141. loff_t offset,
  142. size_t count,
  143. struct pnfs_layout_segment *lseg,
  144. void *rpcdata,
  145. gfp_t gfp_flags)
  146. {
  147. struct objlayout_io_state *state;
  148. u64 lseg_end_offset;
  149. dprintk("%s: allocating io_state\n", __func__);
  150. if (objio_alloc_io_state(lseg, &state, gfp_flags))
  151. return NULL;
  152. BUG_ON(offset < lseg->pls_range.offset);
  153. lseg_end_offset = end_offset(lseg->pls_range.offset,
  154. lseg->pls_range.length);
  155. BUG_ON(offset >= lseg_end_offset);
  156. if (offset + count > lseg_end_offset) {
  157. count = lseg->pls_range.length -
  158. (offset - lseg->pls_range.offset);
  159. dprintk("%s: truncated count %Zd\n", __func__, count);
  160. }
  161. if (pgbase > PAGE_SIZE) {
  162. pages += pgbase >> PAGE_SHIFT;
  163. pgbase &= ~PAGE_MASK;
  164. }
  165. INIT_LIST_HEAD(&state->err_list);
  166. state->lseg = lseg;
  167. state->rpcdata = rpcdata;
  168. state->pages = pages;
  169. state->pgbase = pgbase;
  170. state->nr_pages = (pgbase + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
  171. state->offset = offset;
  172. state->count = count;
  173. state->sync = 0;
  174. return state;
  175. }
  176. static void
  177. objlayout_free_io_state(struct objlayout_io_state *state)
  178. {
  179. dprintk("%s: freeing io_state\n", __func__);
  180. if (unlikely(!state))
  181. return;
  182. objio_free_io_state(state);
  183. }
  184. /*
  185. * I/O done common code
  186. */
  187. static void
  188. objlayout_iodone(struct objlayout_io_state *state)
  189. {
  190. dprintk("%s: state %p status\n", __func__, state);
  191. if (likely(state->status >= 0)) {
  192. objlayout_free_io_state(state);
  193. } else {
  194. struct objlayout *objlay = OBJLAYOUT(state->lseg->pls_layout);
  195. spin_lock(&objlay->lock);
  196. objlay->delta_space_valid = OBJ_DSU_INVALID;
  197. list_add(&objlay->err_list, &state->err_list);
  198. spin_unlock(&objlay->lock);
  199. }
  200. }
  201. /*
  202. * objlayout_io_set_result - Set an osd_error code on a specific osd comp.
  203. *
  204. * The @index component IO failed (error returned from target). Register
  205. * the error for later reporting at layout-return.
  206. */
  207. void
  208. objlayout_io_set_result(struct objlayout_io_state *state, unsigned index,
  209. struct pnfs_osd_objid *pooid, int osd_error,
  210. u64 offset, u64 length, bool is_write)
  211. {
  212. struct pnfs_osd_ioerr *ioerr = &state->ioerrs[index];
  213. BUG_ON(index >= state->num_comps);
  214. if (osd_error) {
  215. ioerr->oer_component = *pooid;
  216. ioerr->oer_comp_offset = offset;
  217. ioerr->oer_comp_length = length;
  218. ioerr->oer_iswrite = is_write;
  219. ioerr->oer_errno = osd_error;
  220. dprintk("%s: err[%d]: errno=%d is_write=%d dev(%llx:%llx) "
  221. "par=0x%llx obj=0x%llx offset=0x%llx length=0x%llx\n",
  222. __func__, index, ioerr->oer_errno,
  223. ioerr->oer_iswrite,
  224. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  225. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  226. ioerr->oer_component.oid_partition_id,
  227. ioerr->oer_component.oid_object_id,
  228. ioerr->oer_comp_offset,
  229. ioerr->oer_comp_length);
  230. } else {
  231. /* User need not call if no error is reported */
  232. ioerr->oer_errno = 0;
  233. }
  234. }
  235. /* Function scheduled on rpc workqueue to call ->nfs_readlist_complete().
  236. * This is because the osd completion is called with ints-off from
  237. * the block layer
  238. */
  239. static void _rpc_read_complete(struct work_struct *work)
  240. {
  241. struct rpc_task *task;
  242. struct nfs_read_data *rdata;
  243. dprintk("%s enter\n", __func__);
  244. task = container_of(work, struct rpc_task, u.tk_work);
  245. rdata = container_of(task, struct nfs_read_data, task);
  246. pnfs_ld_read_done(rdata);
  247. }
  248. void
  249. objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync)
  250. {
  251. int eof = state->eof;
  252. struct nfs_read_data *rdata;
  253. state->status = status;
  254. dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof);
  255. rdata = state->rpcdata;
  256. rdata->task.tk_status = status;
  257. if (likely(status >= 0)) {
  258. rdata->res.count = status;
  259. rdata->res.eof = eof;
  260. } else {
  261. rdata->pnfs_error = status;
  262. }
  263. objlayout_iodone(state);
  264. /* must not use state after this point */
  265. if (sync)
  266. pnfs_ld_read_done(rdata);
  267. else {
  268. INIT_WORK(&rdata->task.u.tk_work, _rpc_read_complete);
  269. schedule_work(&rdata->task.u.tk_work);
  270. }
  271. }
  272. /*
  273. * Perform sync or async reads.
  274. */
  275. enum pnfs_try_status
  276. objlayout_read_pagelist(struct nfs_read_data *rdata)
  277. {
  278. loff_t offset = rdata->args.offset;
  279. size_t count = rdata->args.count;
  280. struct objlayout_io_state *state;
  281. ssize_t status = 0;
  282. loff_t eof;
  283. dprintk("%s: Begin inode %p offset %llu count %d\n",
  284. __func__, rdata->inode, offset, (int)count);
  285. eof = i_size_read(rdata->inode);
  286. if (unlikely(offset + count > eof)) {
  287. if (offset >= eof) {
  288. status = 0;
  289. rdata->res.count = 0;
  290. rdata->res.eof = 1;
  291. goto out;
  292. }
  293. count = eof - offset;
  294. }
  295. state = objlayout_alloc_io_state(NFS_I(rdata->inode)->layout,
  296. rdata->args.pages, rdata->args.pgbase,
  297. offset, count,
  298. rdata->lseg, rdata,
  299. GFP_KERNEL);
  300. if (unlikely(!state)) {
  301. status = -ENOMEM;
  302. goto out;
  303. }
  304. state->eof = state->offset + state->count >= eof;
  305. status = objio_read_pagelist(state);
  306. out:
  307. dprintk("%s: Return status %Zd\n", __func__, status);
  308. rdata->pnfs_error = status;
  309. return PNFS_ATTEMPTED;
  310. }
  311. /* Function scheduled on rpc workqueue to call ->nfs_writelist_complete().
  312. * This is because the osd completion is called with ints-off from
  313. * the block layer
  314. */
  315. static void _rpc_write_complete(struct work_struct *work)
  316. {
  317. struct rpc_task *task;
  318. struct nfs_write_data *wdata;
  319. dprintk("%s enter\n", __func__);
  320. task = container_of(work, struct rpc_task, u.tk_work);
  321. wdata = container_of(task, struct nfs_write_data, task);
  322. pnfs_ld_write_done(wdata);
  323. }
  324. void
  325. objlayout_write_done(struct objlayout_io_state *state, ssize_t status,
  326. bool sync)
  327. {
  328. struct nfs_write_data *wdata;
  329. dprintk("%s: Begin\n", __func__);
  330. wdata = state->rpcdata;
  331. state->status = status;
  332. wdata->task.tk_status = status;
  333. if (likely(status >= 0)) {
  334. wdata->res.count = status;
  335. wdata->verf.committed = state->committed;
  336. dprintk("%s: Return status %d committed %d\n",
  337. __func__, wdata->task.tk_status,
  338. wdata->verf.committed);
  339. } else {
  340. wdata->pnfs_error = status;
  341. dprintk("%s: Return status %d\n",
  342. __func__, wdata->task.tk_status);
  343. }
  344. objlayout_iodone(state);
  345. /* must not use state after this point */
  346. if (sync)
  347. pnfs_ld_write_done(wdata);
  348. else {
  349. INIT_WORK(&wdata->task.u.tk_work, _rpc_write_complete);
  350. schedule_work(&wdata->task.u.tk_work);
  351. }
  352. }
  353. /*
  354. * Perform sync or async writes.
  355. */
  356. enum pnfs_try_status
  357. objlayout_write_pagelist(struct nfs_write_data *wdata,
  358. int how)
  359. {
  360. struct objlayout_io_state *state;
  361. ssize_t status;
  362. dprintk("%s: Begin inode %p offset %llu count %u\n",
  363. __func__, wdata->inode, wdata->args.offset, wdata->args.count);
  364. state = objlayout_alloc_io_state(NFS_I(wdata->inode)->layout,
  365. wdata->args.pages,
  366. wdata->args.pgbase,
  367. wdata->args.offset,
  368. wdata->args.count,
  369. wdata->lseg, wdata,
  370. GFP_NOFS);
  371. if (unlikely(!state)) {
  372. status = -ENOMEM;
  373. goto out;
  374. }
  375. state->sync = how & FLUSH_SYNC;
  376. status = objio_write_pagelist(state, how & FLUSH_STABLE);
  377. out:
  378. dprintk("%s: Return status %Zd\n", __func__, status);
  379. wdata->pnfs_error = status;
  380. return PNFS_ATTEMPTED;
  381. }
  382. void
  383. objlayout_encode_layoutcommit(struct pnfs_layout_hdr *pnfslay,
  384. struct xdr_stream *xdr,
  385. const struct nfs4_layoutcommit_args *args)
  386. {
  387. struct objlayout *objlay = OBJLAYOUT(pnfslay);
  388. struct pnfs_osd_layoutupdate lou;
  389. __be32 *start;
  390. dprintk("%s: Begin\n", __func__);
  391. spin_lock(&objlay->lock);
  392. lou.dsu_valid = (objlay->delta_space_valid == OBJ_DSU_VALID);
  393. lou.dsu_delta = objlay->delta_space_used;
  394. objlay->delta_space_used = 0;
  395. objlay->delta_space_valid = OBJ_DSU_INIT;
  396. lou.olu_ioerr_flag = !list_empty(&objlay->err_list);
  397. spin_unlock(&objlay->lock);
  398. start = xdr_reserve_space(xdr, 4);
  399. BUG_ON(pnfs_osd_xdr_encode_layoutupdate(xdr, &lou));
  400. *start = cpu_to_be32((xdr->p - start - 1) * 4);
  401. dprintk("%s: Return delta_space_used %lld err %d\n", __func__,
  402. lou.dsu_delta, lou.olu_ioerr_flag);
  403. }
  404. static int
  405. err_prio(u32 oer_errno)
  406. {
  407. switch (oer_errno) {
  408. case 0:
  409. return 0;
  410. case PNFS_OSD_ERR_RESOURCE:
  411. return OSD_ERR_PRI_RESOURCE;
  412. case PNFS_OSD_ERR_BAD_CRED:
  413. return OSD_ERR_PRI_BAD_CRED;
  414. case PNFS_OSD_ERR_NO_ACCESS:
  415. return OSD_ERR_PRI_NO_ACCESS;
  416. case PNFS_OSD_ERR_UNREACHABLE:
  417. return OSD_ERR_PRI_UNREACHABLE;
  418. case PNFS_OSD_ERR_NOT_FOUND:
  419. return OSD_ERR_PRI_NOT_FOUND;
  420. case PNFS_OSD_ERR_NO_SPACE:
  421. return OSD_ERR_PRI_NO_SPACE;
  422. default:
  423. WARN_ON(1);
  424. /* fallthrough */
  425. case PNFS_OSD_ERR_EIO:
  426. return OSD_ERR_PRI_EIO;
  427. }
  428. }
  429. static void
  430. merge_ioerr(struct pnfs_osd_ioerr *dest_err,
  431. const struct pnfs_osd_ioerr *src_err)
  432. {
  433. u64 dest_end, src_end;
  434. if (!dest_err->oer_errno) {
  435. *dest_err = *src_err;
  436. /* accumulated device must be blank */
  437. memset(&dest_err->oer_component.oid_device_id, 0,
  438. sizeof(dest_err->oer_component.oid_device_id));
  439. return;
  440. }
  441. if (dest_err->oer_component.oid_partition_id !=
  442. src_err->oer_component.oid_partition_id)
  443. dest_err->oer_component.oid_partition_id = 0;
  444. if (dest_err->oer_component.oid_object_id !=
  445. src_err->oer_component.oid_object_id)
  446. dest_err->oer_component.oid_object_id = 0;
  447. if (dest_err->oer_comp_offset > src_err->oer_comp_offset)
  448. dest_err->oer_comp_offset = src_err->oer_comp_offset;
  449. dest_end = end_offset(dest_err->oer_comp_offset,
  450. dest_err->oer_comp_length);
  451. src_end = end_offset(src_err->oer_comp_offset,
  452. src_err->oer_comp_length);
  453. if (dest_end < src_end)
  454. dest_end = src_end;
  455. dest_err->oer_comp_length = dest_end - dest_err->oer_comp_offset;
  456. if ((src_err->oer_iswrite == dest_err->oer_iswrite) &&
  457. (err_prio(src_err->oer_errno) > err_prio(dest_err->oer_errno))) {
  458. dest_err->oer_errno = src_err->oer_errno;
  459. } else if (src_err->oer_iswrite) {
  460. dest_err->oer_iswrite = true;
  461. dest_err->oer_errno = src_err->oer_errno;
  462. }
  463. }
  464. static void
  465. encode_accumulated_error(struct objlayout *objlay, __be32 *p)
  466. {
  467. struct objlayout_io_state *state, *tmp;
  468. struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0};
  469. list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
  470. unsigned i;
  471. for (i = 0; i < state->num_comps; i++) {
  472. struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
  473. if (!ioerr->oer_errno)
  474. continue;
  475. printk(KERN_ERR "%s: err[%d]: errno=%d is_write=%d "
  476. "dev(%llx:%llx) par=0x%llx obj=0x%llx "
  477. "offset=0x%llx length=0x%llx\n",
  478. __func__, i, ioerr->oer_errno,
  479. ioerr->oer_iswrite,
  480. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  481. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  482. ioerr->oer_component.oid_partition_id,
  483. ioerr->oer_component.oid_object_id,
  484. ioerr->oer_comp_offset,
  485. ioerr->oer_comp_length);
  486. merge_ioerr(&accumulated_err, ioerr);
  487. }
  488. list_del(&state->err_list);
  489. objlayout_free_io_state(state);
  490. }
  491. pnfs_osd_xdr_encode_ioerr(p, &accumulated_err);
  492. }
  493. void
  494. objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
  495. struct xdr_stream *xdr,
  496. const struct nfs4_layoutreturn_args *args)
  497. {
  498. struct objlayout *objlay = OBJLAYOUT(pnfslay);
  499. struct objlayout_io_state *state, *tmp;
  500. __be32 *start;
  501. dprintk("%s: Begin\n", __func__);
  502. start = xdr_reserve_space(xdr, 4);
  503. BUG_ON(!start);
  504. spin_lock(&objlay->lock);
  505. list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
  506. __be32 *last_xdr = NULL, *p;
  507. unsigned i;
  508. int res = 0;
  509. for (i = 0; i < state->num_comps; i++) {
  510. struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
  511. if (!ioerr->oer_errno)
  512. continue;
  513. dprintk("%s: err[%d]: errno=%d is_write=%d "
  514. "dev(%llx:%llx) par=0x%llx obj=0x%llx "
  515. "offset=0x%llx length=0x%llx\n",
  516. __func__, i, ioerr->oer_errno,
  517. ioerr->oer_iswrite,
  518. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  519. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  520. ioerr->oer_component.oid_partition_id,
  521. ioerr->oer_component.oid_object_id,
  522. ioerr->oer_comp_offset,
  523. ioerr->oer_comp_length);
  524. p = pnfs_osd_xdr_ioerr_reserve_space(xdr);
  525. if (unlikely(!p)) {
  526. res = -E2BIG;
  527. break; /* accumulated_error */
  528. }
  529. last_xdr = p;
  530. pnfs_osd_xdr_encode_ioerr(p, &state->ioerrs[i]);
  531. }
  532. /* TODO: use xdr_write_pages */
  533. if (unlikely(res)) {
  534. /* no space for even one error descriptor */
  535. BUG_ON(!last_xdr);
  536. /* we've encountered a situation with lots and lots of
  537. * errors and no space to encode them all. Use the last
  538. * available slot to report the union of all the
  539. * remaining errors.
  540. */
  541. encode_accumulated_error(objlay, last_xdr);
  542. goto loop_done;
  543. }
  544. list_del(&state->err_list);
  545. objlayout_free_io_state(state);
  546. }
  547. loop_done:
  548. spin_unlock(&objlay->lock);
  549. *start = cpu_to_be32((xdr->p - start - 1) * 4);
  550. dprintk("%s: Return\n", __func__);
  551. }
  552. /*
  553. * Get Device Info API for io engines
  554. */
  555. struct objlayout_deviceinfo {
  556. struct page *page;
  557. struct pnfs_osd_deviceaddr da; /* This must be last */
  558. };
  559. /* Initialize and call nfs_getdeviceinfo, then decode and return a
  560. * "struct pnfs_osd_deviceaddr *" Eventually objlayout_put_deviceinfo()
  561. * should be called.
  562. */
  563. int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay,
  564. struct nfs4_deviceid *d_id, struct pnfs_osd_deviceaddr **deviceaddr,
  565. gfp_t gfp_flags)
  566. {
  567. struct objlayout_deviceinfo *odi;
  568. struct pnfs_device pd;
  569. struct super_block *sb;
  570. struct page *page, **pages;
  571. u32 *p;
  572. int err;
  573. page = alloc_page(gfp_flags);
  574. if (!page)
  575. return -ENOMEM;
  576. pages = &page;
  577. pd.pages = pages;
  578. memcpy(&pd.dev_id, d_id, sizeof(*d_id));
  579. pd.layout_type = LAYOUT_OSD2_OBJECTS;
  580. pd.pages = &page;
  581. pd.pgbase = 0;
  582. pd.pglen = PAGE_SIZE;
  583. pd.mincount = 0;
  584. sb = pnfslay->plh_inode->i_sb;
  585. err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd);
  586. dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err);
  587. if (err)
  588. goto err_out;
  589. p = page_address(page);
  590. odi = kzalloc(sizeof(*odi), gfp_flags);
  591. if (!odi) {
  592. err = -ENOMEM;
  593. goto err_out;
  594. }
  595. pnfs_osd_xdr_decode_deviceaddr(&odi->da, p);
  596. odi->page = page;
  597. *deviceaddr = &odi->da;
  598. return 0;
  599. err_out:
  600. __free_page(page);
  601. return err;
  602. }
  603. void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr)
  604. {
  605. struct objlayout_deviceinfo *odi = container_of(deviceaddr,
  606. struct objlayout_deviceinfo,
  607. da);
  608. __free_page(odi->page);
  609. kfree(odi);
  610. }