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