ios.c 9.2 KB

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