^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) * Simple zone file system for zoned block devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019 Western Digital Corporation or its affiliates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #ifndef __ZONEFS_H__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define __ZONEFS_H__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/magic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/uuid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/rwsem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Maximum length of file names: this only needs to be large enough to fit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * the zone group directory names and a decimal zone number for file names.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * 16 characters is plenty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define ZONEFS_NAME_MAX 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Zone types: ZONEFS_ZTYPE_SEQ is used for all sequential zone types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * defined in linux/blkzoned.h, that is, BLK_ZONE_TYPE_SEQWRITE_REQ and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * BLK_ZONE_TYPE_SEQWRITE_PREF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) enum zonefs_ztype {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ZONEFS_ZTYPE_CNV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ZONEFS_ZTYPE_SEQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ZONEFS_ZTYPE_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static inline enum zonefs_ztype zonefs_zone_type(struct blk_zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return ZONEFS_ZTYPE_CNV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return ZONEFS_ZTYPE_SEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define ZONEFS_ZONE_OPEN (1 << 0)
^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) * In-memory inode data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct zonefs_inode_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct inode i_vnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* File zone type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) enum zonefs_ztype i_ztype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* File zone start sector (512B unit) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) sector_t i_zsector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* File zone write pointer position (sequential zones only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) loff_t i_wpoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* File maximum size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) loff_t i_max_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* File zone size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) loff_t i_zone_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * To serialise fully against both syscall and mmap based IO and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * sequential file truncation, two locks are used. For serializing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * zonefs_seq_file_truncate() against zonefs_iomap_begin(), that is,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * file truncate operations against block mapping, i_truncate_mutex is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * used. i_truncate_mutex also protects against concurrent accesses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * and changes to the inode private data, and in particular changes to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * a sequential file size on completion of direct IO writes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Serialization of mmap read IOs with truncate and syscall IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * operations is done with i_mmap_sem in addition to i_truncate_mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Only zonefs_seq_file_truncate() takes both lock (i_mmap_sem first,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * i_truncate_mutex second).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct mutex i_truncate_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct rw_semaphore i_mmap_sem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* guarded by i_truncate_mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int i_wr_refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int i_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static inline struct zonefs_inode_info *ZONEFS_I(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return container_of(inode, struct zonefs_inode_info, i_vnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * On-disk super block (block 0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define ZONEFS_LABEL_LEN 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define ZONEFS_UUID_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define ZONEFS_SUPER_SIZE 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct zonefs_super {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* Magic number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) __le32 s_magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) __le32 s_crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* Volume label */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) char s_label[ZONEFS_LABEL_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* 128-bit uuid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) __u8 s_uuid[ZONEFS_UUID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) __le64 s_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* UID/GID to use for files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) __le32 s_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) __le32 s_gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* File permissions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) __le32 s_perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Padding to ZONEFS_SUPER_SIZE bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) __u8 s_reserved[3988];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) } __packed;
^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) * Feature flags: specified in the s_features field of the on-disk super
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * block struct zonefs_super and in-memory in the s_feartures field of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * struct zonefs_sb_info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) enum zonefs_features {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * Aggregate contiguous conventional zones into a single file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ZONEFS_F_AGGRCNV = 1ULL << 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Use super block specified UID for files instead of default 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ZONEFS_F_UID = 1ULL << 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Use super block specified GID for files instead of default 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ZONEFS_F_GID = 1ULL << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Use super block specified file permissions instead of default 640.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ZONEFS_F_PERM = 1ULL << 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define ZONEFS_F_DEFINED_FEATURES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) (ZONEFS_F_AGGRCNV | ZONEFS_F_UID | ZONEFS_F_GID | ZONEFS_F_PERM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Mount options for zone write pointer error handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define ZONEFS_MNTOPT_ERRORS_RO (1 << 0) /* Make zone file readonly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define ZONEFS_MNTOPT_ERRORS_ZRO (1 << 1) /* Make zone file offline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define ZONEFS_MNTOPT_ERRORS_ZOL (1 << 2) /* Make zone file offline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define ZONEFS_MNTOPT_ERRORS_REPAIR (1 << 3) /* Remount read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define ZONEFS_MNTOPT_ERRORS_MASK \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) (ZONEFS_MNTOPT_ERRORS_RO | ZONEFS_MNTOPT_ERRORS_ZRO | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ZONEFS_MNTOPT_ERRORS_ZOL | ZONEFS_MNTOPT_ERRORS_REPAIR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define ZONEFS_MNTOPT_EXPLICIT_OPEN (1 << 4) /* Explicit open/close of zones on open/close */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * In-memory Super block information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct zonefs_sb_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned long s_mount_opts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) spinlock_t s_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) unsigned long long s_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) kuid_t s_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) kgid_t s_gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) umode_t s_perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) uuid_t s_uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned int s_zone_sectors_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned int s_nr_files[ZONEFS_ZTYPE_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) loff_t s_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) loff_t s_used_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned int s_max_open_zones;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) atomic_t s_open_zones;
^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) static inline struct zonefs_sb_info *ZONEFS_SB(struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return sb->s_fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define zonefs_info(sb, format, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) pr_info("zonefs (%s): " format, sb->s_id, ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define zonefs_err(sb, format, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) pr_err("zonefs (%s) ERROR: " format, sb->s_id, ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define zonefs_warn(sb, format, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) pr_warn("zonefs (%s) WARNING: " format, sb->s_id, ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #endif