objlayout.c 18 KB

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