ios.c 10 KB

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