f2fs: restrict setting up inode.i_advise
authorChao Yu <yuchao0@huawei.com>
Thu, 19 Jul 2018 15:57:54 +0000 (23:57 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 5 Sep 2018 22:12:55 +0000 (15:12 -0700)
In order to give advise to f2fs to recognize hot/cold file, it is possible
that we can set specific bit in inode.i_advise through setxattr(), but
there are several bits which are used internally, such as encrypt_bit,
keep_size_bit, they should never be changed through setxattr().

So that this patch 1) adds FADVISE_MODIFIABLE_BITS to filter modifiable
bits user given, 2) supports to clear {hot,cold}_file bits.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/xattr.c

index 41c8fc67210dd54ffa0ed79f673a2e06b0de1805..080fc0b6c76495d01f98f46fc49d082c223fdf2b 100644 (file)
@@ -605,6 +605,8 @@ enum {
 #define FADVISE_HOT_BIT                0x20
 #define FADVISE_VERITY_BIT     0x40    /* reserved */
 
+#define FADVISE_MODIFIABLE_BITS        (FADVISE_COLD_BIT | FADVISE_HOT_BIT)
+
 #define file_is_cold(inode)    is_file(inode, FADVISE_COLD_BIT)
 #define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT)
 #define file_set_cold(inode)   set_file(inode, FADVISE_COLD_BIT)
index 4b34244dcc69e9480e67d71d9b0621ef9c507746..77a010e625f503b7ec54ca0daef6b8d5d5d4cfaf 100644 (file)
@@ -94,12 +94,22 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
                const char *name, const void *value,
                size_t size, int flags)
 {
+       unsigned char old_advise = F2FS_I(inode)->i_advise;
+       unsigned char new_advise;
+
        if (!inode_owner_or_capable(inode))
                return -EPERM;
        if (value == NULL)
                return -EINVAL;
 
-       F2FS_I(inode)->i_advise |= *(char *)value;
+       new_advise = *(char *)value;
+       if (new_advise & ~FADVISE_MODIFIABLE_BITS)
+               return -EINVAL;
+
+       new_advise = new_advise & FADVISE_MODIFIABLE_BITS;
+       new_advise |= old_advise & ~FADVISE_MODIFIABLE_BITS;
+
+       F2FS_I(inode)->i_advise = new_advise;
        f2fs_mark_inode_dirty_sync(inode, true);
        return 0;
 }