18dcc1a9dSDamien Le Moal /* SPDX-License-Identifier: GPL-2.0 */ 28dcc1a9dSDamien Le Moal /* 38dcc1a9dSDamien Le Moal * Simple zone file system for zoned block devices. 48dcc1a9dSDamien Le Moal * 58dcc1a9dSDamien Le Moal * Copyright (C) 2019 Western Digital Corporation or its affiliates. 68dcc1a9dSDamien Le Moal */ 78dcc1a9dSDamien Le Moal #ifndef __ZONEFS_H__ 88dcc1a9dSDamien Le Moal #define __ZONEFS_H__ 98dcc1a9dSDamien Le Moal 108dcc1a9dSDamien Le Moal #include <linux/fs.h> 118dcc1a9dSDamien Le Moal #include <linux/magic.h> 128dcc1a9dSDamien Le Moal #include <linux/uuid.h> 138dcc1a9dSDamien Le Moal #include <linux/mutex.h> 148dcc1a9dSDamien Le Moal #include <linux/rwsem.h> 159277a6d4SDamien Le Moal #include <linux/kobject.h> 168dcc1a9dSDamien Le Moal 178dcc1a9dSDamien Le Moal /* 188dcc1a9dSDamien Le Moal * Maximum length of file names: this only needs to be large enough to fit 198dcc1a9dSDamien Le Moal * the zone group directory names and a decimal zone number for file names. 208dcc1a9dSDamien Le Moal * 16 characters is plenty. 218dcc1a9dSDamien Le Moal */ 228dcc1a9dSDamien Le Moal #define ZONEFS_NAME_MAX 16 238dcc1a9dSDamien Le Moal 248dcc1a9dSDamien Le Moal /* 258dcc1a9dSDamien Le Moal * Zone types: ZONEFS_ZTYPE_SEQ is used for all sequential zone types 268dcc1a9dSDamien Le Moal * defined in linux/blkzoned.h, that is, BLK_ZONE_TYPE_SEQWRITE_REQ and 278dcc1a9dSDamien Le Moal * BLK_ZONE_TYPE_SEQWRITE_PREF. 288dcc1a9dSDamien Le Moal */ 298dcc1a9dSDamien Le Moal enum zonefs_ztype { 308dcc1a9dSDamien Le Moal ZONEFS_ZTYPE_CNV, 318dcc1a9dSDamien Le Moal ZONEFS_ZTYPE_SEQ, 328dcc1a9dSDamien Le Moal ZONEFS_ZTYPE_MAX, 338dcc1a9dSDamien Le Moal }; 348dcc1a9dSDamien Le Moal 358dcc1a9dSDamien Le Moal static inline enum zonefs_ztype zonefs_zone_type(struct blk_zone *zone) 368dcc1a9dSDamien Le Moal { 378dcc1a9dSDamien Le Moal if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) 388dcc1a9dSDamien Le Moal return ZONEFS_ZTYPE_CNV; 398dcc1a9dSDamien Le Moal return ZONEFS_ZTYPE_SEQ; 408dcc1a9dSDamien Le Moal } 418dcc1a9dSDamien Le Moal 4246a9c526SDamien Le Moal #define ZONEFS_ZONE_INIT_MODE (1U << 0) 4346a9c526SDamien Le Moal #define ZONEFS_ZONE_OPEN (1U << 1) 4446a9c526SDamien Le Moal #define ZONEFS_ZONE_ACTIVE (1U << 2) 4546a9c526SDamien Le Moal #define ZONEFS_ZONE_OFFLINE (1U << 3) 4646a9c526SDamien Le Moal #define ZONEFS_ZONE_READONLY (1U << 4) 4734422914SDamien Le Moal #define ZONEFS_ZONE_CNV (1U << 31) 48b5c00e97SJohannes Thumshirn 498dcc1a9dSDamien Le Moal /* 50*aa7f243fSDamien Le Moal * In-memory per-file inode zone data. 51*aa7f243fSDamien Le Moal */ 52*aa7f243fSDamien Le Moal struct zonefs_zone { 53*aa7f243fSDamien Le Moal /* Zone state flags */ 54*aa7f243fSDamien Le Moal unsigned int z_flags; 55*aa7f243fSDamien Le Moal 56*aa7f243fSDamien Le Moal /* Zone start sector (512B unit) */ 57*aa7f243fSDamien Le Moal sector_t z_sector; 58*aa7f243fSDamien Le Moal 59*aa7f243fSDamien Le Moal /* Zone size (bytes) */ 60*aa7f243fSDamien Le Moal loff_t z_size; 61*aa7f243fSDamien Le Moal 62*aa7f243fSDamien Le Moal /* Zone capacity (file maximum size, bytes) */ 63*aa7f243fSDamien Le Moal loff_t z_capacity; 64*aa7f243fSDamien Le Moal 65*aa7f243fSDamien Le Moal /* Write pointer offset in the zone (sequential zones only, bytes) */ 66*aa7f243fSDamien Le Moal loff_t z_wpoffset; 67*aa7f243fSDamien Le Moal }; 68*aa7f243fSDamien Le Moal 69*aa7f243fSDamien Le Moal /* 70*aa7f243fSDamien Le Moal * In memory zone group information: all zones of a group are exposed 71*aa7f243fSDamien Le Moal * as files, one file per zone. 72*aa7f243fSDamien Le Moal */ 73*aa7f243fSDamien Le Moal struct zonefs_zone_group { 74*aa7f243fSDamien Le Moal unsigned int g_nr_zones; 75*aa7f243fSDamien Le Moal struct zonefs_zone *g_zones; 76*aa7f243fSDamien Le Moal }; 77*aa7f243fSDamien Le Moal 78*aa7f243fSDamien Le Moal /* 798dcc1a9dSDamien Le Moal * In-memory inode data. 808dcc1a9dSDamien Le Moal */ 818dcc1a9dSDamien Le Moal struct zonefs_inode_info { 828dcc1a9dSDamien Le Moal struct inode i_vnode; 838dcc1a9dSDamien Le Moal 848dcc1a9dSDamien Le Moal /* 858dcc1a9dSDamien Le Moal * To serialise fully against both syscall and mmap based IO and 868dcc1a9dSDamien Le Moal * sequential file truncation, two locks are used. For serializing 878dcc1a9dSDamien Le Moal * zonefs_seq_file_truncate() against zonefs_iomap_begin(), that is, 888dcc1a9dSDamien Le Moal * file truncate operations against block mapping, i_truncate_mutex is 898dcc1a9dSDamien Le Moal * used. i_truncate_mutex also protects against concurrent accesses 908dcc1a9dSDamien Le Moal * and changes to the inode private data, and in particular changes to 918dcc1a9dSDamien Le Moal * a sequential file size on completion of direct IO writes. 928dcc1a9dSDamien Le Moal * Serialization of mmap read IOs with truncate and syscall IO 93448f9490SJan Kara * operations is done with invalidate_lock in addition to 94448f9490SJan Kara * i_truncate_mutex. Only zonefs_seq_file_truncate() takes both lock 95448f9490SJan Kara * (invalidate_lock first, i_truncate_mutex second). 968dcc1a9dSDamien Le Moal */ 978dcc1a9dSDamien Le Moal struct mutex i_truncate_mutex; 98b5c00e97SJohannes Thumshirn 99b5c00e97SJohannes Thumshirn /* guarded by i_truncate_mutex */ 100b5c00e97SJohannes Thumshirn unsigned int i_wr_refcnt; 1018dcc1a9dSDamien Le Moal }; 1028dcc1a9dSDamien Le Moal 1038dcc1a9dSDamien Le Moal static inline struct zonefs_inode_info *ZONEFS_I(struct inode *inode) 1048dcc1a9dSDamien Le Moal { 1058dcc1a9dSDamien Le Moal return container_of(inode, struct zonefs_inode_info, i_vnode); 1068dcc1a9dSDamien Le Moal } 1078dcc1a9dSDamien Le Moal 108*aa7f243fSDamien Le Moal static inline bool zonefs_zone_is_cnv(struct zonefs_zone *z) 10934422914SDamien Le Moal { 110*aa7f243fSDamien Le Moal return z->z_flags & ZONEFS_ZONE_CNV; 11134422914SDamien Le Moal } 11234422914SDamien Le Moal 113*aa7f243fSDamien Le Moal static inline bool zonefs_zone_is_seq(struct zonefs_zone *z) 11434422914SDamien Le Moal { 115*aa7f243fSDamien Le Moal return !zonefs_zone_is_cnv(z); 116*aa7f243fSDamien Le Moal } 117*aa7f243fSDamien Le Moal 118*aa7f243fSDamien Le Moal static inline struct zonefs_zone *zonefs_inode_zone(struct inode *inode) 119*aa7f243fSDamien Le Moal { 120*aa7f243fSDamien Le Moal return inode->i_private; 12134422914SDamien Le Moal } 12234422914SDamien Le Moal 12334422914SDamien Le Moal static inline bool zonefs_inode_is_cnv(struct inode *inode) 12434422914SDamien Le Moal { 125*aa7f243fSDamien Le Moal return zonefs_zone_is_cnv(zonefs_inode_zone(inode)); 12634422914SDamien Le Moal } 12734422914SDamien Le Moal 12834422914SDamien Le Moal static inline bool zonefs_inode_is_seq(struct inode *inode) 12934422914SDamien Le Moal { 130*aa7f243fSDamien Le Moal return zonefs_zone_is_seq(zonefs_inode_zone(inode)); 13134422914SDamien Le Moal } 13234422914SDamien Le Moal 1338dcc1a9dSDamien Le Moal /* 1348dcc1a9dSDamien Le Moal * On-disk super block (block 0). 1358dcc1a9dSDamien Le Moal */ 1368dcc1a9dSDamien Le Moal #define ZONEFS_LABEL_LEN 64 1378dcc1a9dSDamien Le Moal #define ZONEFS_UUID_SIZE 16 1388dcc1a9dSDamien Le Moal #define ZONEFS_SUPER_SIZE 4096 1398dcc1a9dSDamien Le Moal 1408dcc1a9dSDamien Le Moal struct zonefs_super { 1418dcc1a9dSDamien Le Moal 1428dcc1a9dSDamien Le Moal /* Magic number */ 1438dcc1a9dSDamien Le Moal __le32 s_magic; 1448dcc1a9dSDamien Le Moal 1458dcc1a9dSDamien Le Moal /* Checksum */ 1468dcc1a9dSDamien Le Moal __le32 s_crc; 1478dcc1a9dSDamien Le Moal 1488dcc1a9dSDamien Le Moal /* Volume label */ 1498dcc1a9dSDamien Le Moal char s_label[ZONEFS_LABEL_LEN]; 1508dcc1a9dSDamien Le Moal 1518dcc1a9dSDamien Le Moal /* 128-bit uuid */ 1528dcc1a9dSDamien Le Moal __u8 s_uuid[ZONEFS_UUID_SIZE]; 1538dcc1a9dSDamien Le Moal 1548dcc1a9dSDamien Le Moal /* Features */ 1558dcc1a9dSDamien Le Moal __le64 s_features; 1568dcc1a9dSDamien Le Moal 1578dcc1a9dSDamien Le Moal /* UID/GID to use for files */ 1588dcc1a9dSDamien Le Moal __le32 s_uid; 1598dcc1a9dSDamien Le Moal __le32 s_gid; 1608dcc1a9dSDamien Le Moal 1618dcc1a9dSDamien Le Moal /* File permissions */ 1628dcc1a9dSDamien Le Moal __le32 s_perm; 1638dcc1a9dSDamien Le Moal 1648dcc1a9dSDamien Le Moal /* Padding to ZONEFS_SUPER_SIZE bytes */ 1658dcc1a9dSDamien Le Moal __u8 s_reserved[3988]; 1668dcc1a9dSDamien Le Moal 1678dcc1a9dSDamien Le Moal } __packed; 1688dcc1a9dSDamien Le Moal 1698dcc1a9dSDamien Le Moal /* 1708dcc1a9dSDamien Le Moal * Feature flags: specified in the s_features field of the on-disk super 1718dcc1a9dSDamien Le Moal * block struct zonefs_super and in-memory in the s_feartures field of 1728dcc1a9dSDamien Le Moal * struct zonefs_sb_info. 1738dcc1a9dSDamien Le Moal */ 1748dcc1a9dSDamien Le Moal enum zonefs_features { 1758dcc1a9dSDamien Le Moal /* 1768dcc1a9dSDamien Le Moal * Aggregate contiguous conventional zones into a single file. 1778dcc1a9dSDamien Le Moal */ 1788dcc1a9dSDamien Le Moal ZONEFS_F_AGGRCNV = 1ULL << 0, 1798dcc1a9dSDamien Le Moal /* 1808dcc1a9dSDamien Le Moal * Use super block specified UID for files instead of default 0. 1818dcc1a9dSDamien Le Moal */ 1828dcc1a9dSDamien Le Moal ZONEFS_F_UID = 1ULL << 1, 1838dcc1a9dSDamien Le Moal /* 1848dcc1a9dSDamien Le Moal * Use super block specified GID for files instead of default 0. 1858dcc1a9dSDamien Le Moal */ 1868dcc1a9dSDamien Le Moal ZONEFS_F_GID = 1ULL << 2, 1878dcc1a9dSDamien Le Moal /* 1888dcc1a9dSDamien Le Moal * Use super block specified file permissions instead of default 640. 1898dcc1a9dSDamien Le Moal */ 1908dcc1a9dSDamien Le Moal ZONEFS_F_PERM = 1ULL << 3, 1918dcc1a9dSDamien Le Moal }; 1928dcc1a9dSDamien Le Moal 1938dcc1a9dSDamien Le Moal #define ZONEFS_F_DEFINED_FEATURES \ 1948dcc1a9dSDamien Le Moal (ZONEFS_F_AGGRCNV | ZONEFS_F_UID | ZONEFS_F_GID | ZONEFS_F_PERM) 1958dcc1a9dSDamien Le Moal 1968dcc1a9dSDamien Le Moal /* 1978dcc1a9dSDamien Le Moal * Mount options for zone write pointer error handling. 1988dcc1a9dSDamien Le Moal */ 1998dcc1a9dSDamien Le Moal #define ZONEFS_MNTOPT_ERRORS_RO (1 << 0) /* Make zone file readonly */ 2008dcc1a9dSDamien Le Moal #define ZONEFS_MNTOPT_ERRORS_ZRO (1 << 1) /* Make zone file offline */ 2018dcc1a9dSDamien Le Moal #define ZONEFS_MNTOPT_ERRORS_ZOL (1 << 2) /* Make zone file offline */ 2028dcc1a9dSDamien Le Moal #define ZONEFS_MNTOPT_ERRORS_REPAIR (1 << 3) /* Remount read-only */ 2038dcc1a9dSDamien Le Moal #define ZONEFS_MNTOPT_ERRORS_MASK \ 2048dcc1a9dSDamien Le Moal (ZONEFS_MNTOPT_ERRORS_RO | ZONEFS_MNTOPT_ERRORS_ZRO | \ 2058dcc1a9dSDamien Le Moal ZONEFS_MNTOPT_ERRORS_ZOL | ZONEFS_MNTOPT_ERRORS_REPAIR) 206b5c00e97SJohannes Thumshirn #define ZONEFS_MNTOPT_EXPLICIT_OPEN (1 << 4) /* Explicit open/close of zones on open/close */ 2078dcc1a9dSDamien Le Moal 2088dcc1a9dSDamien Le Moal /* 2098dcc1a9dSDamien Le Moal * In-memory Super block information. 2108dcc1a9dSDamien Le Moal */ 2118dcc1a9dSDamien Le Moal struct zonefs_sb_info { 2128dcc1a9dSDamien Le Moal 2138dcc1a9dSDamien Le Moal unsigned long s_mount_opts; 2148dcc1a9dSDamien Le Moal 2158dcc1a9dSDamien Le Moal spinlock_t s_lock; 2168dcc1a9dSDamien Le Moal 2178dcc1a9dSDamien Le Moal unsigned long long s_features; 2188dcc1a9dSDamien Le Moal kuid_t s_uid; 2198dcc1a9dSDamien Le Moal kgid_t s_gid; 2208dcc1a9dSDamien Le Moal umode_t s_perm; 2218dcc1a9dSDamien Le Moal uuid_t s_uuid; 2228dcc1a9dSDamien Le Moal unsigned int s_zone_sectors_shift; 2238dcc1a9dSDamien Le Moal 224*aa7f243fSDamien Le Moal struct zonefs_zone_group s_zgroup[ZONEFS_ZTYPE_MAX]; 2258dcc1a9dSDamien Le Moal 2268dcc1a9dSDamien Le Moal loff_t s_blocks; 2278dcc1a9dSDamien Le Moal loff_t s_used_blocks; 228b5c00e97SJohannes Thumshirn 2292b95a23cSDamien Le Moal unsigned int s_max_wro_seq_files; 2302b95a23cSDamien Le Moal atomic_t s_wro_seq_files; 2319277a6d4SDamien Le Moal 23287c9ce3fSDamien Le Moal unsigned int s_max_active_seq_files; 23387c9ce3fSDamien Le Moal atomic_t s_active_seq_files; 23487c9ce3fSDamien Le Moal 2359277a6d4SDamien Le Moal bool s_sysfs_registered; 2369277a6d4SDamien Le Moal struct kobject s_kobj; 2379277a6d4SDamien Le Moal struct completion s_kobj_unregister; 2388dcc1a9dSDamien Le Moal }; 2398dcc1a9dSDamien Le Moal 2408dcc1a9dSDamien Le Moal static inline struct zonefs_sb_info *ZONEFS_SB(struct super_block *sb) 2418dcc1a9dSDamien Le Moal { 2428dcc1a9dSDamien Le Moal return sb->s_fs_info; 2438dcc1a9dSDamien Le Moal } 2448dcc1a9dSDamien Le Moal 2458dcc1a9dSDamien Le Moal #define zonefs_info(sb, format, args...) \ 2468dcc1a9dSDamien Le Moal pr_info("zonefs (%s): " format, sb->s_id, ## args) 2478dcc1a9dSDamien Le Moal #define zonefs_err(sb, format, args...) \ 2488dcc1a9dSDamien Le Moal pr_err("zonefs (%s) ERROR: " format, sb->s_id, ## args) 2498dcc1a9dSDamien Le Moal #define zonefs_warn(sb, format, args...) \ 2508dcc1a9dSDamien Le Moal pr_warn("zonefs (%s) WARNING: " format, sb->s_id, ## args) 2518dcc1a9dSDamien Le Moal 2524008e2a0SDamien Le Moal /* In super.c */ 253*aa7f243fSDamien Le Moal void zonefs_inode_account_active(struct inode *inode); 254*aa7f243fSDamien Le Moal int zonefs_inode_zone_mgmt(struct inode *inode, enum req_op op); 2554008e2a0SDamien Le Moal void zonefs_i_size_write(struct inode *inode, loff_t isize); 2564008e2a0SDamien Le Moal void zonefs_update_stats(struct inode *inode, loff_t new_isize); 2574008e2a0SDamien Le Moal void __zonefs_io_error(struct inode *inode, bool write); 2584008e2a0SDamien Le Moal 2594008e2a0SDamien Le Moal static inline void zonefs_io_error(struct inode *inode, bool write) 2604008e2a0SDamien Le Moal { 2614008e2a0SDamien Le Moal struct zonefs_inode_info *zi = ZONEFS_I(inode); 2624008e2a0SDamien Le Moal 2634008e2a0SDamien Le Moal mutex_lock(&zi->i_truncate_mutex); 2644008e2a0SDamien Le Moal __zonefs_io_error(inode, write); 2654008e2a0SDamien Le Moal mutex_unlock(&zi->i_truncate_mutex); 2664008e2a0SDamien Le Moal } 2674008e2a0SDamien Le Moal 2684008e2a0SDamien Le Moal /* In file.c */ 2694008e2a0SDamien Le Moal extern const struct address_space_operations zonefs_file_aops; 2704008e2a0SDamien Le Moal extern const struct file_operations zonefs_file_operations; 2714008e2a0SDamien Le Moal int zonefs_file_truncate(struct inode *inode, loff_t isize); 2724008e2a0SDamien Le Moal 2734008e2a0SDamien Le Moal /* In sysfs.c */ 2749277a6d4SDamien Le Moal int zonefs_sysfs_register(struct super_block *sb); 2759277a6d4SDamien Le Moal void zonefs_sysfs_unregister(struct super_block *sb); 2769277a6d4SDamien Le Moal int zonefs_sysfs_init(void); 2779277a6d4SDamien Le Moal void zonefs_sysfs_exit(void); 2789277a6d4SDamien Le Moal 2798dcc1a9dSDamien Le Moal #endif 280