Commit ca4d147e62df370c334898464023aa7f9126abe1

Authored by Herbert Poetzl
Committed by Mark Fasheh
1 parent b4c98f625f

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

... ... @@ -16,6 +16,7 @@
16 16 file.o \
17 17 heartbeat.o \
18 18 inode.o \
  19 + ioctl.o \
19 20 journal.o \
20 21 localalloc.o \
21 22 mmap.o \
... ... @@ -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 }
... ... @@ -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 */
... ... @@ -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 };
... ... @@ -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);
... ... @@ -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 */
  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 +}
  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 */
... ... @@ -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 */