Skip to content

Commit 4b73c55

Browse files
fdmananakdave
authored andcommitted
btrfs: skip compression property for anything other than files and dirs
The compression property only has effect on regular files and directories (so that it's propagated to files and subdirectories created inside a directory). For any other inode type (symlink, fifo, device, socket), it's pointless to set the compression property because it does nothing and ends up unnecessarily wasting leaf space due to the pointless xattr (75 or 76 bytes, depending on the compression value). Symlinks in particular are very common (for example, I have almost 10k symlinks under /etc, /usr and /var alone) and therefore it's worth to avoid wasting leaf space with the compression xattr. For example, the compression property can end up on a symlink or character device implicitly, through inheritance from a parent directory $ mkdir /mnt/testdir $ btrfs property set /mnt/testdir compression lzo $ ln -s yadayada /mnt/testdir/lnk $ mknod /mnt/testdir/dev c 0 0 Or explicitly like this: $ ln -s yadayda /mnt/lnk $ setfattr -h -n btrfs.compression -v lzo /mnt/lnk So skip the compression property on inodes that are neither a regular file nor a directory. CC: [email protected] # 5.4+ Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 193b4e8 commit 4b73c55

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

fs/btrfs/props.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct prop_handler {
2121
size_t len);
2222
int (*apply)(struct inode *inode, const char *value, size_t len);
2323
const char *(*extract)(struct inode *inode);
24+
bool (*ignore)(const struct btrfs_inode *inode);
2425
int inheritable;
2526
};
2627

@@ -74,6 +75,28 @@ int btrfs_validate_prop(const struct btrfs_inode *inode, const char *name,
7475
return handler->validate(inode, value, value_len);
7576
}
7677

78+
/*
79+
* Check if a property should be ignored (not set) for an inode.
80+
*
81+
* @inode: The target inode.
82+
* @name: The property's name.
83+
*
84+
* The caller must be sure the given property name is valid, for example by
85+
* having previously called btrfs_validate_prop().
86+
*
87+
* Returns: true if the property should be ignored for the given inode
88+
* false if the property must not be ignored for the given inode
89+
*/
90+
bool btrfs_ignore_prop(const struct btrfs_inode *inode, const char *name)
91+
{
92+
const struct prop_handler *handler;
93+
94+
handler = find_prop_handler(name, NULL);
95+
ASSERT(handler != NULL);
96+
97+
return handler->ignore(inode);
98+
}
99+
77100
int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
78101
const char *name, const char *value, size_t value_len,
79102
int flags)
@@ -316,6 +339,22 @@ static int prop_compression_apply(struct inode *inode, const char *value,
316339
return 0;
317340
}
318341

342+
static bool prop_compression_ignore(const struct btrfs_inode *inode)
343+
{
344+
/*
345+
* Compression only has effect for regular files, and for directories
346+
* we set it just to propagate it to new files created inside them.
347+
* Everything else (symlinks, devices, sockets, fifos) is pointless as
348+
* it will do nothing, so don't waste metadata space on a compression
349+
* xattr for anything that is neither a file nor a directory.
350+
*/
351+
if (!S_ISREG(inode->vfs_inode.i_mode) &&
352+
!S_ISDIR(inode->vfs_inode.i_mode))
353+
return true;
354+
355+
return false;
356+
}
357+
319358
static const char *prop_compression_extract(struct inode *inode)
320359
{
321360
switch (BTRFS_I(inode)->prop_compress) {
@@ -336,6 +375,7 @@ static struct prop_handler prop_handlers[] = {
336375
.validate = prop_compression_validate,
337376
.apply = prop_compression_apply,
338377
.extract = prop_compression_extract,
378+
.ignore = prop_compression_ignore,
339379
.inheritable = 1
340380
},
341381
};
@@ -362,6 +402,9 @@ static int inherit_props(struct btrfs_trans_handle *trans,
362402
if (!h->inheritable)
363403
continue;
364404

405+
if (h->ignore(BTRFS_I(inode)))
406+
continue;
407+
365408
value = h->extract(parent);
366409
if (!value)
367410
continue;

fs/btrfs/props.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
1515
int flags);
1616
int btrfs_validate_prop(const struct btrfs_inode *inode, const char *name,
1717
const char *value, size_t value_len);
18+
bool btrfs_ignore_prop(const struct btrfs_inode *inode, const char *name);
1819

1920
int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path);
2021

fs/btrfs/xattr.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
408408
if (ret)
409409
return ret;
410410

411+
if (btrfs_ignore_prop(BTRFS_I(inode), name))
412+
return 0;
413+
411414
trans = btrfs_start_transaction(root, 2);
412415
if (IS_ERR(trans))
413416
return PTR_ERR(trans);

0 commit comments

Comments
 (0)