Skip to content

Commit 9050ba3

Browse files
committed
Merge tag 'for-5.18-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few more fixes mostly around how some file attributes could be set. - fix handling of compression property: - don't allow setting it on anything else than regular file or directory - do not allow setting it on nodatacow files via properties - improved error handling when setting xattr - make sure symlinks are always properly logged" * tag 'for-5.18-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: skip compression property for anything other than files and dirs btrfs: do not BUG_ON() on failure to update inode when setting xattr btrfs: always log symlinks in full mode btrfs: do not allow compression on nodatacow files btrfs: export a helper for compression hard check
2 parents 672c0c5 + 4b73c55 commit 9050ba3

File tree

6 files changed

+91
-23
lines changed

6 files changed

+91
-23
lines changed

fs/btrfs/btrfs_inode.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,17 @@ static inline bool btrfs_inode_in_log(struct btrfs_inode *inode, u64 generation)
384384
return ret;
385385
}
386386

387+
/*
388+
* Check if the inode has flags compatible with compression
389+
*/
390+
static inline bool btrfs_inode_can_compress(const struct btrfs_inode *inode)
391+
{
392+
if (inode->flags & BTRFS_INODE_NODATACOW ||
393+
inode->flags & BTRFS_INODE_NODATASUM)
394+
return false;
395+
return true;
396+
}
397+
387398
struct btrfs_dio_private {
388399
struct inode *inode;
389400

fs/btrfs/inode.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -480,17 +480,6 @@ static noinline int add_async_extent(struct async_chunk *cow,
480480
return 0;
481481
}
482482

483-
/*
484-
* Check if the inode has flags compatible with compression
485-
*/
486-
static inline bool inode_can_compress(struct btrfs_inode *inode)
487-
{
488-
if (inode->flags & BTRFS_INODE_NODATACOW ||
489-
inode->flags & BTRFS_INODE_NODATASUM)
490-
return false;
491-
return true;
492-
}
493-
494483
/*
495484
* Check if the inode needs to be submitted to compression, based on mount
496485
* options, defragmentation, properties or heuristics.
@@ -500,7 +489,7 @@ static inline int inode_need_compress(struct btrfs_inode *inode, u64 start,
500489
{
501490
struct btrfs_fs_info *fs_info = inode->root->fs_info;
502491

503-
if (!inode_can_compress(inode)) {
492+
if (!btrfs_inode_can_compress(inode)) {
504493
WARN(IS_ENABLED(CONFIG_BTRFS_DEBUG),
505494
KERN_ERR "BTRFS: unexpected compression for ino %llu\n",
506495
btrfs_ino(inode));
@@ -2019,7 +2008,7 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page
20192008
ASSERT(!zoned || btrfs_is_data_reloc_root(inode->root));
20202009
ret = run_delalloc_nocow(inode, locked_page, start, end,
20212010
page_started, nr_written);
2022-
} else if (!inode_can_compress(inode) ||
2011+
} else if (!btrfs_inode_can_compress(inode) ||
20232012
!inode_need_compress(inode, start, end)) {
20242013
if (zoned)
20252014
ret = run_delalloc_zoned(inode, locked_page, start, end,

fs/btrfs/props.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ static DEFINE_HASHTABLE(prop_handlers_ht, BTRFS_PROP_HANDLERS_HT_BITS);
1717
struct prop_handler {
1818
struct hlist_node node;
1919
const char *xattr_name;
20-
int (*validate)(const char *value, size_t len);
20+
int (*validate)(const struct btrfs_inode *inode, const char *value,
21+
size_t len);
2122
int (*apply)(struct inode *inode, const char *value, size_t len);
2223
const char *(*extract)(struct inode *inode);
24+
bool (*ignore)(const struct btrfs_inode *inode);
2325
int inheritable;
2426
};
2527

@@ -55,7 +57,8 @@ find_prop_handler(const char *name,
5557
return NULL;
5658
}
5759

58-
int btrfs_validate_prop(const char *name, const char *value, size_t value_len)
60+
int btrfs_validate_prop(const struct btrfs_inode *inode, const char *name,
61+
const char *value, size_t value_len)
5962
{
6063
const struct prop_handler *handler;
6164

@@ -69,7 +72,29 @@ int btrfs_validate_prop(const char *name, const char *value, size_t value_len)
6972
if (value_len == 0)
7073
return 0;
7174

72-
return handler->validate(value, value_len);
75+
return handler->validate(inode, value, value_len);
76+
}
77+
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);
7398
}
7499

75100
int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
@@ -252,8 +277,12 @@ int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path)
252277
return ret;
253278
}
254279

255-
static int prop_compression_validate(const char *value, size_t len)
280+
static int prop_compression_validate(const struct btrfs_inode *inode,
281+
const char *value, size_t len)
256282
{
283+
if (!btrfs_inode_can_compress(inode))
284+
return -EINVAL;
285+
257286
if (!value)
258287
return 0;
259288

@@ -310,6 +339,22 @@ static int prop_compression_apply(struct inode *inode, const char *value,
310339
return 0;
311340
}
312341

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+
313358
static const char *prop_compression_extract(struct inode *inode)
314359
{
315360
switch (BTRFS_I(inode)->prop_compress) {
@@ -330,6 +375,7 @@ static struct prop_handler prop_handlers[] = {
330375
.validate = prop_compression_validate,
331376
.apply = prop_compression_apply,
332377
.extract = prop_compression_extract,
378+
.ignore = prop_compression_ignore,
333379
.inheritable = 1
334380
},
335381
};
@@ -356,6 +402,9 @@ static int inherit_props(struct btrfs_trans_handle *trans,
356402
if (!h->inheritable)
357403
continue;
358404

405+
if (h->ignore(BTRFS_I(inode)))
406+
continue;
407+
359408
value = h->extract(parent);
360409
if (!value)
361410
continue;
@@ -364,7 +413,7 @@ static int inherit_props(struct btrfs_trans_handle *trans,
364413
* This is not strictly necessary as the property should be
365414
* valid, but in case it isn't, don't propagate it further.
366415
*/
367-
ret = h->validate(value, strlen(value));
416+
ret = h->validate(BTRFS_I(inode), value, strlen(value));
368417
if (ret)
369418
continue;
370419

fs/btrfs/props.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ void __init btrfs_props_init(void);
1313
int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode,
1414
const char *name, const char *value, size_t value_len,
1515
int flags);
16-
int btrfs_validate_prop(const char *name, const char *value, size_t value_len);
16+
int btrfs_validate_prop(const struct btrfs_inode *inode, const char *name,
17+
const char *value, size_t value_len);
18+
bool btrfs_ignore_prop(const struct btrfs_inode *inode, const char *name);
1719

1820
int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path);
1921

fs/btrfs/tree-log.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5804,6 +5804,18 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
58045804
mutex_lock(&inode->log_mutex);
58055805
}
58065806

5807+
/*
5808+
* For symlinks, we must always log their content, which is stored in an
5809+
* inline extent, otherwise we could end up with an empty symlink after
5810+
* log replay, which is invalid on linux (symlink(2) returns -ENOENT if
5811+
* one attempts to create an empty symlink).
5812+
* We don't need to worry about flushing delalloc, because when we create
5813+
* the inline extent when the symlink is created (we never have delalloc
5814+
* for symlinks).
5815+
*/
5816+
if (S_ISLNK(inode->vfs_inode.i_mode))
5817+
inode_only = LOG_INODE_ALL;
5818+
58075819
/*
58085820
* Before logging the inode item, cache the value returned by
58095821
* inode_logged(), because after that we have the need to figure out if
@@ -6182,7 +6194,7 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
61826194
}
61836195

61846196
ctx->log_new_dentries = false;
6185-
if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK)
6197+
if (type == BTRFS_FT_DIR)
61866198
log_mode = LOG_INODE_ALL;
61876199
ret = btrfs_log_inode(trans, BTRFS_I(di_inode),
61886200
log_mode, ctx);

fs/btrfs/xattr.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name,
262262
inode_inc_iversion(inode);
263263
inode->i_ctime = current_time(inode);
264264
ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
265-
BUG_ON(ret);
265+
if (ret)
266+
btrfs_abort_transaction(trans, ret);
266267
out:
267268
if (start_trans)
268269
btrfs_end_transaction(trans);
@@ -403,10 +404,13 @@ static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
403404
struct btrfs_root *root = BTRFS_I(inode)->root;
404405

405406
name = xattr_full_name(handler, name);
406-
ret = btrfs_validate_prop(name, value, size);
407+
ret = btrfs_validate_prop(BTRFS_I(inode), name, value, size);
407408
if (ret)
408409
return ret;
409410

411+
if (btrfs_ignore_prop(BTRFS_I(inode), name))
412+
return 0;
413+
410414
trans = btrfs_start_transaction(root, 2);
411415
if (IS_ERR(trans))
412416
return PTR_ERR(trans);
@@ -416,7 +420,8 @@ static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
416420
inode_inc_iversion(inode);
417421
inode->i_ctime = current_time(inode);
418422
ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
419-
BUG_ON(ret);
423+
if (ret)
424+
btrfs_abort_transaction(trans, ret);
420425
}
421426

422427
btrfs_end_transaction(trans);

0 commit comments

Comments
 (0)