// SPDX-License-Identifier: GPL-2.0+ /* * NILFS checkpoint file. * * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. * * Written by Koji Sato. */ #include <linux/kernel.h> #include <linux/fs.h> #include <linux/string.h> #include <linux/buffer_head.h> #include <linux/errno.h> #include "mdt.h" #include "cpfile.h" static inline unsigned long nilfs_cpfile_checkpoints_per_block(const struct inode *cpfile) { … } /* block number from the beginning of the file */ static unsigned long nilfs_cpfile_get_blkoff(const struct inode *cpfile, __u64 cno) { … } /* offset in block */ static unsigned long nilfs_cpfile_get_offset(const struct inode *cpfile, __u64 cno) { … } static __u64 nilfs_cpfile_first_checkpoint_in_block(const struct inode *cpfile, unsigned long blkoff) { … } static unsigned long nilfs_cpfile_checkpoints_in_block(const struct inode *cpfile, __u64 curr, __u64 max) { … } static inline int nilfs_cpfile_is_in_first(const struct inode *cpfile, __u64 cno) { … } static unsigned int nilfs_cpfile_block_add_valid_checkpoints(const struct inode *cpfile, struct buffer_head *bh, void *kaddr, unsigned int n) { … } static unsigned int nilfs_cpfile_block_sub_valid_checkpoints(const struct inode *cpfile, struct buffer_head *bh, void *kaddr, unsigned int n) { … } static inline struct nilfs_cpfile_header * nilfs_cpfile_block_get_header(const struct inode *cpfile, struct buffer_head *bh, void *kaddr) { … } static struct nilfs_checkpoint * nilfs_cpfile_block_get_checkpoint(const struct inode *cpfile, __u64 cno, struct buffer_head *bh, void *kaddr) { … } static void nilfs_cpfile_block_init(struct inode *cpfile, struct buffer_head *bh, void *kaddr) { … } static inline int nilfs_cpfile_get_header_block(struct inode *cpfile, struct buffer_head **bhp) { … } static inline int nilfs_cpfile_get_checkpoint_block(struct inode *cpfile, __u64 cno, int create, struct buffer_head **bhp) { … } /** * nilfs_cpfile_find_checkpoint_block - find and get a buffer on cpfile * @cpfile: inode of cpfile * @start_cno: start checkpoint number (inclusive) * @end_cno: end checkpoint number (inclusive) * @cnop: place to store the next checkpoint number * @bhp: place to store a pointer to buffer_head struct * * Return Value: On success, it returns 0. On error, the following negative * error code is returned. * * %-ENOMEM - Insufficient memory available. * * %-EIO - I/O error * * %-ENOENT - no block exists in the range. */ static int nilfs_cpfile_find_checkpoint_block(struct inode *cpfile, __u64 start_cno, __u64 end_cno, __u64 *cnop, struct buffer_head **bhp) { … } static inline int nilfs_cpfile_delete_checkpoint_block(struct inode *cpfile, __u64 cno) { … } /** * nilfs_cpfile_read_checkpoint - read a checkpoint entry in cpfile * @cpfile: checkpoint file inode * @cno: number of checkpoint entry to read * @root: nilfs root object * @ifile: ifile's inode to read and attach to @root * * This function imports checkpoint information from the checkpoint file and * stores it to the inode file given by @ifile and the nilfs root object * given by @root. * * Return: 0 on success, or the following negative error code on failure. * * %-EINVAL - Invalid checkpoint. * * %-ENOMEM - Insufficient memory available. * * %-EIO - I/O error (including metadata corruption). */ int nilfs_cpfile_read_checkpoint(struct inode *cpfile, __u64 cno, struct nilfs_root *root, struct inode *ifile) { … } /** * nilfs_cpfile_create_checkpoint - create a checkpoint entry on cpfile * @cpfile: checkpoint file inode * @cno: number of checkpoint to set up * * This function creates a checkpoint with the number specified by @cno on * cpfile. If the specified checkpoint entry already exists due to a past * failure, it will be reused without returning an error. * In either case, the buffer of the block containing the checkpoint entry * and the cpfile inode are made dirty for inclusion in the write log. * * Return: 0 on success, or the following negative error code on failure. * * %-ENOMEM - Insufficient memory available. * * %-EIO - I/O error (including metadata corruption). * * %-EROFS - Read only filesystem */ int nilfs_cpfile_create_checkpoint(struct inode *cpfile, __u64 cno) { … } /** * nilfs_cpfile_finalize_checkpoint - fill in a checkpoint entry in cpfile * @cpfile: checkpoint file inode * @cno: checkpoint number * @root: nilfs root object * @blkinc: number of blocks added by this checkpoint * @ctime: checkpoint creation time * @minor: minor checkpoint flag * * This function completes the checkpoint entry numbered by @cno in the * cpfile with the data given by the arguments @root, @blkinc, @ctime, and * @minor. * * Return: 0 on success, or the following negative error code on failure. * * %-ENOMEM - Insufficient memory available. * * %-EIO - I/O error (including metadata corruption). */ int nilfs_cpfile_finalize_checkpoint(struct inode *cpfile, __u64 cno, struct nilfs_root *root, __u64 blkinc, time64_t ctime, bool minor) { … } /** * nilfs_cpfile_delete_checkpoints - delete checkpoints * @cpfile: inode of checkpoint file * @start: start checkpoint number * @end: end checkpoint number * * Description: nilfs_cpfile_delete_checkpoints() deletes the checkpoints in * the period from @start to @end, excluding @end itself. The checkpoints * which have been already deleted are ignored. * * Return Value: On success, 0 is returned. On error, one of the following * negative error codes is returned. * * %-EIO - I/O error. * * %-ENOMEM - Insufficient amount of memory available. * * %-EINVAL - invalid checkpoints. */ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, __u64 start, __u64 end) { … } static void nilfs_cpfile_checkpoint_to_cpinfo(struct inode *cpfile, struct nilfs_checkpoint *cp, struct nilfs_cpinfo *ci) { … } static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, void *buf, unsigned int cisz, size_t nci) { … } static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, void *buf, unsigned int cisz, size_t nci) { … } /** * nilfs_cpfile_get_cpinfo - get information on checkpoints * @cpfile: checkpoint file inode * @cnop: place to pass a starting checkpoint number and receive a * checkpoint number to continue the search * @mode: mode of checkpoints that the caller wants to retrieve * @buf: buffer for storing checkpoints' information * @cisz: byte size of one checkpoint info item in array * @nci: number of checkpoint info items to retrieve * * nilfs_cpfile_get_cpinfo() searches for checkpoints in @mode state * starting from the checkpoint number stored in @cnop, and stores * information about found checkpoints in @buf. * The buffer pointed to by @buf must be large enough to store information * for @nci checkpoints. If at least one checkpoint information is * successfully retrieved, @cnop is updated to point to the checkpoint * number to continue searching. * * Return: Count of checkpoint info items stored in the output buffer on * success, or the following negative error code on failure. * * %-EINVAL - Invalid checkpoint mode. * * %-ENOMEM - Insufficient memory available. * * %-EIO - I/O error (including metadata corruption). * * %-ENOENT - Invalid checkpoint number specified. */ ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode, void *buf, unsigned int cisz, size_t nci) { … } /** * nilfs_cpfile_delete_checkpoint - * @cpfile: * @cno: */ int nilfs_cpfile_delete_checkpoint(struct inode *cpfile, __u64 cno) { … } static struct nilfs_snapshot_list * nilfs_cpfile_block_get_snapshot_list(const struct inode *cpfile, __u64 cno, struct buffer_head *bh, void *kaddr) { … } static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno) { … } static int nilfs_cpfile_clear_snapshot(struct inode *cpfile, __u64 cno) { … } /** * nilfs_cpfile_is_snapshot - * @cpfile: inode of checkpoint file * @cno: checkpoint number * * Description: * * Return Value: On success, 1 is returned if the checkpoint specified by * @cno is a snapshot, or 0 if not. On error, one of the following negative * error codes is returned. * * %-EIO - I/O error. * * %-ENOMEM - Insufficient amount of memory available. * * %-ENOENT - No such checkpoint. */ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) { … } /** * nilfs_cpfile_change_cpmode - change checkpoint mode * @cpfile: inode of checkpoint file * @cno: checkpoint number * @mode: mode of checkpoint * * Description: nilfs_change_cpmode() changes the mode of the checkpoint * specified by @cno. The mode @mode is NILFS_CHECKPOINT or NILFS_SNAPSHOT. * * Return Value: On success, 0 is returned. On error, one of the following * negative error codes is returned. * * %-EIO - I/O error. * * %-ENOMEM - Insufficient amount of memory available. * * %-ENOENT - No such checkpoint. */ int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode) { … } /** * nilfs_cpfile_get_stat - get checkpoint statistics * @cpfile: inode of checkpoint file * @cpstat: pointer to a structure of checkpoint statistics * * Description: nilfs_cpfile_get_stat() returns information about checkpoints. * * Return Value: On success, 0 is returned, and checkpoints information is * stored in the place pointed by @cpstat. On error, one of the following * negative error codes is returned. * * %-EIO - I/O error. * * %-ENOMEM - Insufficient amount of memory available. */ int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat) { … } /** * nilfs_cpfile_read - read or get cpfile inode * @sb: super block instance * @cpsize: size of a checkpoint entry * @raw_inode: on-disk cpfile inode * @inodep: buffer to store the inode */ int nilfs_cpfile_read(struct super_block *sb, size_t cpsize, struct nilfs_inode *raw_inode, struct inode **inodep) { … }