aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/Makefile1
-rw-r--r--fs/ocfs2/dlmglue.c9
-rw-r--r--fs/ocfs2/dlmglue.h5
-rw-r--r--fs/ocfs2/file.c3
-rw-r--r--fs/ocfs2/inode.c28
-rw-r--r--fs/ocfs2/inode.h3
-rw-r--r--fs/ocfs2/ioctl.c134
-rw-r--r--fs/ocfs2/ioctl.h16
-rw-r--r--fs/ocfs2/ocfs2_fs.h24
9 files changed, 217 insertions, 6 deletions
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 7d3be845a614..9fb8132f19b0 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -16,6 +16,7 @@ ocfs2-objs := \
16 file.o \ 16 file.o \
17 heartbeat.o \ 17 heartbeat.o \
18 inode.o \ 18 inode.o \
19 ioctl.o \
19 journal.o \ 20 journal.o \
20 localalloc.o \ 21 localalloc.o \
21 mmap.o \ 22 mmap.o \
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 762eb1fbb34d..151b41781eab 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -1330,6 +1330,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
1330 cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); 1330 cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime));
1331 lvb->lvb_imtime_packed = 1331 lvb->lvb_imtime_packed =
1332 cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); 1332 cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime));
1333 lvb->lvb_iattr = cpu_to_be32(oi->ip_attr);
1333 1334
1334 mlog_meta_lvb(0, lockres); 1335 mlog_meta_lvb(0, lockres);
1335 1336
@@ -1360,6 +1361,9 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
1360 oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); 1361 oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters);
1361 i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); 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 /* fast-symlinks are a special case */ 1367 /* fast-symlinks are a special case */
1364 if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) 1368 if (S_ISLNK(inode->i_mode) && !oi->ip_clusters)
1365 inode->i_blocks = 0; 1369 inode->i_blocks = 0;
@@ -2899,8 +2903,9 @@ void ocfs2_dump_meta_lvb_info(u64 level,
2899 be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), 2903 be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
2900 be16_to_cpu(lvb->lvb_imode)); 2904 be16_to_cpu(lvb->lvb_imode));
2901 mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " 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 (long long)be64_to_cpu(lvb->lvb_iatime_packed), 2907 (long long)be64_to_cpu(lvb->lvb_iatime_packed),
2904 (long long)be64_to_cpu(lvb->lvb_ictime_packed), 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}
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index 8f2d1db2d9ea..243ae862ece5 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -27,7 +27,7 @@
27#ifndef DLMGLUE_H 27#ifndef DLMGLUE_H
28#define DLMGLUE_H 28#define DLMGLUE_H
29 29
30#define OCFS2_LVB_VERSION 2 30#define OCFS2_LVB_VERSION 3
31 31
32struct ocfs2_meta_lvb { 32struct ocfs2_meta_lvb {
33 __be32 lvb_version; 33 __be32 lvb_version;
@@ -40,7 +40,8 @@ struct ocfs2_meta_lvb {
40 __be64 lvb_isize; 40 __be64 lvb_isize;
41 __be16 lvb_imode; 41 __be16 lvb_imode;
42 __be16 lvb_inlink; 42 __be16 lvb_inlink;
43 __be32 lvb_reserved[3]; 43 __be32 lvb_iattr;
44 __be32 lvb_reserved[2];
44}; 45};
45 46
46/* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */ 47/* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index a9559c874530..2bbfa17090cf 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -44,6 +44,7 @@
44#include "file.h" 44#include "file.h"
45#include "sysfile.h" 45#include "sysfile.h"
46#include "inode.h" 46#include "inode.h"
47#include "ioctl.h"
47#include "journal.h" 48#include "journal.h"
48#include "mmap.h" 49#include "mmap.h"
49#include "suballoc.h" 50#include "suballoc.h"
@@ -1227,10 +1228,12 @@ const struct file_operations ocfs2_fops = {
1227 .open = ocfs2_file_open, 1228 .open = ocfs2_file_open,
1228 .aio_read = ocfs2_file_aio_read, 1229 .aio_read = ocfs2_file_aio_read,
1229 .aio_write = ocfs2_file_aio_write, 1230 .aio_write = ocfs2_file_aio_write,
1231 .ioctl = ocfs2_ioctl,
1230}; 1232};
1231 1233
1232const struct file_operations ocfs2_dops = { 1234const struct file_operations ocfs2_dops = {
1233 .read = generic_read_dir, 1235 .read = generic_read_dir,
1234 .readdir = ocfs2_readdir, 1236 .readdir = ocfs2_readdir,
1235 .fsync = ocfs2_sync_file, 1237 .fsync = ocfs2_sync_file,
1238 .ioctl = ocfs2_ioctl,
1236}; 1239};
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 327a5b7b86ed..3f496c41fea8 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -71,6 +71,26 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
71 struct inode *inode, 71 struct inode *inode,
72 struct buffer_head *fe_bh); 72 struct buffer_head *fe_bh);
73 73
74void 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
74struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, 94struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb,
75 u64 blkno, 95 u64 blkno,
76 int delete_vote) 96 int delete_vote)
@@ -260,7 +280,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
260 inode->i_blocks = 280 inode->i_blocks =
261 ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); 281 ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size));
262 inode->i_mapping->a_ops = &ocfs2_aops; 282 inode->i_mapping->a_ops = &ocfs2_aops;
263 inode->i_flags |= S_NOATIME;
264 inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); 283 inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
265 inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); 284 inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
266 inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); 285 inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
@@ -276,6 +295,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
276 295
277 OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); 296 OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
278 OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; 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 if (create_ino) 300 if (create_ino)
281 inode->i_ino = ino_from_blkno(inode->i_sb, 301 inode->i_ino = ino_from_blkno(inode->i_sb,
@@ -330,6 +350,9 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
330 ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, 350 ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres,
331 OCFS2_LOCK_TYPE_DATA, inode); 351 OCFS2_LOCK_TYPE_DATA, inode);
332 352
353 ocfs2_set_inode_flags(inode);
354 inode->i_flags |= S_NOATIME;
355
333 status = 0; 356 status = 0;
334bail: 357bail:
335 mlog_exit(status); 358 mlog_exit(status);
@@ -1131,6 +1154,7 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
1131 1154
1132 spin_lock(&OCFS2_I(inode)->ip_lock); 1155 spin_lock(&OCFS2_I(inode)->ip_lock);
1133 fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); 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 spin_unlock(&OCFS2_I(inode)->ip_lock); 1158 spin_unlock(&OCFS2_I(inode)->ip_lock);
1135 1159
1136 fe->i_size = cpu_to_le64(i_size_read(inode)); 1160 fe->i_size = cpu_to_le64(i_size_read(inode));
@@ -1169,6 +1193,8 @@ void ocfs2_refresh_inode(struct inode *inode,
1169 spin_lock(&OCFS2_I(inode)->ip_lock); 1193 spin_lock(&OCFS2_I(inode)->ip_lock);
1170 1194
1171 OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); 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 i_size_write(inode, le64_to_cpu(fe->i_size)); 1198 i_size_write(inode, le64_to_cpu(fe->i_size));
1173 inode->i_nlink = le16_to_cpu(fe->i_links_count); 1199 inode->i_nlink = le16_to_cpu(fe->i_links_count);
1174 inode->i_uid = le32_to_cpu(fe->i_uid); 1200 inode->i_uid = le32_to_cpu(fe->i_uid);
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 35140f6cf840..4d1e53992566 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -56,6 +56,7 @@ struct ocfs2_inode_info
56 struct ocfs2_journal_handle *ip_handle; 56 struct ocfs2_journal_handle *ip_handle;
57 57
58 u32 ip_flags; /* see below */ 58 u32 ip_flags; /* see below */
59 u32 ip_attr; /* inode attributes */
59 60
60 /* protected by recovery_lock. */ 61 /* protected by recovery_lock. */
61 struct inode *ip_next_orphan; 62 struct inode *ip_next_orphan;
@@ -142,4 +143,6 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
142int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); 143int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
143int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); 144int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
144 145
146void ocfs2_set_inode_flags(struct inode *inode);
147
145#endif /* OCFS2_INODE_H */ 148#endif /* OCFS2_INODE_H */
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
new file mode 100644
index 000000000000..68f4806d3a35
--- /dev/null
+++ b/fs/ocfs2/ioctl.c
@@ -0,0 +1,134 @@
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
23static 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
39static 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);
98bail_unlock:
99 ocfs2_meta_unlock(inode, 1);
100bail:
101 mutex_unlock(&inode->i_mutex);
102
103 if (bh)
104 brelse(bh);
105
106 mlog_exit(status);
107 return status;
108}
109
110int 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}
134
diff --git a/fs/ocfs2/ioctl.h b/fs/ocfs2/ioctl.h
new file mode 100644
index 000000000000..4a7c82931dba
--- /dev/null
+++ b/fs/ocfs2/ioctl.h
@@ -0,0 +1,16 @@
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
13int ocfs2_ioctl(struct inode * inode, struct file * filp,
14 unsigned int cmd, unsigned long arg);
15
16#endif /* OCFS2_IOCTL_H */
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index c5b1ac547c15..3330a5dc6be2 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -114,6 +114,26 @@
114#define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ 114#define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */
115#define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ 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
131/*
132 * ioctl commands
133 */
134#define OCFS2_IOC_GETFLAGS _IOR('f', 1, long)
135#define OCFS2_IOC_SETFLAGS _IOW('f', 2, long)
136
117/* 137/*
118 * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) 138 * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
119 */ 139 */
@@ -399,7 +419,9 @@ struct ocfs2_dinode {
399 __le32 i_atime_nsec; 419 __le32 i_atime_nsec;
400 __le32 i_ctime_nsec; 420 __le32 i_ctime_nsec;
401 __le32 i_mtime_nsec; 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/*B8*/ union { 425/*B8*/ union {
404 __le64 i_pad1; /* Generic way to refer to this 426 __le64 i_pad1; /* Generic way to refer to this
405 64bit union */ 427 64bit union */