]> git.baikalelectronics.ru Git - kernel.git/commitdiff
fs: common implementation of file type
authorPhillip Potter <phil@philpotter.co.uk>
Mon, 21 Jan 2019 00:54:27 +0000 (00:54 +0000)
committerJan Kara <jack@suse.cz>
Mon, 21 Jan 2019 16:48:13 +0000 (17:48 +0100)
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>
MAINTAINERS
fs/Makefile
fs/fs_types.c [new file with mode: 0644]
include/linux/fs.h
include/linux/fs_types.h [new file with mode: 0644]

index 51029a425dbece776924ff73dc0f078698f29da8..0afaaf0aa6be87777ce0246ac2056d0be01b0a2b 100644 (file)
@@ -5881,6 +5881,7 @@ L:        linux-fsdevel@vger.kernel.org
 S:     Maintained
 F:     fs/*
 F:     include/linux/fs.h
+F:     include/linux/fs_types.h
 F:     include/uapi/linux/fs.h
 
 FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
index 293733f61594bc073fcd98ed94bb19fd8a93da21..23fcd8c164a3579cef3e2f70a5aedf88ee404ba1 100644 (file)
@@ -12,7 +12,8 @@ obj-y :=      open.o read_write.o file_table.o super.o \
                attr.o bad_inode.o file.o filesystems.o namespace.o \
                seq_file.o xattr.o libfs.o fs-writeback.o \
                pnode.o splice.o sync.o utimes.o d_path.o \
-               stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
+               stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
+               fs_types.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=       buffer.o block_dev.o direct-io.o mpage.o
diff --git a/fs/fs_types.c b/fs/fs_types.c
new file mode 100644 (file)
index 0000000..78365e5
--- /dev/null
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/fs.h>
+#include <linux/export.h>
+
+/*
+ * fs on-disk file type to dirent file type conversion
+ */
+static const unsigned char fs_dtype_by_ftype[FT_MAX] = {
+       [FT_UNKNOWN]    = DT_UNKNOWN,
+       [FT_REG_FILE]   = DT_REG,
+       [FT_DIR]        = DT_DIR,
+       [FT_CHRDEV]     = DT_CHR,
+       [FT_BLKDEV]     = DT_BLK,
+       [FT_FIFO]       = DT_FIFO,
+       [FT_SOCK]       = DT_SOCK,
+       [FT_SYMLINK]    = DT_LNK
+};
+
+/**
+ * fs_ftype_to_dtype() - fs on-disk file type to dirent type.
+ * @filetype: The on-disk file type to convert.
+ *
+ * This function converts the on-disk file type value (FT_*) to the directory
+ * entry type (DT_*).
+ *
+ * Context: Any context.
+ * Return:
+ * * DT_UNKNOWN                - Unknown type
+ * * DT_FIFO           - FIFO
+ * * DT_CHR            - Character device
+ * * DT_DIR            - Directory
+ * * DT_BLK            - Block device
+ * * DT_REG            - Regular file
+ * * DT_LNK            - Symbolic link
+ * * DT_SOCK           - Local-domain socket
+ */
+unsigned char fs_ftype_to_dtype(unsigned int filetype)
+{
+       if (filetype >= FT_MAX)
+               return DT_UNKNOWN;
+
+       return fs_dtype_by_ftype[filetype];
+}
+EXPORT_SYMBOL_GPL(fs_ftype_to_dtype);
+
+/*
+ * dirent file type to fs on-disk file type conversion
+ * Values not initialized explicitly are FT_UNKNOWN (0).
+ */
+static const unsigned char fs_ftype_by_dtype[DT_MAX] = {
+       [DT_REG]        = FT_REG_FILE,
+       [DT_DIR]        = FT_DIR,
+       [DT_LNK]        = FT_SYMLINK,
+       [DT_CHR]        = FT_CHRDEV,
+       [DT_BLK]        = FT_BLKDEV,
+       [DT_FIFO]       = FT_FIFO,
+       [DT_SOCK]       = FT_SOCK,
+};
+
+/**
+ * fs_umode_to_ftype() - file mode to on-disk file type.
+ * @mode: The file mode to convert.
+ *
+ * This function converts the file mode value to the on-disk file type (FT_*).
+ *
+ * Context: Any context.
+ * Return:
+ * * FT_UNKNOWN                - Unknown type
+ * * FT_REG_FILE       - Regular file
+ * * FT_DIR            - Directory
+ * * FT_CHRDEV         - Character device
+ * * FT_BLKDEV         - Block device
+ * * FT_FIFO           - FIFO
+ * * FT_SOCK           - Local-domain socket
+ * * FT_SYMLINK                - Symbolic link
+ */
+unsigned char fs_umode_to_ftype(umode_t mode)
+{
+       return fs_ftype_by_dtype[S_DT(mode)];
+}
+EXPORT_SYMBOL_GPL(fs_umode_to_ftype);
+
+/**
+ * fs_umode_to_dtype() - file mode to dirent file type.
+ * @mode: The file mode to convert.
+ *
+ * This function converts the file mode value to the directory
+ * entry type (DT_*).
+ *
+ * Context: Any context.
+ * Return:
+ * * DT_UNKNOWN                - Unknown type
+ * * DT_FIFO           - FIFO
+ * * DT_CHR            - Character device
+ * * DT_DIR            - Directory
+ * * DT_BLK            - Block device
+ * * DT_REG            - Regular file
+ * * DT_LNK            - Symbolic link
+ * * DT_SOCK           - Local-domain socket
+ */
+unsigned char fs_umode_to_dtype(umode_t mode)
+{
+       return fs_ftype_to_dtype(fs_umode_to_ftype(mode));
+}
+EXPORT_SYMBOL_GPL(fs_umode_to_dtype);
index 811c77743dad2870282e6c3c85e8f238f8643767..92966678539d5fe52c348a3d3590136b13e240ee 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/uuid.h>
 #include <linux/errseq.h>
 #include <linux/ioprio.h>
+#include <linux/fs_types.h>
 
 #include <asm/byteorder.h>
 #include <uapi/linux/fs.h>
@@ -1699,22 +1700,6 @@ int fiemap_fill_next_extent(struct fiemap_extent_info *info, u64 logical,
                            u64 phys, u64 len, u32 flags);
 int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags);
 
-/*
- * File types
- *
- * NOTE! These match bits 12..15 of stat.st_mode
- * (ie "(i_mode >> 12) & 15").
- */
-#define DT_UNKNOWN     0
-#define DT_FIFO                1
-#define DT_CHR         2
-#define DT_DIR         4
-#define DT_BLK         6
-#define DT_REG         8
-#define DT_LNK         10
-#define DT_SOCK                12
-#define DT_WHT         14
-
 /*
  * This is the "filldir" function type, used by readdir() to let
  * the kernel specify what kind of dirent layout it wants to have.
diff --git a/include/linux/fs_types.h b/include/linux/fs_types.h
new file mode 100644 (file)
index 0000000..5481679
--- /dev/null
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_FS_TYPES_H
+#define _LINUX_FS_TYPES_H
+
+/*
+ * This is a header for the common implementation of dirent
+ * to fs on-disk file type conversion.  Although the fs on-disk
+ * bits are specific to every file system, in practice, many
+ * file systems use the exact same on-disk format to describe
+ * the lower 3 file type bits that represent the 7 POSIX file
+ * types.
+ *
+ * It is important to note that the definitions in this
+ * header MUST NOT change. This would break both the
+ * userspace ABI and the on-disk format of filesystems
+ * using this code.
+ *
+ * All those file systems can use this generic code for the
+ * conversions.
+ */
+
+/*
+ * struct dirent file types
+ * exposed to user via getdents(2), readdir(3)
+ *
+ * These match bits 12..15 of stat.st_mode
+ * (ie "(i_mode >> 12) & 15").
+ */
+#define S_DT_SHIFT     12
+#define S_DT(mode)     (((mode) & S_IFMT) >> S_DT_SHIFT)
+#define S_DT_MASK      (S_IFMT >> S_DT_SHIFT)
+
+/* these are defined by POSIX and also present in glibc's dirent.h */
+#define DT_UNKNOWN     0
+#define DT_FIFO                1
+#define DT_CHR         2
+#define DT_DIR         4
+#define DT_BLK         6
+#define DT_REG         8
+#define DT_LNK         10
+#define DT_SOCK                12
+#define DT_WHT         14
+
+#define DT_MAX         (S_DT_MASK + 1) /* 16 */
+
+/*
+ * fs on-disk file types.
+ * Only the low 3 bits are used for the POSIX file types.
+ * Other bits are reserved for fs private use.
+ * These definitions are shared and used by multiple filesystems,
+ * and MUST NOT change under any circumstances.
+ *
+ * Note that no fs currently stores the whiteout type on-disk,
+ * so whiteout dirents are exposed to user as DT_CHR.
+ */
+#define FT_UNKNOWN     0
+#define FT_REG_FILE    1
+#define FT_DIR         2
+#define FT_CHRDEV      3
+#define FT_BLKDEV      4
+#define FT_FIFO                5
+#define FT_SOCK                6
+#define FT_SYMLINK     7
+
+#define FT_MAX         8
+
+/*
+ * declarations for helper functions, accompanying implementation
+ * is in fs/fs_types.c
+ */
+extern unsigned char fs_ftype_to_dtype(unsigned int filetype);
+extern unsigned char fs_umode_to_ftype(umode_t mode);
+extern unsigned char fs_umode_to_dtype(umode_t mode);
+
+#endif