cpfile.c 30 KB

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