From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wj0-f195.google.com ([209.85.210.195]:33672 "EHLO mail-wj0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932542AbcLTHhj (ORCPT ); Tue, 20 Dec 2016 02:37:39 -0500 Received: by mail-wj0-f195.google.com with SMTP id kp2so26441753wjc.0 for ; Mon, 19 Dec 2016 23:37:38 -0800 (PST) From: Amir Goldstein To: Jan Kara , Theodore Ts'o , "Darrick J . Wong" Cc: Dave Chinner , Chris Mason , Boaz Harrosh , Jaegeuk Kim , Ryusuke Konishi , Mark Fasheh , Evgeniy Dushistov , Miklos Szeredi , Al Viro , linux-fsdevel@vger.kernel.org Subject: [RFC][PATCH v2 01/11] fs: common implementation of file type conversions Date: Tue, 20 Dec 2016 09:37:17 +0200 Message-Id: <1482219437-28672-1-git-send-email-amir73il@gmail.com> In-Reply-To: <1482178268-22883-2-git-send-email-amir73il@gmail.com> References: <1482178268-22883-2-git-send-email-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: 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 --- include/linux/file_type.h | 107 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 17 +------- 2 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 include/linux/file_type.h Fixed a comment by Darrick and a build warning reported by kbuild robot. These changes are local to the common implementation, so not re-spamming with all the non changed fs patches. v2: - s/DT_MASK/S_DT_MASK to fix redefinition in drivers/scsi/qla2xxx/qla_def.h - explicit initialization of fs_dtype_by_ftype[] using [FT_*] = DT_* v1: - initial implementation diff --git a/include/linux/file_type.h b/include/linux/file_type.h new file mode 100644 index 0000000..bb218f4 --- /dev/null +++ b/include/linux/file_type.h @@ -0,0 +1,107 @@ +#ifndef _LINUX_FILE_TYPE_H +#define _LINUX_FILE_TYPE_H + +/* + * This is a 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. + * All those file systems can use this generic code for the + * conversions: + * i_mode -> fs on-disk file type (ftype) + * fs on-disk file type (ftype) -> dirent file type (dtype) + * i_mode -> dirent file type (dtype) + */ + +/* + * 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) + +#define DT_UNKNOWN 0 +#define DT_FIFO S_DT(S_IFIFO) /* 1 */ +#define DT_CHR S_DT(S_IFCHR) /* 2 */ +#define DT_DIR S_DT(S_IFDIR) /* 4 */ +#define DT_BLK S_DT(S_IFBLK) /* 6 */ +#define DT_REG S_DT(S_IFREG) /* 8 */ +#define DT_LNK S_DT(S_IFLNK) /* 10 */ +#define DT_SOCK S_DT(S_IFSOCK) /* 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. + * + * 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 + +/* + * fs on-disk file type to dirent file type conversion + */ +static 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 +}; + +static inline unsigned char fs_dtype(int filetype) +{ + if (filetype >= FT_MAX) + return DT_UNKNOWN; + + return fs_dtype_by_ftype[filetype]; +} + +/* + * dirent file type to fs on-disk file type conversion + * Values not initialized explicitly are FT_UNKNOWN (0). + */ +static 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, +}; + +/* st_mode to fs on-disk file type conversion */ +static inline unsigned char fs_umode_to_ftype(umode_t mode) +{ + return fs_ftype_by_dtype[S_DT(mode)]; +} + +/* st_mode to dirent file type conversion */ +static inline unsigned char fs_umode_to_dtype(umode_t mode) +{ + return fs_dtype(fs_umode_to_ftype(mode)); +} + +#endif diff --git a/include/linux/fs.h b/include/linux/fs.h index e6e4146..8f1580d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1582,22 +1583,6 @@ int fiemap_fill_next_extent(struct fiemap_extent_info *info, u64 logical, 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. * This allows the kernel to read directories into kernel space or -- 2.7.4