Message ID | 1482178268-22883-2-git-send-email-amir73il@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Dec 19, 2016 at 10:10:58PM +0200, Amir Goldstein wrote: > 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> > --- > 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 > > diff --git a/include/linux/file_type.h b/include/linux/file_type.h > new file mode 100644 > index 0000000..03ee1a1 > --- /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 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 (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[] = { > + DT_UNKNOWN, [FT_UNKNOWN] = DT_UNKNOWN, etc? It's not strictly necessary but it makes the mapping more explicit. --D > + DT_REG, > + DT_DIR, > + DT_CHR, > + DT_BLK, > + DT_FIFO, > + DT_SOCK, > + 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 <linux/workqueue.h> > #include <linux/percpu-rwsem.h> > #include <linux/delayed_call.h> > +#include <linux/file_type.h> > > #include <asm/byteorder.h> > #include <uapi/linux/fs.h> > @@ -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 > -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Dec 19, 2016 at 11:13 PM, Darrick J. Wong <darrick.wong@oracle.com> wrote: > On Mon, Dec 19, 2016 at 10:10:58PM +0200, Amir Goldstein wrote: >> 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> >> --- >> 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 >> >> diff --git a/include/linux/file_type.h b/include/linux/file_type.h >> new file mode 100644 >> index 0000000..03ee1a1 >> --- /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 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 (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[] = { >> + DT_UNKNOWN, > > [FT_UNKNOWN] = DT_UNKNOWN, etc? > sure. > It's not strictly necessary but it makes the mapping more explicit. > > --D > >> + DT_REG, >> + DT_DIR, >> + DT_CHR, >> + DT_BLK, >> + DT_FIFO, >> + DT_SOCK, >> + 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 <linux/workqueue.h> >> #include <linux/percpu-rwsem.h> >> #include <linux/delayed_call.h> >> +#include <linux/file_type.h> >> >> #include <asm/byteorder.h> >> #include <uapi/linux/fs.h> >> @@ -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 >> -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/file_type.h b/include/linux/file_type.h new file mode 100644 index 0000000..03ee1a1 --- /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 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 (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[] = { + DT_UNKNOWN, + DT_REG, + DT_DIR, + DT_CHR, + DT_BLK, + DT_FIFO, + DT_SOCK, + 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 <linux/workqueue.h> #include <linux/percpu-rwsem.h> #include <linux/delayed_call.h> +#include <linux/file_type.h> #include <asm/byteorder.h> #include <uapi/linux/fs.h> @@ -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
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> --- 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