btrfs: separate defrag and property compression
authorDavid Sterba <dsterba@suse.com>
Mon, 17 Jul 2017 17:41:31 +0000 (19:41 +0200)
committerDavid Sterba <dsterba@suse.com>
Wed, 16 Aug 2017 14:12:05 +0000 (16:12 +0200)
Add new value for compression to distinguish between defrag and
property. Previously, a single variable was used and this caused clashes
when the per-file 'compression' was set and a defrag -c was called.

The property-compression is loaded when the file is open, defrag will
overwrite the same variable and reset to 0 (ie. NONE) at when the file
defragmentaion is finished. That's considered a usability bug.

Now we won't touch the property value, use the defrag-compression. The
precedence of defrag is higher than for property (and whole-filesystem).

Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/btrfs_inode.h
fs/btrfs/inode.c
fs/btrfs/ioctl.c

index fa11803..eccadb5 100644 (file)
@@ -182,6 +182,11 @@ struct btrfs_inode {
         * Cached values of inode properties
         */
        unsigned prop_compress;         /* per-file compression algorithm */
+       /*
+        * Force compression on the file using the defrag ioctl, could be
+        * different from prop_compress and takes precedence if set
+        */
+       unsigned defrag_compress;
 
        struct btrfs_delayed_node *delayed_node;
 
index c60a6d6..1e8eb5e 100644 (file)
@@ -402,6 +402,9 @@ static inline int inode_need_compress(struct inode *inode, u64 start, u64 end)
        /* bad compression ratios */
        if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS)
                return 0;
+       /* defrag ioctl */
+       if (BTRFS_I(inode)->defrag_compress)
+               return 1;
        if (btrfs_test_opt(fs_info, COMPRESS) ||
            BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS ||
            BTRFS_I(inode)->prop_compress)
@@ -511,7 +514,9 @@ again:
                        goto cont;
                }
 
-               if (BTRFS_I(inode)->prop_compress)
+               if (BTRFS_I(inode)->defrag_compress)
+                       compress_type = BTRFS_I(inode)->defrag_compress;
+               else if (BTRFS_I(inode)->prop_compress)
                        compress_type = BTRFS_I(inode)->prop_compress;
 
                /*
@@ -9434,6 +9439,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
 
        ei->runtime_flags = 0;
        ei->prop_compress = BTRFS_COMPRESS_NONE;
+       ei->defrag_compress = BTRFS_COMPRESS_NONE;
 
        ei->delayed_node = NULL;
 
index e1c15a2..1d6603d 100644 (file)
@@ -1371,7 +1371,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 
                inode_lock(inode);
                if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
-                       BTRFS_I(inode)->prop_compress = compress_type;
+                       BTRFS_I(inode)->defrag_compress = compress_type;
                ret = cluster_pages_for_defrag(inode, pages, i, cluster);
                if (ret < 0) {
                        inode_unlock(inode);
@@ -1442,7 +1442,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 out_ra:
        if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
                inode_lock(inode);
-               BTRFS_I(inode)->prop_compress = BTRFS_COMPRESS_NONE;
+               BTRFS_I(inode)->defrag_compress = BTRFS_COMPRESS_NONE;
                inode_unlock(inode);
        }
        if (!file)