Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs: common implementation of file type

Many file systems use a copy&paste implementation
of dirent to on-disk file type conversions.

Create a common implementation to be used by file systems
with some useful conversion helpers to reduce open coded
file type conversions in file system code.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Phillip Potter <phil@philpotter.co.uk>
Signed-off-by: Jan Kara <jack@suse.cz>

authored by

Phillip Potter and committed by
Jan Kara
bbe7449e 49a57857

+184 -17
+1
MAINTAINERS
··· 5881 5881 S: Maintained 5882 5882 F: fs/* 5883 5883 F: include/linux/fs.h 5884 + F: include/linux/fs_types.h 5884 5885 F: include/uapi/linux/fs.h 5885 5886 5886 5887 FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
+2 -1
fs/Makefile
··· 12 12 attr.o bad_inode.o file.o filesystems.o namespace.o \ 13 13 seq_file.o xattr.o libfs.o fs-writeback.o \ 14 14 pnode.o splice.o sync.o utimes.o d_path.o \ 15 - stack.o fs_struct.o statfs.o fs_pin.o nsfs.o 15 + stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \ 16 + fs_types.o 16 17 17 18 ifeq ($(CONFIG_BLOCK),y) 18 19 obj-y += buffer.o block_dev.o direct-io.o mpage.o
+105
fs/fs_types.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/fs.h> 3 + #include <linux/export.h> 4 + 5 + /* 6 + * fs on-disk file type to dirent file type conversion 7 + */ 8 + static const unsigned char fs_dtype_by_ftype[FT_MAX] = { 9 + [FT_UNKNOWN] = DT_UNKNOWN, 10 + [FT_REG_FILE] = DT_REG, 11 + [FT_DIR] = DT_DIR, 12 + [FT_CHRDEV] = DT_CHR, 13 + [FT_BLKDEV] = DT_BLK, 14 + [FT_FIFO] = DT_FIFO, 15 + [FT_SOCK] = DT_SOCK, 16 + [FT_SYMLINK] = DT_LNK 17 + }; 18 + 19 + /** 20 + * fs_ftype_to_dtype() - fs on-disk file type to dirent type. 21 + * @filetype: The on-disk file type to convert. 22 + * 23 + * This function converts the on-disk file type value (FT_*) to the directory 24 + * entry type (DT_*). 25 + * 26 + * Context: Any context. 27 + * Return: 28 + * * DT_UNKNOWN - Unknown type 29 + * * DT_FIFO - FIFO 30 + * * DT_CHR - Character device 31 + * * DT_DIR - Directory 32 + * * DT_BLK - Block device 33 + * * DT_REG - Regular file 34 + * * DT_LNK - Symbolic link 35 + * * DT_SOCK - Local-domain socket 36 + */ 37 + unsigned char fs_ftype_to_dtype(unsigned int filetype) 38 + { 39 + if (filetype >= FT_MAX) 40 + return DT_UNKNOWN; 41 + 42 + return fs_dtype_by_ftype[filetype]; 43 + } 44 + EXPORT_SYMBOL_GPL(fs_ftype_to_dtype); 45 + 46 + /* 47 + * dirent file type to fs on-disk file type conversion 48 + * Values not initialized explicitly are FT_UNKNOWN (0). 49 + */ 50 + static const unsigned char fs_ftype_by_dtype[DT_MAX] = { 51 + [DT_REG] = FT_REG_FILE, 52 + [DT_DIR] = FT_DIR, 53 + [DT_LNK] = FT_SYMLINK, 54 + [DT_CHR] = FT_CHRDEV, 55 + [DT_BLK] = FT_BLKDEV, 56 + [DT_FIFO] = FT_FIFO, 57 + [DT_SOCK] = FT_SOCK, 58 + }; 59 + 60 + /** 61 + * fs_umode_to_ftype() - file mode to on-disk file type. 62 + * @mode: The file mode to convert. 63 + * 64 + * This function converts the file mode value to the on-disk file type (FT_*). 65 + * 66 + * Context: Any context. 67 + * Return: 68 + * * FT_UNKNOWN - Unknown type 69 + * * FT_REG_FILE - Regular file 70 + * * FT_DIR - Directory 71 + * * FT_CHRDEV - Character device 72 + * * FT_BLKDEV - Block device 73 + * * FT_FIFO - FIFO 74 + * * FT_SOCK - Local-domain socket 75 + * * FT_SYMLINK - Symbolic link 76 + */ 77 + unsigned char fs_umode_to_ftype(umode_t mode) 78 + { 79 + return fs_ftype_by_dtype[S_DT(mode)]; 80 + } 81 + EXPORT_SYMBOL_GPL(fs_umode_to_ftype); 82 + 83 + /** 84 + * fs_umode_to_dtype() - file mode to dirent file type. 85 + * @mode: The file mode to convert. 86 + * 87 + * This function converts the file mode value to the directory 88 + * entry type (DT_*). 89 + * 90 + * Context: Any context. 91 + * Return: 92 + * * DT_UNKNOWN - Unknown type 93 + * * DT_FIFO - FIFO 94 + * * DT_CHR - Character device 95 + * * DT_DIR - Directory 96 + * * DT_BLK - Block device 97 + * * DT_REG - Regular file 98 + * * DT_LNK - Symbolic link 99 + * * DT_SOCK - Local-domain socket 100 + */ 101 + unsigned char fs_umode_to_dtype(umode_t mode) 102 + { 103 + return fs_ftype_to_dtype(fs_umode_to_ftype(mode)); 104 + } 105 + EXPORT_SYMBOL_GPL(fs_umode_to_dtype);
+1 -16
include/linux/fs.h
··· 37 37 #include <linux/uuid.h> 38 38 #include <linux/errseq.h> 39 39 #include <linux/ioprio.h> 40 + #include <linux/fs_types.h> 40 41 41 42 #include <asm/byteorder.h> 42 43 #include <uapi/linux/fs.h> ··· 1699 1698 int fiemap_fill_next_extent(struct fiemap_extent_info *info, u64 logical, 1700 1699 u64 phys, u64 len, u32 flags); 1701 1700 int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags); 1702 - 1703 - /* 1704 - * File types 1705 - * 1706 - * NOTE! These match bits 12..15 of stat.st_mode 1707 - * (ie "(i_mode >> 12) & 15"). 1708 - */ 1709 - #define DT_UNKNOWN 0 1710 - #define DT_FIFO 1 1711 - #define DT_CHR 2 1712 - #define DT_DIR 4 1713 - #define DT_BLK 6 1714 - #define DT_REG 8 1715 - #define DT_LNK 10 1716 - #define DT_SOCK 12 1717 - #define DT_WHT 14 1718 1701 1719 1702 /* 1720 1703 * This is the "filldir" function type, used by readdir() to let
+75
include/linux/fs_types.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _LINUX_FS_TYPES_H 3 + #define _LINUX_FS_TYPES_H 4 + 5 + /* 6 + * This is a header for the common implementation of dirent 7 + * to fs on-disk file type conversion. Although the fs on-disk 8 + * bits are specific to every file system, in practice, many 9 + * file systems use the exact same on-disk format to describe 10 + * the lower 3 file type bits that represent the 7 POSIX file 11 + * types. 12 + * 13 + * It is important to note that the definitions in this 14 + * header MUST NOT change. This would break both the 15 + * userspace ABI and the on-disk format of filesystems 16 + * using this code. 17 + * 18 + * All those file systems can use this generic code for the 19 + * conversions. 20 + */ 21 + 22 + /* 23 + * struct dirent file types 24 + * exposed to user via getdents(2), readdir(3) 25 + * 26 + * These match bits 12..15 of stat.st_mode 27 + * (ie "(i_mode >> 12) & 15"). 28 + */ 29 + #define S_DT_SHIFT 12 30 + #define S_DT(mode) (((mode) & S_IFMT) >> S_DT_SHIFT) 31 + #define S_DT_MASK (S_IFMT >> S_DT_SHIFT) 32 + 33 + /* these are defined by POSIX and also present in glibc's dirent.h */ 34 + #define DT_UNKNOWN 0 35 + #define DT_FIFO 1 36 + #define DT_CHR 2 37 + #define DT_DIR 4 38 + #define DT_BLK 6 39 + #define DT_REG 8 40 + #define DT_LNK 10 41 + #define DT_SOCK 12 42 + #define DT_WHT 14 43 + 44 + #define DT_MAX (S_DT_MASK + 1) /* 16 */ 45 + 46 + /* 47 + * fs on-disk file types. 48 + * Only the low 3 bits are used for the POSIX file types. 49 + * Other bits are reserved for fs private use. 50 + * These definitions are shared and used by multiple filesystems, 51 + * and MUST NOT change under any circumstances. 52 + * 53 + * Note that no fs currently stores the whiteout type on-disk, 54 + * so whiteout dirents are exposed to user as DT_CHR. 55 + */ 56 + #define FT_UNKNOWN 0 57 + #define FT_REG_FILE 1 58 + #define FT_DIR 2 59 + #define FT_CHRDEV 3 60 + #define FT_BLKDEV 4 61 + #define FT_FIFO 5 62 + #define FT_SOCK 6 63 + #define FT_SYMLINK 7 64 + 65 + #define FT_MAX 8 66 + 67 + /* 68 + * declarations for helper functions, accompanying implementation 69 + * is in fs/fs_types.c 70 + */ 71 + extern unsigned char fs_ftype_to_dtype(unsigned int filetype); 72 + extern unsigned char fs_umode_to_ftype(umode_t mode); 73 + extern unsigned char fs_umode_to_dtype(umode_t mode); 74 + 75 + #endif