|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 |
| 2 | + * |
| 3 | + * linux/drivers/staging/erofs/internal.h |
| 4 | + * |
| 5 | + * Copyright (C) 2017-2018 HUAWEI, Inc. |
| 6 | + * http://www.huawei.com/ |
| 7 | + * Created by Gao Xiang <gaoxiang25@huawei.com> |
| 8 | + * |
| 9 | + * This file is subject to the terms and conditions of the GNU General Public |
| 10 | + * License. See the file COPYING in the main directory of the Linux |
| 11 | + * distribution for more details. |
| 12 | + */ |
| 13 | +#ifndef __INTERNAL_H |
| 14 | +#define __INTERNAL_H |
| 15 | + |
| 16 | +#include <linux/fs.h> |
| 17 | +#include <linux/dcache.h> |
| 18 | +#include <linux/mm.h> |
| 19 | +#include <linux/pagemap.h> |
| 20 | +#include <linux/bio.h> |
| 21 | +#include <linux/buffer_head.h> |
| 22 | +#include <linux/cleancache.h> |
| 23 | +#include <linux/slab.h> |
| 24 | +#include <linux/vmalloc.h> |
| 25 | +#include "erofs_fs.h" |
| 26 | + |
| 27 | +/* redefine pr_fmt "erofs: " */ |
| 28 | +#undef pr_fmt |
| 29 | +#define pr_fmt(fmt) "erofs: " fmt |
| 30 | + |
| 31 | +#define errln(x, ...) pr_err(x "\n", ##__VA_ARGS__) |
| 32 | +#define infoln(x, ...) pr_info(x "\n", ##__VA_ARGS__) |
| 33 | +#ifdef CONFIG_EROFS_FS_DEBUG |
| 34 | +#define debugln(x, ...) pr_debug(x "\n", ##__VA_ARGS__) |
| 35 | + |
| 36 | +#define dbg_might_sleep might_sleep |
| 37 | +#define DBG_BUGON BUG_ON |
| 38 | +#else |
| 39 | +#define debugln(x, ...) ((void)0) |
| 40 | + |
| 41 | +#define dbg_might_sleep() ((void)0) |
| 42 | +#define DBG_BUGON(...) ((void)0) |
| 43 | +#endif |
| 44 | + |
| 45 | +/* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ |
| 46 | +#define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 |
| 47 | + |
| 48 | +typedef u64 erofs_nid_t; |
| 49 | + |
| 50 | +struct erofs_sb_info { |
| 51 | + u32 blocks; |
| 52 | + u32 meta_blkaddr; |
| 53 | + |
| 54 | + /* inode slot unit size in bit shift */ |
| 55 | + unsigned char islotbits; |
| 56 | + |
| 57 | + u32 build_time_nsec; |
| 58 | + u64 build_time; |
| 59 | + |
| 60 | + /* what we really care is nid, rather than ino.. */ |
| 61 | + erofs_nid_t root_nid; |
| 62 | + /* used for statfs, f_files - f_favail */ |
| 63 | + u64 inos; |
| 64 | + |
| 65 | + u8 uuid[16]; /* 128-bit uuid for volume */ |
| 66 | + u8 volume_name[16]; /* volume name */ |
| 67 | + char *dev_name; |
| 68 | + |
| 69 | + unsigned int mount_opt; |
| 70 | +}; |
| 71 | + |
| 72 | +#define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) |
| 73 | +#define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info) |
| 74 | + |
| 75 | +#define clear_opt(sbi, option) ((sbi)->mount_opt &= ~EROFS_MOUNT_##option) |
| 76 | +#define set_opt(sbi, option) ((sbi)->mount_opt |= EROFS_MOUNT_##option) |
| 77 | +#define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) |
| 78 | + |
| 79 | +/* we strictly follow PAGE_SIZE and no buffer head yet */ |
| 80 | +#define LOG_BLOCK_SIZE PAGE_SHIFT |
| 81 | + |
| 82 | +#undef LOG_SECTORS_PER_BLOCK |
| 83 | +#define LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) |
| 84 | + |
| 85 | +#undef SECTORS_PER_BLOCK |
| 86 | +#define SECTORS_PER_BLOCK (1 << SECTORS_PER_BLOCK) |
| 87 | + |
| 88 | +#define EROFS_BLKSIZ (1 << LOG_BLOCK_SIZE) |
| 89 | + |
| 90 | +#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ) |
| 91 | +#error erofs cannot be used in this platform |
| 92 | +#endif |
| 93 | + |
| 94 | +#define ROOT_NID(sb) ((sb)->root_nid) |
| 95 | + |
| 96 | +typedef u64 erofs_off_t; |
| 97 | + |
| 98 | +/* data type for filesystem-wide blocks number */ |
| 99 | +typedef u32 erofs_blk_t; |
| 100 | + |
| 101 | +#define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) |
| 102 | +#define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) |
| 103 | +#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) |
| 104 | + |
| 105 | +static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid) |
| 106 | +{ |
| 107 | + return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits); |
| 108 | +} |
| 109 | + |
| 110 | +#define inode_set_inited_xattr(inode) (EROFS_V(inode)->flags |= 1) |
| 111 | +#define inode_has_inited_xattr(inode) (EROFS_V(inode)->flags & 1) |
| 112 | + |
| 113 | +struct erofs_vnode { |
| 114 | + erofs_nid_t nid; |
| 115 | + unsigned int flags; |
| 116 | + |
| 117 | + unsigned char data_mapping_mode; |
| 118 | + /* inline size in bytes */ |
| 119 | + unsigned char inode_isize; |
| 120 | + unsigned short xattr_isize; |
| 121 | + |
| 122 | + unsigned xattr_shared_count; |
| 123 | + unsigned *xattr_shared_xattrs; |
| 124 | + |
| 125 | + erofs_blk_t raw_blkaddr; |
| 126 | + |
| 127 | + /* the corresponding vfs inode */ |
| 128 | + struct inode vfs_inode; |
| 129 | +}; |
| 130 | + |
| 131 | +#define EROFS_V(ptr) \ |
| 132 | + container_of(ptr, struct erofs_vnode, vfs_inode) |
| 133 | + |
| 134 | +#define __inode_advise(x, bit, bits) \ |
| 135 | + (((x) >> (bit)) & ((1 << (bits)) - 1)) |
| 136 | + |
| 137 | +#define __inode_version(advise) \ |
| 138 | + __inode_advise(advise, EROFS_I_VERSION_BIT, \ |
| 139 | + EROFS_I_VERSION_BITS) |
| 140 | + |
| 141 | +#define __inode_data_mapping(advise) \ |
| 142 | + __inode_advise(advise, EROFS_I_DATA_MAPPING_BIT,\ |
| 143 | + EROFS_I_DATA_MAPPING_BITS) |
| 144 | + |
| 145 | +static inline unsigned long inode_datablocks(struct inode *inode) |
| 146 | +{ |
| 147 | + /* since i_size cannot be changed */ |
| 148 | + return DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); |
| 149 | +} |
| 150 | + |
| 151 | +static inline bool is_inode_layout_plain(struct inode *inode) |
| 152 | +{ |
| 153 | + return EROFS_V(inode)->data_mapping_mode == EROFS_INODE_LAYOUT_PLAIN; |
| 154 | +} |
| 155 | + |
| 156 | +static inline bool is_inode_layout_compression(struct inode *inode) |
| 157 | +{ |
| 158 | + return EROFS_V(inode)->data_mapping_mode == |
| 159 | + EROFS_INODE_LAYOUT_COMPRESSION; |
| 160 | +} |
| 161 | + |
| 162 | +static inline bool is_inode_layout_inline(struct inode *inode) |
| 163 | +{ |
| 164 | + return EROFS_V(inode)->data_mapping_mode == EROFS_INODE_LAYOUT_INLINE; |
| 165 | +} |
| 166 | + |
| 167 | +extern const struct super_operations erofs_sops; |
| 168 | +extern const struct inode_operations erofs_dir_iops; |
| 169 | +extern const struct file_operations erofs_dir_fops; |
| 170 | + |
| 171 | +extern const struct address_space_operations erofs_raw_access_aops; |
| 172 | + |
| 173 | +/* |
| 174 | + * Logical to physical block mapping, used by erofs_map_blocks() |
| 175 | + * |
| 176 | + * Different with other file systems, it is used for 2 access modes: |
| 177 | + * |
| 178 | + * 1) RAW access mode: |
| 179 | + * |
| 180 | + * Users pass a valid (m_lblk, m_lofs -- usually 0) pair, |
| 181 | + * and get the valid m_pblk, m_pofs and the longest m_len(in bytes). |
| 182 | + * |
| 183 | + * Note that m_lblk in the RAW access mode refers to the number of |
| 184 | + * the compressed ondisk block rather than the uncompressed |
| 185 | + * in-memory block for the compressed file. |
| 186 | + * |
| 187 | + * m_pofs equals to m_lofs except for the inline data page. |
| 188 | + * |
| 189 | + * 2) Normal access mode: |
| 190 | + * |
| 191 | + * If the inode is not compressed, it has no difference with |
| 192 | + * the RAW access mode. However, if the inode is compressed, |
| 193 | + * users should pass a valid (m_lblk, m_lofs) pair, and get |
| 194 | + * the needed m_pblk, m_pofs, m_len to get the compressed data |
| 195 | + * and the updated m_lblk, m_lofs which indicates the start |
| 196 | + * of the corresponding uncompressed data in the file. |
| 197 | + */ |
| 198 | +enum { |
| 199 | + BH_Zipped = BH_PrivateStart, |
| 200 | +}; |
| 201 | + |
| 202 | +/* Has a disk mapping */ |
| 203 | +#define EROFS_MAP_MAPPED (1 << BH_Mapped) |
| 204 | +/* Located in metadata (could be copied from bd_inode) */ |
| 205 | +#define EROFS_MAP_META (1 << BH_Meta) |
| 206 | +/* The extent has been compressed */ |
| 207 | +#define EROFS_MAP_ZIPPED (1 << BH_Zipped) |
| 208 | + |
| 209 | +struct erofs_map_blocks { |
| 210 | + erofs_off_t m_pa, m_la; |
| 211 | + u64 m_plen, m_llen; |
| 212 | + |
| 213 | + unsigned int m_flags; |
| 214 | +}; |
| 215 | + |
| 216 | +/* Flags used by erofs_map_blocks() */ |
| 217 | +#define EROFS_GET_BLOCKS_RAW 0x0001 |
| 218 | + |
| 219 | +/* data.c */ |
| 220 | +extern struct page *erofs_get_meta_page(struct super_block *sb, |
| 221 | + erofs_blk_t blkaddr, bool prio); |
| 222 | +extern int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); |
| 223 | + |
| 224 | +static inline struct page *erofs_get_inline_page(struct inode *inode, |
| 225 | + erofs_blk_t blkaddr) |
| 226 | +{ |
| 227 | + return erofs_get_meta_page(inode->i_sb, |
| 228 | + blkaddr, S_ISDIR(inode->i_mode)); |
| 229 | +} |
| 230 | + |
| 231 | +/* inode.c */ |
| 232 | +extern struct inode *erofs_iget(struct super_block *sb, |
| 233 | + erofs_nid_t nid, bool dir); |
| 234 | + |
| 235 | +/* dir.c */ |
| 236 | +int erofs_namei(struct inode *dir, struct qstr *name, |
| 237 | + erofs_nid_t *nid, unsigned *d_type); |
| 238 | + |
| 239 | +/* xattr.c */ |
| 240 | +extern const struct xattr_handler *erofs_xattr_handlers[]; |
| 241 | + |
| 242 | +/* symlink */ |
| 243 | +static inline void set_inode_fast_symlink(struct inode *inode) |
| 244 | +{ |
| 245 | + inode->i_op = &simple_symlink_inode_operations; |
| 246 | +} |
| 247 | + |
| 248 | +static inline bool is_inode_fast_symlink(struct inode *inode) |
| 249 | +{ |
| 250 | + return inode->i_op == &simple_symlink_inode_operations; |
| 251 | +} |
| 252 | + |
| 253 | +static inline void *erofs_vmap(struct page **pages, unsigned int count) |
| 254 | +{ |
| 255 | +#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM |
| 256 | + int i = 0; |
| 257 | + |
| 258 | + while (1) { |
| 259 | + void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); |
| 260 | + /* retry two more times (totally 3 times) */ |
| 261 | + if (addr != NULL || ++i >= 3) |
| 262 | + return addr; |
| 263 | + vm_unmap_aliases(); |
| 264 | + } |
| 265 | + return NULL; |
| 266 | +#else |
| 267 | + return vmap(pages, count, VM_MAP, PAGE_KERNEL); |
| 268 | +#endif |
| 269 | +} |
| 270 | + |
| 271 | +static inline void erofs_vunmap(const void *mem, unsigned int count) |
| 272 | +{ |
| 273 | +#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM |
| 274 | + vm_unmap_ram(mem, count); |
| 275 | +#else |
| 276 | + vunmap(mem); |
| 277 | +#endif |
| 278 | +} |
| 279 | + |
| 280 | +#endif |
| 281 | + |
0 commit comments