bmap.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. /*
  2. * bmap.c - NILFS block mapping.
  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/fs.h>
  23. #include <linux/string.h>
  24. #include <linux/errno.h>
  25. #include "nilfs.h"
  26. #include "bmap.h"
  27. #include "sb.h"
  28. #include "btnode.h"
  29. #include "mdt.h"
  30. #include "dat.h"
  31. #include "alloc.h"
  32. struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
  33. {
  34. return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
  35. }
  36. int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
  37. __u64 *ptrp)
  38. {
  39. sector_t blocknr;
  40. int ret;
  41. down_read(&bmap->b_sem);
  42. ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
  43. if (ret < 0)
  44. goto out;
  45. if (NILFS_BMAP_USE_VBN(bmap)) {
  46. ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
  47. &blocknr);
  48. if (!ret)
  49. *ptrp = blocknr;
  50. }
  51. out:
  52. up_read(&bmap->b_sem);
  53. return ret;
  54. }
  55. int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
  56. unsigned maxblocks)
  57. {
  58. int ret;
  59. down_read(&bmap->b_sem);
  60. ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
  61. up_read(&bmap->b_sem);
  62. return ret;
  63. }
  64. /**
  65. * nilfs_bmap_lookup - find a record
  66. * @bmap: bmap
  67. * @key: key
  68. * @recp: pointer to record
  69. *
  70. * Description: nilfs_bmap_lookup() finds a record whose key matches @key in
  71. * @bmap.
  72. *
  73. * Return Value: On success, 0 is returned and the record associated with @key
  74. * is stored in the place pointed by @recp. On error, one of the following
  75. * negative error codes is returned.
  76. *
  77. * %-EIO - I/O error.
  78. *
  79. * %-ENOMEM - Insufficient amount of memory available.
  80. *
  81. * %-ENOENT - A record associated with @key does not exist.
  82. */
  83. int nilfs_bmap_lookup(struct nilfs_bmap *bmap,
  84. unsigned long key,
  85. unsigned long *recp)
  86. {
  87. __u64 ptr;
  88. int ret;
  89. /* XXX: use macro for level 1 */
  90. ret = nilfs_bmap_lookup_at_level(bmap, key, 1, &ptr);
  91. if (recp != NULL)
  92. *recp = ptr;
  93. return ret;
  94. }
  95. static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
  96. {
  97. __u64 keys[NILFS_BMAP_SMALL_HIGH + 1];
  98. __u64 ptrs[NILFS_BMAP_SMALL_HIGH + 1];
  99. int ret, n;
  100. if (bmap->b_ops->bop_check_insert != NULL) {
  101. ret = bmap->b_ops->bop_check_insert(bmap, key);
  102. if (ret > 0) {
  103. n = bmap->b_ops->bop_gather_data(
  104. bmap, keys, ptrs, NILFS_BMAP_SMALL_HIGH + 1);
  105. if (n < 0)
  106. return n;
  107. ret = nilfs_btree_convert_and_insert(
  108. bmap, key, ptr, keys, ptrs, n);
  109. if (ret == 0)
  110. bmap->b_u.u_flags |= NILFS_BMAP_LARGE;
  111. return ret;
  112. } else if (ret < 0)
  113. return ret;
  114. }
  115. return bmap->b_ops->bop_insert(bmap, key, ptr);
  116. }
  117. /**
  118. * nilfs_bmap_insert - insert a new key-record pair into a bmap
  119. * @bmap: bmap
  120. * @key: key
  121. * @rec: record
  122. *
  123. * Description: nilfs_bmap_insert() inserts the new key-record pair specified
  124. * by @key and @rec into @bmap.
  125. *
  126. * Return Value: On success, 0 is returned. On error, one of the following
  127. * negative error codes is returned.
  128. *
  129. * %-EIO - I/O error.
  130. *
  131. * %-ENOMEM - Insufficient amount of memory available.
  132. *
  133. * %-EEXIST - A record associated with @key already exist.
  134. */
  135. int nilfs_bmap_insert(struct nilfs_bmap *bmap,
  136. unsigned long key,
  137. unsigned long rec)
  138. {
  139. int ret;
  140. down_write(&bmap->b_sem);
  141. ret = nilfs_bmap_do_insert(bmap, key, rec);
  142. up_write(&bmap->b_sem);
  143. return ret;
  144. }
  145. static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
  146. {
  147. __u64 keys[NILFS_BMAP_LARGE_LOW + 1];
  148. __u64 ptrs[NILFS_BMAP_LARGE_LOW + 1];
  149. int ret, n;
  150. if (bmap->b_ops->bop_check_delete != NULL) {
  151. ret = bmap->b_ops->bop_check_delete(bmap, key);
  152. if (ret > 0) {
  153. n = bmap->b_ops->bop_gather_data(
  154. bmap, keys, ptrs, NILFS_BMAP_LARGE_LOW + 1);
  155. if (n < 0)
  156. return n;
  157. ret = nilfs_direct_delete_and_convert(
  158. bmap, key, keys, ptrs, n);
  159. if (ret == 0)
  160. bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE;
  161. return ret;
  162. } else if (ret < 0)
  163. return ret;
  164. }
  165. return bmap->b_ops->bop_delete(bmap, key);
  166. }
  167. int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key)
  168. {
  169. __u64 lastkey;
  170. int ret;
  171. down_read(&bmap->b_sem);
  172. ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
  173. if (!ret)
  174. *key = lastkey;
  175. up_read(&bmap->b_sem);
  176. return ret;
  177. }
  178. /**
  179. * nilfs_bmap_delete - delete a key-record pair from a bmap
  180. * @bmap: bmap
  181. * @key: key
  182. *
  183. * Description: nilfs_bmap_delete() deletes the key-record pair specified by
  184. * @key from @bmap.
  185. *
  186. * Return Value: On success, 0 is returned. On error, one of the following
  187. * negative error codes is returned.
  188. *
  189. * %-EIO - I/O error.
  190. *
  191. * %-ENOMEM - Insufficient amount of memory available.
  192. *
  193. * %-ENOENT - A record associated with @key does not exist.
  194. */
  195. int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key)
  196. {
  197. int ret;
  198. down_write(&bmap->b_sem);
  199. ret = nilfs_bmap_do_delete(bmap, key);
  200. up_write(&bmap->b_sem);
  201. return ret;
  202. }
  203. static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key)
  204. {
  205. __u64 lastkey;
  206. int ret;
  207. ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
  208. if (ret < 0) {
  209. if (ret == -ENOENT)
  210. ret = 0;
  211. return ret;
  212. }
  213. while (key <= lastkey) {
  214. ret = nilfs_bmap_do_delete(bmap, lastkey);
  215. if (ret < 0)
  216. return ret;
  217. ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
  218. if (ret < 0) {
  219. if (ret == -ENOENT)
  220. ret = 0;
  221. return ret;
  222. }
  223. }
  224. return 0;
  225. }
  226. /**
  227. * nilfs_bmap_truncate - truncate a bmap to a specified key
  228. * @bmap: bmap
  229. * @key: key
  230. *
  231. * Description: nilfs_bmap_truncate() removes key-record pairs whose keys are
  232. * greater than or equal to @key from @bmap.
  233. *
  234. * Return Value: On success, 0 is returned. On error, one of the following
  235. * negative error codes is returned.
  236. *
  237. * %-EIO - I/O error.
  238. *
  239. * %-ENOMEM - Insufficient amount of memory available.
  240. */
  241. int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key)
  242. {
  243. int ret;
  244. down_write(&bmap->b_sem);
  245. ret = nilfs_bmap_do_truncate(bmap, key);
  246. up_write(&bmap->b_sem);
  247. return ret;
  248. }
  249. /**
  250. * nilfs_bmap_clear - free resources a bmap holds
  251. * @bmap: bmap
  252. *
  253. * Description: nilfs_bmap_clear() frees resources associated with @bmap.
  254. */
  255. void nilfs_bmap_clear(struct nilfs_bmap *bmap)
  256. {
  257. down_write(&bmap->b_sem);
  258. if (bmap->b_ops->bop_clear != NULL)
  259. bmap->b_ops->bop_clear(bmap);
  260. up_write(&bmap->b_sem);
  261. }
  262. /**
  263. * nilfs_bmap_propagate - propagate dirty state
  264. * @bmap: bmap
  265. * @bh: buffer head
  266. *
  267. * Description: nilfs_bmap_propagate() marks the buffers that directly or
  268. * indirectly refer to the block specified by @bh dirty.
  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_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh)
  278. {
  279. int ret;
  280. down_write(&bmap->b_sem);
  281. ret = bmap->b_ops->bop_propagate(bmap, bh);
  282. up_write(&bmap->b_sem);
  283. return ret;
  284. }
  285. /**
  286. * nilfs_bmap_lookup_dirty_buffers -
  287. * @bmap: bmap
  288. * @listp: pointer to buffer head list
  289. */
  290. void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *bmap,
  291. struct list_head *listp)
  292. {
  293. if (bmap->b_ops->bop_lookup_dirty_buffers != NULL)
  294. bmap->b_ops->bop_lookup_dirty_buffers(bmap, listp);
  295. }
  296. /**
  297. * nilfs_bmap_assign - assign a new block number to a block
  298. * @bmap: bmap
  299. * @bhp: pointer to buffer head
  300. * @blocknr: block number
  301. * @binfo: block information
  302. *
  303. * Description: nilfs_bmap_assign() assigns the block number @blocknr to the
  304. * buffer specified by @bh.
  305. *
  306. * Return Value: On success, 0 is returned and the buffer head of a newly
  307. * create buffer and the block information associated with the buffer are
  308. * stored in the place pointed by @bh and @binfo, respectively. On error, one
  309. * of the following negative error codes is returned.
  310. *
  311. * %-EIO - I/O error.
  312. *
  313. * %-ENOMEM - Insufficient amount of memory available.
  314. */
  315. int nilfs_bmap_assign(struct nilfs_bmap *bmap,
  316. struct buffer_head **bh,
  317. unsigned long blocknr,
  318. union nilfs_binfo *binfo)
  319. {
  320. int ret;
  321. down_write(&bmap->b_sem);
  322. ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo);
  323. up_write(&bmap->b_sem);
  324. return ret;
  325. }
  326. /**
  327. * nilfs_bmap_mark - mark block dirty
  328. * @bmap: bmap
  329. * @key: key
  330. * @level: level
  331. *
  332. * Description: nilfs_bmap_mark() marks the block specified by @key and @level
  333. * as dirty.
  334. *
  335. * Return Value: On success, 0 is returned. On error, one of the following
  336. * negative error codes is returned.
  337. *
  338. * %-EIO - I/O error.
  339. *
  340. * %-ENOMEM - Insufficient amount of memory available.
  341. */
  342. int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level)
  343. {
  344. int ret;
  345. if (bmap->b_ops->bop_mark == NULL)
  346. return 0;
  347. down_write(&bmap->b_sem);
  348. ret = bmap->b_ops->bop_mark(bmap, key, level);
  349. up_write(&bmap->b_sem);
  350. return ret;
  351. }
  352. /**
  353. * nilfs_bmap_test_and_clear_dirty - test and clear a bmap dirty state
  354. * @bmap: bmap
  355. *
  356. * Description: nilfs_test_and_clear() is the atomic operation to test and
  357. * clear the dirty state of @bmap.
  358. *
  359. * Return Value: 1 is returned if @bmap is dirty, or 0 if clear.
  360. */
  361. int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
  362. {
  363. int ret;
  364. down_write(&bmap->b_sem);
  365. ret = nilfs_bmap_dirty(bmap);
  366. nilfs_bmap_clear_dirty(bmap);
  367. up_write(&bmap->b_sem);
  368. return ret;
  369. }
  370. /*
  371. * Internal use only
  372. */
  373. void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n)
  374. {
  375. inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
  376. if (NILFS_MDT(bmap->b_inode))
  377. nilfs_mdt_mark_dirty(bmap->b_inode);
  378. else
  379. mark_inode_dirty(bmap->b_inode);
  380. }
  381. void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
  382. {
  383. inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
  384. if (NILFS_MDT(bmap->b_inode))
  385. nilfs_mdt_mark_dirty(bmap->b_inode);
  386. else
  387. mark_inode_dirty(bmap->b_inode);
  388. }
  389. __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
  390. const struct buffer_head *bh)
  391. {
  392. struct buffer_head *pbh;
  393. __u64 key;
  394. key = page_index(bh->b_page) << (PAGE_CACHE_SHIFT -
  395. bmap->b_inode->i_blkbits);
  396. for (pbh = page_buffers(bh->b_page); pbh != bh;
  397. pbh = pbh->b_this_page, key++);
  398. return key;
  399. }
  400. __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key)
  401. {
  402. __s64 diff;
  403. diff = key - bmap->b_last_allocated_key;
  404. if ((nilfs_bmap_keydiff_abs(diff) < NILFS_INODE_BMAP_SIZE) &&
  405. (bmap->b_last_allocated_ptr != NILFS_BMAP_INVALID_PTR) &&
  406. (bmap->b_last_allocated_ptr + diff > 0))
  407. return bmap->b_last_allocated_ptr + diff;
  408. else
  409. return NILFS_BMAP_INVALID_PTR;
  410. }
  411. #define NILFS_BMAP_GROUP_DIV 8
  412. __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
  413. {
  414. struct inode *dat = nilfs_bmap_get_dat(bmap);
  415. unsigned long entries_per_group = nilfs_palloc_entries_per_group(dat);
  416. unsigned long group = bmap->b_inode->i_ino / entries_per_group;
  417. return group * entries_per_group +
  418. (bmap->b_inode->i_ino % NILFS_BMAP_GROUP_DIV) *
  419. (entries_per_group / NILFS_BMAP_GROUP_DIV);
  420. }
  421. int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *bmap,
  422. union nilfs_bmap_ptr_req *req)
  423. {
  424. return nilfs_dat_prepare_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
  425. }
  426. void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *bmap,
  427. union nilfs_bmap_ptr_req *req)
  428. {
  429. nilfs_dat_commit_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
  430. }
  431. void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *bmap,
  432. union nilfs_bmap_ptr_req *req)
  433. {
  434. nilfs_dat_abort_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
  435. }
  436. int nilfs_bmap_start_v(struct nilfs_bmap *bmap, union nilfs_bmap_ptr_req *req,
  437. sector_t blocknr)
  438. {
  439. struct inode *dat = nilfs_bmap_get_dat(bmap);
  440. int ret;
  441. ret = nilfs_dat_prepare_start(dat, &req->bpr_req);
  442. if (likely(!ret))
  443. nilfs_dat_commit_start(dat, &req->bpr_req, blocknr);
  444. return ret;
  445. }
  446. int nilfs_bmap_prepare_end_v(struct nilfs_bmap *bmap,
  447. union nilfs_bmap_ptr_req *req)
  448. {
  449. return nilfs_dat_prepare_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
  450. }
  451. void nilfs_bmap_commit_end_v(struct nilfs_bmap *bmap,
  452. union nilfs_bmap_ptr_req *req)
  453. {
  454. nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req,
  455. bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
  456. }
  457. void nilfs_bmap_abort_end_v(struct nilfs_bmap *bmap,
  458. union nilfs_bmap_ptr_req *req)
  459. {
  460. nilfs_dat_abort_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
  461. }
  462. int nilfs_bmap_move_v(const struct nilfs_bmap *bmap, __u64 vblocknr,
  463. sector_t blocknr)
  464. {
  465. return nilfs_dat_move(nilfs_bmap_get_dat(bmap), vblocknr, blocknr);
  466. }
  467. int nilfs_bmap_mark_dirty(const struct nilfs_bmap *bmap, __u64 vblocknr)
  468. {
  469. return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), vblocknr);
  470. }
  471. int nilfs_bmap_prepare_update_v(struct nilfs_bmap *bmap,
  472. union nilfs_bmap_ptr_req *oldreq,
  473. union nilfs_bmap_ptr_req *newreq)
  474. {
  475. struct inode *dat = nilfs_bmap_get_dat(bmap);
  476. int ret;
  477. ret = nilfs_dat_prepare_end(dat, &oldreq->bpr_req);
  478. if (ret < 0)
  479. return ret;
  480. ret = nilfs_dat_prepare_alloc(dat, &newreq->bpr_req);
  481. if (ret < 0)
  482. nilfs_dat_abort_end(dat, &oldreq->bpr_req);
  483. return ret;
  484. }
  485. void nilfs_bmap_commit_update_v(struct nilfs_bmap *bmap,
  486. union nilfs_bmap_ptr_req *oldreq,
  487. union nilfs_bmap_ptr_req *newreq)
  488. {
  489. struct inode *dat = nilfs_bmap_get_dat(bmap);
  490. nilfs_dat_commit_end(dat, &oldreq->bpr_req,
  491. bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
  492. nilfs_dat_commit_alloc(dat, &newreq->bpr_req);
  493. }
  494. void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap,
  495. union nilfs_bmap_ptr_req *oldreq,
  496. union nilfs_bmap_ptr_req *newreq)
  497. {
  498. struct inode *dat = nilfs_bmap_get_dat(bmap);
  499. nilfs_dat_abort_end(dat, &oldreq->bpr_req);
  500. nilfs_dat_abort_alloc(dat, &newreq->bpr_req);
  501. }
  502. static struct lock_class_key nilfs_bmap_dat_lock_key;
  503. static struct lock_class_key nilfs_bmap_mdt_lock_key;
  504. /**
  505. * nilfs_bmap_read - read a bmap from an inode
  506. * @bmap: bmap
  507. * @raw_inode: on-disk inode
  508. *
  509. * Description: nilfs_bmap_read() initializes the bmap @bmap.
  510. *
  511. * Return Value: On success, 0 is returned. On error, the following negative
  512. * error code is returned.
  513. *
  514. * %-ENOMEM - Insufficient amount of memory available.
  515. */
  516. int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
  517. {
  518. if (raw_inode == NULL)
  519. memset(bmap->b_u.u_data, 0, NILFS_BMAP_SIZE);
  520. else
  521. memcpy(bmap->b_u.u_data, raw_inode->i_bmap, NILFS_BMAP_SIZE);
  522. init_rwsem(&bmap->b_sem);
  523. bmap->b_state = 0;
  524. bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
  525. switch (bmap->b_inode->i_ino) {
  526. case NILFS_DAT_INO:
  527. bmap->b_ptr_type = NILFS_BMAP_PTR_P;
  528. bmap->b_last_allocated_key = 0;
  529. bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
  530. lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
  531. break;
  532. case NILFS_CPFILE_INO:
  533. case NILFS_SUFILE_INO:
  534. bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
  535. bmap->b_last_allocated_key = 0;
  536. bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
  537. lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
  538. break;
  539. case NILFS_IFILE_INO:
  540. lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
  541. /* Fall through */
  542. default:
  543. bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
  544. bmap->b_last_allocated_key = 0;
  545. bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
  546. break;
  547. }
  548. return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ?
  549. nilfs_btree_init(bmap) : nilfs_direct_init(bmap);
  550. }
  551. /**
  552. * nilfs_bmap_write - write back a bmap to an inode
  553. * @bmap: bmap
  554. * @raw_inode: on-disk inode
  555. *
  556. * Description: nilfs_bmap_write() stores @bmap in @raw_inode.
  557. */
  558. void nilfs_bmap_write(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
  559. {
  560. down_write(&bmap->b_sem);
  561. memcpy(raw_inode->i_bmap, bmap->b_u.u_data,
  562. NILFS_INODE_BMAP_SIZE * sizeof(__le64));
  563. if (bmap->b_inode->i_ino == NILFS_DAT_INO)
  564. bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
  565. up_write(&bmap->b_sem);
  566. }
  567. void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
  568. {
  569. memset(&bmap->b_u, 0, NILFS_BMAP_SIZE);
  570. init_rwsem(&bmap->b_sem);
  571. bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
  572. bmap->b_ptr_type = NILFS_BMAP_PTR_U;
  573. bmap->b_last_allocated_key = 0;
  574. bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
  575. bmap->b_state = 0;
  576. nilfs_btree_init_gc(bmap);
  577. }
  578. void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
  579. {
  580. memcpy(gcbmap, bmap, sizeof(union nilfs_bmap_union));
  581. init_rwsem(&gcbmap->b_sem);
  582. lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
  583. gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode;
  584. }
  585. void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
  586. {
  587. memcpy(bmap, gcbmap, sizeof(union nilfs_bmap_union));
  588. init_rwsem(&bmap->b_sem);
  589. lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
  590. bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
  591. }