summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-01-21 08:11:53 -0900
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:35:20 -0800
commit38ba3c88c89c4faba95454d8faa5ce681290b147 (patch)
treee04e1ac810f000ee09012f0554cc394094ea95e7
parent1756202b161ed0f70220b123c2d5d1c90aca044d (diff)
bcachefs: Inode flags improvements
-rw-r--r--drivers/md/bcache/fs.c109
-rw-r--r--include/uapi/linux/bcache.h40
2 files changed, 100 insertions, 49 deletions
diff --git a/drivers/md/bcache/fs.c b/drivers/md/bcache/fs.c
index b158ca0012b6..1dd2d6e18ac6 100644
--- a/drivers/md/bcache/fs.c
+++ b/drivers/md/bcache/fs.c
@@ -431,21 +431,6 @@ static struct inode *bch_vfs_inode_get(struct super_block *sb, u64 inum)
return inode;
}
-static void bch_set_inode_flags(struct inode *inode)
-{
- unsigned flags = to_bch_ei(inode)->i_flags;
-
- inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME);
- if (flags & FS_SYNC_FL)
- inode->i_flags |= S_SYNC;
- if (flags & FS_APPEND_FL)
- inode->i_flags |= S_APPEND;
- if (flags & FS_IMMUTABLE_FL)
- inode->i_flags |= S_IMMUTABLE;
- if (flags & FS_NOATIME_FL)
- inode->i_flags |= S_NOATIME;
-}
-
static struct inode *bch_vfs_inode_create(struct cache_set *c,
struct inode *parent,
umode_t mode, dev_t rdev)
@@ -1670,36 +1655,78 @@ out:
return bch_journal_flush_seq(&c->journal, ei->journal_seq);
}
-/* Flags that are appropriate for non-directories/regular files. */
-#define BCH_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
+/* Inode flags: */
+
+static const unsigned bch_inode_flags_to_vfs_flags_map[] = {
+ [__BCH_INODE_SYNC] = S_SYNC,
+ [__BCH_INODE_IMMUTABLE] = S_IMMUTABLE,
+ [__BCH_INODE_APPEND] = S_APPEND,
+ [__BCH_INODE_NOATIME] = S_NOATIME,
+};
+
+static const unsigned bch_inode_flags_to_user_flags_map[] = {
+ [__BCH_INODE_SYNC] = FS_SYNC_FL,
+ [__BCH_INODE_IMMUTABLE] = FS_IMMUTABLE_FL,
+ [__BCH_INODE_APPEND] = FS_APPEND_FL,
+ [__BCH_INODE_NODUMP] = FS_NODUMP_FL,
+ [__BCH_INODE_NOATIME] = FS_NOATIME_FL,
+};
+
+/* Set VFS inode flags from bcache inode: */
+static void bch_inode_flags_to_vfs(struct inode *inode)
+{
+ unsigned i, flags = to_bch_ei(inode)->i_flags;
+
+ for (i = 0; i < ARRAY_SIZE(bch_inode_flags_to_vfs_flags_map); i++)
+ if (flags & (1 << i))
+ inode->i_flags |= bch_inode_flags_to_vfs_flags_map[i];
+ else
+ inode->i_flags &= ~bch_inode_flags_to_vfs_flags_map[i];
+}
-static inline bool bch_flags_allowed(umode_t mode, u32 flags)
+/* Get FS_IOC_GETFLAGS flags from bcache inode: */
+static unsigned bch_inode_flags_to_user_flags(unsigned flags)
{
- if ((flags & BCH_FL_USER_FLAGS) != flags)
- return false;
+ unsigned i, ret = 0;
- if (!S_ISREG(mode) &&
- !S_ISDIR(mode) &&
- (flags & BCH_OTHER_FLMASK) != flags)
- return false;
+ for (i = 0; i < ARRAY_SIZE(bch_inode_flags_to_user_flags_map); i++)
+ if (flags & (1 << i))
+ ret |= bch_inode_flags_to_user_flags_map[i];
- return true;
+ return ret;
}
-static int bch_inode_set_flags(struct bch_inode_info *ei, struct bch_inode *bi,
- void *p)
+static int bch_inode_user_flags_set(struct bch_inode_info *ei,
+ struct bch_inode *bi,
+ void *p)
{
- unsigned oldflags = le32_to_cpu(bi->i_flags);
+ /*
+ * We're relying on btree locking here for exclusion with other ioctl
+ * calls - use the flags in the btree (@bi), not ei->i_flags:
+ */
+ unsigned bch_flags = le32_to_cpu(bi->i_flags);
+ unsigned oldflags = bch_inode_flags_to_user_flags(bch_flags);
unsigned newflags = *((unsigned *) p);
+ unsigned i;
if (((newflags ^ oldflags) & (FS_APPEND_FL|FS_IMMUTABLE_FL)) &&
!capable(CAP_LINUX_IMMUTABLE))
return -EPERM;
- newflags = newflags & BCH_FL_USER_FLAGS;
- newflags |= oldflags & ~BCH_FL_USER_FLAGS;
- bi->i_flags = cpu_to_le32(newflags);
+ for (i = 0; i < ARRAY_SIZE(bch_inode_flags_to_user_flags_map); i++) {
+ if (newflags & bch_inode_flags_to_user_flags_map[i])
+ bch_flags |= (1 << i);
+ else
+ bch_flags &= ~(1 << i);
+
+ newflags &= ~bch_inode_flags_to_user_flags_map[i];
+ oldflags &= ~bch_inode_flags_to_user_flags_map[i];
+ }
+ if (oldflags != newflags)
+ return -EOPNOTSUPP;
+
+ bi->i_flags = cpu_to_le32(bch_flags);
ei->vfs_inode.i_ctime = CURRENT_TIME;
return 0;
@@ -1718,8 +1745,8 @@ static long bch_fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
switch (cmd) {
case FS_IOC_GETFLAGS:
- flags = ei->i_flags & BCH_FL_USER_FLAGS;
- return put_user(flags, (int __user *) arg);
+ return put_user(bch_inode_flags_to_user_flags(ei->i_flags),
+ (int __user *) arg);
case FS_IOC_SETFLAGS: {
ret = mnt_want_write_file(filp);
@@ -1736,7 +1763,9 @@ static long bch_fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
goto setflags_out;
}
- if (!bch_flags_allowed(inode->i_mode, flags)) {
+ if (!S_ISREG(inode->i_mode) &&
+ !S_ISDIR(inode->i_mode) &&
+ (flags & (FS_NODUMP_FL|FS_NOATIME_FL)) != flags) {
ret = -EINVAL;
goto setflags_out;
}
@@ -1744,17 +1773,23 @@ static long bch_fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
inode_lock(inode);
mutex_lock(&ei->update_lock);
- ret = __bch_write_inode(c, ei, bch_inode_set_flags, &flags);
+ ret = __bch_write_inode(c, ei, bch_inode_user_flags_set, &flags);
mutex_unlock(&ei->update_lock);
if (!ret)
- bch_set_inode_flags(inode);
+ bch_inode_flags_to_vfs(inode);
inode_unlock(inode);
setflags_out:
mnt_drop_write_file(filp);
return ret;
}
+
+ case FS_IOC_GETVERSION:
+ return -ENOTTY;
+ case FS_IOC_SETVERSION:
+ return -ENOTTY;
+
case FS_IOC_GOINGDOWN:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -2855,7 +2890,7 @@ static void bch_inode_init(struct bch_inode_info *ei,
inode->i_atime = ns_to_timespec(le64_to_cpu(bi->i_atime));
inode->i_mtime = ns_to_timespec(le64_to_cpu(bi->i_mtime));
inode->i_ctime = ns_to_timespec(le64_to_cpu(bi->i_ctime));
- bch_set_inode_flags(inode);
+ bch_inode_flags_to_vfs(inode);
inode->i_mapping->a_ops = &bch_address_space_operations;
diff --git a/include/uapi/linux/bcache.h b/include/uapi/linux/bcache.h
index d783a3792c03..f75edb1edf38 100644
--- a/include/uapi/linux/bcache.h
+++ b/include/uapi/linux/bcache.h
@@ -77,7 +77,7 @@ struct bpos {
#else
#error edit for your odd byteorder.
#endif
-} __attribute__((packed)) __attribute__((aligned(4)));
+} __attribute__((packed, aligned(4)));
#define KEY_INODE_MAX ((__u64)~0ULL)
#define KEY_OFFSET_MAX ((__u64)~0ULL)
@@ -127,7 +127,7 @@ struct bkey {
__u8 pad[1];
#endif
-} __attribute__((packed)) __attribute__((aligned(8)));
+} __attribute__((packed, aligned(8)));
struct bkey_packed {
__u64 _data[0];
@@ -149,7 +149,7 @@ struct bkey_packed {
* to the same size as struct bkey should hopefully be safest.
*/
__u8 pad[sizeof(struct bkey) - 3];
-} __attribute__((packed)) __attribute__((aligned(8)));
+} __attribute__((packed, aligned(8)));
#define BKEY_U64s (sizeof(struct bkey) / sizeof(__u64))
#define KEY_PACKED_BITS_START 24
@@ -368,7 +368,7 @@ struct bch_extent_crc32 {
offset:7,
type:1;
#endif
-} __attribute__((packed)) __attribute__((aligned(8)));
+} __attribute__((packed, aligned(8)));
#define CRC32_EXTENT_SIZE_MAX (1U << 7)
@@ -389,7 +389,7 @@ struct bch_extent_crc64 {
type:3;
#endif
__u64 csum;
-} __attribute__((packed)) __attribute__((aligned(8)));
+} __attribute__((packed, aligned(8)));
#define CRC64_EXTENT_SIZE_MAX (1U << 17)
@@ -412,7 +412,7 @@ struct bch_extent_ptr {
erasure_coded:1,
type:2;
#endif
-} __attribute__((packed)) __attribute__((aligned(8)));
+} __attribute__((packed, aligned(8)));
union bch_extent_entry {
#if defined(__LITTLE_ENDIAN__) || BITS_PER_LONG == 64
@@ -449,7 +449,7 @@ struct bch_extent {
union bch_extent_entry start[0];
__u64 _data[0];
-} __attribute__((packed)) __attribute__((aligned(8)));
+} __attribute__((packed, aligned(8)));
BKEY_VAL_TYPE(extent, BCH_EXTENT);
/* Inodes */
@@ -465,13 +465,29 @@ enum bch_inode_types {
};
enum {
- BCH_FS_PRIVATE_START = 16,
- __BCH_INODE_I_SIZE_DIRTY = 16,
-};
+ /*
+ * User flags (get/settable with FS_IOC_*FLAGS, correspond to FS_*_FL
+ * flags)
+ */
+ __BCH_INODE_SYNC = 0,
+ __BCH_INODE_IMMUTABLE = 1,
+ __BCH_INODE_APPEND = 2,
+ __BCH_INODE_NODUMP = 3,
+ __BCH_INODE_NOATIME = 4,
-#define BCH_FL_USER_FLAGS ((1U << BCH_FS_PRIVATE_START) - 1)
+ __BCH_INODE_I_SIZE_DIRTY= 5,
+ /* not implemented yet: */
+ __BCH_INODE_HAS_XATTRS = 6, /* has xattrs in xattr btree */
+};
+
+#define BCH_INODE_SYNC (1 << __BCH_INODE_SYNC)
+#define BCH_INODE_IMMUTABLE (1 << __BCH_INODE_IMMUTABLE)
+#define BCH_INODE_APPEND (1 << __BCH_INODE_APPEND)
+#define BCH_INODE_NODUMP (1 << __BCH_INODE_NODUMP)
+#define BCH_INODE_NOATIME (1 << __BCH_INODE_NOATIME)
#define BCH_INODE_I_SIZE_DIRTY (1 << __BCH_INODE_I_SIZE_DIRTY)
+#define BCH_INODE_HAS_XATTRS (1 << __BCH_INODE_HAS_XATTRS)
struct bch_inode {
struct bch_val v;
@@ -501,7 +517,7 @@ struct bch_inode_blockdev {
uuid_le i_uuid;
__u8 i_label[32];
-} __attribute__((packed));
+} __attribute__((packed, aligned(8)));
BKEY_VAL_TYPE(inode_blockdev, BCH_INODE_BLOCKDEV);
/* Dirents */