mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 23:23:03 +00:00
for-6.12-rc2-tag
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmcH4qAACgkQxWXV+ddt
WDtDig//czntfO+iRvDERZWTIB6vdVExfLd3r3ZNYlO1pIvgCuvqx3iYva+0ZhGW
8A+gcRax7cz0jCaxDp/+5lIRfdNxZH6/LwjZsDgU8Ly7himeRmwhtn2fCgNeiH/K
bUl92+ZMo2vwqTKXYa3xF1g3Hz6cRXVW7gJrMwNhb1hpPTGx+lgYJU02m/Io/vjK
1jcrZ84OEPIOY5uiAoDyO2hgsT/zVEeuuOiSTpKSzrghPbo0vmjLiYJ5T+CE5Uw3
u3w7/Fqnw49NwucqtncvyFFDXY9EWNuQhowi3hqJgOYTInqwwJigIpQV0hDDwYxb
ohGUGjazGfAEf/cy1jZXMbwCVgg8/Nj9x0eDKKhfs19VYUbMkEYQ8LKRTUlCeBwS
H/2AmqpqHEEO+tPY3P+w6MVwkNho8JNpWPdP5OzJs7XrD067IViOjD06HPM/k5ci
TU3zp9NYvgHVtmfZK1Aqsg9OYVhI1klVXejmlAzOLxejRPWXK/1hBw3kXbC6I+k1
50l0Yh1dgEnclMI3yWsKoj8IYUAkh2eudt0pNsot4a5vICMY++NVS2eukdz5UcEz
ix7hcpYcCcmzoOaelyEgmdAncWVGJT5w2Nzy85YaOp+Z1C65Ywb41utU+sSY+swB
kZfwl9vrsfu754vX7UKBherCvvYo+Lnj3GeX8Oe+1LoT2BP0TPk=
=lTqc
-----END PGP SIGNATURE-----
Merge tag 'for-6.12-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
- update fstrim loop and add more cancellation points, fix reported
delayed or blocked suspend if there's a huge chunk queued
- fix error handling in recent qgroup xarray conversion
- in zoned mode, fix warning printing device path without RCU
protection
- again fix invalid extent xarray state (6252690f7e
), lost due to
refactoring
* tag 'for-6.12-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix clear_dirty and writeback ordering in submit_one_sector()
btrfs: zoned: fix missing RCU locking in error message when loading zone info
btrfs: fix missing error handling when adding delayed ref with qgroups enabled
btrfs: add cancellation points to trim loops
btrfs: split remaining space to discard in chunks
This commit is contained in:
commit
eb952c47d1
@ -840,6 +840,8 @@ static void init_delayed_ref_head(struct btrfs_delayed_ref_head *head_ref,
|
||||
* helper function to actually insert a head node into the rbtree.
|
||||
* this does all the dirty work in terms of maintaining the correct
|
||||
* overall modification count.
|
||||
*
|
||||
* Returns an error pointer in case of an error.
|
||||
*/
|
||||
static noinline struct btrfs_delayed_ref_head *
|
||||
add_delayed_ref_head(struct btrfs_trans_handle *trans,
|
||||
@ -862,6 +864,9 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
|
||||
if (ret) {
|
||||
/* Clean up if insertion fails or item exists. */
|
||||
xa_release(&delayed_refs->dirty_extents, qrecord->bytenr);
|
||||
/* Caller responsible for freeing qrecord on error. */
|
||||
if (ret < 0)
|
||||
return ERR_PTR(ret);
|
||||
kfree(qrecord);
|
||||
} else {
|
||||
qrecord_inserted = true;
|
||||
@ -1000,27 +1005,35 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
struct btrfs_delayed_ref_node *node;
|
||||
struct btrfs_delayed_ref_head *head_ref;
|
||||
struct btrfs_delayed_ref_head *new_head_ref;
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
struct btrfs_qgroup_extent_record *record = NULL;
|
||||
bool qrecord_inserted;
|
||||
int action = generic_ref->action;
|
||||
bool merged;
|
||||
int ret;
|
||||
|
||||
node = kmem_cache_alloc(btrfs_delayed_ref_node_cachep, GFP_NOFS);
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS);
|
||||
if (!head_ref)
|
||||
if (!head_ref) {
|
||||
ret = -ENOMEM;
|
||||
goto free_node;
|
||||
}
|
||||
|
||||
if (btrfs_qgroup_full_accounting(fs_info) && !generic_ref->skip_qgroup) {
|
||||
record = kzalloc(sizeof(*record), GFP_NOFS);
|
||||
if (!record)
|
||||
if (!record) {
|
||||
ret = -ENOMEM;
|
||||
goto free_head_ref;
|
||||
}
|
||||
if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents,
|
||||
generic_ref->bytenr, GFP_NOFS))
|
||||
generic_ref->bytenr, GFP_NOFS)) {
|
||||
ret = -ENOMEM;
|
||||
goto free_record;
|
||||
}
|
||||
}
|
||||
|
||||
init_delayed_ref_common(fs_info, node, generic_ref);
|
||||
@ -1034,8 +1047,14 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
|
||||
* insert both the head node and the new ref without dropping
|
||||
* the spin lock
|
||||
*/
|
||||
head_ref = add_delayed_ref_head(trans, head_ref, record,
|
||||
action, &qrecord_inserted);
|
||||
new_head_ref = add_delayed_ref_head(trans, head_ref, record,
|
||||
action, &qrecord_inserted);
|
||||
if (IS_ERR(new_head_ref)) {
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
ret = PTR_ERR(new_head_ref);
|
||||
goto free_record;
|
||||
}
|
||||
head_ref = new_head_ref;
|
||||
|
||||
merged = insert_delayed_ref(trans, head_ref, node);
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
@ -1063,7 +1082,7 @@ free_head_ref:
|
||||
kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref);
|
||||
free_node:
|
||||
kmem_cache_free(btrfs_delayed_ref_node_cachep, node);
|
||||
return -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1094,6 +1113,7 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_delayed_extent_op *extent_op)
|
||||
{
|
||||
struct btrfs_delayed_ref_head *head_ref;
|
||||
struct btrfs_delayed_ref_head *head_ref_ret;
|
||||
struct btrfs_delayed_ref_root *delayed_refs;
|
||||
struct btrfs_ref generic_ref = {
|
||||
.type = BTRFS_REF_METADATA,
|
||||
@ -1113,11 +1133,15 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
|
||||
delayed_refs = &trans->transaction->delayed_refs;
|
||||
spin_lock(&delayed_refs->lock);
|
||||
|
||||
add_delayed_ref_head(trans, head_ref, NULL, BTRFS_UPDATE_DELAYED_HEAD,
|
||||
NULL);
|
||||
|
||||
head_ref_ret = add_delayed_ref_head(trans, head_ref, NULL,
|
||||
BTRFS_UPDATE_DELAYED_HEAD, NULL);
|
||||
spin_unlock(&delayed_refs->lock);
|
||||
|
||||
if (IS_ERR(head_ref_ret)) {
|
||||
kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref);
|
||||
return PTR_ERR(head_ref_ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to update the delayed_refs_rsv with any changes we may have
|
||||
* made.
|
||||
|
@ -1300,13 +1300,29 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
|
||||
bytes_left = end - start;
|
||||
}
|
||||
|
||||
if (bytes_left) {
|
||||
while (bytes_left) {
|
||||
u64 bytes_to_discard = min(BTRFS_MAX_DISCARD_CHUNK_SIZE, bytes_left);
|
||||
|
||||
ret = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT,
|
||||
bytes_left >> SECTOR_SHIFT,
|
||||
bytes_to_discard >> SECTOR_SHIFT,
|
||||
GFP_NOFS);
|
||||
if (!ret)
|
||||
*discarded_bytes += bytes_left;
|
||||
|
||||
if (ret) {
|
||||
if (ret != -EOPNOTSUPP)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
start += bytes_to_discard;
|
||||
bytes_left -= bytes_to_discard;
|
||||
*discarded_bytes += bytes_to_discard;
|
||||
|
||||
if (btrfs_trim_interrupted()) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -6459,7 +6475,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed)
|
||||
start += len;
|
||||
*trimmed += bytes;
|
||||
|
||||
if (fatal_signal_pending(current)) {
|
||||
if (btrfs_trim_interrupted()) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
@ -1306,6 +1306,13 @@ static int submit_one_sector(struct btrfs_inode *inode,
|
||||
free_extent_map(em);
|
||||
em = NULL;
|
||||
|
||||
/*
|
||||
* Although the PageDirty bit is cleared before entering this
|
||||
* function, subpage dirty bit is not cleared.
|
||||
* So clear subpage dirty bit here so next time we won't submit
|
||||
* a folio for a range already written to disk.
|
||||
*/
|
||||
btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize);
|
||||
btrfs_set_range_writeback(inode, filepos, filepos + sectorsize - 1);
|
||||
/*
|
||||
* Above call should set the whole folio with writeback flag, even
|
||||
@ -1315,13 +1322,6 @@ static int submit_one_sector(struct btrfs_inode *inode,
|
||||
*/
|
||||
ASSERT(folio_test_writeback(folio));
|
||||
|
||||
/*
|
||||
* Although the PageDirty bit is cleared before entering this
|
||||
* function, subpage dirty bit is not cleared.
|
||||
* So clear subpage dirty bit here so next time we won't submit
|
||||
* folio for range already written to disk.
|
||||
*/
|
||||
btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize);
|
||||
submit_extent_folio(bio_ctrl, disk_bytenr, folio,
|
||||
sectorsize, filepos - folio_pos(folio));
|
||||
return 0;
|
||||
|
@ -3809,7 +3809,7 @@ next:
|
||||
if (async && *total_trimmed)
|
||||
break;
|
||||
|
||||
if (fatal_signal_pending(current)) {
|
||||
if (btrfs_trim_interrupted()) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
@ -4000,7 +4000,7 @@ next:
|
||||
}
|
||||
block_group->discard_cursor = start;
|
||||
|
||||
if (fatal_signal_pending(current)) {
|
||||
if (btrfs_trim_interrupted()) {
|
||||
if (start != offset)
|
||||
reset_trimming_bitmap(ctl, offset);
|
||||
ret = -ERESTARTSYS;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/freezer.h>
|
||||
#include "fs.h"
|
||||
|
||||
struct inode;
|
||||
@ -56,6 +57,11 @@ static inline bool btrfs_free_space_trimming_bitmap(
|
||||
return (info->trim_state == BTRFS_TRIM_STATE_TRIMMING);
|
||||
}
|
||||
|
||||
static inline bool btrfs_trim_interrupted(void)
|
||||
{
|
||||
return fatal_signal_pending(current) || freezing(current);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deltas are an effective way to populate global statistics. Give macro names
|
||||
* to make it clear what we're doing. An example is discard_extents in
|
||||
|
@ -30,6 +30,12 @@ struct btrfs_zoned_device_info;
|
||||
|
||||
#define BTRFS_MAX_DATA_CHUNK_SIZE (10ULL * SZ_1G)
|
||||
|
||||
/*
|
||||
* Arbitratry maximum size of one discard request to limit potentially long time
|
||||
* spent in blkdev_issue_discard().
|
||||
*/
|
||||
#define BTRFS_MAX_DISCARD_CHUNK_SIZE (SZ_1G)
|
||||
|
||||
extern struct mutex uuid_mutex;
|
||||
|
||||
#define BTRFS_STRIPE_LEN SZ_64K
|
||||
|
@ -1340,7 +1340,7 @@ static int btrfs_load_zone_info(struct btrfs_fs_info *fs_info, int zone_idx,
|
||||
switch (zone.cond) {
|
||||
case BLK_ZONE_COND_OFFLINE:
|
||||
case BLK_ZONE_COND_READONLY:
|
||||
btrfs_err(fs_info,
|
||||
btrfs_err_in_rcu(fs_info,
|
||||
"zoned: offline/readonly zone %llu on device %s (devid %llu)",
|
||||
(info->physical >> device->zone_info->zone_size_shift),
|
||||
rcu_str_deref(device->name), device->devid);
|
||||
|
Loading…
Reference in New Issue
Block a user