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