cpfile.c 26 KB

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