dat.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * dat.c - NILFS disk address translation.
  3. *
  4. * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. * Written by Koji Sato <koji@osrg.net>.
  21. */
  22. #include <linux/types.h>
  23. #include <linux/buffer_head.h>
  24. #include <linux/string.h>
  25. #include <linux/errno.h>
  26. #include "nilfs.h"
  27. #include "mdt.h"
  28. #include "alloc.h"
  29. #include "dat.h"
  30. #define NILFS_CNO_MIN ((__u64)1)
  31. #define NILFS_CNO_MAX (~(__u64)0)
  32. struct nilfs_dat_info {
  33. struct nilfs_mdt_info mi;
  34. struct nilfs_palloc_cache palloc_cache;
  35. };
  36. static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
  37. {
  38. return (struct nilfs_dat_info *)NILFS_MDT(dat);
  39. }
  40. static int nilfs_dat_prepare_entry(struct inode *dat,
  41. struct nilfs_palloc_req *req, int create)
  42. {
  43. return nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
  44. create, &req->pr_entry_bh);
  45. }
  46. static void nilfs_dat_commit_entry(struct inode *dat,
  47. struct nilfs_palloc_req *req)
  48. {
  49. nilfs_mdt_mark_buffer_dirty(req->pr_entry_bh);
  50. nilfs_mdt_mark_dirty(dat);
  51. brelse(req->pr_entry_bh);
  52. }
  53. static void nilfs_dat_abort_entry(struct inode *dat,
  54. struct nilfs_palloc_req *req)
  55. {
  56. brelse(req->pr_entry_bh);
  57. }
  58. int nilfs_dat_prepare_alloc(struct inode *dat, struct nilfs_palloc_req *req)
  59. {
  60. int ret;
  61. ret = nilfs_palloc_prepare_alloc_entry(dat, req);
  62. if (ret < 0)
  63. return ret;
  64. ret = nilfs_dat_prepare_entry(dat, req, 1);
  65. if (ret < 0)
  66. nilfs_palloc_abort_alloc_entry(dat, req);
  67. return ret;
  68. }
  69. void nilfs_dat_commit_alloc(struct inode *dat, struct nilfs_palloc_req *req)
  70. {
  71. struct nilfs_dat_entry *entry;
  72. void *kaddr;
  73. kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
  74. entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
  75. req->pr_entry_bh, kaddr);
  76. entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
  77. entry->de_end = cpu_to_le64(NILFS_CNO_MAX);
  78. entry->de_blocknr = cpu_to_le64(0);
  79. kunmap_atomic(kaddr, KM_USER0);
  80. nilfs_palloc_commit_alloc_entry(dat, req);
  81. nilfs_dat_commit_entry(dat, req);
  82. }
  83. void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req)
  84. {
  85. nilfs_dat_abort_entry(dat, req);
  86. nilfs_palloc_abort_alloc_entry(dat, req);
  87. }
  88. void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req)
  89. {
  90. struct nilfs_dat_entry *entry;
  91. void *kaddr;
  92. kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
  93. entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
  94. req->pr_entry_bh, kaddr);
  95. entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
  96. entry->de_end = cpu_to_le64(NILFS_CNO_MIN);
  97. entry->de_blocknr = cpu_to_le64(0);
  98. kunmap_atomic(kaddr, KM_USER0);
  99. nilfs_dat_commit_entry(dat, req);
  100. nilfs_palloc_commit_free_entry(dat, req);
  101. }
  102. int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req)
  103. {
  104. int ret;
  105. ret = nilfs_dat_prepare_entry(dat, req, 0);
  106. WARN_ON(ret == -ENOENT);
  107. return ret;
  108. }
  109. void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
  110. sector_t blocknr)
  111. {
  112. struct nilfs_dat_entry *entry;
  113. void *kaddr;
  114. kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
  115. entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
  116. req->pr_entry_bh, kaddr);
  117. entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat));
  118. entry->de_blocknr = cpu_to_le64(blocknr);
  119. kunmap_atomic(kaddr, KM_USER0);
  120. nilfs_dat_commit_entry(dat, req);
  121. }
  122. int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
  123. {
  124. struct nilfs_dat_entry *entry;
  125. __u64 start;
  126. sector_t blocknr;
  127. void *kaddr;
  128. int ret;
  129. ret = nilfs_dat_prepare_entry(dat, req, 0);
  130. if (ret < 0) {
  131. WARN_ON(ret == -ENOENT);
  132. return ret;
  133. }
  134. kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
  135. entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
  136. req->pr_entry_bh, kaddr);
  137. start = le64_to_cpu(entry->de_start);
  138. blocknr = le64_to_cpu(entry->de_blocknr);
  139. kunmap_atomic(kaddr, KM_USER0);
  140. if (blocknr == 0) {
  141. ret = nilfs_palloc_prepare_free_entry(dat, req);
  142. if (ret < 0) {
  143. nilfs_dat_abort_entry(dat, req);
  144. return ret;
  145. }
  146. }
  147. return 0;
  148. }
  149. void nilfs_dat_commit_end(struct inode *dat, struct nilfs_palloc_req *req,
  150. int dead)
  151. {
  152. struct nilfs_dat_entry *entry;
  153. __u64 start, end;
  154. sector_t blocknr;
  155. void *kaddr;
  156. kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
  157. entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
  158. req->pr_entry_bh, kaddr);
  159. end = start = le64_to_cpu(entry->de_start);
  160. if (!dead) {
  161. end = nilfs_mdt_cno(dat);
  162. WARN_ON(start > end);
  163. }
  164. entry->de_end = cpu_to_le64(end);
  165. blocknr = le64_to_cpu(entry->de_blocknr);
  166. kunmap_atomic(kaddr, KM_USER0);
  167. if (blocknr == 0)
  168. nilfs_dat_commit_free(dat, req);
  169. else
  170. nilfs_dat_commit_entry(dat, req);
  171. }
  172. void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req)
  173. {
  174. struct nilfs_dat_entry *entry;
  175. __u64 start;
  176. sector_t blocknr;
  177. void *kaddr;
  178. kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
  179. entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
  180. req->pr_entry_bh, kaddr);
  181. start = le64_to_cpu(entry->de_start);
  182. blocknr = le64_to_cpu(entry->de_blocknr);
  183. kunmap_atomic(kaddr, KM_USER0);
  184. if (start == nilfs_mdt_cno(dat) && blocknr == 0)
  185. nilfs_palloc_abort_free_entry(dat, req);
  186. nilfs_dat_abort_entry(dat, req);
  187. }
  188. int nilfs_dat_prepare_update(struct inode *dat,
  189. struct nilfs_palloc_req *oldreq,
  190. struct nilfs_palloc_req *newreq)
  191. {
  192. int ret;
  193. ret = nilfs_dat_prepare_end(dat, oldreq);
  194. if (!ret) {
  195. ret = nilfs_dat_prepare_alloc(dat, newreq);
  196. if (ret < 0)
  197. nilfs_dat_abort_end(dat, oldreq);
  198. }
  199. return ret;
  200. }
  201. void nilfs_dat_commit_update(struct inode *dat,
  202. struct nilfs_palloc_req *oldreq,
  203. struct nilfs_palloc_req *newreq, int dead)
  204. {
  205. nilfs_dat_commit_end(dat, oldreq, dead);
  206. nilfs_dat_commit_alloc(dat, newreq);
  207. }
  208. void nilfs_dat_abort_update(struct inode *dat,
  209. struct nilfs_palloc_req *oldreq,
  210. struct nilfs_palloc_req *newreq)
  211. {
  212. nilfs_dat_abort_end(dat, oldreq);
  213. nilfs_dat_abort_alloc(dat, newreq);
  214. }
  215. /**
  216. * nilfs_dat_mark_dirty -
  217. * @dat: DAT file inode
  218. * @vblocknr: virtual block number
  219. *
  220. * Description:
  221. *
  222. * Return Value: On success, 0 is returned. On error, one of the following
  223. * negative error codes is returned.
  224. *
  225. * %-EIO - I/O error.
  226. *
  227. * %-ENOMEM - Insufficient amount of memory available.
  228. */
  229. int nilfs_dat_mark_dirty(struct inode *dat, __u64 vblocknr)
  230. {
  231. struct nilfs_palloc_req req;
  232. int ret;
  233. req.pr_entry_nr = vblocknr;
  234. ret = nilfs_dat_prepare_entry(dat, &req, 0);
  235. if (ret == 0)
  236. nilfs_dat_commit_entry(dat, &req);
  237. return ret;
  238. }
  239. /**
  240. * nilfs_dat_freev - free virtual block numbers
  241. * @dat: DAT file inode
  242. * @vblocknrs: array of virtual block numbers
  243. * @nitems: number of virtual block numbers
  244. *
  245. * Description: nilfs_dat_freev() frees the virtual block numbers specified by
  246. * @vblocknrs and @nitems.
  247. *
  248. * Return Value: On success, 0 is returned. On error, one of the following
  249. * negative error codes is returned.
  250. *
  251. * %-EIO - I/O error.
  252. *
  253. * %-ENOMEM - Insufficient amount of memory available.
  254. *
  255. * %-ENOENT - The virtual block number have not been allocated.
  256. */
  257. int nilfs_dat_freev(struct inode *dat, __u64 *vblocknrs, size_t nitems)
  258. {
  259. return nilfs_palloc_freev(dat, vblocknrs, nitems);
  260. }
  261. /**
  262. * nilfs_dat_move - change a block number
  263. * @dat: DAT file inode
  264. * @vblocknr: virtual block number
  265. * @blocknr: block number
  266. *
  267. * Description: nilfs_dat_move() changes the block number associated with
  268. * @vblocknr to @blocknr.
  269. *
  270. * Return Value: On success, 0 is returned. On error, one of the following
  271. * negative error codes is returned.
  272. *
  273. * %-EIO - I/O error.
  274. *
  275. * %-ENOMEM - Insufficient amount of memory available.
  276. */
  277. int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
  278. {
  279. struct buffer_head *entry_bh;
  280. struct nilfs_dat_entry *entry;
  281. void *kaddr;
  282. int ret;
  283. ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
  284. if (ret < 0)
  285. return ret;
  286. kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
  287. entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
  288. if (unlikely(entry->de_blocknr == cpu_to_le64(0))) {
  289. printk(KERN_CRIT "%s: vbn = %llu, [%llu, %llu)\n", __func__,
  290. (unsigned long long)vblocknr,
  291. (unsigned long long)le64_to_cpu(entry->de_start),
  292. (unsigned long long)le64_to_cpu(entry->de_end));
  293. kunmap_atomic(kaddr, KM_USER0);
  294. brelse(entry_bh);
  295. return -EINVAL;
  296. }
  297. WARN_ON(blocknr == 0);
  298. entry->de_blocknr = cpu_to_le64(blocknr);
  299. kunmap_atomic(kaddr, KM_USER0);
  300. nilfs_mdt_mark_buffer_dirty(entry_bh);
  301. nilfs_mdt_mark_dirty(dat);
  302. brelse(entry_bh);
  303. return 0;
  304. }
  305. /**
  306. * nilfs_dat_translate - translate a virtual block number to a block number
  307. * @dat: DAT file inode
  308. * @vblocknr: virtual block number
  309. * @blocknrp: pointer to a block number
  310. *
  311. * Description: nilfs_dat_translate() maps the virtual block number @vblocknr
  312. * to the corresponding block number.
  313. *
  314. * Return Value: On success, 0 is returned and the block number associated
  315. * with @vblocknr is stored in the place pointed by @blocknrp. On error, one
  316. * of the following negative error codes is returned.
  317. *
  318. * %-EIO - I/O error.
  319. *
  320. * %-ENOMEM - Insufficient amount of memory available.
  321. *
  322. * %-ENOENT - A block number associated with @vblocknr does not exist.
  323. */
  324. int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
  325. {
  326. struct buffer_head *entry_bh;
  327. struct nilfs_dat_entry *entry;
  328. sector_t blocknr;
  329. void *kaddr;
  330. int ret;
  331. ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
  332. if (ret < 0)
  333. return ret;
  334. kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
  335. entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
  336. blocknr = le64_to_cpu(entry->de_blocknr);
  337. if (blocknr == 0) {
  338. ret = -ENOENT;
  339. goto out;
  340. }
  341. *blocknrp = blocknr;
  342. out:
  343. kunmap_atomic(kaddr, KM_USER0);
  344. brelse(entry_bh);
  345. return ret;
  346. }
  347. ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
  348. size_t nvi)
  349. {
  350. struct buffer_head *entry_bh;
  351. struct nilfs_dat_entry *entry;
  352. struct nilfs_vinfo *vinfo = buf;
  353. __u64 first, last;
  354. void *kaddr;
  355. unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block;
  356. int i, j, n, ret;
  357. for (i = 0; i < nvi; i += n) {
  358. ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr,
  359. 0, &entry_bh);
  360. if (ret < 0)
  361. return ret;
  362. kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
  363. /* last virtual block number in this block */
  364. first = vinfo->vi_vblocknr;
  365. do_div(first, entries_per_block);
  366. first *= entries_per_block;
  367. last = first + entries_per_block - 1;
  368. for (j = i, n = 0;
  369. j < nvi && vinfo->vi_vblocknr >= first &&
  370. vinfo->vi_vblocknr <= last;
  371. j++, n++, vinfo = (void *)vinfo + visz) {
  372. entry = nilfs_palloc_block_get_entry(
  373. dat, vinfo->vi_vblocknr, entry_bh, kaddr);
  374. vinfo->vi_start = le64_to_cpu(entry->de_start);
  375. vinfo->vi_end = le64_to_cpu(entry->de_end);
  376. vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
  377. }
  378. kunmap_atomic(kaddr, KM_USER0);
  379. brelse(entry_bh);
  380. }
  381. return nvi;
  382. }
  383. /**
  384. * nilfs_dat_read - read dat inode
  385. * @dat: dat inode
  386. * @raw_inode: on-disk dat inode
  387. */
  388. int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode)
  389. {
  390. return nilfs_read_inode_common(dat, raw_inode);
  391. }
  392. /**
  393. * nilfs_dat_new - create dat file
  394. * @nilfs: nilfs object
  395. * @entry_size: size of a dat entry
  396. */
  397. struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size)
  398. {
  399. static struct lock_class_key dat_lock_key;
  400. struct inode *dat;
  401. struct nilfs_dat_info *di;
  402. int err;
  403. dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO, sizeof(*di));
  404. if (dat) {
  405. err = nilfs_palloc_init_blockgroup(dat, entry_size);
  406. if (unlikely(err)) {
  407. nilfs_mdt_destroy(dat);
  408. return NULL;
  409. }
  410. di = NILFS_DAT_I(dat);
  411. lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
  412. nilfs_palloc_setup_cache(dat, &di->palloc_cache);
  413. }
  414. return dat;
  415. }