cpfile.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. /*
  2. * cpfile.c - NILFS checkpoint file.
  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/kernel.h>
  23. #include <linux/fs.h>
  24. #include <linux/string.h>
  25. #include <linux/buffer_head.h>
  26. #include <linux/errno.h>
  27. #include <linux/nilfs2_fs.h>
  28. #include "mdt.h"
  29. #include "cpfile.h"
  30. static inline unsigned long
  31. nilfs_cpfile_checkpoints_per_block(const struct inode *cpfile)
  32. {
  33. return NILFS_MDT(cpfile)->mi_entries_per_block;
  34. }
  35. /* block number from the beginning of the file */
  36. static unsigned long
  37. nilfs_cpfile_get_blkoff(const struct inode *cpfile, __u64 cno)
  38. {
  39. __u64 tcno = cno + NILFS_MDT(cpfile)->mi_first_entry_offset - 1;
  40. do_div(tcno, nilfs_cpfile_checkpoints_per_block(cpfile));
  41. return (unsigned long)tcno;
  42. }
  43. /* offset in block */
  44. static unsigned long
  45. nilfs_cpfile_get_offset(const struct inode *cpfile, __u64 cno)
  46. {
  47. __u64 tcno = cno + NILFS_MDT(cpfile)->mi_first_entry_offset - 1;
  48. return do_div(tcno, nilfs_cpfile_checkpoints_per_block(cpfile));
  49. }
  50. static unsigned long
  51. nilfs_cpfile_checkpoints_in_block(const struct inode *cpfile,
  52. __u64 curr,
  53. __u64 max)
  54. {
  55. return min_t(__u64,
  56. nilfs_cpfile_checkpoints_per_block(cpfile) -
  57. nilfs_cpfile_get_offset(cpfile, curr),
  58. max - curr);
  59. }
  60. static inline int nilfs_cpfile_is_in_first(const struct inode *cpfile,
  61. __u64 cno)
  62. {
  63. return nilfs_cpfile_get_blkoff(cpfile, cno) == 0;
  64. }
  65. static unsigned int
  66. nilfs_cpfile_block_add_valid_checkpoints(const struct inode *cpfile,
  67. struct buffer_head *bh,
  68. void *kaddr,
  69. unsigned int n)
  70. {
  71. struct nilfs_checkpoint *cp = kaddr + bh_offset(bh);
  72. unsigned int count;
  73. count = le32_to_cpu(cp->cp_checkpoints_count) + n;
  74. cp->cp_checkpoints_count = cpu_to_le32(count);
  75. return count;
  76. }
  77. static unsigned int
  78. nilfs_cpfile_block_sub_valid_checkpoints(const struct inode *cpfile,
  79. struct buffer_head *bh,
  80. void *kaddr,
  81. unsigned int n)
  82. {
  83. struct nilfs_checkpoint *cp = kaddr + bh_offset(bh);
  84. unsigned int count;
  85. WARN_ON(le32_to_cpu(cp->cp_checkpoints_count) < n);
  86. count = le32_to_cpu(cp->cp_checkpoints_count) - n;
  87. cp->cp_checkpoints_count = cpu_to_le32(count);
  88. return count;
  89. }
  90. static inline struct nilfs_cpfile_header *
  91. nilfs_cpfile_block_get_header(const struct inode *cpfile,
  92. struct buffer_head *bh,
  93. void *kaddr)
  94. {
  95. return kaddr + bh_offset(bh);
  96. }
  97. static struct nilfs_checkpoint *
  98. nilfs_cpfile_block_get_checkpoint(const struct inode *cpfile, __u64 cno,
  99. struct buffer_head *bh,
  100. void *kaddr)
  101. {
  102. return kaddr + bh_offset(bh) + nilfs_cpfile_get_offset(cpfile, cno) *
  103. NILFS_MDT(cpfile)->mi_entry_size;
  104. }
  105. static void nilfs_cpfile_block_init(struct inode *cpfile,
  106. struct buffer_head *bh,
  107. void *kaddr)
  108. {
  109. struct nilfs_checkpoint *cp = kaddr + bh_offset(bh);
  110. size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size;
  111. int n = nilfs_cpfile_checkpoints_per_block(cpfile);
  112. while (n-- > 0) {
  113. nilfs_checkpoint_set_invalid(cp);
  114. cp = (void *)cp + cpsz;
  115. }
  116. }
  117. static inline int nilfs_cpfile_get_header_block(struct inode *cpfile,
  118. struct buffer_head **bhp)
  119. {
  120. return nilfs_mdt_get_block(cpfile, 0, 0, NULL, bhp);
  121. }
  122. static inline int nilfs_cpfile_get_checkpoint_block(struct inode *cpfile,
  123. __u64 cno,
  124. int create,
  125. struct buffer_head **bhp)
  126. {
  127. return nilfs_mdt_get_block(cpfile,
  128. nilfs_cpfile_get_blkoff(cpfile, cno),
  129. create, nilfs_cpfile_block_init, bhp);
  130. }
  131. static inline int nilfs_cpfile_delete_checkpoint_block(struct inode *cpfile,
  132. __u64 cno)
  133. {
  134. return nilfs_mdt_delete_block(cpfile,
  135. nilfs_cpfile_get_blkoff(cpfile, cno));
  136. }
  137. /**
  138. * nilfs_cpfile_get_checkpoint - get a checkpoint
  139. * @cpfile: inode of checkpoint file
  140. * @cno: checkpoint number
  141. * @create: create flag
  142. * @cpp: pointer to a checkpoint
  143. * @bhp: pointer to a buffer head
  144. *
  145. * Description: nilfs_cpfile_get_checkpoint() acquires the checkpoint
  146. * specified by @cno. A new checkpoint will be created if @cno is the current
  147. * checkpoint number and @create is nonzero.
  148. *
  149. * Return Value: On success, 0 is returned, and the checkpoint and the
  150. * buffer head of the buffer on which the checkpoint is located are stored in
  151. * the place pointed by @cpp and @bhp, respectively. On error, one of the
  152. * following negative error codes is returned.
  153. *
  154. * %-EIO - I/O error.
  155. *
  156. * %-ENOMEM - Insufficient amount of memory available.
  157. *
  158. * %-ENOENT - No such checkpoint.
  159. *
  160. * %-EINVAL - invalid checkpoint.
  161. */
  162. int nilfs_cpfile_get_checkpoint(struct inode *cpfile,
  163. __u64 cno,
  164. int create,
  165. struct nilfs_checkpoint **cpp,
  166. struct buffer_head **bhp)
  167. {
  168. struct buffer_head *header_bh, *cp_bh;
  169. struct nilfs_cpfile_header *header;
  170. struct nilfs_checkpoint *cp;
  171. void *kaddr;
  172. int ret;
  173. if (unlikely(cno < 1 || cno > nilfs_mdt_cno(cpfile) ||
  174. (cno < nilfs_mdt_cno(cpfile) && create)))
  175. return -EINVAL;
  176. down_write(&NILFS_MDT(cpfile)->mi_sem);
  177. ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
  178. if (ret < 0)
  179. goto out_sem;
  180. ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, create, &cp_bh);
  181. if (ret < 0)
  182. goto out_header;
  183. kaddr = kmap(cp_bh->b_page);
  184. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
  185. if (nilfs_checkpoint_invalid(cp)) {
  186. if (!create) {
  187. kunmap(cp_bh->b_page);
  188. brelse(cp_bh);
  189. ret = -ENOENT;
  190. goto out_header;
  191. }
  192. /* a newly-created checkpoint */
  193. nilfs_checkpoint_clear_invalid(cp);
  194. if (!nilfs_cpfile_is_in_first(cpfile, cno))
  195. nilfs_cpfile_block_add_valid_checkpoints(cpfile, cp_bh,
  196. kaddr, 1);
  197. mark_buffer_dirty(cp_bh);
  198. kaddr = kmap_atomic(header_bh->b_page);
  199. header = nilfs_cpfile_block_get_header(cpfile, header_bh,
  200. kaddr);
  201. le64_add_cpu(&header->ch_ncheckpoints, 1);
  202. kunmap_atomic(kaddr);
  203. mark_buffer_dirty(header_bh);
  204. nilfs_mdt_mark_dirty(cpfile);
  205. }
  206. if (cpp != NULL)
  207. *cpp = cp;
  208. *bhp = cp_bh;
  209. out_header:
  210. brelse(header_bh);
  211. out_sem:
  212. up_write(&NILFS_MDT(cpfile)->mi_sem);
  213. return ret;
  214. }
  215. /**
  216. * nilfs_cpfile_put_checkpoint - put a checkpoint
  217. * @cpfile: inode of checkpoint file
  218. * @cno: checkpoint number
  219. * @bh: buffer head
  220. *
  221. * Description: nilfs_cpfile_put_checkpoint() releases the checkpoint
  222. * specified by @cno. @bh must be the buffer head which has been returned by
  223. * a previous call to nilfs_cpfile_get_checkpoint() with @cno.
  224. */
  225. void nilfs_cpfile_put_checkpoint(struct inode *cpfile, __u64 cno,
  226. struct buffer_head *bh)
  227. {
  228. kunmap(bh->b_page);
  229. brelse(bh);
  230. }
  231. /**
  232. * nilfs_cpfile_delete_checkpoints - delete checkpoints
  233. * @cpfile: inode of checkpoint file
  234. * @start: start checkpoint number
  235. * @end: end checkpoint numer
  236. *
  237. * Description: nilfs_cpfile_delete_checkpoints() deletes the checkpoints in
  238. * the period from @start to @end, excluding @end itself. The checkpoints
  239. * which have been already deleted are ignored.
  240. *
  241. * Return Value: On success, 0 is returned. On error, one of the following
  242. * negative error codes is returned.
  243. *
  244. * %-EIO - I/O error.
  245. *
  246. * %-ENOMEM - Insufficient amount of memory available.
  247. *
  248. * %-EINVAL - invalid checkpoints.
  249. */
  250. int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
  251. __u64 start,
  252. __u64 end)
  253. {
  254. struct buffer_head *header_bh, *cp_bh;
  255. struct nilfs_cpfile_header *header;
  256. struct nilfs_checkpoint *cp;
  257. size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size;
  258. __u64 cno;
  259. void *kaddr;
  260. unsigned long tnicps;
  261. int ret, ncps, nicps, count, i;
  262. if (unlikely(start == 0 || start > end)) {
  263. printk(KERN_ERR "%s: invalid range of checkpoint numbers: "
  264. "[%llu, %llu)\n", __func__,
  265. (unsigned long long)start, (unsigned long long)end);
  266. return -EINVAL;
  267. }
  268. down_write(&NILFS_MDT(cpfile)->mi_sem);
  269. ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
  270. if (ret < 0)
  271. goto out_sem;
  272. tnicps = 0;
  273. for (cno = start; cno < end; cno += ncps) {
  274. ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, end);
  275. ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
  276. if (ret < 0) {
  277. if (ret != -ENOENT)
  278. break;
  279. /* skip hole */
  280. ret = 0;
  281. continue;
  282. }
  283. kaddr = kmap_atomic(cp_bh->b_page);
  284. cp = nilfs_cpfile_block_get_checkpoint(
  285. cpfile, cno, cp_bh, kaddr);
  286. nicps = 0;
  287. for (i = 0; i < ncps; i++, cp = (void *)cp + cpsz) {
  288. WARN_ON(nilfs_checkpoint_snapshot(cp));
  289. if (!nilfs_checkpoint_invalid(cp)) {
  290. nilfs_checkpoint_set_invalid(cp);
  291. nicps++;
  292. }
  293. }
  294. if (nicps > 0) {
  295. tnicps += nicps;
  296. mark_buffer_dirty(cp_bh);
  297. nilfs_mdt_mark_dirty(cpfile);
  298. if (!nilfs_cpfile_is_in_first(cpfile, cno)) {
  299. count =
  300. nilfs_cpfile_block_sub_valid_checkpoints(
  301. cpfile, cp_bh, kaddr, nicps);
  302. if (count == 0) {
  303. /* make hole */
  304. kunmap_atomic(kaddr);
  305. brelse(cp_bh);
  306. ret =
  307. nilfs_cpfile_delete_checkpoint_block(
  308. cpfile, cno);
  309. if (ret == 0)
  310. continue;
  311. printk(KERN_ERR
  312. "%s: cannot delete block\n",
  313. __func__);
  314. break;
  315. }
  316. }
  317. }
  318. kunmap_atomic(kaddr);
  319. brelse(cp_bh);
  320. }
  321. if (tnicps > 0) {
  322. kaddr = kmap_atomic(header_bh->b_page);
  323. header = nilfs_cpfile_block_get_header(cpfile, header_bh,
  324. kaddr);
  325. le64_add_cpu(&header->ch_ncheckpoints, -(u64)tnicps);
  326. mark_buffer_dirty(header_bh);
  327. nilfs_mdt_mark_dirty(cpfile);
  328. kunmap_atomic(kaddr);
  329. }
  330. brelse(header_bh);
  331. out_sem:
  332. up_write(&NILFS_MDT(cpfile)->mi_sem);
  333. return ret;
  334. }
  335. static void nilfs_cpfile_checkpoint_to_cpinfo(struct inode *cpfile,
  336. struct nilfs_checkpoint *cp,
  337. struct nilfs_cpinfo *ci)
  338. {
  339. ci->ci_flags = le32_to_cpu(cp->cp_flags);
  340. ci->ci_cno = le64_to_cpu(cp->cp_cno);
  341. ci->ci_create = le64_to_cpu(cp->cp_create);
  342. ci->ci_nblk_inc = le64_to_cpu(cp->cp_nblk_inc);
  343. ci->ci_inodes_count = le64_to_cpu(cp->cp_inodes_count);
  344. ci->ci_blocks_count = le64_to_cpu(cp->cp_blocks_count);
  345. ci->ci_next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
  346. }
  347. static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
  348. void *buf, unsigned cisz, size_t nci)
  349. {
  350. struct nilfs_checkpoint *cp;
  351. struct nilfs_cpinfo *ci = buf;
  352. struct buffer_head *bh;
  353. size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size;
  354. __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop;
  355. void *kaddr;
  356. int n, ret;
  357. int ncps, i;
  358. if (cno == 0)
  359. return -ENOENT; /* checkpoint number 0 is invalid */
  360. down_read(&NILFS_MDT(cpfile)->mi_sem);
  361. for (n = 0; cno < cur_cno && n < nci; cno += ncps) {
  362. ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno);
  363. ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh);
  364. if (ret < 0) {
  365. if (ret != -ENOENT)
  366. goto out;
  367. continue; /* skip hole */
  368. }
  369. kaddr = kmap_atomic(bh->b_page);
  370. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
  371. for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) {
  372. if (!nilfs_checkpoint_invalid(cp)) {
  373. nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp,
  374. ci);
  375. ci = (void *)ci + cisz;
  376. n++;
  377. }
  378. }
  379. kunmap_atomic(kaddr);
  380. brelse(bh);
  381. }
  382. ret = n;
  383. if (n > 0) {
  384. ci = (void *)ci - cisz;
  385. *cnop = ci->ci_cno + 1;
  386. }
  387. out:
  388. up_read(&NILFS_MDT(cpfile)->mi_sem);
  389. return ret;
  390. }
  391. static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
  392. void *buf, unsigned cisz, size_t nci)
  393. {
  394. struct buffer_head *bh;
  395. struct nilfs_cpfile_header *header;
  396. struct nilfs_checkpoint *cp;
  397. struct nilfs_cpinfo *ci = buf;
  398. __u64 curr = *cnop, next;
  399. unsigned long curr_blkoff, next_blkoff;
  400. void *kaddr;
  401. int n = 0, ret;
  402. down_read(&NILFS_MDT(cpfile)->mi_sem);
  403. if (curr == 0) {
  404. ret = nilfs_cpfile_get_header_block(cpfile, &bh);
  405. if (ret < 0)
  406. goto out;
  407. kaddr = kmap_atomic(bh->b_page);
  408. header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr);
  409. curr = le64_to_cpu(header->ch_snapshot_list.ssl_next);
  410. kunmap_atomic(kaddr);
  411. brelse(bh);
  412. if (curr == 0) {
  413. ret = 0;
  414. goto out;
  415. }
  416. } else if (unlikely(curr == ~(__u64)0)) {
  417. ret = 0;
  418. goto out;
  419. }
  420. curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr);
  421. ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh);
  422. if (unlikely(ret < 0)) {
  423. if (ret == -ENOENT)
  424. ret = 0; /* No snapshots (started from a hole block) */
  425. goto out;
  426. }
  427. kaddr = kmap_atomic(bh->b_page);
  428. while (n < nci) {
  429. cp = nilfs_cpfile_block_get_checkpoint(cpfile, curr, bh, kaddr);
  430. curr = ~(__u64)0; /* Terminator */
  431. if (unlikely(nilfs_checkpoint_invalid(cp) ||
  432. !nilfs_checkpoint_snapshot(cp)))
  433. break;
  434. nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, ci);
  435. ci = (void *)ci + cisz;
  436. n++;
  437. next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
  438. if (next == 0)
  439. break; /* reach end of the snapshot list */
  440. next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next);
  441. if (curr_blkoff != next_blkoff) {
  442. kunmap_atomic(kaddr);
  443. brelse(bh);
  444. ret = nilfs_cpfile_get_checkpoint_block(cpfile, next,
  445. 0, &bh);
  446. if (unlikely(ret < 0)) {
  447. WARN_ON(ret == -ENOENT);
  448. goto out;
  449. }
  450. kaddr = kmap_atomic(bh->b_page);
  451. }
  452. curr = next;
  453. curr_blkoff = next_blkoff;
  454. }
  455. kunmap_atomic(kaddr);
  456. brelse(bh);
  457. *cnop = curr;
  458. ret = n;
  459. out:
  460. up_read(&NILFS_MDT(cpfile)->mi_sem);
  461. return ret;
  462. }
  463. /**
  464. * nilfs_cpfile_get_cpinfo -
  465. * @cpfile:
  466. * @cno:
  467. * @ci:
  468. * @nci:
  469. */
  470. ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode,
  471. void *buf, unsigned cisz, size_t nci)
  472. {
  473. switch (mode) {
  474. case NILFS_CHECKPOINT:
  475. return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, buf, cisz, nci);
  476. case NILFS_SNAPSHOT:
  477. return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, buf, cisz, nci);
  478. default:
  479. return -EINVAL;
  480. }
  481. }
  482. /**
  483. * nilfs_cpfile_delete_checkpoint -
  484. * @cpfile:
  485. * @cno:
  486. */
  487. int nilfs_cpfile_delete_checkpoint(struct inode *cpfile, __u64 cno)
  488. {
  489. struct nilfs_cpinfo ci;
  490. __u64 tcno = cno;
  491. ssize_t nci;
  492. nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, sizeof(ci), 1);
  493. if (nci < 0)
  494. return nci;
  495. else if (nci == 0 || ci.ci_cno != cno)
  496. return -ENOENT;
  497. else if (nilfs_cpinfo_snapshot(&ci))
  498. return -EBUSY;
  499. return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1);
  500. }
  501. static struct nilfs_snapshot_list *
  502. nilfs_cpfile_block_get_snapshot_list(const struct inode *cpfile,
  503. __u64 cno,
  504. struct buffer_head *bh,
  505. void *kaddr)
  506. {
  507. struct nilfs_cpfile_header *header;
  508. struct nilfs_checkpoint *cp;
  509. struct nilfs_snapshot_list *list;
  510. if (cno != 0) {
  511. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
  512. list = &cp->cp_snapshot_list;
  513. } else {
  514. header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr);
  515. list = &header->ch_snapshot_list;
  516. }
  517. return list;
  518. }
  519. static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno)
  520. {
  521. struct buffer_head *header_bh, *curr_bh, *prev_bh, *cp_bh;
  522. struct nilfs_cpfile_header *header;
  523. struct nilfs_checkpoint *cp;
  524. struct nilfs_snapshot_list *list;
  525. __u64 curr, prev;
  526. unsigned long curr_blkoff, prev_blkoff;
  527. void *kaddr;
  528. int ret;
  529. if (cno == 0)
  530. return -ENOENT; /* checkpoint number 0 is invalid */
  531. down_write(&NILFS_MDT(cpfile)->mi_sem);
  532. ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
  533. if (ret < 0)
  534. goto out_sem;
  535. kaddr = kmap_atomic(cp_bh->b_page);
  536. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
  537. if (nilfs_checkpoint_invalid(cp)) {
  538. ret = -ENOENT;
  539. kunmap_atomic(kaddr);
  540. goto out_cp;
  541. }
  542. if (nilfs_checkpoint_snapshot(cp)) {
  543. ret = 0;
  544. kunmap_atomic(kaddr);
  545. goto out_cp;
  546. }
  547. kunmap_atomic(kaddr);
  548. ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
  549. if (ret < 0)
  550. goto out_cp;
  551. kaddr = kmap_atomic(header_bh->b_page);
  552. header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr);
  553. list = &header->ch_snapshot_list;
  554. curr_bh = header_bh;
  555. get_bh(curr_bh);
  556. curr = 0;
  557. curr_blkoff = 0;
  558. prev = le64_to_cpu(list->ssl_prev);
  559. while (prev > cno) {
  560. prev_blkoff = nilfs_cpfile_get_blkoff(cpfile, prev);
  561. curr = prev;
  562. if (curr_blkoff != prev_blkoff) {
  563. kunmap_atomic(kaddr);
  564. brelse(curr_bh);
  565. ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr,
  566. 0, &curr_bh);
  567. if (ret < 0)
  568. goto out_header;
  569. kaddr = kmap_atomic(curr_bh->b_page);
  570. }
  571. curr_blkoff = prev_blkoff;
  572. cp = nilfs_cpfile_block_get_checkpoint(
  573. cpfile, curr, curr_bh, kaddr);
  574. list = &cp->cp_snapshot_list;
  575. prev = le64_to_cpu(list->ssl_prev);
  576. }
  577. kunmap_atomic(kaddr);
  578. if (prev != 0) {
  579. ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0,
  580. &prev_bh);
  581. if (ret < 0)
  582. goto out_curr;
  583. } else {
  584. prev_bh = header_bh;
  585. get_bh(prev_bh);
  586. }
  587. kaddr = kmap_atomic(curr_bh->b_page);
  588. list = nilfs_cpfile_block_get_snapshot_list(
  589. cpfile, curr, curr_bh, kaddr);
  590. list->ssl_prev = cpu_to_le64(cno);
  591. kunmap_atomic(kaddr);
  592. kaddr = kmap_atomic(cp_bh->b_page);
  593. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
  594. cp->cp_snapshot_list.ssl_next = cpu_to_le64(curr);
  595. cp->cp_snapshot_list.ssl_prev = cpu_to_le64(prev);
  596. nilfs_checkpoint_set_snapshot(cp);
  597. kunmap_atomic(kaddr);
  598. kaddr = kmap_atomic(prev_bh->b_page);
  599. list = nilfs_cpfile_block_get_snapshot_list(
  600. cpfile, prev, prev_bh, kaddr);
  601. list->ssl_next = cpu_to_le64(cno);
  602. kunmap_atomic(kaddr);
  603. kaddr = kmap_atomic(header_bh->b_page);
  604. header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr);
  605. le64_add_cpu(&header->ch_nsnapshots, 1);
  606. kunmap_atomic(kaddr);
  607. mark_buffer_dirty(prev_bh);
  608. mark_buffer_dirty(curr_bh);
  609. mark_buffer_dirty(cp_bh);
  610. mark_buffer_dirty(header_bh);
  611. nilfs_mdt_mark_dirty(cpfile);
  612. brelse(prev_bh);
  613. out_curr:
  614. brelse(curr_bh);
  615. out_header:
  616. brelse(header_bh);
  617. out_cp:
  618. brelse(cp_bh);
  619. out_sem:
  620. up_write(&NILFS_MDT(cpfile)->mi_sem);
  621. return ret;
  622. }
  623. static int nilfs_cpfile_clear_snapshot(struct inode *cpfile, __u64 cno)
  624. {
  625. struct buffer_head *header_bh, *next_bh, *prev_bh, *cp_bh;
  626. struct nilfs_cpfile_header *header;
  627. struct nilfs_checkpoint *cp;
  628. struct nilfs_snapshot_list *list;
  629. __u64 next, prev;
  630. void *kaddr;
  631. int ret;
  632. if (cno == 0)
  633. return -ENOENT; /* checkpoint number 0 is invalid */
  634. down_write(&NILFS_MDT(cpfile)->mi_sem);
  635. ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
  636. if (ret < 0)
  637. goto out_sem;
  638. kaddr = kmap_atomic(cp_bh->b_page);
  639. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
  640. if (nilfs_checkpoint_invalid(cp)) {
  641. ret = -ENOENT;
  642. kunmap_atomic(kaddr);
  643. goto out_cp;
  644. }
  645. if (!nilfs_checkpoint_snapshot(cp)) {
  646. ret = 0;
  647. kunmap_atomic(kaddr);
  648. goto out_cp;
  649. }
  650. list = &cp->cp_snapshot_list;
  651. next = le64_to_cpu(list->ssl_next);
  652. prev = le64_to_cpu(list->ssl_prev);
  653. kunmap_atomic(kaddr);
  654. ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
  655. if (ret < 0)
  656. goto out_cp;
  657. if (next != 0) {
  658. ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 0,
  659. &next_bh);
  660. if (ret < 0)
  661. goto out_header;
  662. } else {
  663. next_bh = header_bh;
  664. get_bh(next_bh);
  665. }
  666. if (prev != 0) {
  667. ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0,
  668. &prev_bh);
  669. if (ret < 0)
  670. goto out_next;
  671. } else {
  672. prev_bh = header_bh;
  673. get_bh(prev_bh);
  674. }
  675. kaddr = kmap_atomic(next_bh->b_page);
  676. list = nilfs_cpfile_block_get_snapshot_list(
  677. cpfile, next, next_bh, kaddr);
  678. list->ssl_prev = cpu_to_le64(prev);
  679. kunmap_atomic(kaddr);
  680. kaddr = kmap_atomic(prev_bh->b_page);
  681. list = nilfs_cpfile_block_get_snapshot_list(
  682. cpfile, prev, prev_bh, kaddr);
  683. list->ssl_next = cpu_to_le64(next);
  684. kunmap_atomic(kaddr);
  685. kaddr = kmap_atomic(cp_bh->b_page);
  686. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
  687. cp->cp_snapshot_list.ssl_next = cpu_to_le64(0);
  688. cp->cp_snapshot_list.ssl_prev = cpu_to_le64(0);
  689. nilfs_checkpoint_clear_snapshot(cp);
  690. kunmap_atomic(kaddr);
  691. kaddr = kmap_atomic(header_bh->b_page);
  692. header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr);
  693. le64_add_cpu(&header->ch_nsnapshots, -1);
  694. kunmap_atomic(kaddr);
  695. mark_buffer_dirty(next_bh);
  696. mark_buffer_dirty(prev_bh);
  697. mark_buffer_dirty(cp_bh);
  698. mark_buffer_dirty(header_bh);
  699. nilfs_mdt_mark_dirty(cpfile);
  700. brelse(prev_bh);
  701. out_next:
  702. brelse(next_bh);
  703. out_header:
  704. brelse(header_bh);
  705. out_cp:
  706. brelse(cp_bh);
  707. out_sem:
  708. up_write(&NILFS_MDT(cpfile)->mi_sem);
  709. return ret;
  710. }
  711. /**
  712. * nilfs_cpfile_is_snapshot -
  713. * @cpfile: inode of checkpoint file
  714. * @cno: checkpoint number
  715. *
  716. * Description:
  717. *
  718. * Return Value: On success, 1 is returned if the checkpoint specified by
  719. * @cno is a snapshot, or 0 if not. On error, one of the following negative
  720. * error codes is returned.
  721. *
  722. * %-EIO - I/O error.
  723. *
  724. * %-ENOMEM - Insufficient amount of memory available.
  725. *
  726. * %-ENOENT - No such checkpoint.
  727. */
  728. int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno)
  729. {
  730. struct buffer_head *bh;
  731. struct nilfs_checkpoint *cp;
  732. void *kaddr;
  733. int ret;
  734. /* CP number is invalid if it's zero or larger than the
  735. largest exist one.*/
  736. if (cno == 0 || cno >= nilfs_mdt_cno(cpfile))
  737. return -ENOENT;
  738. down_read(&NILFS_MDT(cpfile)->mi_sem);
  739. ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh);
  740. if (ret < 0)
  741. goto out;
  742. kaddr = kmap_atomic(bh->b_page);
  743. cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
  744. if (nilfs_checkpoint_invalid(cp))
  745. ret = -ENOENT;
  746. else
  747. ret = nilfs_checkpoint_snapshot(cp);
  748. kunmap_atomic(kaddr);
  749. brelse(bh);
  750. out:
  751. up_read(&NILFS_MDT(cpfile)->mi_sem);
  752. return ret;
  753. }
  754. /**
  755. * nilfs_cpfile_change_cpmode - change checkpoint mode
  756. * @cpfile: inode of checkpoint file
  757. * @cno: checkpoint number
  758. * @status: mode of checkpoint
  759. *
  760. * Description: nilfs_change_cpmode() changes the mode of the checkpoint
  761. * specified by @cno. The mode @mode is NILFS_CHECKPOINT or NILFS_SNAPSHOT.
  762. *
  763. * Return Value: On success, 0 is returned. On error, one of the following
  764. * negative error codes is returned.
  765. *
  766. * %-EIO - I/O error.
  767. *
  768. * %-ENOMEM - Insufficient amount of memory available.
  769. *
  770. * %-ENOENT - No such checkpoint.
  771. */
  772. int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode)
  773. {
  774. int ret;
  775. switch (mode) {
  776. case NILFS_CHECKPOINT:
  777. if (nilfs_checkpoint_is_mounted(cpfile->i_sb, cno))
  778. /*
  779. * Current implementation does not have to protect
  780. * plain read-only mounts since they are exclusive
  781. * with a read/write mount and are protected from the
  782. * cleaner.
  783. */
  784. ret = -EBUSY;
  785. else
  786. ret = nilfs_cpfile_clear_snapshot(cpfile, cno);
  787. return ret;
  788. case NILFS_SNAPSHOT:
  789. return nilfs_cpfile_set_snapshot(cpfile, cno);
  790. default:
  791. return -EINVAL;
  792. }
  793. }
  794. /**
  795. * nilfs_cpfile_get_stat - get checkpoint statistics
  796. * @cpfile: inode of checkpoint file
  797. * @stat: pointer to a structure of checkpoint statistics
  798. *
  799. * Description: nilfs_cpfile_get_stat() returns information about checkpoints.
  800. *
  801. * Return Value: On success, 0 is returned, and checkpoints information is
  802. * stored in the place pointed by @stat. On error, one of the following
  803. * negative error codes is returned.
  804. *
  805. * %-EIO - I/O error.
  806. *
  807. * %-ENOMEM - Insufficient amount of memory available.
  808. */
  809. int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat)
  810. {
  811. struct buffer_head *bh;
  812. struct nilfs_cpfile_header *header;
  813. void *kaddr;
  814. int ret;
  815. down_read(&NILFS_MDT(cpfile)->mi_sem);
  816. ret = nilfs_cpfile_get_header_block(cpfile, &bh);
  817. if (ret < 0)
  818. goto out_sem;
  819. kaddr = kmap_atomic(bh->b_page);
  820. header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr);
  821. cpstat->cs_cno = nilfs_mdt_cno(cpfile);
  822. cpstat->cs_ncps = le64_to_cpu(header->ch_ncheckpoints);
  823. cpstat->cs_nsss = le64_to_cpu(header->ch_nsnapshots);
  824. kunmap_atomic(kaddr);
  825. brelse(bh);
  826. out_sem:
  827. up_read(&NILFS_MDT(cpfile)->mi_sem);
  828. return ret;
  829. }
  830. /**
  831. * nilfs_cpfile_read - read or get cpfile inode
  832. * @sb: super block instance
  833. * @cpsize: size of a checkpoint entry
  834. * @raw_inode: on-disk cpfile inode
  835. * @inodep: buffer to store the inode
  836. */
  837. int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
  838. struct nilfs_inode *raw_inode, struct inode **inodep)
  839. {
  840. struct inode *cpfile;
  841. int err;
  842. cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO);
  843. if (unlikely(!cpfile))
  844. return -ENOMEM;
  845. if (!(cpfile->i_state & I_NEW))
  846. goto out;
  847. err = nilfs_mdt_init(cpfile, NILFS_MDT_GFP, 0);
  848. if (err)
  849. goto failed;
  850. nilfs_mdt_set_entry_size(cpfile, cpsize,
  851. sizeof(struct nilfs_cpfile_header));
  852. err = nilfs_read_inode_common(cpfile, raw_inode);
  853. if (err)
  854. goto failed;
  855. unlock_new_inode(cpfile);
  856. out:
  857. *inodep = cpfile;
  858. return 0;
  859. failed:
  860. iget_failed(cpfile);
  861. return err;
  862. }