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