Commit ca4d147e62df370c334898464023aa7f9126abe1
Committed by
Mark Fasheh
1 parent
b4c98f625f
Exists in
master
and in
4 other branches
ocfs2: add ext2 attributes
Support immutable, and other attributes. Some renaming and other minor fixes done by myself. Signed-off-by: Herbert Poetzl <herbert@13thfloor.at> Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Showing 9 changed files with 217 additions and 6 deletions Side-by-side Diff
fs/ocfs2/Makefile
fs/ocfs2/dlmglue.c
... | ... | @@ -1330,6 +1330,7 @@ |
1330 | 1330 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); |
1331 | 1331 | lvb->lvb_imtime_packed = |
1332 | 1332 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); |
1333 | + lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); | |
1333 | 1334 | |
1334 | 1335 | mlog_meta_lvb(0, lockres); |
1335 | 1336 | |
... | ... | @@ -1360,6 +1361,9 @@ |
1360 | 1361 | oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); |
1361 | 1362 | i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); |
1362 | 1363 | |
1364 | + oi->ip_attr = be32_to_cpu(lvb->lvb_iattr); | |
1365 | + ocfs2_set_inode_flags(inode); | |
1366 | + | |
1363 | 1367 | /* fast-symlinks are a special case */ |
1364 | 1368 | if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) |
1365 | 1369 | inode->i_blocks = 0; |
1366 | 1370 | |
... | ... | @@ -2899,9 +2903,10 @@ |
2899 | 2903 | be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), |
2900 | 2904 | be16_to_cpu(lvb->lvb_imode)); |
2901 | 2905 | mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " |
2902 | - "mtime_packed 0x%llx\n", be16_to_cpu(lvb->lvb_inlink), | |
2906 | + "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink), | |
2903 | 2907 | (long long)be64_to_cpu(lvb->lvb_iatime_packed), |
2904 | 2908 | (long long)be64_to_cpu(lvb->lvb_ictime_packed), |
2905 | - (long long)be64_to_cpu(lvb->lvb_imtime_packed)); | |
2909 | + (long long)be64_to_cpu(lvb->lvb_imtime_packed), | |
2910 | + be32_to_cpu(lvb->lvb_iattr)); | |
2906 | 2911 | } |
fs/ocfs2/dlmglue.h
... | ... | @@ -27,7 +27,7 @@ |
27 | 27 | #ifndef DLMGLUE_H |
28 | 28 | #define DLMGLUE_H |
29 | 29 | |
30 | -#define OCFS2_LVB_VERSION 2 | |
30 | +#define OCFS2_LVB_VERSION 3 | |
31 | 31 | |
32 | 32 | struct ocfs2_meta_lvb { |
33 | 33 | __be32 lvb_version; |
... | ... | @@ -40,7 +40,8 @@ |
40 | 40 | __be64 lvb_isize; |
41 | 41 | __be16 lvb_imode; |
42 | 42 | __be16 lvb_inlink; |
43 | - __be32 lvb_reserved[3]; | |
43 | + __be32 lvb_iattr; | |
44 | + __be32 lvb_reserved[2]; | |
44 | 45 | }; |
45 | 46 | |
46 | 47 | /* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */ |
fs/ocfs2/file.c
... | ... | @@ -44,6 +44,7 @@ |
44 | 44 | #include "file.h" |
45 | 45 | #include "sysfile.h" |
46 | 46 | #include "inode.h" |
47 | +#include "ioctl.h" | |
47 | 48 | #include "journal.h" |
48 | 49 | #include "mmap.h" |
49 | 50 | #include "suballoc.h" |
50 | 51 | |
... | ... | @@ -1227,11 +1228,13 @@ |
1227 | 1228 | .open = ocfs2_file_open, |
1228 | 1229 | .aio_read = ocfs2_file_aio_read, |
1229 | 1230 | .aio_write = ocfs2_file_aio_write, |
1231 | + .ioctl = ocfs2_ioctl, | |
1230 | 1232 | }; |
1231 | 1233 | |
1232 | 1234 | const struct file_operations ocfs2_dops = { |
1233 | 1235 | .read = generic_read_dir, |
1234 | 1236 | .readdir = ocfs2_readdir, |
1235 | 1237 | .fsync = ocfs2_sync_file, |
1238 | + .ioctl = ocfs2_ioctl, | |
1236 | 1239 | }; |
fs/ocfs2/inode.c
... | ... | @@ -71,6 +71,26 @@ |
71 | 71 | struct inode *inode, |
72 | 72 | struct buffer_head *fe_bh); |
73 | 73 | |
74 | +void ocfs2_set_inode_flags(struct inode *inode) | |
75 | +{ | |
76 | + unsigned int flags = OCFS2_I(inode)->ip_attr; | |
77 | + | |
78 | + inode->i_flags &= ~(S_IMMUTABLE | | |
79 | + S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC); | |
80 | + | |
81 | + if (flags & OCFS2_IMMUTABLE_FL) | |
82 | + inode->i_flags |= S_IMMUTABLE; | |
83 | + | |
84 | + if (flags & OCFS2_SYNC_FL) | |
85 | + inode->i_flags |= S_SYNC; | |
86 | + if (flags & OCFS2_APPEND_FL) | |
87 | + inode->i_flags |= S_APPEND; | |
88 | + if (flags & OCFS2_NOATIME_FL) | |
89 | + inode->i_flags |= S_NOATIME; | |
90 | + if (flags & OCFS2_DIRSYNC_FL) | |
91 | + inode->i_flags |= S_DIRSYNC; | |
92 | +} | |
93 | + | |
74 | 94 | struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, |
75 | 95 | u64 blkno, |
76 | 96 | int delete_vote) |
... | ... | @@ -260,7 +280,6 @@ |
260 | 280 | inode->i_blocks = |
261 | 281 | ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); |
262 | 282 | inode->i_mapping->a_ops = &ocfs2_aops; |
263 | - inode->i_flags |= S_NOATIME; | |
264 | 283 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); |
265 | 284 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); |
266 | 285 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); |
... | ... | @@ -276,6 +295,7 @@ |
276 | 295 | |
277 | 296 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
278 | 297 | OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; |
298 | + OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | |
279 | 299 | |
280 | 300 | if (create_ino) |
281 | 301 | inode->i_ino = ino_from_blkno(inode->i_sb, |
... | ... | @@ -330,6 +350,9 @@ |
330 | 350 | ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, |
331 | 351 | OCFS2_LOCK_TYPE_DATA, inode); |
332 | 352 | |
353 | + ocfs2_set_inode_flags(inode); | |
354 | + inode->i_flags |= S_NOATIME; | |
355 | + | |
333 | 356 | status = 0; |
334 | 357 | bail: |
335 | 358 | mlog_exit(status); |
... | ... | @@ -1131,6 +1154,7 @@ |
1131 | 1154 | |
1132 | 1155 | spin_lock(&OCFS2_I(inode)->ip_lock); |
1133 | 1156 | fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); |
1157 | + fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr); | |
1134 | 1158 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
1135 | 1159 | |
1136 | 1160 | fe->i_size = cpu_to_le64(i_size_read(inode)); |
... | ... | @@ -1169,6 +1193,8 @@ |
1169 | 1193 | spin_lock(&OCFS2_I(inode)->ip_lock); |
1170 | 1194 | |
1171 | 1195 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
1196 | + OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | |
1197 | + ocfs2_set_inode_flags(inode); | |
1172 | 1198 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
1173 | 1199 | inode->i_nlink = le16_to_cpu(fe->i_links_count); |
1174 | 1200 | inode->i_uid = le32_to_cpu(fe->i_uid); |
fs/ocfs2/inode.h
... | ... | @@ -56,6 +56,7 @@ |
56 | 56 | struct ocfs2_journal_handle *ip_handle; |
57 | 57 | |
58 | 58 | u32 ip_flags; /* see below */ |
59 | + u32 ip_attr; /* inode attributes */ | |
59 | 60 | |
60 | 61 | /* protected by recovery_lock. */ |
61 | 62 | struct inode *ip_next_orphan; |
... | ... | @@ -141,6 +142,8 @@ |
141 | 142 | struct buffer_head *bh); |
142 | 143 | int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); |
143 | 144 | int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); |
145 | + | |
146 | +void ocfs2_set_inode_flags(struct inode *inode); | |
144 | 147 | |
145 | 148 | #endif /* OCFS2_INODE_H */ |
fs/ocfs2/ioctl.c
1 | +/* | |
2 | + * linux/fs/ocfs2/ioctl.c | |
3 | + * | |
4 | + * Copyright (C) 2006 Herbert Poetzl | |
5 | + * adapted from Remy Card's ext2/ioctl.c | |
6 | + */ | |
7 | + | |
8 | +#include <linux/fs.h> | |
9 | +#include <linux/mount.h> | |
10 | + | |
11 | +#define MLOG_MASK_PREFIX ML_INODE | |
12 | +#include <cluster/masklog.h> | |
13 | + | |
14 | +#include "ocfs2.h" | |
15 | +#include "alloc.h" | |
16 | +#include "dlmglue.h" | |
17 | +#include "inode.h" | |
18 | +#include "journal.h" | |
19 | + | |
20 | +#include "ocfs2_fs.h" | |
21 | +#include <linux/ext2_fs.h> | |
22 | + | |
23 | +static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) | |
24 | +{ | |
25 | + int status; | |
26 | + | |
27 | + status = ocfs2_meta_lock(inode, NULL, NULL, 0); | |
28 | + if (status < 0) { | |
29 | + mlog_errno(status); | |
30 | + return status; | |
31 | + } | |
32 | + *flags = OCFS2_I(inode)->ip_attr; | |
33 | + ocfs2_meta_unlock(inode, 0); | |
34 | + | |
35 | + mlog_exit(status); | |
36 | + return status; | |
37 | +} | |
38 | + | |
39 | +static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, | |
40 | + unsigned mask) | |
41 | +{ | |
42 | + struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode); | |
43 | + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | |
44 | + struct ocfs2_journal_handle *handle = NULL; | |
45 | + struct buffer_head *bh = NULL; | |
46 | + unsigned oldflags; | |
47 | + int status; | |
48 | + | |
49 | + mutex_lock(&inode->i_mutex); | |
50 | + | |
51 | + status = ocfs2_meta_lock(inode, NULL, &bh, 1); | |
52 | + if (status < 0) { | |
53 | + mlog_errno(status); | |
54 | + goto bail; | |
55 | + } | |
56 | + | |
57 | + status = -EROFS; | |
58 | + if (IS_RDONLY(inode)) | |
59 | + goto bail_unlock; | |
60 | + | |
61 | + status = -EACCES; | |
62 | + if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | |
63 | + goto bail_unlock; | |
64 | + | |
65 | + if (!S_ISDIR(inode->i_mode)) | |
66 | + flags &= ~OCFS2_DIRSYNC_FL; | |
67 | + | |
68 | + handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); | |
69 | + if (IS_ERR(handle)) { | |
70 | + status = PTR_ERR(handle); | |
71 | + mlog_errno(status); | |
72 | + goto bail_unlock; | |
73 | + } | |
74 | + | |
75 | + oldflags = ocfs2_inode->ip_attr; | |
76 | + flags = flags & mask; | |
77 | + flags |= oldflags & ~mask; | |
78 | + | |
79 | + /* | |
80 | + * The IMMUTABLE and APPEND_ONLY flags can only be changed by | |
81 | + * the relevant capability. | |
82 | + */ | |
83 | + status = -EPERM; | |
84 | + if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & | |
85 | + (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { | |
86 | + if (!capable(CAP_LINUX_IMMUTABLE)) | |
87 | + goto bail_unlock; | |
88 | + } | |
89 | + | |
90 | + ocfs2_inode->ip_attr = flags; | |
91 | + ocfs2_set_inode_flags(inode); | |
92 | + | |
93 | + status = ocfs2_mark_inode_dirty(handle, inode, bh); | |
94 | + if (status < 0) | |
95 | + mlog_errno(status); | |
96 | + | |
97 | + ocfs2_commit_trans(handle); | |
98 | +bail_unlock: | |
99 | + ocfs2_meta_unlock(inode, 1); | |
100 | +bail: | |
101 | + mutex_unlock(&inode->i_mutex); | |
102 | + | |
103 | + if (bh) | |
104 | + brelse(bh); | |
105 | + | |
106 | + mlog_exit(status); | |
107 | + return status; | |
108 | +} | |
109 | + | |
110 | +int ocfs2_ioctl(struct inode * inode, struct file * filp, | |
111 | + unsigned int cmd, unsigned long arg) | |
112 | +{ | |
113 | + unsigned int flags; | |
114 | + int status; | |
115 | + | |
116 | + switch (cmd) { | |
117 | + case OCFS2_IOC_GETFLAGS: | |
118 | + status = ocfs2_get_inode_attr(inode, &flags); | |
119 | + if (status < 0) | |
120 | + return status; | |
121 | + | |
122 | + flags &= OCFS2_FL_VISIBLE; | |
123 | + return put_user(flags, (int __user *) arg); | |
124 | + case OCFS2_IOC_SETFLAGS: | |
125 | + if (get_user(flags, (int __user *) arg)) | |
126 | + return -EFAULT; | |
127 | + | |
128 | + return ocfs2_set_inode_attr(inode, flags, | |
129 | + OCFS2_FL_MODIFIABLE); | |
130 | + default: | |
131 | + return -ENOTTY; | |
132 | + } | |
133 | +} |
fs/ocfs2/ioctl.h
1 | +/* | |
2 | + * ioctl.h | |
3 | + * | |
4 | + * Function prototypes | |
5 | + * | |
6 | + * Copyright (C) 2006 Herbert Poetzl | |
7 | + * | |
8 | + */ | |
9 | + | |
10 | +#ifndef OCFS2_IOCTL_H | |
11 | +#define OCFS2_IOCTL_H | |
12 | + | |
13 | +int ocfs2_ioctl(struct inode * inode, struct file * filp, | |
14 | + unsigned int cmd, unsigned long arg); | |
15 | + | |
16 | +#endif /* OCFS2_IOCTL_H */ |
fs/ocfs2/ocfs2_fs.h
... | ... | @@ -114,7 +114,27 @@ |
114 | 114 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ |
115 | 115 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ |
116 | 116 | |
117 | +/* Inode attributes, keep in sync with EXT2 */ | |
118 | +#define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */ | |
119 | +#define OCFS2_UNRM_FL (0x00000002) /* Undelete */ | |
120 | +#define OCFS2_COMPR_FL (0x00000004) /* Compress file */ | |
121 | +#define OCFS2_SYNC_FL (0x00000008) /* Synchronous updates */ | |
122 | +#define OCFS2_IMMUTABLE_FL (0x00000010) /* Immutable file */ | |
123 | +#define OCFS2_APPEND_FL (0x00000020) /* writes to file may only append */ | |
124 | +#define OCFS2_NODUMP_FL (0x00000040) /* do not dump file */ | |
125 | +#define OCFS2_NOATIME_FL (0x00000080) /* do not update atime */ | |
126 | +#define OCFS2_DIRSYNC_FL (0x00010000) /* dirsync behaviour (directories only) */ | |
127 | + | |
128 | +#define OCFS2_FL_VISIBLE (0x000100FF) /* User visible flags */ | |
129 | +#define OCFS2_FL_MODIFIABLE (0x000100FF) /* User modifiable flags */ | |
130 | + | |
117 | 131 | /* |
132 | + * ioctl commands | |
133 | + */ | |
134 | +#define OCFS2_IOC_GETFLAGS _IOR('f', 1, long) | |
135 | +#define OCFS2_IOC_SETFLAGS _IOW('f', 2, long) | |
136 | + | |
137 | +/* | |
118 | 138 | * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) |
119 | 139 | */ |
120 | 140 | #define OCFS2_JOURNAL_DIRTY_FL (0x00000001) /* Journal needs recovery */ |
... | ... | @@ -399,7 +419,9 @@ |
399 | 419 | __le32 i_atime_nsec; |
400 | 420 | __le32 i_ctime_nsec; |
401 | 421 | __le32 i_mtime_nsec; |
402 | -/*70*/ __le64 i_reserved1[9]; | |
422 | + __le32 i_attr; | |
423 | + __le32 i_reserved1; | |
424 | +/*70*/ __le64 i_reserved2[8]; | |
403 | 425 | /*B8*/ union { |
404 | 426 | __le64 i_pad1; /* Generic way to refer to this |
405 | 427 | 64bit union */ |