objlayout.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  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 <ooo@electrozaur.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 <linux/kmod.h>
  40. #include <linux/moduleparam.h>
  41. #include <linux/ratelimit.h>
  42. #include <scsi/osd_initiator.h>
  43. #include "objlayout.h"
  44. #define NFSDBG_FACILITY NFSDBG_PNFS_LD
  45. /*
  46. * Create a objlayout layout structure for the given inode and return it.
  47. */
  48. struct pnfs_layout_hdr *
  49. objlayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
  50. {
  51. struct objlayout *objlay;
  52. objlay = kzalloc(sizeof(struct objlayout), gfp_flags);
  53. if (!objlay)
  54. return NULL;
  55. spin_lock_init(&objlay->lock);
  56. INIT_LIST_HEAD(&objlay->err_list);
  57. dprintk("%s: Return %p\n", __func__, objlay);
  58. return &objlay->pnfs_layout;
  59. }
  60. /*
  61. * Free an objlayout layout structure
  62. */
  63. void
  64. objlayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
  65. {
  66. struct objlayout *objlay = OBJLAYOUT(lo);
  67. dprintk("%s: objlay %p\n", __func__, objlay);
  68. WARN_ON(!list_empty(&objlay->err_list));
  69. kfree(objlay);
  70. }
  71. /*
  72. * Unmarshall layout and store it in pnfslay.
  73. */
  74. struct pnfs_layout_segment *
  75. objlayout_alloc_lseg(struct pnfs_layout_hdr *pnfslay,
  76. struct nfs4_layoutget_res *lgr,
  77. gfp_t gfp_flags)
  78. {
  79. int status = -ENOMEM;
  80. struct xdr_stream stream;
  81. struct xdr_buf buf = {
  82. .pages = lgr->layoutp->pages,
  83. .page_len = lgr->layoutp->len,
  84. .buflen = lgr->layoutp->len,
  85. .len = lgr->layoutp->len,
  86. };
  87. struct page *scratch;
  88. struct pnfs_layout_segment *lseg;
  89. dprintk("%s: Begin pnfslay %p\n", __func__, pnfslay);
  90. scratch = alloc_page(gfp_flags);
  91. if (!scratch)
  92. goto err_nofree;
  93. xdr_init_decode(&stream, &buf, NULL);
  94. xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
  95. status = objio_alloc_lseg(&lseg, pnfslay, &lgr->range, &stream, gfp_flags);
  96. if (unlikely(status)) {
  97. dprintk("%s: objio_alloc_lseg Return err %d\n", __func__,
  98. status);
  99. goto err;
  100. }
  101. __free_page(scratch);
  102. dprintk("%s: Return %p\n", __func__, lseg);
  103. return lseg;
  104. err:
  105. __free_page(scratch);
  106. err_nofree:
  107. dprintk("%s: Err Return=>%d\n", __func__, status);
  108. return ERR_PTR(status);
  109. }
  110. /*
  111. * Free a layout segement
  112. */
  113. void
  114. objlayout_free_lseg(struct pnfs_layout_segment *lseg)
  115. {
  116. dprintk("%s: freeing layout segment %p\n", __func__, lseg);
  117. if (unlikely(!lseg))
  118. return;
  119. objio_free_lseg(lseg);
  120. }
  121. /*
  122. * I/O Operations
  123. */
  124. static inline u64
  125. end_offset(u64 start, u64 len)
  126. {
  127. u64 end;
  128. end = start + len;
  129. return end >= start ? end : NFS4_MAX_UINT64;
  130. }
  131. static void _fix_verify_io_params(struct pnfs_layout_segment *lseg,
  132. struct page ***p_pages, unsigned *p_pgbase,
  133. u64 offset, unsigned long count)
  134. {
  135. u64 lseg_end_offset;
  136. BUG_ON(offset < lseg->pls_range.offset);
  137. lseg_end_offset = end_offset(lseg->pls_range.offset,
  138. lseg->pls_range.length);
  139. BUG_ON(offset >= lseg_end_offset);
  140. WARN_ON(offset + count > lseg_end_offset);
  141. if (*p_pgbase > PAGE_SIZE) {
  142. dprintk("%s: pgbase(0x%x) > PAGE_SIZE\n", __func__, *p_pgbase);
  143. *p_pages += *p_pgbase >> PAGE_SHIFT;
  144. *p_pgbase &= ~PAGE_MASK;
  145. }
  146. }
  147. /*
  148. * I/O done common code
  149. */
  150. static void
  151. objlayout_iodone(struct objlayout_io_res *oir)
  152. {
  153. if (likely(oir->status >= 0)) {
  154. objio_free_result(oir);
  155. } else {
  156. struct objlayout *objlay = oir->objlay;
  157. spin_lock(&objlay->lock);
  158. objlay->delta_space_valid = OBJ_DSU_INVALID;
  159. list_add(&objlay->err_list, &oir->err_list);
  160. spin_unlock(&objlay->lock);
  161. }
  162. }
  163. /*
  164. * objlayout_io_set_result - Set an osd_error code on a specific osd comp.
  165. *
  166. * The @index component IO failed (error returned from target). Register
  167. * the error for later reporting at layout-return.
  168. */
  169. void
  170. objlayout_io_set_result(struct objlayout_io_res *oir, unsigned index,
  171. struct pnfs_osd_objid *pooid, int osd_error,
  172. u64 offset, u64 length, bool is_write)
  173. {
  174. struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[index];
  175. BUG_ON(index >= oir->num_comps);
  176. if (osd_error) {
  177. ioerr->oer_component = *pooid;
  178. ioerr->oer_comp_offset = offset;
  179. ioerr->oer_comp_length = length;
  180. ioerr->oer_iswrite = is_write;
  181. ioerr->oer_errno = osd_error;
  182. dprintk("%s: err[%d]: errno=%d is_write=%d dev(%llx:%llx) "
  183. "par=0x%llx obj=0x%llx offset=0x%llx length=0x%llx\n",
  184. __func__, index, ioerr->oer_errno,
  185. ioerr->oer_iswrite,
  186. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  187. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  188. ioerr->oer_component.oid_partition_id,
  189. ioerr->oer_component.oid_object_id,
  190. ioerr->oer_comp_offset,
  191. ioerr->oer_comp_length);
  192. } else {
  193. /* User need not call if no error is reported */
  194. ioerr->oer_errno = 0;
  195. }
  196. }
  197. /* Function scheduled on rpc workqueue to call ->nfs_readlist_complete().
  198. * This is because the osd completion is called with ints-off from
  199. * the block layer
  200. */
  201. static void _rpc_read_complete(struct work_struct *work)
  202. {
  203. struct rpc_task *task;
  204. struct nfs_pgio_header *hdr;
  205. dprintk("%s enter\n", __func__);
  206. task = container_of(work, struct rpc_task, u.tk_work);
  207. hdr = container_of(task, struct nfs_pgio_header, task);
  208. pnfs_ld_read_done(hdr);
  209. }
  210. void
  211. objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
  212. {
  213. struct nfs_pgio_header *hdr = oir->rpcdata;
  214. oir->status = hdr->task.tk_status = status;
  215. if (status >= 0)
  216. hdr->res.count = status;
  217. else
  218. hdr->pnfs_error = status;
  219. objlayout_iodone(oir);
  220. /* must not use oir after this point */
  221. dprintk("%s: Return status=%zd eof=%d sync=%d\n", __func__,
  222. status, hdr->res.eof, sync);
  223. if (sync)
  224. pnfs_ld_read_done(hdr);
  225. else {
  226. INIT_WORK(&hdr->task.u.tk_work, _rpc_read_complete);
  227. schedule_work(&hdr->task.u.tk_work);
  228. }
  229. }
  230. /*
  231. * Perform sync or async reads.
  232. */
  233. enum pnfs_try_status
  234. objlayout_read_pagelist(struct nfs_pgio_header *hdr)
  235. {
  236. struct inode *inode = hdr->inode;
  237. loff_t offset = hdr->args.offset;
  238. size_t count = hdr->args.count;
  239. int err;
  240. loff_t eof;
  241. eof = i_size_read(inode);
  242. if (unlikely(offset + count > eof)) {
  243. if (offset >= eof) {
  244. err = 0;
  245. hdr->res.count = 0;
  246. hdr->res.eof = 1;
  247. /*FIXME: do we need to call pnfs_ld_read_done() */
  248. goto out;
  249. }
  250. count = eof - offset;
  251. }
  252. hdr->res.eof = (offset + count) >= eof;
  253. _fix_verify_io_params(hdr->lseg, &hdr->args.pages,
  254. &hdr->args.pgbase,
  255. hdr->args.offset, hdr->args.count);
  256. dprintk("%s: inode(%lx) offset 0x%llx count 0x%Zx eof=%d\n",
  257. __func__, inode->i_ino, offset, count, hdr->res.eof);
  258. err = objio_read_pagelist(hdr);
  259. out:
  260. if (unlikely(err)) {
  261. hdr->pnfs_error = err;
  262. dprintk("%s: Returned Error %d\n", __func__, err);
  263. return PNFS_NOT_ATTEMPTED;
  264. }
  265. return PNFS_ATTEMPTED;
  266. }
  267. /* Function scheduled on rpc workqueue to call ->nfs_writelist_complete().
  268. * This is because the osd completion is called with ints-off from
  269. * the block layer
  270. */
  271. static void _rpc_write_complete(struct work_struct *work)
  272. {
  273. struct rpc_task *task;
  274. struct nfs_pgio_header *hdr;
  275. dprintk("%s enter\n", __func__);
  276. task = container_of(work, struct rpc_task, u.tk_work);
  277. hdr = container_of(task, struct nfs_pgio_header, task);
  278. pnfs_ld_write_done(hdr);
  279. }
  280. void
  281. objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
  282. {
  283. struct nfs_pgio_header *hdr = oir->rpcdata;
  284. oir->status = hdr->task.tk_status = status;
  285. if (status >= 0) {
  286. hdr->res.count = status;
  287. hdr->verf.committed = oir->committed;
  288. } else {
  289. hdr->pnfs_error = status;
  290. }
  291. objlayout_iodone(oir);
  292. /* must not use oir after this point */
  293. dprintk("%s: Return status %zd committed %d sync=%d\n", __func__,
  294. status, hdr->verf.committed, sync);
  295. if (sync)
  296. pnfs_ld_write_done(hdr);
  297. else {
  298. INIT_WORK(&hdr->task.u.tk_work, _rpc_write_complete);
  299. schedule_work(&hdr->task.u.tk_work);
  300. }
  301. }
  302. /*
  303. * Perform sync or async writes.
  304. */
  305. enum pnfs_try_status
  306. objlayout_write_pagelist(struct nfs_pgio_header *hdr, int how)
  307. {
  308. int err;
  309. _fix_verify_io_params(hdr->lseg, &hdr->args.pages,
  310. &hdr->args.pgbase,
  311. hdr->args.offset, hdr->args.count);
  312. err = objio_write_pagelist(hdr, how);
  313. if (unlikely(err)) {
  314. hdr->pnfs_error = err;
  315. dprintk("%s: Returned Error %d\n", __func__, err);
  316. return PNFS_NOT_ATTEMPTED;
  317. }
  318. return PNFS_ATTEMPTED;
  319. }
  320. void
  321. objlayout_encode_layoutcommit(struct pnfs_layout_hdr *pnfslay,
  322. struct xdr_stream *xdr,
  323. const struct nfs4_layoutcommit_args *args)
  324. {
  325. struct objlayout *objlay = OBJLAYOUT(pnfslay);
  326. struct pnfs_osd_layoutupdate lou;
  327. __be32 *start;
  328. dprintk("%s: Begin\n", __func__);
  329. spin_lock(&objlay->lock);
  330. lou.dsu_valid = (objlay->delta_space_valid == OBJ_DSU_VALID);
  331. lou.dsu_delta = objlay->delta_space_used;
  332. objlay->delta_space_used = 0;
  333. objlay->delta_space_valid = OBJ_DSU_INIT;
  334. lou.olu_ioerr_flag = !list_empty(&objlay->err_list);
  335. spin_unlock(&objlay->lock);
  336. start = xdr_reserve_space(xdr, 4);
  337. BUG_ON(pnfs_osd_xdr_encode_layoutupdate(xdr, &lou));
  338. *start = cpu_to_be32((xdr->p - start - 1) * 4);
  339. dprintk("%s: Return delta_space_used %lld err %d\n", __func__,
  340. lou.dsu_delta, lou.olu_ioerr_flag);
  341. }
  342. static int
  343. err_prio(u32 oer_errno)
  344. {
  345. switch (oer_errno) {
  346. case 0:
  347. return 0;
  348. case PNFS_OSD_ERR_RESOURCE:
  349. return OSD_ERR_PRI_RESOURCE;
  350. case PNFS_OSD_ERR_BAD_CRED:
  351. return OSD_ERR_PRI_BAD_CRED;
  352. case PNFS_OSD_ERR_NO_ACCESS:
  353. return OSD_ERR_PRI_NO_ACCESS;
  354. case PNFS_OSD_ERR_UNREACHABLE:
  355. return OSD_ERR_PRI_UNREACHABLE;
  356. case PNFS_OSD_ERR_NOT_FOUND:
  357. return OSD_ERR_PRI_NOT_FOUND;
  358. case PNFS_OSD_ERR_NO_SPACE:
  359. return OSD_ERR_PRI_NO_SPACE;
  360. default:
  361. WARN_ON(1);
  362. /* fallthrough */
  363. case PNFS_OSD_ERR_EIO:
  364. return OSD_ERR_PRI_EIO;
  365. }
  366. }
  367. static void
  368. merge_ioerr(struct pnfs_osd_ioerr *dest_err,
  369. const struct pnfs_osd_ioerr *src_err)
  370. {
  371. u64 dest_end, src_end;
  372. if (!dest_err->oer_errno) {
  373. *dest_err = *src_err;
  374. /* accumulated device must be blank */
  375. memset(&dest_err->oer_component.oid_device_id, 0,
  376. sizeof(dest_err->oer_component.oid_device_id));
  377. return;
  378. }
  379. if (dest_err->oer_component.oid_partition_id !=
  380. src_err->oer_component.oid_partition_id)
  381. dest_err->oer_component.oid_partition_id = 0;
  382. if (dest_err->oer_component.oid_object_id !=
  383. src_err->oer_component.oid_object_id)
  384. dest_err->oer_component.oid_object_id = 0;
  385. if (dest_err->oer_comp_offset > src_err->oer_comp_offset)
  386. dest_err->oer_comp_offset = src_err->oer_comp_offset;
  387. dest_end = end_offset(dest_err->oer_comp_offset,
  388. dest_err->oer_comp_length);
  389. src_end = end_offset(src_err->oer_comp_offset,
  390. src_err->oer_comp_length);
  391. if (dest_end < src_end)
  392. dest_end = src_end;
  393. dest_err->oer_comp_length = dest_end - dest_err->oer_comp_offset;
  394. if ((src_err->oer_iswrite == dest_err->oer_iswrite) &&
  395. (err_prio(src_err->oer_errno) > err_prio(dest_err->oer_errno))) {
  396. dest_err->oer_errno = src_err->oer_errno;
  397. } else if (src_err->oer_iswrite) {
  398. dest_err->oer_iswrite = true;
  399. dest_err->oer_errno = src_err->oer_errno;
  400. }
  401. }
  402. static void
  403. encode_accumulated_error(struct objlayout *objlay, __be32 *p)
  404. {
  405. struct objlayout_io_res *oir, *tmp;
  406. struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0};
  407. list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) {
  408. unsigned i;
  409. for (i = 0; i < oir->num_comps; i++) {
  410. struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i];
  411. if (!ioerr->oer_errno)
  412. continue;
  413. printk(KERN_ERR "NFS: %s: err[%d]: errno=%d "
  414. "is_write=%d dev(%llx:%llx) par=0x%llx "
  415. "obj=0x%llx offset=0x%llx length=0x%llx\n",
  416. __func__, i, ioerr->oer_errno,
  417. ioerr->oer_iswrite,
  418. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  419. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  420. ioerr->oer_component.oid_partition_id,
  421. ioerr->oer_component.oid_object_id,
  422. ioerr->oer_comp_offset,
  423. ioerr->oer_comp_length);
  424. merge_ioerr(&accumulated_err, ioerr);
  425. }
  426. list_del(&oir->err_list);
  427. objio_free_result(oir);
  428. }
  429. pnfs_osd_xdr_encode_ioerr(p, &accumulated_err);
  430. }
  431. void
  432. objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
  433. struct xdr_stream *xdr,
  434. const struct nfs4_layoutreturn_args *args)
  435. {
  436. struct objlayout *objlay = OBJLAYOUT(pnfslay);
  437. struct objlayout_io_res *oir, *tmp;
  438. __be32 *start;
  439. dprintk("%s: Begin\n", __func__);
  440. start = xdr_reserve_space(xdr, 4);
  441. BUG_ON(!start);
  442. spin_lock(&objlay->lock);
  443. list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) {
  444. __be32 *last_xdr = NULL, *p;
  445. unsigned i;
  446. int res = 0;
  447. for (i = 0; i < oir->num_comps; i++) {
  448. struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i];
  449. if (!ioerr->oer_errno)
  450. continue;
  451. dprintk("%s: err[%d]: errno=%d is_write=%d "
  452. "dev(%llx:%llx) par=0x%llx obj=0x%llx "
  453. "offset=0x%llx length=0x%llx\n",
  454. __func__, i, ioerr->oer_errno,
  455. ioerr->oer_iswrite,
  456. _DEVID_LO(&ioerr->oer_component.oid_device_id),
  457. _DEVID_HI(&ioerr->oer_component.oid_device_id),
  458. ioerr->oer_component.oid_partition_id,
  459. ioerr->oer_component.oid_object_id,
  460. ioerr->oer_comp_offset,
  461. ioerr->oer_comp_length);
  462. p = pnfs_osd_xdr_ioerr_reserve_space(xdr);
  463. if (unlikely(!p)) {
  464. res = -E2BIG;
  465. break; /* accumulated_error */
  466. }
  467. last_xdr = p;
  468. pnfs_osd_xdr_encode_ioerr(p, &oir->ioerrs[i]);
  469. }
  470. /* TODO: use xdr_write_pages */
  471. if (unlikely(res)) {
  472. /* no space for even one error descriptor */
  473. BUG_ON(!last_xdr);
  474. /* we've encountered a situation with lots and lots of
  475. * errors and no space to encode them all. Use the last
  476. * available slot to report the union of all the
  477. * remaining errors.
  478. */
  479. encode_accumulated_error(objlay, last_xdr);
  480. goto loop_done;
  481. }
  482. list_del(&oir->err_list);
  483. objio_free_result(oir);
  484. }
  485. loop_done:
  486. spin_unlock(&objlay->lock);
  487. *start = cpu_to_be32((xdr->p - start - 1) * 4);
  488. dprintk("%s: Return\n", __func__);
  489. }
  490. enum {
  491. OBJLAYOUT_MAX_URI_LEN = 256, OBJLAYOUT_MAX_OSDNAME_LEN = 64,
  492. OBJLAYOUT_MAX_SYSID_HEX_LEN = OSD_SYSTEMID_LEN * 2 + 1,
  493. OSD_LOGIN_UPCALL_PATHLEN = 256
  494. };
  495. static char osd_login_prog[OSD_LOGIN_UPCALL_PATHLEN] = "/sbin/osd_login";
  496. module_param_string(osd_login_prog, osd_login_prog, sizeof(osd_login_prog),
  497. 0600);
  498. MODULE_PARM_DESC(osd_login_prog, "Path to the osd_login upcall program");
  499. struct __auto_login {
  500. char uri[OBJLAYOUT_MAX_URI_LEN];
  501. char osdname[OBJLAYOUT_MAX_OSDNAME_LEN];
  502. char systemid_hex[OBJLAYOUT_MAX_SYSID_HEX_LEN];
  503. };
  504. static int __objlayout_upcall(struct __auto_login *login)
  505. {
  506. static char *envp[] = { "HOME=/",
  507. "TERM=linux",
  508. "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
  509. NULL
  510. };
  511. char *argv[8];
  512. int ret;
  513. if (unlikely(!osd_login_prog[0])) {
  514. dprintk("%s: osd_login_prog is disabled\n", __func__);
  515. return -EACCES;
  516. }
  517. dprintk("%s uri: %s\n", __func__, login->uri);
  518. dprintk("%s osdname %s\n", __func__, login->osdname);
  519. dprintk("%s systemid_hex %s\n", __func__, login->systemid_hex);
  520. argv[0] = (char *)osd_login_prog;
  521. argv[1] = "-u";
  522. argv[2] = login->uri;
  523. argv[3] = "-o";
  524. argv[4] = login->osdname;
  525. argv[5] = "-s";
  526. argv[6] = login->systemid_hex;
  527. argv[7] = NULL;
  528. ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
  529. /*
  530. * Disable the upcall mechanism if we're getting an ENOENT or
  531. * EACCES error. The admin can re-enable it on the fly by using
  532. * sysfs to set the objlayoutdriver.osd_login_prog module parameter once
  533. * the problem has been fixed.
  534. */
  535. if (ret == -ENOENT || ret == -EACCES) {
  536. printk(KERN_ERR "PNFS-OBJ: %s was not found please set "
  537. "objlayoutdriver.osd_login_prog kernel parameter!\n",
  538. osd_login_prog);
  539. osd_login_prog[0] = '\0';
  540. }
  541. dprintk("%s %s return value: %d\n", __func__, osd_login_prog, ret);
  542. return ret;
  543. }
  544. /* Assume dest is all zeros */
  545. static void __copy_nfsS_and_zero_terminate(struct nfs4_string s,
  546. char *dest, int max_len,
  547. const char *var_name)
  548. {
  549. if (!s.len)
  550. return;
  551. if (s.len >= max_len) {
  552. pr_warn_ratelimited(
  553. "objlayout_autologin: %s: s.len(%d) >= max_len(%d)",
  554. var_name, s.len, max_len);
  555. s.len = max_len - 1; /* space for null terminator */
  556. }
  557. memcpy(dest, s.data, s.len);
  558. }
  559. /* Assume sysid is all zeros */
  560. static void _sysid_2_hex(struct nfs4_string s,
  561. char sysid[OBJLAYOUT_MAX_SYSID_HEX_LEN])
  562. {
  563. int i;
  564. char *cur;
  565. if (!s.len)
  566. return;
  567. if (s.len != OSD_SYSTEMID_LEN) {
  568. pr_warn_ratelimited(
  569. "objlayout_autologin: systemid_len(%d) != OSD_SYSTEMID_LEN",
  570. s.len);
  571. if (s.len > OSD_SYSTEMID_LEN)
  572. s.len = OSD_SYSTEMID_LEN;
  573. }
  574. cur = sysid;
  575. for (i = 0; i < s.len; i++)
  576. cur = hex_byte_pack(cur, s.data[i]);
  577. }
  578. int objlayout_autologin(struct pnfs_osd_deviceaddr *deviceaddr)
  579. {
  580. int rc;
  581. struct __auto_login login;
  582. if (!deviceaddr->oda_targetaddr.ota_netaddr.r_addr.len)
  583. return -ENODEV;
  584. memset(&login, 0, sizeof(login));
  585. __copy_nfsS_and_zero_terminate(
  586. deviceaddr->oda_targetaddr.ota_netaddr.r_addr,
  587. login.uri, sizeof(login.uri), "URI");
  588. __copy_nfsS_and_zero_terminate(
  589. deviceaddr->oda_osdname,
  590. login.osdname, sizeof(login.osdname), "OSDNAME");
  591. _sysid_2_hex(deviceaddr->oda_systemid, login.systemid_hex);
  592. rc = __objlayout_upcall(&login);
  593. if (rc > 0) /* script returns positive values */
  594. rc = -ENODEV;
  595. return rc;
  596. }