cpfile.c 26 KB

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