objlayout.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  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=%ld eof=%d\n", __func__, status, eof);
  255. rdata = state->rpcdata;
  256. rdata->task.tk_status = status;
  257. if (status >= 0) {
  258. rdata->res.count = status;
  259. rdata->res.eof = eof;
  260. }
  261. objlayout_iodone(state);
  262. /* must not use state after this point */
  263. if (sync)
  264. pnfs_ld_read_done(rdata);
  265. else {
  266. INIT_WORK(&rdata->task.u.tk_work, _rpc_read_complete);
  267. schedule_work(&rdata->task.u.tk_work);
  268. }
  269. }
  270. /*
  271. * Perform sync or async reads.
  272. */
  273. enum pnfs_try_status
  274. objlayout_read_pagelist(struct nfs_read_data *rdata)
  275. {
  276. loff_t offset = rdata->args.offset;
  277. size_t count = rdata->args.count;
  278. struct objlayout_io_state *state;
  279. ssize_t status = 0;
  280. loff_t eof;
  281. dprintk("%s: Begin inode %p offset %llu count %d\n",
  282. __func__, rdata->inode, offset, (int)count);
  283. eof = i_size_read(rdata->inode);
  284. if (unlikely(offset + count > eof)) {
  285. if (offset >= eof) {
  286. status = 0;
  287. rdata->res.count = 0;
  288. rdata->res.eof = 1;
  289. goto out;
  290. }
  291. count = eof - offset;
  292. }
  293. state = objlayout_alloc_io_state(NFS_I(rdata->inode)->layout,
  294. rdata->args.pages, rdata->args.pgbase,
  295. offset, count,
  296. rdata->lseg, rdata,
  297. GFP_KERNEL);
  298. if (unlikely(!state)) {
  299. status = -ENOMEM;
  300. goto out;
  301. }
  302. state->eof = state->offset + state->count >= eof;
  303. status = objio_read_pagelist(state);
  304. out:
  305. dprintk("%s: Return status %Zd\n", __func__, status);
  306. rdata->pnfs_error = status;
  307. return PNFS_ATTEMPTED;
  308. }
  309. /* Function scheduled on rpc workqueue to call ->nfs_writelist_complete().
  310. * This is because the osd completion is called with ints-off from
  311. * the block layer
  312. */
  313. static void _rpc_write_complete(struct work_struct *work)
  314. {
  315. struct rpc_task *task;
  316. struct nfs_write_data *wdata;
  317. dprintk("%s enter\n", __func__);
  318. task = container_of(work, struct rpc_task, u.tk_work);
  319. wdata = container_of(task, struct nfs_write_data, task);
  320. pnfs_ld_write_done(wdata);
  321. }
  322. void
  323. objlayout_write_done(struct objlayout_io_state *state, ssize_t status,
  324. bool sync)
  325. {
  326. struct nfs_write_data *wdata;
  327. dprintk("%s: Begin\n", __func__);
  328. wdata = state->rpcdata;
  329. state->status = status;
  330. wdata->task.tk_status = status;
  331. if (status >= 0) {
  332. wdata->res.count = status;
  333. wdata->verf.committed = state->committed;
  334. dprintk("%s: Return status %d committed %d\n",
  335. __func__, wdata->task.tk_status,
  336. wdata->verf.committed);
  337. } else
  338. dprintk("%s: Return status %d\n",
  339. __func__, wdata->task.tk_status);
  340. objlayout_iodone(state);
  341. /* must not use state after this point */
  342. if (sync)
  343. pnfs_ld_write_done(wdata);
  344. else {
  345. INIT_WORK(&wdata->task.u.tk_work, _rpc_write_complete);
  346. schedule_work(&wdata->task.u.tk_work);
  347. }
  348. }
  349. /*
  350. * Perform sync or async writes.
  351. */
  352. enum pnfs_try_status
  353. objlayout_write_pagelist(struct nfs_write_data *wdata,
  354. int how)
  355. {
  356. struct objlayout_io_state *state;
  357. ssize_t status;
  358. dprintk("%s: Begin inode %p offset %llu count %u\n",
  359. __func__, wdata->inode, wdata->args.offset, wdata->args.count);
  360. state = objlayout_alloc_io_state(NFS_I(wdata->inode)->layout,
  361. wdata->args.pages,
  362. wdata->args.pgbase,
  363. wdata->args.offset,
  364. wdata->args.count,
  365. wdata->lseg, wdata,
  366. GFP_NOFS);
  367. if (unlikely(!state)) {
  368. status = -ENOMEM;
  369. goto out;
  370. }
  371. state->sync = how & FLUSH_SYNC;
  372. status = objio_write_pagelist(state, how & FLUSH_STABLE);
  373. out:
  374. dprintk("%s: Return status %Zd\n", __func__, status);
  375. wdata->pnfs_error = status;
  376. return PNFS_ATTEMPTED;
  377. }
  378. void
  379. objlayout_encode_layoutcommit(struct pnfs_layout_hdr *pnfslay,
  380. struct xdr_stream *xdr,
  381. const struct nfs4_layoutcommit_args *args)
  382. {
  383. struct objlayout *objlay = OBJLAYOUT(pnfslay);
  384. struct pnfs_osd_layoutupdate lou;
  385. __be32 *start;
  386. dprintk("%s: Begin\n", __func__);
  387. spin_lock(&objlay->lock);
  388. lou.dsu_valid = (objlay->delta_space_valid == OBJ_DSU_VALID);
  389. lou.dsu_delta = objlay->delta_space_used;
  390. objlay->delta_space_used = 0;
  391. objlay->delta_space_valid = OBJ_DSU_INIT;
  392. lou.olu_ioerr_flag = !list_empty(&objlay->err_list);
  393. spin_unlock(&objlay->lock);
  394. start = xdr_reserve_space(xdr, 4);
  395. BUG_ON(pnfs_osd_xdr_encode_layoutupdate(xdr, &lou));
  396. *start = cpu_to_be32((xdr->p - start - 1) * 4);
  397. dprintk("%s: Return delta_space_used %lld err %d\n", __func__,
  398. lou.dsu_delta, lou.olu_ioerr_flag);
  399. }
  400. static int
  401. err_prio(u32 oer_errno)
  402. {
  403. switch (oer_errno) {
  404. case 0:
  405. return 0;
  406. case PNFS_OSD_ERR_RESOURCE:
  407. return OSD_ERR_PRI_RESOURCE;
  408. case PNFS_OSD_ERR_BAD_CRED:
  409. return OSD_ERR_PRI_BAD_CRED;
  410. case PNFS_OSD_ERR_NO_ACCESS:
  411. return OSD_ERR_PRI_NO_ACCESS;
  412. case PNFS_OSD_ERR_UNREACHABLE:
  413. return OSD_ERR_PRI_UNREACHABLE;
  414. case PNFS_OSD_ERR_NOT_FOUND:
  415. return OSD_ERR_PRI_NOT_FOUND;
  416. case PNFS_OSD_ERR_NO_SPACE:
  417. return OSD_ERR_PRI_NO_SPACE;
  418. default:
  419. WARN_ON(1);
  420. /* fallthrough */
  421. case PNFS_OSD_ERR_EIO:
  422. return OSD_ERR_PRI_EIO;
  423. }
  424. }
  425. static void
  426. merge_ioerr(struct pnfs_osd_ioerr *dest_err,
  427. const struct pnfs_osd_ioerr *src_err)
  428. {
  429. u64 dest_end, src_end;
  430. if (!dest_err->oer_errno) {
  431. *dest_err = *src_err;
  432. /* accumulated device must be blank */
  433. memset(&dest_err->oer_component.oid_device_id, 0,
  434. sizeof(dest_err->oer_component.oid_device_id));
  435. return;
  436. }
  437. if (dest_err->oer_component.oid_partition_id !=
  438. src_err->oer_component.oid_partition_id)
  439. dest_err->oer_component.oid_partition_id = 0;
  440. if (dest_err->oer_component.oid_object_id !=
  441. src_err->oer_component.oid_object_id)
  442. dest_err->oer_component.oid_object_id = 0;
  443. if (dest_err->oer_comp_offset > src_err->oer_comp_offset)
  444. dest_err->oer_comp_offset = src_err->oer_comp_offset;
  445. dest_end = end_offset(dest_err->oer_comp_offset,
  446. dest_err->oer_comp_length);
  447. src_end = end_offset(src_err->oer_comp_offset,
  448. src_err->oer_comp_length);
  449. if (dest_end < src_end)
  450. dest_end = src_end;
  451. dest_err->oer_comp_length = dest_end - dest_err->oer_comp_offset;
  452. if ((src_err->oer_iswrite == dest_err->oer_iswrite) &&
  453. (err_prio(src_err->oer_errno) > err_prio(dest_err->oer_errno))) {
  454. dest_err->oer_errno = src_err->oer_errno;
  455. } else if (src_err->oer_iswrite) {
  456. dest_err->oer_iswrite = true;
  457. dest_err->oer_errno = src_err->oer_errno;
  458. }
  459. }
  460. static void
  461. encode_accumulated_error(struct objlayout *objlay, __be32 *p)
  462. {
  463. struct objlayout_io_state *state, *tmp;
  464. struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0};
  465. list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
  466. unsigned i;
  467. for (i = 0; i < state->num_comps; i++) {
  468. struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
  469. if (!ioerr->oer_errno)
  470. continue;
  471. printk(KERN_ERR "%s: err[%d]: errno=%d is_write=%d "
  472. "dev(%llx:%llx) par=0x%llx obj=0x%llx "
  473. "offset=0x%llx length=0x%llx\n",
  474. __func__, i, ioerr->oer_errno,
  475. ioerr->oer_iswrite,
  476. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  477. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  478. ioerr->oer_component.oid_partition_id,
  479. ioerr->oer_component.oid_object_id,
  480. ioerr->oer_comp_offset,
  481. ioerr->oer_comp_length);
  482. merge_ioerr(&accumulated_err, ioerr);
  483. }
  484. list_del(&state->err_list);
  485. objlayout_free_io_state(state);
  486. }
  487. pnfs_osd_xdr_encode_ioerr(p, &accumulated_err);
  488. }
  489. void
  490. objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
  491. struct xdr_stream *xdr,
  492. const struct nfs4_layoutreturn_args *args)
  493. {
  494. struct objlayout *objlay = OBJLAYOUT(pnfslay);
  495. struct objlayout_io_state *state, *tmp;
  496. __be32 *start;
  497. dprintk("%s: Begin\n", __func__);
  498. start = xdr_reserve_space(xdr, 4);
  499. BUG_ON(!start);
  500. spin_lock(&objlay->lock);
  501. list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
  502. __be32 *last_xdr = NULL, *p;
  503. unsigned i;
  504. int res = 0;
  505. for (i = 0; i < state->num_comps; i++) {
  506. struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
  507. if (!ioerr->oer_errno)
  508. continue;
  509. dprintk("%s: err[%d]: errno=%d is_write=%d "
  510. "dev(%llx:%llx) par=0x%llx obj=0x%llx "
  511. "offset=0x%llx length=0x%llx\n",
  512. __func__, i, ioerr->oer_errno,
  513. ioerr->oer_iswrite,
  514. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  515. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  516. ioerr->oer_component.oid_partition_id,
  517. ioerr->oer_component.oid_object_id,
  518. ioerr->oer_comp_offset,
  519. ioerr->oer_comp_length);
  520. p = pnfs_osd_xdr_ioerr_reserve_space(xdr);
  521. if (unlikely(!p)) {
  522. res = -E2BIG;
  523. break; /* accumulated_error */
  524. }
  525. last_xdr = p;
  526. pnfs_osd_xdr_encode_ioerr(p, &state->ioerrs[i]);
  527. }
  528. /* TODO: use xdr_write_pages */
  529. if (unlikely(res)) {
  530. /* no space for even one error descriptor */
  531. BUG_ON(!last_xdr);
  532. /* we've encountered a situation with lots and lots of
  533. * errors and no space to encode them all. Use the last
  534. * available slot to report the union of all the
  535. * remaining errors.
  536. */
  537. encode_accumulated_error(objlay, last_xdr);
  538. goto loop_done;
  539. }
  540. list_del(&state->err_list);
  541. objlayout_free_io_state(state);
  542. }
  543. loop_done:
  544. spin_unlock(&objlay->lock);
  545. *start = cpu_to_be32((xdr->p - start - 1) * 4);
  546. dprintk("%s: Return\n", __func__);
  547. }
  548. /*
  549. * Get Device Info API for io engines
  550. */
  551. struct objlayout_deviceinfo {
  552. struct page *page;
  553. struct pnfs_osd_deviceaddr da; /* This must be last */
  554. };
  555. /* Initialize and call nfs_getdeviceinfo, then decode and return a
  556. * "struct pnfs_osd_deviceaddr *" Eventually objlayout_put_deviceinfo()
  557. * should be called.
  558. */
  559. int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay,
  560. struct nfs4_deviceid *d_id, struct pnfs_osd_deviceaddr **deviceaddr,
  561. gfp_t gfp_flags)
  562. {
  563. struct objlayout_deviceinfo *odi;
  564. struct pnfs_device pd;
  565. struct super_block *sb;
  566. struct page *page, **pages;
  567. u32 *p;
  568. int err;
  569. page = alloc_page(gfp_flags);
  570. if (!page)
  571. return -ENOMEM;
  572. pages = &page;
  573. pd.pages = pages;
  574. memcpy(&pd.dev_id, d_id, sizeof(*d_id));
  575. pd.layout_type = LAYOUT_OSD2_OBJECTS;
  576. pd.pages = &page;
  577. pd.pgbase = 0;
  578. pd.pglen = PAGE_SIZE;
  579. pd.mincount = 0;
  580. sb = pnfslay->plh_inode->i_sb;
  581. err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd);
  582. dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err);
  583. if (err)
  584. goto err_out;
  585. p = page_address(page);
  586. odi = kzalloc(sizeof(*odi), gfp_flags);
  587. if (!odi) {
  588. err = -ENOMEM;
  589. goto err_out;
  590. }
  591. pnfs_osd_xdr_decode_deviceaddr(&odi->da, p);
  592. odi->page = page;
  593. *deviceaddr = &odi->da;
  594. return 0;
  595. err_out:
  596. __free_page(page);
  597. return err;
  598. }
  599. void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr)
  600. {
  601. struct objlayout_deviceinfo *odi = container_of(deviceaddr,
  602. struct objlayout_deviceinfo,
  603. da);
  604. __free_page(odi->page);
  605. kfree(odi);
  606. }