From 7ea9ea832212c4a755650f7c7cc1ff0b63292a41 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 31 Mar 2006 15:01:28 -0500 Subject: [GFS2] Update ioctl() to new interface This is designed as a fs independent way to set flags on a particular inode. The values of the ioctl() and flags are designed to be identical to the ext2/3 values. Assuming that this plan is acceptable to people in general, the plan is to then move other fs across to using the same set of #defines, etc. Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_file.c | 138 ++++++++++++-------------------------------- include/linux/gfs2_ondisk.h | 16 +++++ include/linux/iflags.h | 104 +++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 102 deletions(-) create mode 100644 include/linux/iflags.h diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index ac8e1238cb6f..db4484a3efcc 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -536,110 +537,44 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) return error; } -const struct gfs2_flag_eattr { - u32 flag; - u32 ext2; -} gfs2_flag_eattrs[] = { - { - .flag = GFS2_DIF_IMMUTABLE, - .ext2 = EXT2_IMMUTABLE_FL, - }, { - .flag = GFS2_DIF_APPENDONLY, - .ext2 = EXT2_APPEND_FL, - }, { - .flag = GFS2_DIF_JDATA, - .ext2 = EXT2_JOURNAL_DATA_FL, - }, { - .flag = GFS2_DIF_EXHASH, - .ext2 = EXT2_INDEX_FL, - }, { - .flag = GFS2_DIF_EA_INDIRECT, - }, { - .flag = GFS2_DIF_DIRECTIO, - }, { - .flag = GFS2_DIF_NOATIME, - .ext2 = EXT2_NOATIME_FL, - }, { - .flag = GFS2_DIF_SYNC, - .ext2 = EXT2_SYNC_FL, - }, { - .flag = GFS2_DIF_SYSTEM, - }, { - .flag = GFS2_DIF_TRUNC_IN_PROG, - }, { - .flag = GFS2_DIF_INHERIT_JDATA, - }, { - .flag = GFS2_DIF_INHERIT_DIRECTIO, - }, { - }, +static const u32 iflags_to_gfs2[32] = { + [iflag_Sync] = GFS2_DIF_SYNC, + [iflag_Immutable] = GFS2_DIF_IMMUTABLE, + [iflag_Append] = GFS2_DIF_APPENDONLY, + [iflag_NoAtime] = GFS2_DIF_NOATIME, + [iflag_Index] = GFS2_DIF_EXHASH, + [iflag_JournalData] = GFS2_DIF_JDATA, + [iflag_DirectIO] = GFS2_DIF_DIRECTIO, + [iflag_InheritDirectIO] = GFS2_DIF_INHERIT_DIRECTIO, + [iflag_InheritJdata] = GFS2_DIF_INHERIT_JDATA, }; -static const struct gfs2_flag_eattr *get_by_ext2(u32 ext2) -{ - const struct gfs2_flag_eattr *p = gfs2_flag_eattrs; - for(; p->flag; p++) { - if (ext2 == p->ext2) - return p; - } - return NULL; -} - -static const struct gfs2_flag_eattr *get_by_gfs2(u32 gfs2) -{ - const struct gfs2_flag_eattr *p = gfs2_flag_eattrs; - for(; p->flag; p++) { - if (gfs2 == p->flag) - return p; - } - return NULL; -} - -static u32 gfs2_flags_to_ext2(u32 gfs2) -{ - const struct gfs2_flag_eattr *ea; - u32 ext2 = 0; - u32 mask = 1; - - for(; mask != 0; mask <<=1) { - if (mask & gfs2) { - ea = get_by_gfs2(mask); - if (ea) - ext2 |= ea->ext2; - } - } - return ext2; -} - -static int gfs2_flags_from_ext2(u32 *gfs2, u32 ext2) -{ - const struct gfs2_flag_eattr *ea; - u32 mask = 1; - - for(; mask != 0; mask <<= 1) { - if (mask & ext2) { - ea = get_by_ext2(mask); - if (ea == NULL) - return -EINVAL; - *gfs2 |= ea->flag; - } - } - return 0; -} +static const u32 gfs2_to_iflags[32] = { + [gfs2fl_Sync] = IFLAG_SYNC, + [gfs2fl_Immutable] = IFLAG_IMMUTABLE, + [gfs2fl_AppendOnly] = IFLAG_APPEND, + [gfs2fl_NoAtime] = IFLAG_NOATIME, + [gfs2fl_ExHash] = IFLAG_INDEX, + [gfs2fl_Jdata] = IFLAG_JOURNAL_DATA, + [gfs2fl_Directio] = IFLAG_DIRECTIO, + [gfs2fl_InheritDirectio] = IFLAG_INHERITDIRECTIO, + [gfs2fl_InheritJdata] = IFLAG_INHERITJDATA, +}; -static int get_ext2_flags(struct inode *inode, u32 __user *ptr) +static int gfs2_get_flags(struct inode *inode, u32 __user *ptr) { struct gfs2_inode *ip = inode->u.generic_ip; struct gfs2_holder gh; int error; - u32 ext2; + u32 iflags; gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); error = gfs2_glock_nq_m_atime(1, &gh); if (error) return error; - ext2 = gfs2_flags_to_ext2(ip->i_di.di_flags); - if (put_user(ext2, ptr)) + iflags = iflags_cvt(gfs2_to_iflags, ip->i_di.di_flags); + if (put_user(iflags, ptr)) error = -EFAULT; gfs2_glock_dq_m(1, &gh); @@ -665,7 +600,7 @@ static int get_ext2_flags(struct inode *inode, u32 __user *ptr) * @mask: Indicates which flags are valid * */ -static int gfs2_set_flags(struct inode *inode, u32 flags, u32 mask) +static int do_gfs2_set_flags(struct inode *inode, u32 flags, u32 mask) { struct gfs2_inode *ip = inode->u.generic_ip; struct buffer_head *bh; @@ -717,24 +652,23 @@ out: return error; } -static int set_ext2_flags(struct inode *inode, u32 __user *ptr) +static int gfs2_set_flags(struct inode *inode, u32 __user *ptr) { - u32 ext2, gfs2; - if (get_user(ext2, ptr)) + u32 iflags, gfsflags; + if (get_user(iflags, ptr)) return -EFAULT; - if (gfs2_flags_from_ext2(&gfs2, ext2)) - return -EINVAL; - return gfs2_set_flags(inode, gfs2, ~0); + gfsflags = iflags_cvt(iflags_to_gfs2, iflags); + return do_gfs2_set_flags(inode, gfsflags, ~0); } int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { - case EXT2_IOC_GETFLAGS: - return get_ext2_flags(inode, (u32 __user *)arg); - case EXT2_IOC_SETFLAGS: - return set_ext2_flags(inode, (u32 __user *)arg); + case IFLAGS_GET_IOC: + return gfs2_get_flags(inode, (u32 __user *)arg); + case IFLAGS_SET_IOC: + return gfs2_set_flags(inode, (u32 __user *)arg); } return -ENOTTY; } diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index a5fb4f99aa45..3ab40917383f 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -197,6 +197,22 @@ struct gfs2_quota { #define DT2IF(dt) (((dt) << 12) & S_IFMT) #define IF2DT(sif) (((sif) & S_IFMT) >> 12) +enum { + gfs2fl_Jdata = 0, + gfs2fl_ExHash = 1, + gfs2fl_Unused = 2, + gfs2fl_EaIndirect = 3, + gfs2fl_Directio = 4, + gfs2fl_Immutable = 5, + gfs2fl_AppendOnly = 6, + gfs2fl_NoAtime = 7, + gfs2fl_Sync = 8, + gfs2fl_System = 9, + gfs2fl_TruncInProg = 29, + gfs2fl_InheritDirectio = 30, + gfs2fl_InheritJdata = 31, +}; + /* Dinode flags */ #define GFS2_DIF_JDATA 0x00000001 #define GFS2_DIF_EXHASH 0x00000002 diff --git a/include/linux/iflags.h b/include/linux/iflags.h new file mode 100644 index 000000000000..1b4d9ef5d62b --- /dev/null +++ b/include/linux/iflags.h @@ -0,0 +1,104 @@ +#ifndef _LINUX_IFLAGS_H +#define _LINUX_IFLAGS_H + +/* + * A universal set of inode flags. + * + * Originally taken from ext2/3 with additions for other filesystems. + * Filesystems supporting this interface should interoperate with + * the lsattr and chattr command line tools. + * + * This interface is supported in whole or in part by: + * ext2 + * ext3 + * xfs + * jfs + * gfs2 + * + */ + +#define IFLAGS_GET_IOC _IOR('f', 1, long) +#define IFLAGS_SET_IOC _IOW('f', 2, long) + +/* + * These values are provided for use as indices of an array + * for use with the iflags_cvt function below + */ +enum { + iflag_SecureRm = 0, /* Secure deletion */ + iflag_Unrm = 1, /* Undelete */ + iflag_Compress = 2, /* Compress file */ + iflag_Sync = 3, /* Synchronous updates */ + iflag_Immutable = 4, /* Immutable */ + iflag_Append = 5, /* Append */ + iflag_NoDump = 6, /* Don't dump file */ + iflag_NoAtime = 7, /* No atime updates */ + /* Reserved for compression usage */ + iflag_Dirty = 8, + iflag_ComprBlk = 9, /* One or more compressed clusters */ + iflag_NoComp = 10, /* Don't compress */ + iflag_Ecompr = 11, /* Compression error */ + /* End of compression flags */ + iflag_Btree = 12, /* btree format dir */ + iflag_Index = 12, /* hash-indexed directory */ + iflag_Imagic = 13, /* AFS directory */ + iflag_JournalData = 14, /* file data should be journaled */ + iflag_NoTail = 15, /* file tail should not be merged */ + iflag_DirSync = 16, /* dirsync behaviour */ + iflag_TopDir = 17, /* Top of directory hierarchies */ + iflag_DirectIO = 18, /* Always use direct I/O on this file */ + iflag_InheritDirectIO = 19, /* Set DirectIO on new files in dir */ + iflag_InheritJdata = 20, /* Set JournalData on create in dir */ + iflag_Reserved = 31 /* reserved for ext2/3 lib */ +}; + +#define __IFL(x) (1<<(iflag_##x)) +#define IFLAG_SECRM __IFL(SecureRm) /* 0x00000001 */ +#define IFLAG_UNRM __IFL(Unrm) /* 0x00000002 */ +#define IFLAG_COMPR __IFL(Compr) /* 0x00000004 */ +#define IFLAG_SYNC __IFL(Sync) /* 0x00000008 */ +#define IFLAG_IMMUTABLE __IFL(Immutable) /* 0x00000010 */ +#define IFLAG_APPEND __IFL(Append) /* 0x00000020 */ +#define IFLAG_NODUMP __IFL(NoDump) /* 0x00000040 */ +#define IFLAG_NOATIME __IFL(NoAtime) /* 0x00000080 */ +#define IFLAG_DIRTY __IFL(Dirty) /* 0x00000100 */ +#define IFLAG_COMPRBLK __IFL(ComprBlk) /* 0x00000200 */ +#define IFLAG_NOCOMP __IFL(NoComp) /* 0x00000400 */ +#define IFLAG_ECOMPR __IFL(Ecompr) /* 0x00000800 */ +#define IFLAG_BTREE __IFL(Btree) /* 0x00001000 */ +#define IFLAG_INDEX __IFL(Index) /* 0x00001000 */ +#define IFLAG_IMAGIC __IFL(Imagic) /* 0x00002000 */ +#define IFLAG_JOURNAL_DATA __IFL(JournalData) /* 0x00004000 */ +#define IFLAG_NOTAIL __IFL(NoTail) /* 0x00008000 */ +#define IFLAG_DIRSYNC __IFL(DirSync) /* 0x00010000 */ +#define IFLAG_TOPDIR __IFL(TopDir) /* 0x00020000 */ +#define IFLAG_DIRECTIO __IFL(DirectIO) /* 0x00040000 */ +#define IFLAG_INHERITDIRECTIO __IFL(InheritDirectIO) /* 0x00080000 */ +#define IFLAG_INHERITJDATA __IFL(InheritJdata) /* 0x00100000 */ +#define IFLAG_RESERVED __IFL(Reserved) /* 0x80000000 */ + +#ifdef __KERNEL__ +/** + * iflags_cvt + * @table: A table of 32 u32 flags + * @val: a 32 bit value to convert + * + * This function can be used to convert between IFLAGS values and + * the filesystem's own flags values. + * + * Returns: the converted flags + */ +static inline u32 iflags_cvt(const u32 *table, u32 val) +{ + u32 res = 0; + while(val) { + if (val & 1) + res |= *table; + table++; + val >>= 1; + } + return res; +} +#endif /* __KERNEL__ */ + +#endif /* _LINUX_IFLAGS_H */ -- cgit v1.2.3