Skip to content

Commit bc512ae

Browse files
committed
Merge branch 'for-6.11/block' into for-next
* for-6.11/block: loop: Fix a race between loop detach and loop open block: Delete blk_queue_flag_test_and_set()
2 parents e21d057 + 18048c1 commit bc512ae

File tree

3 files changed

+36
-54
lines changed

3 files changed

+36
-54
lines changed

block/blk-core.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,6 @@ void blk_queue_flag_clear(unsigned int flag, struct request_queue *q)
9494
}
9595
EXPORT_SYMBOL(blk_queue_flag_clear);
9696

97-
/**
98-
* blk_queue_flag_test_and_set - atomically test and set a queue flag
99-
* @flag: flag to be set
100-
* @q: request queue
101-
*
102-
* Returns the previous value of @flag - 0 if the flag was not set and 1 if
103-
* the flag was already set.
104-
*/
105-
bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q)
106-
{
107-
return test_and_set_bit(flag, &q->queue_flags);
108-
}
109-
EXPORT_SYMBOL_GPL(blk_queue_flag_test_and_set);
110-
11197
#define REQ_OP_NAME(name) [REQ_OP_##name] = #name
11298
static const char *const blk_op_name[] = {
11399
REQ_OP_NAME(READ),

drivers/block/loop.c

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,20 +1146,12 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
11461146
return error;
11471147
}
11481148

1149-
static void __loop_clr_fd(struct loop_device *lo, bool release)
1149+
static void __loop_clr_fd(struct loop_device *lo)
11501150
{
11511151
struct queue_limits lim;
11521152
struct file *filp;
11531153
gfp_t gfp = lo->old_gfp_mask;
11541154

1155-
/*
1156-
* Freeze the request queue when unbinding on a live file descriptor and
1157-
* thus an open device. When called from ->release we are guaranteed
1158-
* that there is no I/O in progress already.
1159-
*/
1160-
if (!release)
1161-
blk_mq_freeze_queue(lo->lo_queue);
1162-
11631155
spin_lock_irq(&lo->lo_lock);
11641156
filp = lo->lo_backing_file;
11651157
lo->lo_backing_file = NULL;
@@ -1184,8 +1176,6 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
11841176
mapping_set_gfp_mask(filp->f_mapping, gfp);
11851177
/* This is safe: open() is still holding a reference. */
11861178
module_put(THIS_MODULE);
1187-
if (!release)
1188-
blk_mq_unfreeze_queue(lo->lo_queue);
11891179

11901180
disk_force_media_change(lo->lo_disk);
11911181

@@ -1200,11 +1190,7 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
12001190
* must be at least one and it can only become zero when the
12011191
* current holder is released.
12021192
*/
1203-
if (!release)
1204-
mutex_lock(&lo->lo_disk->open_mutex);
12051193
err = bdev_disk_changed(lo->lo_disk, false);
1206-
if (!release)
1207-
mutex_unlock(&lo->lo_disk->open_mutex);
12081194
if (err)
12091195
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
12101196
__func__, lo->lo_number, err);
@@ -1253,24 +1239,16 @@ static int loop_clr_fd(struct loop_device *lo)
12531239
return -ENXIO;
12541240
}
12551241
/*
1256-
* If we've explicitly asked to tear down the loop device,
1257-
* and it has an elevated reference count, set it for auto-teardown when
1258-
* the last reference goes away. This stops $!~#$@ udev from
1259-
* preventing teardown because it decided that it needs to run blkid on
1260-
* the loopback device whenever they appear. xfstests is notorious for
1261-
* failing tests because blkid via udev races with a losetup
1262-
* <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
1263-
* command to fail with EBUSY.
1242+
* Mark the device for removing the backing device on last close.
1243+
* If we are the only opener, also switch the state to roundown here to
1244+
* prevent new openers from coming in.
12641245
*/
1265-
if (disk_openers(lo->lo_disk) > 1) {
1266-
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
1267-
loop_global_unlock(lo, true);
1268-
return 0;
1269-
}
1270-
lo->lo_state = Lo_rundown;
1246+
1247+
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
1248+
if (disk_openers(lo->lo_disk) == 1)
1249+
lo->lo_state = Lo_rundown;
12711250
loop_global_unlock(lo, true);
12721251

1273-
__loop_clr_fd(lo, false);
12741252
return 0;
12751253
}
12761254

@@ -1737,25 +1715,43 @@ static int lo_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
17371715
}
17381716
#endif
17391717

1718+
static int lo_open(struct gendisk *disk, blk_mode_t mode)
1719+
{
1720+
struct loop_device *lo = disk->private_data;
1721+
int err;
1722+
1723+
err = mutex_lock_killable(&lo->lo_mutex);
1724+
if (err)
1725+
return err;
1726+
1727+
if (lo->lo_state == Lo_deleting || lo->lo_state == Lo_rundown)
1728+
err = -ENXIO;
1729+
mutex_unlock(&lo->lo_mutex);
1730+
return err;
1731+
}
1732+
17401733
static void lo_release(struct gendisk *disk)
17411734
{
17421735
struct loop_device *lo = disk->private_data;
1736+
bool need_clear = false;
17431737

17441738
if (disk_openers(disk) > 0)
17451739
return;
1740+
/*
1741+
* Clear the backing device information if this is the last close of
1742+
* a device that's been marked for auto clear, or on which LOOP_CLR_FD
1743+
* has been called.
1744+
*/
17461745

17471746
mutex_lock(&lo->lo_mutex);
1748-
if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR)) {
1747+
if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR))
17491748
lo->lo_state = Lo_rundown;
1750-
mutex_unlock(&lo->lo_mutex);
1751-
/*
1752-
* In autoclear mode, stop the loop thread
1753-
* and remove configuration after last close.
1754-
*/
1755-
__loop_clr_fd(lo, true);
1756-
return;
1757-
}
1749+
1750+
need_clear = (lo->lo_state == Lo_rundown);
17581751
mutex_unlock(&lo->lo_mutex);
1752+
1753+
if (need_clear)
1754+
__loop_clr_fd(lo);
17591755
}
17601756

17611757
static void lo_free_disk(struct gendisk *disk)
@@ -1772,6 +1768,7 @@ static void lo_free_disk(struct gendisk *disk)
17721768

17731769
static const struct block_device_operations lo_fops = {
17741770
.owner = THIS_MODULE,
1771+
.open = lo_open,
17751772
.release = lo_release,
17761773
.ioctl = lo_ioctl,
17771774
#ifdef CONFIG_COMPAT

include/linux/blkdev.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,6 @@ struct request_queue {
609609

610610
void blk_queue_flag_set(unsigned int flag, struct request_queue *q);
611611
void blk_queue_flag_clear(unsigned int flag, struct request_queue *q);
612-
bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
613612

614613
#define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
615614
#define blk_queue_dying(q) test_bit(QUEUE_FLAG_DYING, &(q)->queue_flags)

0 commit comments

Comments
 (0)