ios.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * Copyright (C) 2005, 2006
  3. * Avishay Traeger (avishay@gmail.com)
  4. * Copyright (C) 2008, 2009
  5. * Boaz Harrosh <bharrosh@panasas.com>
  6. *
  7. * This file is part of exofs.
  8. *
  9. * exofs is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation. Since it is based on ext2, and the only
  12. * valid version of GPL for the Linux kernel is version 2, the only valid
  13. * version of GPL for exofs is version 2.
  14. *
  15. * exofs is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with exofs; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. */
  24. #include <scsi/scsi_device.h>
  25. #include "exofs.h"
  26. #define EXOFS_DBGMSG2(M...) do {} while (0)
  27. /* #define EXOFS_DBGMSG2 EXOFS_DBGMSG */
  28. void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
  29. {
  30. osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
  31. }
  32. int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
  33. u64 offset, void *p, unsigned length)
  34. {
  35. struct osd_request *or = osd_start_request(od, GFP_KERNEL);
  36. /* struct osd_sense_info osi = {.key = 0};*/
  37. int ret;
  38. if (unlikely(!or)) {
  39. EXOFS_DBGMSG("%s: osd_start_request failed.\n", __func__);
  40. return -ENOMEM;
  41. }
  42. ret = osd_req_read_kern(or, obj, offset, p, length);
  43. if (unlikely(ret)) {
  44. EXOFS_DBGMSG("%s: osd_req_read_kern failed.\n", __func__);
  45. goto out;
  46. }
  47. ret = osd_finalize_request(or, 0, cred, NULL);
  48. if (unlikely(ret)) {
  49. EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret);
  50. goto out;
  51. }
  52. ret = osd_execute_request(or);
  53. if (unlikely(ret))
  54. EXOFS_DBGMSG("osd_execute_request() => %d\n", ret);
  55. /* osd_req_decode_sense(or, ret); */
  56. out:
  57. osd_end_request(or);
  58. return ret;
  59. }
  60. int exofs_get_io_state(struct exofs_layout *layout,
  61. struct exofs_io_state **pios)
  62. {
  63. struct exofs_io_state *ios;
  64. /*TODO: Maybe use kmem_cach per sbi of size
  65. * exofs_io_state_size(layout->s_numdevs)
  66. */
  67. ios = kzalloc(exofs_io_state_size(layout->s_numdevs), GFP_KERNEL);
  68. if (unlikely(!ios)) {
  69. EXOFS_DBGMSG("Faild kzalloc bytes=%d\n",
  70. exofs_io_state_size(layout->s_numdevs));
  71. *pios = NULL;
  72. return -ENOMEM;
  73. }
  74. ios->layout = layout;
  75. ios->obj.partition = layout->s_pid;
  76. *pios = ios;
  77. return 0;
  78. }
  79. void exofs_put_io_state(struct exofs_io_state *ios)
  80. {
  81. if (ios) {
  82. unsigned i;
  83. for (i = 0; i < ios->numdevs; i++) {
  84. struct exofs_per_dev_state *per_dev = &ios->per_dev[i];
  85. if (per_dev->or)
  86. osd_end_request(per_dev->or);
  87. if (per_dev->bio)
  88. bio_put(per_dev->bio);
  89. }
  90. kfree(ios);
  91. }
  92. }
  93. unsigned exofs_layout_od_id(struct exofs_layout *layout,
  94. osd_id obj_no, unsigned layout_index)
  95. {
  96. return layout_index;
  97. }
  98. static inline struct osd_dev *exofs_ios_od(struct exofs_io_state *ios,
  99. unsigned layout_index)
  100. {
  101. return ios->layout->s_ods[
  102. exofs_layout_od_id(ios->layout, ios->obj.id, layout_index)];
  103. }
  104. static void _sync_done(struct exofs_io_state *ios, void *p)
  105. {
  106. struct completion *waiting = p;
  107. complete(waiting);
  108. }
  109. static void _last_io(struct kref *kref)
  110. {
  111. struct exofs_io_state *ios = container_of(
  112. kref, struct exofs_io_state, kref);
  113. ios->done(ios, ios->private);
  114. }
  115. static void _done_io(struct osd_request *or, void *p)
  116. {
  117. struct exofs_io_state *ios = p;
  118. kref_put(&ios->kref, _last_io);
  119. }
  120. static int exofs_io_execute(struct exofs_io_state *ios)
  121. {
  122. DECLARE_COMPLETION_ONSTACK(wait);
  123. bool sync = (ios->done == NULL);
  124. int i, ret;
  125. if (sync) {
  126. ios->done = _sync_done;
  127. ios->private = &wait;
  128. }
  129. for (i = 0; i < ios->numdevs; i++) {
  130. struct osd_request *or = ios->per_dev[i].or;
  131. if (unlikely(!or))
  132. continue;
  133. ret = osd_finalize_request(or, 0, ios->cred, NULL);
  134. if (unlikely(ret)) {
  135. EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n",
  136. ret);
  137. return ret;
  138. }
  139. }
  140. kref_init(&ios->kref);
  141. for (i = 0; i < ios->numdevs; i++) {
  142. struct osd_request *or = ios->per_dev[i].or;
  143. if (unlikely(!or))
  144. continue;
  145. kref_get(&ios->kref);
  146. osd_execute_request_async(or, _done_io, ios);
  147. }
  148. kref_put(&ios->kref, _last_io);
  149. ret = 0;
  150. if (sync) {
  151. wait_for_completion(&wait);
  152. ret = exofs_check_io(ios, NULL);
  153. }
  154. return ret;
  155. }
  156. static void _clear_bio(struct bio *bio)
  157. {
  158. struct bio_vec *bv;
  159. unsigned i;
  160. __bio_for_each_segment(bv, bio, i, 0) {
  161. unsigned this_count = bv->bv_len;
  162. if (likely(PAGE_SIZE == this_count))
  163. clear_highpage(bv->bv_page);
  164. else
  165. zero_user(bv->bv_page, bv->bv_offset, this_count);
  166. }
  167. }
  168. int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
  169. {
  170. enum osd_err_priority acumulated_osd_err = 0;
  171. int acumulated_lin_err = 0;
  172. int i;
  173. for (i = 0; i < ios->numdevs; i++) {
  174. struct osd_sense_info osi;
  175. struct osd_request *or = ios->per_dev[i].or;
  176. int ret;
  177. if (unlikely(!or))
  178. continue;
  179. ret = osd_req_decode_sense(or, &osi);
  180. if (likely(!ret))
  181. continue;
  182. if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
  183. /* start read offset passed endof file */
  184. _clear_bio(ios->per_dev[i].bio);
  185. EXOFS_DBGMSG("start read offset passed end of file "
  186. "offset=0x%llx, length=0x%llx\n",
  187. _LLU(ios->offset),
  188. _LLU(ios->length));
  189. continue; /* we recovered */
  190. }
  191. if (osi.osd_err_pri >= acumulated_osd_err) {
  192. acumulated_osd_err = osi.osd_err_pri;
  193. acumulated_lin_err = ret;
  194. }
  195. }
  196. /* TODO: raid specific residual calculations */
  197. if (resid) {
  198. if (likely(!acumulated_lin_err))
  199. *resid = 0;
  200. else
  201. *resid = ios->length;
  202. }
  203. return acumulated_lin_err;
  204. }
  205. int exofs_sbi_create(struct exofs_io_state *ios)
  206. {
  207. int i, ret;
  208. for (i = 0; i < ios->layout->s_numdevs; i++) {
  209. struct osd_request *or;
  210. or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
  211. if (unlikely(!or)) {
  212. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  213. ret = -ENOMEM;
  214. goto out;
  215. }
  216. ios->per_dev[i].or = or;
  217. ios->numdevs++;
  218. osd_req_create_object(or, &ios->obj);
  219. }
  220. ret = exofs_io_execute(ios);
  221. out:
  222. return ret;
  223. }
  224. int exofs_sbi_remove(struct exofs_io_state *ios)
  225. {
  226. int i, ret;
  227. for (i = 0; i < ios->layout->s_numdevs; i++) {
  228. struct osd_request *or;
  229. or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
  230. if (unlikely(!or)) {
  231. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  232. ret = -ENOMEM;
  233. goto out;
  234. }
  235. ios->per_dev[i].or = or;
  236. ios->numdevs++;
  237. osd_req_remove_object(or, &ios->obj);
  238. }
  239. ret = exofs_io_execute(ios);
  240. out:
  241. return ret;
  242. }
  243. int exofs_sbi_write(struct exofs_io_state *ios)
  244. {
  245. int i, ret;
  246. for (i = 0; i < ios->layout->s_numdevs; i++) {
  247. struct osd_request *or;
  248. or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
  249. if (unlikely(!or)) {
  250. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  251. ret = -ENOMEM;
  252. goto out;
  253. }
  254. ios->per_dev[i].or = or;
  255. ios->numdevs++;
  256. if (ios->bio) {
  257. struct bio *bio;
  258. if (i != 0) {
  259. bio = bio_kmalloc(GFP_KERNEL,
  260. ios->bio->bi_max_vecs);
  261. if (unlikely(!bio)) {
  262. EXOFS_DBGMSG(
  263. "Faild to allocate BIO size=%u\n",
  264. ios->bio->bi_max_vecs);
  265. ret = -ENOMEM;
  266. goto out;
  267. }
  268. __bio_clone(bio, ios->bio);
  269. bio->bi_bdev = NULL;
  270. bio->bi_next = NULL;
  271. ios->per_dev[i].bio = bio;
  272. } else {
  273. bio = ios->bio;
  274. }
  275. osd_req_write(or, &ios->obj, ios->offset, bio,
  276. ios->length);
  277. EXOFS_DBGMSG("write(0x%llx) offset=0x%llx "
  278. "length=0x%llx dev=%d\n",
  279. _LLU(ios->obj.id), _LLU(ios->offset),
  280. _LLU(ios->length), i);
  281. } else if (ios->kern_buff) {
  282. osd_req_write_kern(or, &ios->obj, ios->offset,
  283. ios->kern_buff, ios->length);
  284. EXOFS_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
  285. "length=0x%llx dev=%d\n",
  286. _LLU(ios->obj.id), _LLU(ios->offset),
  287. _LLU(ios->length), i);
  288. } else {
  289. osd_req_set_attributes(or, &ios->obj);
  290. EXOFS_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
  291. _LLU(ios->obj.id), ios->out_attr_len, i);
  292. }
  293. if (ios->out_attr)
  294. osd_req_add_set_attr_list(or, ios->out_attr,
  295. ios->out_attr_len);
  296. if (ios->in_attr)
  297. osd_req_add_get_attr_list(or, ios->in_attr,
  298. ios->in_attr_len);
  299. }
  300. ret = exofs_io_execute(ios);
  301. out:
  302. return ret;
  303. }
  304. int exofs_sbi_read(struct exofs_io_state *ios)
  305. {
  306. struct osd_request *or;
  307. struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
  308. unsigned first_dev = (unsigned)ios->obj.id;
  309. first_dev %= ios->layout->s_numdevs;
  310. or = osd_start_request(exofs_ios_od(ios, first_dev), GFP_KERNEL);
  311. if (unlikely(!or)) {
  312. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  313. return -ENOMEM;
  314. }
  315. per_dev->or = or;
  316. ios->numdevs++;
  317. if (ios->bio) {
  318. osd_req_read(or, &ios->obj, ios->offset, ios->bio, ios->length);
  319. EXOFS_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
  320. " dev=%d\n", _LLU(ios->obj.id),
  321. _LLU(ios->offset), _LLU(ios->length),
  322. first_dev);
  323. } else if (ios->kern_buff) {
  324. int ret = osd_req_read_kern(or, &ios->obj, ios->offset,
  325. ios->kern_buff, ios->length);
  326. EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
  327. "length=0x%llx dev=%d ret=>%d\n",
  328. _LLU(ios->obj.id), _LLU(ios->offset),
  329. _LLU(ios->length), first_dev, ret);
  330. if (unlikely(ret))
  331. return ret;
  332. } else {
  333. osd_req_get_attributes(or, &ios->obj);
  334. EXOFS_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
  335. _LLU(ios->obj.id), ios->in_attr_len, first_dev);
  336. }
  337. if (ios->out_attr)
  338. osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
  339. if (ios->in_attr)
  340. osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len);
  341. return exofs_io_execute(ios);
  342. }
  343. int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr)
  344. {
  345. struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
  346. void *iter = NULL;
  347. int nelem;
  348. do {
  349. nelem = 1;
  350. osd_req_decode_get_attr_list(ios->per_dev[0].or,
  351. &cur_attr, &nelem, &iter);
  352. if ((cur_attr.attr_page == attr->attr_page) &&
  353. (cur_attr.attr_id == attr->attr_id)) {
  354. attr->len = cur_attr.len;
  355. attr->val_ptr = cur_attr.val_ptr;
  356. return 0;
  357. }
  358. } while (iter);
  359. return -EIO;
  360. }
  361. int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
  362. {
  363. struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info;
  364. struct exofs_io_state *ios;
  365. struct osd_attr attr;
  366. __be64 newsize;
  367. int i, ret;
  368. if (exofs_get_io_state(&sbi->layout, &ios))
  369. return -ENOMEM;
  370. ios->obj.id = exofs_oi_objno(oi);
  371. ios->cred = oi->i_cred;
  372. newsize = cpu_to_be64(size);
  373. attr = g_attr_logical_length;
  374. attr.val_ptr = &newsize;
  375. for (i = 0; i < sbi->layout.s_numdevs; i++) {
  376. struct osd_request *or;
  377. or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
  378. if (unlikely(!or)) {
  379. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  380. ret = -ENOMEM;
  381. goto out;
  382. }
  383. ios->per_dev[i].or = or;
  384. ios->numdevs++;
  385. osd_req_set_attributes(or, &ios->obj);
  386. osd_req_add_set_attr_list(or, &attr, 1);
  387. }
  388. ret = exofs_io_execute(ios);
  389. out:
  390. exofs_put_io_state(ios);
  391. return ret;
  392. }