Commit 7ea9ea83 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

[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: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent e3167ded
Loading
Loading
Loading
Loading
+36 −102
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/gfs2_ondisk.h>
#include <linux/ext2_fs.h>
#include <linux/crc32.h>
#include <linux/iflags.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>

@@ -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 @@ static int gfs2_set_flags(struct inode *inode, u32 flags, u32 mask)
	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;
}
+16 −0
Original line number Diff line number Diff line
@@ -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

include/linux/iflags.h

0 → 100644
+104 −0
Original line number Diff line number Diff line
#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 */