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