Skip to content

Commit ca4d147

Browse files
herbertpMark Fasheh
authored and
Mark Fasheh
committed
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>
1 parent b4c98f6 commit ca4d147

File tree

9 files changed

+217
-6
lines changed

9 files changed

+217
-6
lines changed

fs/ocfs2/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ocfs2-objs := \
1616
file.o \
1717
heartbeat.o \
1818
inode.o \
19+
ioctl.o \
1920
journal.o \
2021
localalloc.o \
2122
mmap.o \

fs/ocfs2/dlmglue.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
13301330
cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime));
13311331
lvb->lvb_imtime_packed =
13321332
cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime));
1333+
lvb->lvb_iattr = cpu_to_be32(oi->ip_attr);
13331334

13341335
mlog_meta_lvb(0, lockres);
13351336

@@ -1360,6 +1361,9 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
13601361
oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters);
13611362
i_size_write(inode, be64_to_cpu(lvb->lvb_isize));
13621363

1364+
oi->ip_attr = be32_to_cpu(lvb->lvb_iattr);
1365+
ocfs2_set_inode_flags(inode);
1366+
13631367
/* fast-symlinks are a special case */
13641368
if (S_ISLNK(inode->i_mode) && !oi->ip_clusters)
13651369
inode->i_blocks = 0;
@@ -2899,8 +2903,9 @@ void ocfs2_dump_meta_lvb_info(u64 level,
28992903
be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
29002904
be16_to_cpu(lvb->lvb_imode));
29012905
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),
29032907
(long long)be64_to_cpu(lvb->lvb_iatime_packed),
29042908
(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));
29062911
}

fs/ocfs2/dlmglue.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#ifndef DLMGLUE_H
2828
#define DLMGLUE_H
2929

30-
#define OCFS2_LVB_VERSION 2
30+
#define OCFS2_LVB_VERSION 3
3131

3232
struct ocfs2_meta_lvb {
3333
__be32 lvb_version;
@@ -40,7 +40,8 @@ struct ocfs2_meta_lvb {
4040
__be64 lvb_isize;
4141
__be16 lvb_imode;
4242
__be16 lvb_inlink;
43-
__be32 lvb_reserved[3];
43+
__be32 lvb_iattr;
44+
__be32 lvb_reserved[2];
4445
};
4546

4647
/* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */

fs/ocfs2/file.c

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "file.h"
4545
#include "sysfile.h"
4646
#include "inode.h"
47+
#include "ioctl.h"
4748
#include "journal.h"
4849
#include "mmap.h"
4950
#include "suballoc.h"
@@ -1227,10 +1228,12 @@ const struct file_operations ocfs2_fops = {
12271228
.open = ocfs2_file_open,
12281229
.aio_read = ocfs2_file_aio_read,
12291230
.aio_write = ocfs2_file_aio_write,
1231+
.ioctl = ocfs2_ioctl,
12301232
};
12311233

12321234
const struct file_operations ocfs2_dops = {
12331235
.read = generic_read_dir,
12341236
.readdir = ocfs2_readdir,
12351237
.fsync = ocfs2_sync_file,
1238+
.ioctl = ocfs2_ioctl,
12361239
};

fs/ocfs2/inode.c

+27-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,26 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
7171
struct inode *inode,
7272
struct buffer_head *fe_bh);
7373

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+
7494
struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb,
7595
u64 blkno,
7696
int delete_vote)
@@ -260,7 +280,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
260280
inode->i_blocks =
261281
ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size));
262282
inode->i_mapping->a_ops = &ocfs2_aops;
263-
inode->i_flags |= S_NOATIME;
264283
inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
265284
inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
266285
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,
276295

277296
OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
278297
OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT;
298+
OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr);
279299

280300
if (create_ino)
281301
inode->i_ino = ino_from_blkno(inode->i_sb,
@@ -330,6 +350,9 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
330350
ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres,
331351
OCFS2_LOCK_TYPE_DATA, inode);
332352

353+
ocfs2_set_inode_flags(inode);
354+
inode->i_flags |= S_NOATIME;
355+
333356
status = 0;
334357
bail:
335358
mlog_exit(status);
@@ -1131,6 +1154,7 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
11311154

11321155
spin_lock(&OCFS2_I(inode)->ip_lock);
11331156
fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
1157+
fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr);
11341158
spin_unlock(&OCFS2_I(inode)->ip_lock);
11351159

11361160
fe->i_size = cpu_to_le64(i_size_read(inode));
@@ -1169,6 +1193,8 @@ void ocfs2_refresh_inode(struct inode *inode,
11691193
spin_lock(&OCFS2_I(inode)->ip_lock);
11701194

11711195
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);
11721198
i_size_write(inode, le64_to_cpu(fe->i_size));
11731199
inode->i_nlink = le16_to_cpu(fe->i_links_count);
11741200
inode->i_uid = le32_to_cpu(fe->i_uid);

fs/ocfs2/inode.h

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct ocfs2_inode_info
5656
struct ocfs2_journal_handle *ip_handle;
5757

5858
u32 ip_flags; /* see below */
59+
u32 ip_attr; /* inode attributes */
5960

6061
/* protected by recovery_lock. */
6162
struct inode *ip_next_orphan;
@@ -142,4 +143,6 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
142143
int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
143144
int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
144145

146+
void ocfs2_set_inode_flags(struct inode *inode);
147+
145148
#endif /* OCFS2_INODE_H */

fs/ocfs2/ioctl.c

+134
Original file line numberDiff line numberDiff line change
@@ -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+
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+
}
134+

fs/ocfs2/ioctl.h

+16
Original file line numberDiff line numberDiff line change
@@ -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+
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

+23-1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,26 @@
114114
#define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */
115115
#define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */
116116

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+
117137
/*
118138
* Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
119139
*/
@@ -399,7 +419,9 @@ struct ocfs2_dinode {
399419
__le32 i_atime_nsec;
400420
__le32 i_ctime_nsec;
401421
__le32 i_mtime_nsec;
402-
/*70*/ __le64 i_reserved1[9];
422+
__le32 i_attr;
423+
__le32 i_reserved1;
424+
/*70*/ __le64 i_reserved2[8];
403425
/*B8*/ union {
404426
__le64 i_pad1; /* Generic way to refer to this
405427
64bit union */

0 commit comments

Comments
 (0)