sufile.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * NILFS segment usage file.
  4. *
  5. * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
  6. *
  7. * Written by Koji Sato.
  8. * Revised by Ryusuke Konishi.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/fs.h>
  12. #include <linux/string.h>
  13. #include <linux/buffer_head.h>
  14. #include <linux/errno.h>
  15. #include "mdt.h"
  16. #include "sufile.h"
  17. #include <trace/events/nilfs2.h>
  18. /**
  19. * struct nilfs_sufile_info - on-memory private data of sufile
  20. * @mi: on-memory private data of metadata file
  21. * @ncleansegs: number of clean segments
  22. * @allocmin: lower limit of allocatable segment range
  23. * @allocmax: upper limit of allocatable segment range
  24. */
  25. struct nilfs_sufile_info {
  26. struct nilfs_mdt_info mi;
  27. unsigned long ncleansegs;/* number of clean segments */
  28. __u64 allocmin; /* lower limit of allocatable segment range */
  29. __u64 allocmax; /* upper limit of allocatable segment range */
  30. };
  31. static inline struct nilfs_sufile_info *NILFS_SUI(struct inode *sufile)
  32. {
  33. return (struct nilfs_sufile_info *)NILFS_MDT(sufile);
  34. }
  35. static inline unsigned long
  36. nilfs_sufile_segment_usages_per_block(const struct inode *sufile)
  37. {
  38. return NILFS_MDT(sufile)->mi_entries_per_block;
  39. }
  40. static unsigned long
  41. nilfs_sufile_get_blkoff(const struct inode *sufile, __u64 segnum)
  42. {
  43. __u64 t = segnum + NILFS_MDT(sufile)->mi_first_entry_offset;
  44. t = div64_ul(t, nilfs_sufile_segment_usages_per_block(sufile));
  45. return (unsigned long)t;
  46. }
  47. static unsigned long
  48. nilfs_sufile_get_offset(const struct inode *sufile, __u64 segnum)
  49. {
  50. __u64 t = segnum + NILFS_MDT(sufile)->mi_first_entry_offset;
  51. return do_div(t, nilfs_sufile_segment_usages_per_block(sufile));
  52. }
  53. static unsigned long
  54. nilfs_sufile_segment_usages_in_block(const struct inode *sufile, __u64 curr,
  55. __u64 max)
  56. {
  57. return min_t(unsigned long,
  58. nilfs_sufile_segment_usages_per_block(sufile) -
  59. nilfs_sufile_get_offset(sufile, curr),
  60. max - curr + 1);
  61. }
  62. /**
  63. * nilfs_sufile_segment_usage_offset - calculate the byte offset of a segment
  64. * usage entry in the folio containing it
  65. * @sufile: segment usage file inode
  66. * @segnum: number of segment usage
  67. * @bh: buffer head of block containing segment usage indexed by @segnum
  68. *
  69. * Return: Byte offset in the folio of the segment usage entry.
  70. */
  71. static size_t nilfs_sufile_segment_usage_offset(const struct inode *sufile,
  72. __u64 segnum,
  73. struct buffer_head *bh)
  74. {
  75. return offset_in_folio(bh->b_folio, bh->b_data) +
  76. nilfs_sufile_get_offset(sufile, segnum) *
  77. NILFS_MDT(sufile)->mi_entry_size;
  78. }
  79. static int nilfs_sufile_get_header_block(struct inode *sufile,
  80. struct buffer_head **bhp)
  81. {
  82. int err = nilfs_mdt_get_block(sufile, 0, 0, NULL, bhp);
  83. if (unlikely(err == -ENOENT)) {
  84. nilfs_error(sufile->i_sb,
  85. "missing header block in segment usage metadata");
  86. err = -EIO;
  87. }
  88. return err;
  89. }
  90. static inline int
  91. nilfs_sufile_get_segment_usage_block(struct inode *sufile, __u64 segnum,
  92. int create, struct buffer_head **bhp)
  93. {
  94. return nilfs_mdt_get_block(sufile,
  95. nilfs_sufile_get_blkoff(sufile, segnum),
  96. create, NULL, bhp);
  97. }
  98. static int nilfs_sufile_delete_segment_usage_block(struct inode *sufile,
  99. __u64 segnum)
  100. {
  101. return nilfs_mdt_delete_block(sufile,
  102. nilfs_sufile_get_blkoff(sufile, segnum));
  103. }
  104. static void nilfs_sufile_mod_counter(struct buffer_head *header_bh,
  105. u64 ncleanadd, u64 ndirtyadd)
  106. {
  107. struct nilfs_sufile_header *header;
  108. header = kmap_local_folio(header_bh->b_folio, 0);
  109. le64_add_cpu(&header->sh_ncleansegs, ncleanadd);
  110. le64_add_cpu(&header->sh_ndirtysegs, ndirtyadd);
  111. kunmap_local(header);
  112. mark_buffer_dirty(header_bh);
  113. }
  114. /**
  115. * nilfs_sufile_get_ncleansegs - return the number of clean segments
  116. * @sufile: inode of segment usage file
  117. *
  118. * Return: Number of clean segments.
  119. */
  120. unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile)
  121. {
  122. return NILFS_SUI(sufile)->ncleansegs;
  123. }
  124. /**
  125. * nilfs_sufile_updatev - modify multiple segment usages at a time
  126. * @sufile: inode of segment usage file
  127. * @segnumv: array of segment numbers
  128. * @nsegs: size of @segnumv array
  129. * @create: creation flag
  130. * @ndone: place to store number of modified segments on @segnumv
  131. * @dofunc: primitive operation for the update
  132. *
  133. * Description: nilfs_sufile_updatev() repeatedly calls @dofunc
  134. * against the given array of segments. The @dofunc is called with
  135. * buffers of a header block and the sufile block in which the target
  136. * segment usage entry is contained. If @ndone is given, the number
  137. * of successfully modified segments from the head is stored in the
  138. * place @ndone points to.
  139. *
  140. * Return: 0 on success, or one of the following negative error codes on
  141. * failure:
  142. * * %-EINVAL - Invalid segment usage number
  143. * * %-EIO - I/O error (including metadata corruption).
  144. * * %-ENOENT - Given segment usage is in hole block (may be returned if
  145. * @create is zero)
  146. * * %-ENOMEM - Insufficient memory available.
  147. */
  148. int nilfs_sufile_updatev(struct inode *sufile, __u64 *segnumv, size_t nsegs,
  149. int create, size_t *ndone,
  150. void (*dofunc)(struct inode *, __u64,
  151. struct buffer_head *,
  152. struct buffer_head *))
  153. {
  154. struct buffer_head *header_bh, *bh;
  155. unsigned long blkoff, prev_blkoff;
  156. __u64 *seg;
  157. size_t nerr = 0, n = 0;
  158. int ret = 0;
  159. if (unlikely(nsegs == 0))
  160. goto out;
  161. down_write(&NILFS_MDT(sufile)->mi_sem);
  162. for (seg = segnumv; seg < segnumv + nsegs; seg++) {
  163. if (unlikely(*seg >= nilfs_sufile_get_nsegments(sufile))) {
  164. nilfs_warn(sufile->i_sb,
  165. "%s: invalid segment number: %llu",
  166. __func__, (unsigned long long)*seg);
  167. nerr++;
  168. }
  169. }
  170. if (nerr > 0) {
  171. ret = -EINVAL;
  172. goto out_sem;
  173. }
  174. ret = nilfs_sufile_get_header_block(sufile, &header_bh);
  175. if (ret < 0)
  176. goto out_sem;
  177. seg = segnumv;
  178. blkoff = nilfs_sufile_get_blkoff(sufile, *seg);
  179. ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh);
  180. if (ret < 0)
  181. goto out_header;
  182. for (;;) {
  183. dofunc(sufile, *seg, header_bh, bh);
  184. if (++seg >= segnumv + nsegs)
  185. break;
  186. prev_blkoff = blkoff;
  187. blkoff = nilfs_sufile_get_blkoff(sufile, *seg);
  188. if (blkoff == prev_blkoff)
  189. continue;
  190. /* get different block */
  191. brelse(bh);
  192. ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh);
  193. if (unlikely(ret < 0))
  194. goto out_header;
  195. }
  196. brelse(bh);
  197. out_header:
  198. n = seg - segnumv;
  199. brelse(header_bh);
  200. out_sem:
  201. up_write(&NILFS_MDT(sufile)->mi_sem);
  202. out:
  203. if (ndone)
  204. *ndone = n;
  205. return ret;
  206. }
  207. int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create,
  208. void (*dofunc)(struct inode *, __u64,
  209. struct buffer_head *,
  210. struct buffer_head *))
  211. {
  212. struct buffer_head *header_bh, *bh;
  213. int ret;
  214. if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) {
  215. nilfs_warn(sufile->i_sb, "%s: invalid segment number: %llu",
  216. __func__, (unsigned long long)segnum);
  217. return -EINVAL;
  218. }
  219. down_write(&NILFS_MDT(sufile)->mi_sem);
  220. ret = nilfs_sufile_get_header_block(sufile, &header_bh);
  221. if (ret < 0)
  222. goto out_sem;
  223. ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, create, &bh);
  224. if (!ret) {
  225. dofunc(sufile, segnum, header_bh, bh);
  226. brelse(bh);
  227. }
  228. brelse(header_bh);
  229. out_sem:
  230. up_write(&NILFS_MDT(sufile)->mi_sem);
  231. return ret;
  232. }
  233. /**
  234. * nilfs_sufile_set_alloc_range - limit range of segment to be allocated
  235. * @sufile: inode of segment usage file
  236. * @start: minimum segment number of allocatable region (inclusive)
  237. * @end: maximum segment number of allocatable region (inclusive)
  238. *
  239. * Return: 0 on success, or %-ERANGE if segment range is invalid.
  240. */
  241. int nilfs_sufile_set_alloc_range(struct inode *sufile, __u64 start, __u64 end)
  242. {
  243. struct nilfs_sufile_info *sui = NILFS_SUI(sufile);
  244. __u64 nsegs;
  245. int ret = -ERANGE;
  246. down_write(&NILFS_MDT(sufile)->mi_sem);
  247. nsegs = nilfs_sufile_get_nsegments(sufile);
  248. if (start <= end && end < nsegs) {
  249. sui->allocmin = start;
  250. sui->allocmax = end;
  251. ret = 0;
  252. }
  253. up_write(&NILFS_MDT(sufile)->mi_sem);
  254. return ret;
  255. }
  256. /**
  257. * nilfs_sufile_alloc - allocate a segment
  258. * @sufile: inode of segment usage file
  259. * @segnump: pointer to segment number
  260. *
  261. * Description: nilfs_sufile_alloc() allocates a clean segment, and stores
  262. * its segment number in the place pointed to by @segnump.
  263. *
  264. * Return: 0 on success, or one of the following negative error codes on
  265. * failure:
  266. * * %-EIO - I/O error (including metadata corruption).
  267. * * %-ENOMEM - Insufficient memory available.
  268. * * %-ENOSPC - No clean segment left.
  269. */
  270. int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
  271. {
  272. struct buffer_head *header_bh, *su_bh;
  273. struct nilfs_sufile_header *header;
  274. struct nilfs_segment_usage *su;
  275. struct nilfs_sufile_info *sui = NILFS_SUI(sufile);
  276. size_t susz = NILFS_MDT(sufile)->mi_entry_size;
  277. __u64 segnum, maxsegnum, last_alloc;
  278. size_t offset;
  279. void *kaddr;
  280. unsigned long nsegments, nsus, cnt;
  281. int ret, j;
  282. down_write(&NILFS_MDT(sufile)->mi_sem);
  283. ret = nilfs_sufile_get_header_block(sufile, &header_bh);
  284. if (ret < 0)
  285. goto out_sem;
  286. header = kmap_local_folio(header_bh->b_folio, 0);
  287. last_alloc = le64_to_cpu(header->sh_last_alloc);
  288. kunmap_local(header);
  289. nsegments = nilfs_sufile_get_nsegments(sufile);
  290. maxsegnum = sui->allocmax;
  291. segnum = last_alloc + 1;
  292. if (segnum < sui->allocmin || segnum > sui->allocmax)
  293. segnum = sui->allocmin;
  294. for (cnt = 0; cnt < nsegments; cnt += nsus) {
  295. if (segnum > maxsegnum) {
  296. if (cnt < sui->allocmax - sui->allocmin + 1) {
  297. /*
  298. * wrap around in the limited region.
  299. * if allocation started from
  300. * sui->allocmin, this never happens.
  301. */
  302. segnum = sui->allocmin;
  303. maxsegnum = last_alloc;
  304. } else if (segnum > sui->allocmin &&
  305. sui->allocmax + 1 < nsegments) {
  306. segnum = sui->allocmax + 1;
  307. maxsegnum = nsegments - 1;
  308. } else if (sui->allocmin > 0) {
  309. segnum = 0;
  310. maxsegnum = sui->allocmin - 1;
  311. } else {
  312. break; /* never happens */
  313. }
  314. }
  315. trace_nilfs2_segment_usage_check(sufile, segnum, cnt);
  316. ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 1,
  317. &su_bh);
  318. if (ret < 0)
  319. goto out_header;
  320. offset = nilfs_sufile_segment_usage_offset(sufile, segnum,
  321. su_bh);
  322. su = kaddr = kmap_local_folio(su_bh->b_folio, offset);
  323. nsus = nilfs_sufile_segment_usages_in_block(
  324. sufile, segnum, maxsegnum);
  325. for (j = 0; j < nsus; j++, su = (void *)su + susz, segnum++) {
  326. if (!nilfs_segment_usage_clean(su))
  327. continue;
  328. /* found a clean segment */
  329. nilfs_segment_usage_set_dirty(su);
  330. kunmap_local(kaddr);
  331. header = kmap_local_folio(header_bh->b_folio, 0);
  332. le64_add_cpu(&header->sh_ncleansegs, -1);
  333. le64_add_cpu(&header->sh_ndirtysegs, 1);
  334. header->sh_last_alloc = cpu_to_le64(segnum);
  335. kunmap_local(header);
  336. sui->ncleansegs--;
  337. mark_buffer_dirty(header_bh);
  338. mark_buffer_dirty(su_bh);
  339. nilfs_mdt_mark_dirty(sufile);
  340. brelse(su_bh);
  341. *segnump = segnum;
  342. trace_nilfs2_segment_usage_allocated(sufile, segnum);
  343. goto out_header;
  344. }
  345. kunmap_local(kaddr);
  346. brelse(su_bh);
  347. }
  348. /* no segments left */
  349. ret = -ENOSPC;
  350. out_header:
  351. brelse(header_bh);
  352. out_sem:
  353. up_write(&NILFS_MDT(sufile)->mi_sem);
  354. return ret;
  355. }
  356. void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum,
  357. struct buffer_head *header_bh,
  358. struct buffer_head *su_bh)
  359. {
  360. struct nilfs_segment_usage *su;
  361. size_t offset;
  362. offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh);
  363. su = kmap_local_folio(su_bh->b_folio, offset);
  364. if (unlikely(!nilfs_segment_usage_clean(su))) {
  365. nilfs_warn(sufile->i_sb, "%s: segment %llu must be clean",
  366. __func__, (unsigned long long)segnum);
  367. kunmap_local(su);
  368. return;
  369. }
  370. nilfs_segment_usage_set_dirty(su);
  371. kunmap_local(su);
  372. nilfs_sufile_mod_counter(header_bh, -1, 1);
  373. NILFS_SUI(sufile)->ncleansegs--;
  374. mark_buffer_dirty(su_bh);
  375. nilfs_mdt_mark_dirty(sufile);
  376. }
  377. void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum,
  378. struct buffer_head *header_bh,
  379. struct buffer_head *su_bh)
  380. {
  381. struct nilfs_segment_usage *su;
  382. size_t offset;
  383. int clean, dirty;
  384. offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh);
  385. su = kmap_local_folio(su_bh->b_folio, offset);
  386. if (su->su_flags == cpu_to_le32(BIT(NILFS_SEGMENT_USAGE_DIRTY)) &&
  387. su->su_nblocks == cpu_to_le32(0)) {
  388. kunmap_local(su);
  389. return;
  390. }
  391. clean = nilfs_segment_usage_clean(su);
  392. dirty = nilfs_segment_usage_dirty(su);
  393. /* make the segment garbage */
  394. su->su_lastmod = cpu_to_le64(0);
  395. su->su_nblocks = cpu_to_le32(0);
  396. su->su_flags = cpu_to_le32(BIT(NILFS_SEGMENT_USAGE_DIRTY));
  397. kunmap_local(su);
  398. nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1);
  399. NILFS_SUI(sufile)->ncleansegs -= clean;
  400. mark_buffer_dirty(su_bh);
  401. nilfs_mdt_mark_dirty(sufile);
  402. }
  403. void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum,
  404. struct buffer_head *header_bh,
  405. struct buffer_head *su_bh)
  406. {
  407. struct nilfs_segment_usage *su;
  408. size_t offset;
  409. int sudirty;
  410. offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh);
  411. su = kmap_local_folio(su_bh->b_folio, offset);
  412. if (nilfs_segment_usage_clean(su)) {
  413. nilfs_warn(sufile->i_sb, "%s: segment %llu is already clean",
  414. __func__, (unsigned long long)segnum);
  415. kunmap_local(su);
  416. return;
  417. }
  418. if (unlikely(nilfs_segment_usage_error(su)))
  419. nilfs_warn(sufile->i_sb, "free segment %llu marked in error",
  420. (unsigned long long)segnum);
  421. sudirty = nilfs_segment_usage_dirty(su);
  422. if (unlikely(!sudirty))
  423. nilfs_warn(sufile->i_sb, "free unallocated segment %llu",
  424. (unsigned long long)segnum);
  425. nilfs_segment_usage_set_clean(su);
  426. kunmap_local(su);
  427. mark_buffer_dirty(su_bh);
  428. nilfs_sufile_mod_counter(header_bh, 1, sudirty ? (u64)-1 : 0);
  429. NILFS_SUI(sufile)->ncleansegs++;
  430. nilfs_mdt_mark_dirty(sufile);
  431. trace_nilfs2_segment_usage_freed(sufile, segnum);
  432. }
  433. /**
  434. * nilfs_sufile_mark_dirty - mark the buffer having a segment usage dirty
  435. * @sufile: inode of segment usage file
  436. * @segnum: segment number
  437. *
  438. * Return: 0 on success, or a negative error code on failure.
  439. */
  440. int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum)
  441. {
  442. struct buffer_head *bh;
  443. size_t offset;
  444. struct nilfs_segment_usage *su;
  445. int ret;
  446. down_write(&NILFS_MDT(sufile)->mi_sem);
  447. ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh);
  448. if (unlikely(ret)) {
  449. if (ret == -ENOENT) {
  450. nilfs_error(sufile->i_sb,
  451. "segment usage for segment %llu is unreadable due to a hole block",
  452. (unsigned long long)segnum);
  453. ret = -EIO;
  454. }
  455. goto out_sem;
  456. }
  457. offset = nilfs_sufile_segment_usage_offset(sufile, segnum, bh);
  458. su = kmap_local_folio(bh->b_folio, offset);
  459. if (unlikely(nilfs_segment_usage_error(su))) {
  460. struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
  461. kunmap_local(su);
  462. brelse(bh);
  463. if (nilfs_segment_is_active(nilfs, segnum)) {
  464. nilfs_error(sufile->i_sb,
  465. "active segment %llu is erroneous",
  466. (unsigned long long)segnum);
  467. } else {
  468. /*
  469. * Segments marked erroneous are never allocated by
  470. * nilfs_sufile_alloc(); only active segments, ie,
  471. * the segments indexed by ns_segnum or ns_nextnum,
  472. * can be erroneous here.
  473. */
  474. WARN_ON_ONCE(1);
  475. }
  476. ret = -EIO;
  477. } else {
  478. nilfs_segment_usage_set_dirty(su);
  479. kunmap_local(su);
  480. mark_buffer_dirty(bh);
  481. nilfs_mdt_mark_dirty(sufile);
  482. brelse(bh);
  483. }
  484. out_sem:
  485. up_write(&NILFS_MDT(sufile)->mi_sem);
  486. return ret;
  487. }
  488. /**
  489. * nilfs_sufile_set_segment_usage - set usage of a segment
  490. * @sufile: inode of segment usage file
  491. * @segnum: segment number
  492. * @nblocks: number of live blocks in the segment
  493. * @modtime: modification time (option)
  494. *
  495. * Return: 0 on success, or a negative error code on failure.
  496. */
  497. int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
  498. unsigned long nblocks, time64_t modtime)
  499. {
  500. struct buffer_head *bh;
  501. struct nilfs_segment_usage *su;
  502. size_t offset;
  503. int ret;
  504. down_write(&NILFS_MDT(sufile)->mi_sem);
  505. ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh);
  506. if (ret < 0)
  507. goto out_sem;
  508. offset = nilfs_sufile_segment_usage_offset(sufile, segnum, bh);
  509. su = kmap_local_folio(bh->b_folio, offset);
  510. if (modtime) {
  511. /*
  512. * Check segusage error and set su_lastmod only when updating
  513. * this entry with a valid timestamp, not for cancellation.
  514. */
  515. WARN_ON_ONCE(nilfs_segment_usage_error(su));
  516. su->su_lastmod = cpu_to_le64(modtime);
  517. }
  518. su->su_nblocks = cpu_to_le32(nblocks);
  519. kunmap_local(su);
  520. mark_buffer_dirty(bh);
  521. nilfs_mdt_mark_dirty(sufile);
  522. brelse(bh);
  523. out_sem:
  524. up_write(&NILFS_MDT(sufile)->mi_sem);
  525. return ret;
  526. }
  527. /**
  528. * nilfs_sufile_get_stat - get segment usage statistics
  529. * @sufile: inode of segment usage file
  530. * @sustat: pointer to a structure of segment usage statistics
  531. *
  532. * Description: nilfs_sufile_get_stat() retrieves segment usage statistics
  533. * and stores them in the location pointed to by @sustat.
  534. *
  535. * Return: 0 on success, or one of the following negative error codes on
  536. * failure:
  537. * * %-EIO - I/O error (including metadata corruption).
  538. * * %-ENOMEM - Insufficient memory available.
  539. */
  540. int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
  541. {
  542. struct buffer_head *header_bh;
  543. struct nilfs_sufile_header *header;
  544. struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
  545. int ret;
  546. down_read(&NILFS_MDT(sufile)->mi_sem);
  547. ret = nilfs_sufile_get_header_block(sufile, &header_bh);
  548. if (ret < 0)
  549. goto out_sem;
  550. header = kmap_local_folio(header_bh->b_folio, 0);
  551. sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile);
  552. sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs);
  553. sustat->ss_ndirtysegs = le64_to_cpu(header->sh_ndirtysegs);
  554. sustat->ss_ctime = nilfs->ns_ctime;
  555. sustat->ss_nongc_ctime = nilfs->ns_nongc_ctime;
  556. spin_lock(&nilfs->ns_last_segment_lock);
  557. sustat->ss_prot_seq = nilfs->ns_prot_seq;
  558. spin_unlock(&nilfs->ns_last_segment_lock);
  559. kunmap_local(header);
  560. brelse(header_bh);
  561. out_sem:
  562. up_read(&NILFS_MDT(sufile)->mi_sem);
  563. return ret;
  564. }
  565. void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum,
  566. struct buffer_head *header_bh,
  567. struct buffer_head *su_bh)
  568. {
  569. struct nilfs_segment_usage *su;
  570. size_t offset;
  571. int suclean;
  572. offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh);
  573. su = kmap_local_folio(su_bh->b_folio, offset);
  574. if (nilfs_segment_usage_error(su)) {
  575. kunmap_local(su);
  576. return;
  577. }
  578. suclean = nilfs_segment_usage_clean(su);
  579. nilfs_segment_usage_set_error(su);
  580. kunmap_local(su);
  581. if (suclean) {
  582. nilfs_sufile_mod_counter(header_bh, -1, 0);
  583. NILFS_SUI(sufile)->ncleansegs--;
  584. }
  585. mark_buffer_dirty(su_bh);
  586. nilfs_mdt_mark_dirty(sufile);
  587. }
  588. /**
  589. * nilfs_sufile_truncate_range - truncate range of segment array
  590. * @sufile: inode of segment usage file
  591. * @start: start segment number (inclusive)
  592. * @end: end segment number (inclusive)
  593. *
  594. * Return: 0 on success, or one of the following negative error codes on
  595. * failure:
  596. * * %-EBUSY - Dirty or active segments are present in the range.
  597. * * %-EINVAL - Invalid number of segments specified.
  598. * * %-EIO - I/O error (including metadata corruption).
  599. * * %-ENOMEM - Insufficient memory available.
  600. */
  601. static int nilfs_sufile_truncate_range(struct inode *sufile,
  602. __u64 start, __u64 end)
  603. {
  604. struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
  605. struct buffer_head *header_bh;
  606. struct buffer_head *su_bh;
  607. struct nilfs_segment_usage *su, *su2;
  608. size_t susz = NILFS_MDT(sufile)->mi_entry_size;
  609. unsigned long segusages_per_block;
  610. unsigned long nsegs, ncleaned;
  611. __u64 segnum;
  612. size_t offset;
  613. ssize_t n, nc;
  614. int ret;
  615. int j;
  616. nsegs = nilfs_sufile_get_nsegments(sufile);
  617. ret = -EINVAL;
  618. if (start > end || start >= nsegs)
  619. goto out;
  620. ret = nilfs_sufile_get_header_block(sufile, &header_bh);
  621. if (ret < 0)
  622. goto out;
  623. segusages_per_block = nilfs_sufile_segment_usages_per_block(sufile);
  624. ncleaned = 0;
  625. for (segnum = start; segnum <= end; segnum += n) {
  626. n = min_t(unsigned long,
  627. segusages_per_block -
  628. nilfs_sufile_get_offset(sufile, segnum),
  629. end - segnum + 1);
  630. ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0,
  631. &su_bh);
  632. if (ret < 0) {
  633. if (ret != -ENOENT)
  634. goto out_header;
  635. /* hole */
  636. continue;
  637. }
  638. offset = nilfs_sufile_segment_usage_offset(sufile, segnum,
  639. su_bh);
  640. su = kmap_local_folio(su_bh->b_folio, offset);
  641. su2 = su;
  642. for (j = 0; j < n; j++, su = (void *)su + susz) {
  643. if ((le32_to_cpu(su->su_flags) &
  644. ~BIT(NILFS_SEGMENT_USAGE_ERROR)) ||
  645. nilfs_segment_is_active(nilfs, segnum + j)) {
  646. ret = -EBUSY;
  647. kunmap_local(su2);
  648. brelse(su_bh);
  649. goto out_header;
  650. }
  651. }
  652. nc = 0;
  653. for (su = su2, j = 0; j < n; j++, su = (void *)su + susz) {
  654. if (nilfs_segment_usage_error(su)) {
  655. nilfs_segment_usage_set_clean(su);
  656. nc++;
  657. }
  658. }
  659. kunmap_local(su2);
  660. if (nc > 0) {
  661. mark_buffer_dirty(su_bh);
  662. ncleaned += nc;
  663. }
  664. brelse(su_bh);
  665. if (n == segusages_per_block) {
  666. /* make hole */
  667. nilfs_sufile_delete_segment_usage_block(sufile, segnum);
  668. }
  669. }
  670. ret = 0;
  671. out_header:
  672. if (ncleaned > 0) {
  673. NILFS_SUI(sufile)->ncleansegs += ncleaned;
  674. nilfs_sufile_mod_counter(header_bh, ncleaned, 0);
  675. nilfs_mdt_mark_dirty(sufile);
  676. }
  677. brelse(header_bh);
  678. out:
  679. return ret;
  680. }
  681. /**
  682. * nilfs_sufile_resize - resize segment array
  683. * @sufile: inode of segment usage file
  684. * @newnsegs: new number of segments
  685. *
  686. * Return: 0 on success, or one of the following negative error codes on
  687. * failure:
  688. * * %-EBUSY - Dirty or active segments exist in the region to be truncated.
  689. * * %-EIO - I/O error (including metadata corruption).
  690. * * %-ENOMEM - Insufficient memory available.
  691. * * %-ENOSPC - Enough free space is not left for shrinking.
  692. */
  693. int nilfs_sufile_resize(struct inode *sufile, __u64 newnsegs)
  694. {
  695. struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
  696. struct buffer_head *header_bh;
  697. struct nilfs_sufile_header *header;
  698. struct nilfs_sufile_info *sui = NILFS_SUI(sufile);
  699. unsigned long nsegs, nrsvsegs;
  700. int ret = 0;
  701. down_write(&NILFS_MDT(sufile)->mi_sem);
  702. nsegs = nilfs_sufile_get_nsegments(sufile);
  703. if (nsegs == newnsegs)
  704. goto out;
  705. ret = -ENOSPC;
  706. nrsvsegs = nilfs_nrsvsegs(nilfs, newnsegs);
  707. if (newnsegs < nsegs && nsegs - newnsegs + nrsvsegs > sui->ncleansegs)
  708. goto out;
  709. ret = nilfs_sufile_get_header_block(sufile, &header_bh);
  710. if (ret < 0)
  711. goto out;
  712. if (newnsegs > nsegs) {
  713. sui->ncleansegs += newnsegs - nsegs;
  714. } else /* newnsegs < nsegs */ {
  715. ret = nilfs_sufile_truncate_range(sufile, newnsegs, nsegs - 1);
  716. if (ret < 0)
  717. goto out_header;
  718. sui->ncleansegs -= nsegs - newnsegs;
  719. /*
  720. * If the sufile is successfully truncated, immediately adjust
  721. * the segment allocation space while locking the semaphore
  722. * "mi_sem" so that nilfs_sufile_alloc() never allocates
  723. * segments in the truncated space.
  724. */
  725. sui->allocmax = newnsegs - 1;
  726. sui->allocmin = 0;
  727. }
  728. header = kmap_local_folio(header_bh->b_folio, 0);
  729. header->sh_ncleansegs = cpu_to_le64(sui->ncleansegs);
  730. kunmap_local(header);
  731. mark_buffer_dirty(header_bh);
  732. nilfs_mdt_mark_dirty(sufile);
  733. nilfs_set_nsegments(nilfs, newnsegs);
  734. out_header:
  735. brelse(header_bh);
  736. out:
  737. up_write(&NILFS_MDT(sufile)->mi_sem);
  738. return ret;
  739. }
  740. /**
  741. * nilfs_sufile_get_suinfo - get segment usage information
  742. * @sufile: inode of segment usage file
  743. * @segnum: segment number to start looking
  744. * @buf: array of suinfo
  745. * @sisz: byte size of suinfo
  746. * @nsi: size of suinfo array
  747. *
  748. * Return: Count of segment usage info items stored in the output buffer on
  749. * success, or one of the following negative error codes on failure:
  750. * * %-EIO - I/O error (including metadata corruption).
  751. * * %-ENOMEM - Insufficient memory available.
  752. */
  753. ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
  754. unsigned int sisz, size_t nsi)
  755. {
  756. struct buffer_head *su_bh;
  757. struct nilfs_segment_usage *su;
  758. struct nilfs_suinfo *si = buf;
  759. size_t susz = NILFS_MDT(sufile)->mi_entry_size;
  760. struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
  761. size_t offset;
  762. void *kaddr;
  763. unsigned long nsegs, segusages_per_block;
  764. ssize_t n;
  765. int ret, i, j;
  766. down_read(&NILFS_MDT(sufile)->mi_sem);
  767. segusages_per_block = nilfs_sufile_segment_usages_per_block(sufile);
  768. nsegs = min_t(unsigned long,
  769. nilfs_sufile_get_nsegments(sufile) - segnum,
  770. nsi);
  771. for (i = 0; i < nsegs; i += n, segnum += n) {
  772. n = min_t(unsigned long,
  773. segusages_per_block -
  774. nilfs_sufile_get_offset(sufile, segnum),
  775. nsegs - i);
  776. ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0,
  777. &su_bh);
  778. if (ret < 0) {
  779. if (ret != -ENOENT)
  780. goto out;
  781. /* hole */
  782. memset(si, 0, sisz * n);
  783. si = (void *)si + sisz * n;
  784. continue;
  785. }
  786. offset = nilfs_sufile_segment_usage_offset(sufile, segnum,
  787. su_bh);
  788. su = kaddr = kmap_local_folio(su_bh->b_folio, offset);
  789. for (j = 0; j < n;
  790. j++, su = (void *)su + susz, si = (void *)si + sisz) {
  791. si->sui_lastmod = le64_to_cpu(su->su_lastmod);
  792. si->sui_nblocks = le32_to_cpu(su->su_nblocks);
  793. si->sui_flags = le32_to_cpu(su->su_flags) &
  794. ~BIT(NILFS_SEGMENT_USAGE_ACTIVE);
  795. if (nilfs_segment_is_active(nilfs, segnum + j))
  796. si->sui_flags |=
  797. BIT(NILFS_SEGMENT_USAGE_ACTIVE);
  798. }
  799. kunmap_local(kaddr);
  800. brelse(su_bh);
  801. }
  802. ret = nsegs;
  803. out:
  804. up_read(&NILFS_MDT(sufile)->mi_sem);
  805. return ret;
  806. }
  807. /**
  808. * nilfs_sufile_set_suinfo - sets segment usage info
  809. * @sufile: inode of segment usage file
  810. * @buf: array of suinfo_update
  811. * @supsz: byte size of suinfo_update
  812. * @nsup: size of suinfo_update array
  813. *
  814. * Description: Takes an array of nilfs_suinfo_update structs and updates
  815. * segment usage accordingly. Only the fields indicated by the sup_flags
  816. * are updated.
  817. *
  818. * Return: 0 on success, or one of the following negative error codes on
  819. * failure:
  820. * * %-EINVAL - Invalid values in input (segment number, flags or nblocks).
  821. * * %-EIO - I/O error (including metadata corruption).
  822. * * %-ENOMEM - Insufficient memory available.
  823. */
  824. ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf,
  825. unsigned int supsz, size_t nsup)
  826. {
  827. struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
  828. struct buffer_head *header_bh, *bh;
  829. struct nilfs_suinfo_update *sup, *supend = buf + supsz * nsup;
  830. struct nilfs_segment_usage *su;
  831. size_t offset;
  832. unsigned long blkoff, prev_blkoff;
  833. int cleansi, cleansu, dirtysi, dirtysu;
  834. long ncleaned = 0, ndirtied = 0;
  835. int ret = 0;
  836. if (unlikely(nsup == 0))
  837. return ret;
  838. for (sup = buf; sup < supend; sup = (void *)sup + supsz) {
  839. if (sup->sup_segnum >= nilfs->ns_nsegments
  840. || (sup->sup_flags &
  841. (~0UL << __NR_NILFS_SUINFO_UPDATE_FIELDS))
  842. || (nilfs_suinfo_update_nblocks(sup) &&
  843. sup->sup_sui.sui_nblocks >
  844. nilfs->ns_blocks_per_segment))
  845. return -EINVAL;
  846. }
  847. down_write(&NILFS_MDT(sufile)->mi_sem);
  848. ret = nilfs_sufile_get_header_block(sufile, &header_bh);
  849. if (ret < 0)
  850. goto out_sem;
  851. sup = buf;
  852. blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
  853. ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
  854. if (ret < 0)
  855. goto out_header;
  856. for (;;) {
  857. offset = nilfs_sufile_segment_usage_offset(
  858. sufile, sup->sup_segnum, bh);
  859. su = kmap_local_folio(bh->b_folio, offset);
  860. if (nilfs_suinfo_update_lastmod(sup))
  861. su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod);
  862. if (nilfs_suinfo_update_nblocks(sup))
  863. su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks);
  864. if (nilfs_suinfo_update_flags(sup)) {
  865. /*
  866. * Active flag is a virtual flag projected by running
  867. * nilfs kernel code - drop it not to write it to
  868. * disk.
  869. */
  870. sup->sup_sui.sui_flags &=
  871. ~BIT(NILFS_SEGMENT_USAGE_ACTIVE);
  872. cleansi = nilfs_suinfo_clean(&sup->sup_sui);
  873. cleansu = nilfs_segment_usage_clean(su);
  874. dirtysi = nilfs_suinfo_dirty(&sup->sup_sui);
  875. dirtysu = nilfs_segment_usage_dirty(su);
  876. if (cleansi && !cleansu)
  877. ++ncleaned;
  878. else if (!cleansi && cleansu)
  879. --ncleaned;
  880. if (dirtysi && !dirtysu)
  881. ++ndirtied;
  882. else if (!dirtysi && dirtysu)
  883. --ndirtied;
  884. su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags);
  885. }
  886. kunmap_local(su);
  887. sup = (void *)sup + supsz;
  888. if (sup >= supend)
  889. break;
  890. prev_blkoff = blkoff;
  891. blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
  892. if (blkoff == prev_blkoff)
  893. continue;
  894. /* get different block */
  895. mark_buffer_dirty(bh);
  896. put_bh(bh);
  897. ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
  898. if (unlikely(ret < 0))
  899. goto out_mark;
  900. }
  901. mark_buffer_dirty(bh);
  902. put_bh(bh);
  903. out_mark:
  904. if (ncleaned || ndirtied) {
  905. nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
  906. (u64)ndirtied);
  907. NILFS_SUI(sufile)->ncleansegs += ncleaned;
  908. }
  909. nilfs_mdt_mark_dirty(sufile);
  910. out_header:
  911. put_bh(header_bh);
  912. out_sem:
  913. up_write(&NILFS_MDT(sufile)->mi_sem);
  914. return ret;
  915. }
  916. /**
  917. * nilfs_sufile_trim_fs() - trim ioctl handle function
  918. * @sufile: inode of segment usage file
  919. * @range: fstrim_range structure
  920. *
  921. * start: First Byte to trim
  922. * len: number of Bytes to trim from start
  923. * minlen: minimum extent length in Bytes
  924. *
  925. * Decription: nilfs_sufile_trim_fs goes through all segments containing bytes
  926. * from start to start+len. start is rounded up to the next block boundary
  927. * and start+len is rounded down. For each clean segment blkdev_issue_discard
  928. * function is invoked.
  929. *
  930. * Return: 0 on success, or a negative error code on failure.
  931. */
  932. int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range)
  933. {
  934. struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
  935. struct buffer_head *su_bh;
  936. struct nilfs_segment_usage *su;
  937. size_t offset;
  938. void *kaddr;
  939. size_t n, i, susz = NILFS_MDT(sufile)->mi_entry_size;
  940. sector_t seg_start, seg_end, start_block, end_block;
  941. sector_t start = 0, nblocks = 0;
  942. u64 segnum, segnum_end, minlen, len, max_blocks, ndiscarded = 0;
  943. int ret = 0;
  944. unsigned int sects_per_block;
  945. sects_per_block = (1 << nilfs->ns_blocksize_bits) /
  946. bdev_logical_block_size(nilfs->ns_bdev);
  947. len = range->len >> nilfs->ns_blocksize_bits;
  948. minlen = range->minlen >> nilfs->ns_blocksize_bits;
  949. max_blocks = ((u64)nilfs->ns_nsegments * nilfs->ns_blocks_per_segment);
  950. if (!len || range->start >= max_blocks << nilfs->ns_blocksize_bits)
  951. return -EINVAL;
  952. start_block = (range->start + nilfs->ns_blocksize - 1) >>
  953. nilfs->ns_blocksize_bits;
  954. /*
  955. * range->len can be very large (actually, it is set to
  956. * ULLONG_MAX by default) - truncate upper end of the range
  957. * carefully so as not to overflow.
  958. */
  959. if (max_blocks - start_block < len)
  960. end_block = max_blocks - 1;
  961. else
  962. end_block = start_block + len - 1;
  963. if (end_block < nilfs->ns_first_data_block)
  964. goto out;
  965. segnum = nilfs_get_segnum_of_block(nilfs, start_block);
  966. segnum_end = nilfs_get_segnum_of_block(nilfs, end_block);
  967. down_read(&NILFS_MDT(sufile)->mi_sem);
  968. while (segnum <= segnum_end) {
  969. n = nilfs_sufile_segment_usages_in_block(sufile, segnum,
  970. segnum_end);
  971. ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0,
  972. &su_bh);
  973. if (ret < 0) {
  974. if (ret != -ENOENT)
  975. goto out_sem;
  976. /* hole */
  977. segnum += n;
  978. continue;
  979. }
  980. offset = nilfs_sufile_segment_usage_offset(sufile, segnum,
  981. su_bh);
  982. su = kaddr = kmap_local_folio(su_bh->b_folio, offset);
  983. for (i = 0; i < n; ++i, ++segnum, su = (void *)su + susz) {
  984. if (!nilfs_segment_usage_clean(su))
  985. continue;
  986. nilfs_get_segment_range(nilfs, segnum, &seg_start,
  987. &seg_end);
  988. if (!nblocks) {
  989. /* start new extent */
  990. start = seg_start;
  991. nblocks = seg_end - seg_start + 1;
  992. continue;
  993. }
  994. if (start + nblocks == seg_start) {
  995. /* add to previous extent */
  996. nblocks += seg_end - seg_start + 1;
  997. continue;
  998. }
  999. /* discard previous extent */
  1000. if (start < start_block) {
  1001. nblocks -= start_block - start;
  1002. start = start_block;
  1003. }
  1004. if (nblocks >= minlen) {
  1005. kunmap_local(kaddr);
  1006. ret = blkdev_issue_discard(nilfs->ns_bdev,
  1007. start * sects_per_block,
  1008. nblocks * sects_per_block,
  1009. GFP_NOFS);
  1010. if (ret < 0) {
  1011. put_bh(su_bh);
  1012. goto out_sem;
  1013. }
  1014. ndiscarded += nblocks;
  1015. offset = nilfs_sufile_segment_usage_offset(
  1016. sufile, segnum, su_bh);
  1017. su = kaddr = kmap_local_folio(su_bh->b_folio,
  1018. offset);
  1019. }
  1020. /* start new extent */
  1021. start = seg_start;
  1022. nblocks = seg_end - seg_start + 1;
  1023. }
  1024. kunmap_local(kaddr);
  1025. put_bh(su_bh);
  1026. }
  1027. if (nblocks) {
  1028. /* discard last extent */
  1029. if (start < start_block) {
  1030. nblocks -= start_block - start;
  1031. start = start_block;
  1032. }
  1033. if (start + nblocks > end_block + 1)
  1034. nblocks = end_block - start + 1;
  1035. if (nblocks >= minlen) {
  1036. ret = blkdev_issue_discard(nilfs->ns_bdev,
  1037. start * sects_per_block,
  1038. nblocks * sects_per_block,
  1039. GFP_NOFS);
  1040. if (!ret)
  1041. ndiscarded += nblocks;
  1042. }
  1043. }
  1044. out_sem:
  1045. up_read(&NILFS_MDT(sufile)->mi_sem);
  1046. out:
  1047. range->len = ndiscarded << nilfs->ns_blocksize_bits;
  1048. return ret;
  1049. }
  1050. /**
  1051. * nilfs_sufile_read - read or get sufile inode
  1052. * @sb: super block instance
  1053. * @susize: size of a segment usage entry
  1054. * @raw_inode: on-disk sufile inode
  1055. * @inodep: buffer to store the inode
  1056. *
  1057. * Return: 0 on success, or a negative error code on failure.
  1058. */
  1059. int nilfs_sufile_read(struct super_block *sb, size_t susize,
  1060. struct nilfs_inode *raw_inode, struct inode **inodep)
  1061. {
  1062. struct inode *sufile;
  1063. struct nilfs_sufile_info *sui;
  1064. struct buffer_head *header_bh;
  1065. struct nilfs_sufile_header *header;
  1066. int err;
  1067. if (susize > sb->s_blocksize) {
  1068. nilfs_err(sb, "too large segment usage size: %zu bytes",
  1069. susize);
  1070. return -EINVAL;
  1071. } else if (susize < NILFS_MIN_SEGMENT_USAGE_SIZE) {
  1072. nilfs_err(sb, "too small segment usage size: %zu bytes",
  1073. susize);
  1074. return -EINVAL;
  1075. }
  1076. sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO);
  1077. if (unlikely(!sufile))
  1078. return -ENOMEM;
  1079. if (!(inode_state_read_once(sufile) & I_NEW))
  1080. goto out;
  1081. err = nilfs_mdt_init(sufile, NILFS_MDT_GFP, sizeof(*sui));
  1082. if (err)
  1083. goto failed;
  1084. nilfs_mdt_set_entry_size(sufile, susize,
  1085. sizeof(struct nilfs_sufile_header));
  1086. err = nilfs_read_inode_common(sufile, raw_inode);
  1087. if (err)
  1088. goto failed;
  1089. err = nilfs_mdt_get_block(sufile, 0, 0, NULL, &header_bh);
  1090. if (unlikely(err)) {
  1091. if (err == -ENOENT) {
  1092. nilfs_err(sb,
  1093. "missing header block in segment usage metadata");
  1094. err = -EINVAL;
  1095. }
  1096. goto failed;
  1097. }
  1098. sui = NILFS_SUI(sufile);
  1099. header = kmap_local_folio(header_bh->b_folio, 0);
  1100. sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
  1101. kunmap_local(header);
  1102. brelse(header_bh);
  1103. sui->allocmax = nilfs_sufile_get_nsegments(sufile) - 1;
  1104. sui->allocmin = 0;
  1105. unlock_new_inode(sufile);
  1106. out:
  1107. *inodep = sufile;
  1108. return 0;
  1109. failed:
  1110. iget_failed(sufile);
  1111. return err;
  1112. }