[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 <swhiteho@redhat.com>
This commit is contained in:
Steven Whitehouse 2006-03-31 15:01:28 -05:00
parent e3167ded1f
commit 7ea9ea8322
3 changed files with 156 additions and 102 deletions

View file

@ -21,6 +21,7 @@
#include <linux/gfs2_ondisk.h> #include <linux/gfs2_ondisk.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/iflags.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -536,110 +537,44 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
return error; return error;
} }
const struct gfs2_flag_eattr { static const u32 iflags_to_gfs2[32] = {
u32 flag; [iflag_Sync] = GFS2_DIF_SYNC,
u32 ext2; [iflag_Immutable] = GFS2_DIF_IMMUTABLE,
} gfs2_flag_eattrs[] = { [iflag_Append] = GFS2_DIF_APPENDONLY,
{ [iflag_NoAtime] = GFS2_DIF_NOATIME,
.flag = GFS2_DIF_IMMUTABLE, [iflag_Index] = GFS2_DIF_EXHASH,
.ext2 = EXT2_IMMUTABLE_FL, [iflag_JournalData] = GFS2_DIF_JDATA,
}, { [iflag_DirectIO] = GFS2_DIF_DIRECTIO,
.flag = GFS2_DIF_APPENDONLY, [iflag_InheritDirectIO] = GFS2_DIF_INHERIT_DIRECTIO,
.ext2 = EXT2_APPEND_FL, [iflag_InheritJdata] = GFS2_DIF_INHERIT_JDATA,
}, {
.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 struct gfs2_flag_eattr *get_by_ext2(u32 ext2) static const u32 gfs2_to_iflags[32] = {
{ [gfs2fl_Sync] = IFLAG_SYNC,
const struct gfs2_flag_eattr *p = gfs2_flag_eattrs; [gfs2fl_Immutable] = IFLAG_IMMUTABLE,
for(; p->flag; p++) { [gfs2fl_AppendOnly] = IFLAG_APPEND,
if (ext2 == p->ext2) [gfs2fl_NoAtime] = IFLAG_NOATIME,
return p; [gfs2fl_ExHash] = IFLAG_INDEX,
} [gfs2fl_Jdata] = IFLAG_JOURNAL_DATA,
return NULL; [gfs2fl_Directio] = IFLAG_DIRECTIO,
} [gfs2fl_InheritDirectio] = IFLAG_INHERITDIRECTIO,
[gfs2fl_InheritJdata] = IFLAG_INHERITJDATA,
};
static const struct gfs2_flag_eattr *get_by_gfs2(u32 gfs2) static int gfs2_get_flags(struct inode *inode, u32 __user *ptr)
{
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 int get_ext2_flags(struct inode *inode, u32 __user *ptr)
{ {
struct gfs2_inode *ip = inode->u.generic_ip; struct gfs2_inode *ip = inode->u.generic_ip;
struct gfs2_holder gh; struct gfs2_holder gh;
int error; int error;
u32 ext2; u32 iflags;
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
error = gfs2_glock_nq_m_atime(1, &gh); error = gfs2_glock_nq_m_atime(1, &gh);
if (error) if (error)
return error; return error;
ext2 = gfs2_flags_to_ext2(ip->i_di.di_flags); iflags = iflags_cvt(gfs2_to_iflags, ip->i_di.di_flags);
if (put_user(ext2, ptr)) if (put_user(iflags, ptr))
error = -EFAULT; error = -EFAULT;
gfs2_glock_dq_m(1, &gh); 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 * @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 gfs2_inode *ip = inode->u.generic_ip;
struct buffer_head *bh; struct buffer_head *bh;
@ -717,24 +652,23 @@ static int gfs2_set_flags(struct inode *inode, u32 flags, u32 mask)
return error; 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; u32 iflags, gfsflags;
if (get_user(ext2, ptr)) if (get_user(iflags, ptr))
return -EFAULT; return -EFAULT;
if (gfs2_flags_from_ext2(&gfs2, ext2)) gfsflags = iflags_cvt(iflags_to_gfs2, iflags);
return -EINVAL; return do_gfs2_set_flags(inode, gfsflags, ~0);
return gfs2_set_flags(inode, gfs2, ~0);
} }
int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
switch(cmd) { switch(cmd) {
case EXT2_IOC_GETFLAGS: case IFLAGS_GET_IOC:
return get_ext2_flags(inode, (u32 __user *)arg); return gfs2_get_flags(inode, (u32 __user *)arg);
case EXT2_IOC_SETFLAGS: case IFLAGS_SET_IOC:
return set_ext2_flags(inode, (u32 __user *)arg); return gfs2_set_flags(inode, (u32 __user *)arg);
} }
return -ENOTTY; return -ENOTTY;
} }

View file

@ -197,6 +197,22 @@ struct gfs2_quota {
#define DT2IF(dt) (((dt) << 12) & S_IFMT) #define DT2IF(dt) (((dt) << 12) & S_IFMT)
#define IF2DT(sif) (((sif) & S_IFMT) >> 12) #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 */ /* Dinode flags */
#define GFS2_DIF_JDATA 0x00000001 #define GFS2_DIF_JDATA 0x00000001
#define GFS2_DIF_EXHASH 0x00000002 #define GFS2_DIF_EXHASH 0x00000002

104
include/linux/iflags.h Normal file
View file

@ -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 */