diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-01-21 08:11:53 -0900 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 12:35:20 -0800 |
commit | 38ba3c88c89c4faba95454d8faa5ce681290b147 (patch) | |
tree | e04e1ac810f000ee09012f0554cc394094ea95e7 | |
parent | 1756202b161ed0f70220b123c2d5d1c90aca044d (diff) |
bcachefs: Inode flags improvements
-rw-r--r-- | drivers/md/bcache/fs.c | 109 | ||||
-rw-r--r-- | include/uapi/linux/bcache.h | 40 |
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 */ |