[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:
parent
e3167ded1f
commit
7ea9ea8322
3 changed files with 156 additions and 102 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
104
include/linux/iflags.h
Normal 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 */
|
Loading…
Reference in a new issue