ios.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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. static void _sync_done(struct exofs_io_state *ios, void *p)
  94. {
  95. struct completion *waiting = p;
  96. complete(waiting);
  97. }
  98. static void _last_io(struct kref *kref)
  99. {
  100. struct exofs_io_state *ios = container_of(
  101. kref, struct exofs_io_state, kref);
  102. ios->done(ios, ios->private);
  103. }
  104. static void _done_io(struct osd_request *or, void *p)
  105. {
  106. struct exofs_io_state *ios = p;
  107. kref_put(&ios->kref, _last_io);
  108. }
  109. static int exofs_io_execute(struct exofs_io_state *ios)
  110. {
  111. DECLARE_COMPLETION_ONSTACK(wait);
  112. bool sync = (ios->done == NULL);
  113. int i, ret;
  114. if (sync) {
  115. ios->done = _sync_done;
  116. ios->private = &wait;
  117. }
  118. for (i = 0; i < ios->numdevs; i++) {
  119. struct osd_request *or = ios->per_dev[i].or;
  120. if (unlikely(!or))
  121. continue;
  122. ret = osd_finalize_request(or, 0, ios->cred, NULL);
  123. if (unlikely(ret)) {
  124. EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n",
  125. ret);
  126. return ret;
  127. }
  128. }
  129. kref_init(&ios->kref);
  130. for (i = 0; i < ios->numdevs; i++) {
  131. struct osd_request *or = ios->per_dev[i].or;
  132. if (unlikely(!or))
  133. continue;
  134. kref_get(&ios->kref);
  135. osd_execute_request_async(or, _done_io, ios);
  136. }
  137. kref_put(&ios->kref, _last_io);
  138. ret = 0;
  139. if (sync) {
  140. wait_for_completion(&wait);
  141. ret = exofs_check_io(ios, NULL);
  142. }
  143. return ret;
  144. }
  145. static void _clear_bio(struct bio *bio)
  146. {
  147. struct bio_vec *bv;
  148. unsigned i;
  149. __bio_for_each_segment(bv, bio, i, 0) {
  150. unsigned this_count = bv->bv_len;
  151. if (likely(PAGE_SIZE == this_count))
  152. clear_highpage(bv->bv_page);
  153. else
  154. zero_user(bv->bv_page, bv->bv_offset, this_count);
  155. }
  156. }
  157. int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
  158. {
  159. enum osd_err_priority acumulated_osd_err = 0;
  160. int acumulated_lin_err = 0;
  161. int i;
  162. for (i = 0; i < ios->numdevs; i++) {
  163. struct osd_sense_info osi;
  164. struct osd_request *or = ios->per_dev[i].or;
  165. int ret;
  166. if (unlikely(!or))
  167. continue;
  168. ret = osd_req_decode_sense(or, &osi);
  169. if (likely(!ret))
  170. continue;
  171. if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
  172. /* start read offset passed endof file */
  173. _clear_bio(ios->per_dev[i].bio);
  174. EXOFS_DBGMSG("start read offset passed end of file "
  175. "offset=0x%llx, length=0x%llx\n",
  176. _LLU(ios->offset),
  177. _LLU(ios->length));
  178. continue; /* we recovered */
  179. }
  180. if (osi.osd_err_pri >= acumulated_osd_err) {
  181. acumulated_osd_err = osi.osd_err_pri;
  182. acumulated_lin_err = ret;
  183. }
  184. }
  185. /* TODO: raid specific residual calculations */
  186. if (resid) {
  187. if (likely(!acumulated_lin_err))
  188. *resid = 0;
  189. else
  190. *resid = ios->length;
  191. }
  192. return acumulated_lin_err;
  193. }
  194. int exofs_sbi_create(struct exofs_io_state *ios)
  195. {
  196. int i, ret;
  197. for (i = 0; i < ios->layout->s_numdevs; i++) {
  198. struct osd_request *or;
  199. or = osd_start_request(ios->layout->s_ods[i], GFP_KERNEL);
  200. if (unlikely(!or)) {
  201. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  202. ret = -ENOMEM;
  203. goto out;
  204. }
  205. ios->per_dev[i].or = or;
  206. ios->numdevs++;
  207. osd_req_create_object(or, &ios->obj);
  208. }
  209. ret = exofs_io_execute(ios);
  210. out:
  211. return ret;
  212. }
  213. int exofs_sbi_remove(struct exofs_io_state *ios)
  214. {
  215. int i, ret;
  216. for (i = 0; i < ios->layout->s_numdevs; i++) {
  217. struct osd_request *or;
  218. or = osd_start_request(ios->layout->s_ods[i], GFP_KERNEL);
  219. if (unlikely(!or)) {
  220. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  221. ret = -ENOMEM;
  222. goto out;
  223. }
  224. ios->per_dev[i].or = or;
  225. ios->numdevs++;
  226. osd_req_remove_object(or, &ios->obj);
  227. }
  228. ret = exofs_io_execute(ios);
  229. out:
  230. return ret;
  231. }
  232. int exofs_sbi_write(struct exofs_io_state *ios)
  233. {
  234. int i, ret;
  235. for (i = 0; i < ios->layout->s_numdevs; i++) {
  236. struct osd_request *or;
  237. or = osd_start_request(ios->layout->s_ods[i], GFP_KERNEL);
  238. if (unlikely(!or)) {
  239. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  240. ret = -ENOMEM;
  241. goto out;
  242. }
  243. ios->per_dev[i].or = or;
  244. ios->numdevs++;
  245. if (ios->bio) {
  246. struct bio *bio;
  247. if (i != 0) {
  248. bio = bio_kmalloc(GFP_KERNEL,
  249. ios->bio->bi_max_vecs);
  250. if (unlikely(!bio)) {
  251. EXOFS_DBGMSG(
  252. "Faild to allocate BIO size=%u\n",
  253. ios->bio->bi_max_vecs);
  254. ret = -ENOMEM;
  255. goto out;
  256. }
  257. __bio_clone(bio, ios->bio);
  258. bio->bi_bdev = NULL;
  259. bio->bi_next = NULL;
  260. ios->per_dev[i].bio = bio;
  261. } else {
  262. bio = ios->bio;
  263. }
  264. osd_req_write(or, &ios->obj, ios->offset, bio,
  265. ios->length);
  266. EXOFS_DBGMSG("write(0x%llx) offset=0x%llx "
  267. "length=0x%llx dev=%d\n",
  268. _LLU(ios->obj.id), _LLU(ios->offset),
  269. _LLU(ios->length), i);
  270. } else if (ios->kern_buff) {
  271. osd_req_write_kern(or, &ios->obj, ios->offset,
  272. ios->kern_buff, ios->length);
  273. EXOFS_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
  274. "length=0x%llx dev=%d\n",
  275. _LLU(ios->obj.id), _LLU(ios->offset),
  276. _LLU(ios->length), i);
  277. } else {
  278. osd_req_set_attributes(or, &ios->obj);
  279. EXOFS_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
  280. _LLU(ios->obj.id), ios->out_attr_len, i);
  281. }
  282. if (ios->out_attr)
  283. osd_req_add_set_attr_list(or, ios->out_attr,
  284. ios->out_attr_len);
  285. if (ios->in_attr)
  286. osd_req_add_get_attr_list(or, ios->in_attr,
  287. ios->in_attr_len);
  288. }
  289. ret = exofs_io_execute(ios);
  290. out:
  291. return ret;
  292. }
  293. int exofs_sbi_read(struct exofs_io_state *ios)
  294. {
  295. struct osd_request *or;
  296. struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
  297. unsigned first_dev = (unsigned)ios->obj.id;
  298. first_dev %= ios->layout->s_numdevs;
  299. or = osd_start_request(ios->layout->s_ods[first_dev], GFP_KERNEL);
  300. if (unlikely(!or)) {
  301. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  302. return -ENOMEM;
  303. }
  304. per_dev->or = or;
  305. ios->numdevs++;
  306. if (ios->bio) {
  307. osd_req_read(or, &ios->obj, ios->offset, ios->bio, ios->length);
  308. EXOFS_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
  309. " dev=%d\n", _LLU(ios->obj.id),
  310. _LLU(ios->offset), _LLU(ios->length),
  311. first_dev);
  312. } else if (ios->kern_buff) {
  313. int ret = osd_req_read_kern(or, &ios->obj, ios->offset,
  314. ios->kern_buff, ios->length);
  315. EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
  316. "length=0x%llx dev=%d ret=>%d\n",
  317. _LLU(ios->obj.id), _LLU(ios->offset),
  318. _LLU(ios->length), first_dev, ret);
  319. if (unlikely(ret))
  320. return ret;
  321. } else {
  322. osd_req_get_attributes(or, &ios->obj);
  323. EXOFS_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
  324. _LLU(ios->obj.id), ios->in_attr_len, first_dev);
  325. }
  326. if (ios->out_attr)
  327. osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
  328. if (ios->in_attr)
  329. osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len);
  330. return exofs_io_execute(ios);
  331. }
  332. int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr)
  333. {
  334. struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
  335. void *iter = NULL;
  336. int nelem;
  337. do {
  338. nelem = 1;
  339. osd_req_decode_get_attr_list(ios->per_dev[0].or,
  340. &cur_attr, &nelem, &iter);
  341. if ((cur_attr.attr_page == attr->attr_page) &&
  342. (cur_attr.attr_id == attr->attr_id)) {
  343. attr->len = cur_attr.len;
  344. attr->val_ptr = cur_attr.val_ptr;
  345. return 0;
  346. }
  347. } while (iter);
  348. return -EIO;
  349. }
  350. int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
  351. {
  352. struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info;
  353. struct exofs_io_state *ios;
  354. struct osd_attr attr;
  355. __be64 newsize;
  356. int i, ret;
  357. if (exofs_get_io_state(&sbi->layout, &ios))
  358. return -ENOMEM;
  359. ios->obj.id = exofs_oi_objno(oi);
  360. ios->cred = oi->i_cred;
  361. newsize = cpu_to_be64(size);
  362. attr = g_attr_logical_length;
  363. attr.val_ptr = &newsize;
  364. for (i = 0; i < sbi->layout.s_numdevs; i++) {
  365. struct osd_request *or;
  366. or = osd_start_request(sbi->layout.s_ods[i], GFP_KERNEL);
  367. if (unlikely(!or)) {
  368. EXOFS_ERR("%s: osd_start_request failed\n", __func__);
  369. ret = -ENOMEM;
  370. goto out;
  371. }
  372. ios->per_dev[i].or = or;
  373. ios->numdevs++;
  374. osd_req_set_attributes(or, &ios->obj);
  375. osd_req_add_set_attr_list(or, &attr, 1);
  376. }
  377. ret = exofs_io_execute(ios);
  378. out:
  379. exofs_put_io_state(ios);
  380. return ret;
  381. }