diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-31 15:01:28 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-31 15:01:28 -0500 |
commit | 7ea9ea832212c4a755650f7c7cc1ff0b63292a41 (patch) | |
tree | 86ccc012c7b841de6391e7408bf3f3097ca2710d | |
parent | e3167ded1f1b16424bc14d5673cdc5414f179970 (diff) |
[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>
-rw-r--r-- | fs/gfs2/ops_file.c | 138 | ||||
-rw-r--r-- | include/linux/gfs2_ondisk.h | 16 | ||||
-rw-r--r-- | include/linux/iflags.h | 104 |
3 files changed, 156 insertions, 102 deletions
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 @@ | |||
21 | #include <linux/gfs2_ondisk.h> | 21 | #include <linux/gfs2_ondisk.h> |
22 | #include <linux/ext2_fs.h> | 22 | #include <linux/ext2_fs.h> |
23 | #include <linux/crc32.h> | 23 | #include <linux/crc32.h> |
24 | #include <linux/iflags.h> | ||
24 | #include <asm/semaphore.h> | 25 | #include <asm/semaphore.h> |
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | 27 | ||
@@ -536,110 +537,44 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
536 | return error; | 537 | return error; |
537 | } | 538 | } |
538 | 539 | ||
539 | const struct gfs2_flag_eattr { | 540 | static const u32 iflags_to_gfs2[32] = { |
540 | u32 flag; | 541 | [iflag_Sync] = GFS2_DIF_SYNC, |
541 | u32 ext2; | 542 | [iflag_Immutable] = GFS2_DIF_IMMUTABLE, |
542 | } gfs2_flag_eattrs[] = { | 543 | [iflag_Append] = GFS2_DIF_APPENDONLY, |
543 | { | 544 | [iflag_NoAtime] = GFS2_DIF_NOATIME, |
544 | .flag = GFS2_DIF_IMMUTABLE, | 545 | [iflag_Index] = GFS2_DIF_EXHASH, |
545 | .ext2 = EXT2_IMMUTABLE_FL, | 546 | [iflag_JournalData] = GFS2_DIF_JDATA, |
546 | }, { | 547 | [iflag_DirectIO] = GFS2_DIF_DIRECTIO, |
547 | .flag = GFS2_DIF_APPENDONLY, | 548 | [iflag_InheritDirectIO] = GFS2_DIF_INHERIT_DIRECTIO, |
548 | .ext2 = EXT2_APPEND_FL, | 549 | [iflag_InheritJdata] = GFS2_DIF_INHERIT_JDATA, |
549 | }, { | ||
550 | .flag = GFS2_DIF_JDATA, | ||
551 | .ext2 = EXT2_JOURNAL_DATA_FL, | ||
552 | }, { | ||
553 | .flag = GFS2_DIF_EXHASH, | ||
554 | .ext2 = EXT2_INDEX_FL, | ||
555 | }, { | ||
556 | .flag = GFS2_DIF_EA_INDIRECT, | ||
557 | }, { | ||
558 | .flag = GFS2_DIF_DIRECTIO, | ||
559 | }, { | ||
560 | .flag = GFS2_DIF_NOATIME, | ||
561 | .ext2 = EXT2_NOATIME_FL, | ||
562 | }, { | ||
563 | .flag = GFS2_DIF_SYNC, | ||
564 | .ext2 = EXT2_SYNC_FL, | ||
565 | }, { | ||
566 | .flag = GFS2_DIF_SYSTEM, | ||
567 | }, { | ||
568 | .flag = GFS2_DIF_TRUNC_IN_PROG, | ||
569 | }, { | ||
570 | .flag = GFS2_DIF_INHERIT_JDATA, | ||
571 | }, { | ||
572 | .flag = GFS2_DIF_INHERIT_DIRECTIO, | ||
573 | }, { | ||
574 | }, | ||
575 | }; | 550 | }; |
576 | 551 | ||
577 | static const struct gfs2_flag_eattr *get_by_ext2(u32 ext2) | 552 | static const u32 gfs2_to_iflags[32] = { |
578 | { | 553 | [gfs2fl_Sync] = IFLAG_SYNC, |
579 | const struct gfs2_flag_eattr *p = gfs2_flag_eattrs; | 554 | [gfs2fl_Immutable] = IFLAG_IMMUTABLE, |
580 | for(; p->flag; p++) { | 555 | [gfs2fl_AppendOnly] = IFLAG_APPEND, |
581 | if (ext2 == p->ext2) | 556 | [gfs2fl_NoAtime] = IFLAG_NOATIME, |
582 | return p; | 557 | [gfs2fl_ExHash] = IFLAG_INDEX, |
583 | } | 558 | [gfs2fl_Jdata] = IFLAG_JOURNAL_DATA, |
584 | return NULL; | 559 | [gfs2fl_Directio] = IFLAG_DIRECTIO, |
585 | } | 560 | [gfs2fl_InheritDirectio] = IFLAG_INHERITDIRECTIO, |
586 | 561 | [gfs2fl_InheritJdata] = IFLAG_INHERITJDATA, | |
587 | static const struct gfs2_flag_eattr *get_by_gfs2(u32 gfs2) | 562 | }; |
588 | { | ||
589 | const struct gfs2_flag_eattr *p = gfs2_flag_eattrs; | ||
590 | for(; p->flag; p++) { | ||
591 | if (gfs2 == p->flag) | ||
592 | return p; | ||
593 | } | ||
594 | return NULL; | ||
595 | } | ||
596 | |||
597 | static u32 gfs2_flags_to_ext2(u32 gfs2) | ||
598 | { | ||
599 | const struct gfs2_flag_eattr *ea; | ||
600 | u32 ext2 = 0; | ||
601 | u32 mask = 1; | ||
602 | |||
603 | for(; mask != 0; mask <<=1) { | ||
604 | if (mask & gfs2) { | ||
605 | ea = get_by_gfs2(mask); | ||
606 | if (ea) | ||
607 | ext2 |= ea->ext2; | ||
608 | } | ||
609 | } | ||
610 | return ext2; | ||
611 | } | ||
612 | |||
613 | static int gfs2_flags_from_ext2(u32 *gfs2, u32 ext2) | ||
614 | { | ||
615 | const struct gfs2_flag_eattr *ea; | ||
616 | u32 mask = 1; | ||
617 | |||
618 | for(; mask != 0; mask <<= 1) { | ||
619 | if (mask & ext2) { | ||
620 | ea = get_by_ext2(mask); | ||
621 | if (ea == NULL) | ||
622 | return -EINVAL; | ||
623 | *gfs2 |= ea->flag; | ||
624 | } | ||
625 | } | ||
626 | return 0; | ||
627 | } | ||
628 | 563 | ||
629 | static int get_ext2_flags(struct inode *inode, u32 __user *ptr) | 564 | static int gfs2_get_flags(struct inode *inode, u32 __user *ptr) |
630 | { | 565 | { |
631 | struct gfs2_inode *ip = inode->u.generic_ip; | 566 | struct gfs2_inode *ip = inode->u.generic_ip; |
632 | struct gfs2_holder gh; | 567 | struct gfs2_holder gh; |
633 | int error; | 568 | int error; |
634 | u32 ext2; | 569 | u32 iflags; |
635 | 570 | ||
636 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); | 571 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); |
637 | error = gfs2_glock_nq_m_atime(1, &gh); | 572 | error = gfs2_glock_nq_m_atime(1, &gh); |
638 | if (error) | 573 | if (error) |
639 | return error; | 574 | return error; |
640 | 575 | ||
641 | ext2 = gfs2_flags_to_ext2(ip->i_di.di_flags); | 576 | iflags = iflags_cvt(gfs2_to_iflags, ip->i_di.di_flags); |
642 | if (put_user(ext2, ptr)) | 577 | if (put_user(iflags, ptr)) |
643 | error = -EFAULT; | 578 | error = -EFAULT; |
644 | 579 | ||
645 | gfs2_glock_dq_m(1, &gh); | 580 | gfs2_glock_dq_m(1, &gh); |
@@ -665,7 +600,7 @@ static int get_ext2_flags(struct inode *inode, u32 __user *ptr) | |||
665 | * @mask: Indicates which flags are valid | 600 | * @mask: Indicates which flags are valid |
666 | * | 601 | * |
667 | */ | 602 | */ |
668 | static int gfs2_set_flags(struct inode *inode, u32 flags, u32 mask) | 603 | static int do_gfs2_set_flags(struct inode *inode, u32 flags, u32 mask) |
669 | { | 604 | { |
670 | struct gfs2_inode *ip = inode->u.generic_ip; | 605 | struct gfs2_inode *ip = inode->u.generic_ip; |
671 | struct buffer_head *bh; | 606 | struct buffer_head *bh; |
@@ -717,24 +652,23 @@ out: | |||
717 | return error; | 652 | return error; |
718 | } | 653 | } |
719 | 654 | ||
720 | static int set_ext2_flags(struct inode *inode, u32 __user *ptr) | 655 | static int gfs2_set_flags(struct inode *inode, u32 __user *ptr) |
721 | { | 656 | { |
722 | u32 ext2, gfs2; | 657 | u32 iflags, gfsflags; |
723 | if (get_user(ext2, ptr)) | 658 | if (get_user(iflags, ptr)) |
724 | return -EFAULT; | 659 | return -EFAULT; |
725 | if (gfs2_flags_from_ext2(&gfs2, ext2)) | 660 | gfsflags = iflags_cvt(iflags_to_gfs2, iflags); |
726 | return -EINVAL; | 661 | return do_gfs2_set_flags(inode, gfsflags, ~0); |
727 | return gfs2_set_flags(inode, gfs2, ~0); | ||
728 | } | 662 | } |
729 | 663 | ||
730 | int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 664 | int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, |
731 | unsigned long arg) | 665 | unsigned long arg) |
732 | { | 666 | { |
733 | switch(cmd) { | 667 | switch(cmd) { |
734 | case EXT2_IOC_GETFLAGS: | 668 | case IFLAGS_GET_IOC: |
735 | return get_ext2_flags(inode, (u32 __user *)arg); | 669 | return gfs2_get_flags(inode, (u32 __user *)arg); |
736 | case EXT2_IOC_SETFLAGS: | 670 | case IFLAGS_SET_IOC: |
737 | return set_ext2_flags(inode, (u32 __user *)arg); | 671 | return gfs2_set_flags(inode, (u32 __user *)arg); |
738 | } | 672 | } |
739 | return -ENOTTY; | 673 | return -ENOTTY; |
740 | } | 674 | } |
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 { | |||
197 | #define DT2IF(dt) (((dt) << 12) & S_IFMT) | 197 | #define DT2IF(dt) (((dt) << 12) & S_IFMT) |
198 | #define IF2DT(sif) (((sif) & S_IFMT) >> 12) | 198 | #define IF2DT(sif) (((sif) & S_IFMT) >> 12) |
199 | 199 | ||
200 | enum { | ||
201 | gfs2fl_Jdata = 0, | ||
202 | gfs2fl_ExHash = 1, | ||
203 | gfs2fl_Unused = 2, | ||
204 | gfs2fl_EaIndirect = 3, | ||
205 | gfs2fl_Directio = 4, | ||
206 | gfs2fl_Immutable = 5, | ||
207 | gfs2fl_AppendOnly = 6, | ||
208 | gfs2fl_NoAtime = 7, | ||
209 | gfs2fl_Sync = 8, | ||
210 | gfs2fl_System = 9, | ||
211 | gfs2fl_TruncInProg = 29, | ||
212 | gfs2fl_InheritDirectio = 30, | ||
213 | gfs2fl_InheritJdata = 31, | ||
214 | }; | ||
215 | |||
200 | /* Dinode flags */ | 216 | /* Dinode flags */ |
201 | #define GFS2_DIF_JDATA 0x00000001 | 217 | #define GFS2_DIF_JDATA 0x00000001 |
202 | #define GFS2_DIF_EXHASH 0x00000002 | 218 | #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 @@ | |||
1 | #ifndef _LINUX_IFLAGS_H | ||
2 | #define _LINUX_IFLAGS_H | ||
3 | |||
4 | /* | ||
5 | * A universal set of inode flags. | ||
6 | * | ||
7 | * Originally taken from ext2/3 with additions for other filesystems. | ||
8 | * Filesystems supporting this interface should interoperate with | ||
9 | * the lsattr and chattr command line tools. | ||
10 | * | ||
11 | * This interface is supported in whole or in part by: | ||
12 | * ext2 | ||
13 | * ext3 | ||
14 | * xfs | ||
15 | * jfs | ||
16 | * gfs2 | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #define IFLAGS_GET_IOC _IOR('f', 1, long) | ||
21 | #define IFLAGS_SET_IOC _IOW('f', 2, long) | ||
22 | |||
23 | /* | ||
24 | * These values are provided for use as indices of an array | ||
25 | * for use with the iflags_cvt function below | ||
26 | */ | ||
27 | enum { | ||
28 | iflag_SecureRm = 0, /* Secure deletion */ | ||
29 | iflag_Unrm = 1, /* Undelete */ | ||
30 | iflag_Compress = 2, /* Compress file */ | ||
31 | iflag_Sync = 3, /* Synchronous updates */ | ||
32 | iflag_Immutable = 4, /* Immutable */ | ||
33 | iflag_Append = 5, /* Append */ | ||
34 | iflag_NoDump = 6, /* Don't dump file */ | ||
35 | iflag_NoAtime = 7, /* No atime updates */ | ||
36 | /* Reserved for compression usage */ | ||
37 | iflag_Dirty = 8, | ||
38 | iflag_ComprBlk = 9, /* One or more compressed clusters */ | ||
39 | iflag_NoComp = 10, /* Don't compress */ | ||
40 | iflag_Ecompr = 11, /* Compression error */ | ||
41 | /* End of compression flags */ | ||
42 | iflag_Btree = 12, /* btree format dir */ | ||
43 | iflag_Index = 12, /* hash-indexed directory */ | ||
44 | iflag_Imagic = 13, /* AFS directory */ | ||
45 | iflag_JournalData = 14, /* file data should be journaled */ | ||
46 | iflag_NoTail = 15, /* file tail should not be merged */ | ||
47 | iflag_DirSync = 16, /* dirsync behaviour */ | ||
48 | iflag_TopDir = 17, /* Top of directory hierarchies */ | ||
49 | iflag_DirectIO = 18, /* Always use direct I/O on this file */ | ||
50 | iflag_InheritDirectIO = 19, /* Set DirectIO on new files in dir */ | ||
51 | iflag_InheritJdata = 20, /* Set JournalData on create in dir */ | ||
52 | iflag_Reserved = 31 /* reserved for ext2/3 lib */ | ||
53 | }; | ||
54 | |||
55 | #define __IFL(x) (1<<(iflag_##x)) | ||
56 | #define IFLAG_SECRM __IFL(SecureRm) /* 0x00000001 */ | ||
57 | #define IFLAG_UNRM __IFL(Unrm) /* 0x00000002 */ | ||
58 | #define IFLAG_COMPR __IFL(Compr) /* 0x00000004 */ | ||
59 | #define IFLAG_SYNC __IFL(Sync) /* 0x00000008 */ | ||
60 | #define IFLAG_IMMUTABLE __IFL(Immutable) /* 0x00000010 */ | ||
61 | #define IFLAG_APPEND __IFL(Append) /* 0x00000020 */ | ||
62 | #define IFLAG_NODUMP __IFL(NoDump) /* 0x00000040 */ | ||
63 | #define IFLAG_NOATIME __IFL(NoAtime) /* 0x00000080 */ | ||
64 | #define IFLAG_DIRTY __IFL(Dirty) /* 0x00000100 */ | ||
65 | #define IFLAG_COMPRBLK __IFL(ComprBlk) /* 0x00000200 */ | ||
66 | #define IFLAG_NOCOMP __IFL(NoComp) /* 0x00000400 */ | ||
67 | #define IFLAG_ECOMPR __IFL(Ecompr) /* 0x00000800 */ | ||
68 | #define IFLAG_BTREE __IFL(Btree) /* 0x00001000 */ | ||
69 | #define IFLAG_INDEX __IFL(Index) /* 0x00001000 */ | ||
70 | #define IFLAG_IMAGIC __IFL(Imagic) /* 0x00002000 */ | ||
71 | #define IFLAG_JOURNAL_DATA __IFL(JournalData) /* 0x00004000 */ | ||
72 | #define IFLAG_NOTAIL __IFL(NoTail) /* 0x00008000 */ | ||
73 | #define IFLAG_DIRSYNC __IFL(DirSync) /* 0x00010000 */ | ||
74 | #define IFLAG_TOPDIR __IFL(TopDir) /* 0x00020000 */ | ||
75 | #define IFLAG_DIRECTIO __IFL(DirectIO) /* 0x00040000 */ | ||
76 | #define IFLAG_INHERITDIRECTIO __IFL(InheritDirectIO) /* 0x00080000 */ | ||
77 | #define IFLAG_INHERITJDATA __IFL(InheritJdata) /* 0x00100000 */ | ||
78 | #define IFLAG_RESERVED __IFL(Reserved) /* 0x80000000 */ | ||
79 | |||
80 | #ifdef __KERNEL__ | ||
81 | /** | ||
82 | * iflags_cvt | ||
83 | * @table: A table of 32 u32 flags | ||
84 | * @val: a 32 bit value to convert | ||
85 | * | ||
86 | * This function can be used to convert between IFLAGS values and | ||
87 | * the filesystem's own flags values. | ||
88 | * | ||
89 | * Returns: the converted flags | ||
90 | */ | ||
91 | static inline u32 iflags_cvt(const u32 *table, u32 val) | ||
92 | { | ||
93 | u32 res = 0; | ||
94 | while(val) { | ||
95 | if (val & 1) | ||
96 | res |= *table; | ||
97 | table++; | ||
98 | val >>= 1; | ||
99 | } | ||
100 | return res; | ||
101 | } | ||
102 | #endif /* __KERNEL__ */ | ||
103 | |||
104 | #endif /* _LINUX_IFLAGS_H */ | ||