Skip to content

Commit 5304ca3

Browse files
davidhildenbrandmstsirkin
authored andcommitted
virtio-mem: simplify high-level unplug handling in Sub Block Mode
Let's simplify by introducing a new virtio_mem_sbm_unplug_any_sb(), similar to virtio_mem_sbm_plug_any_sb(), to simplify high-level memory block selection when unplugging in Sub Block Mode. Rename existing virtio_mem_sbm_unplug_any_sb() to virtio_mem_sbm_unplug_any_sb_raw(). The only change is that we now temporarily unlock the hotplug mutex around cond_resched() when processing offline memory blocks, which doesn't make a real difference as we already have to temporarily unlock in virtio_mem_sbm_unplug_any_sb_offline() when removing a memory block. Signed-off-by: David Hildenbrand <david@redhat.com> Link: https://lore.kernel.org/r/20210602185720.31821-5-david@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
1 parent f4cf803 commit 5304ca3

1 file changed

Lines changed: 57 additions & 46 deletions

File tree

drivers/virtio/virtio_mem.c

Lines changed: 57 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,8 +1453,8 @@ static int virtio_mem_bbm_plug_bb(struct virtio_mem *vm, unsigned long bb_id)
14531453
*
14541454
* Note: can fail after some subblocks were unplugged.
14551455
*/
1456-
static int virtio_mem_sbm_unplug_any_sb(struct virtio_mem *vm,
1457-
unsigned long mb_id, uint64_t *nb_sb)
1456+
static int virtio_mem_sbm_unplug_any_sb_raw(struct virtio_mem *vm,
1457+
unsigned long mb_id, uint64_t *nb_sb)
14581458
{
14591459
int sb_id, count;
14601460
int rc;
@@ -1496,7 +1496,7 @@ static int virtio_mem_sbm_unplug_mb(struct virtio_mem *vm, unsigned long mb_id)
14961496
{
14971497
uint64_t nb_sb = vm->sbm.sbs_per_mb;
14981498

1499-
return virtio_mem_sbm_unplug_any_sb(vm, mb_id, &nb_sb);
1499+
return virtio_mem_sbm_unplug_any_sb_raw(vm, mb_id, &nb_sb);
15001500
}
15011501

15021502
/*
@@ -1806,7 +1806,7 @@ static int virtio_mem_sbm_unplug_any_sb_offline(struct virtio_mem *vm,
18061806
{
18071807
int rc;
18081808

1809-
rc = virtio_mem_sbm_unplug_any_sb(vm, mb_id, nb_sb);
1809+
rc = virtio_mem_sbm_unplug_any_sb_raw(vm, mb_id, nb_sb);
18101810

18111811
/* some subblocks might have been unplugged even on failure */
18121812
if (!virtio_mem_sbm_test_sb_plugged(vm, mb_id, 0, vm->sbm.sbs_per_mb))
@@ -1929,11 +1929,46 @@ static int virtio_mem_sbm_unplug_any_sb_online(struct virtio_mem *vm,
19291929
return 0;
19301930
}
19311931

1932+
/*
1933+
* Unplug the desired number of plugged subblocks of a memory block that is
1934+
* already added to Linux. Will skip subblock of online memory blocks that are
1935+
* busy (by the OS). Will fail if any subblock that's not busy cannot get
1936+
* unplugged.
1937+
*
1938+
* Will modify the state of the memory block. Might temporarily drop the
1939+
* hotplug_mutex.
1940+
*
1941+
* Note: Can fail after some subblocks were successfully unplugged. Can
1942+
* return 0 even if subblocks were busy and could not get unplugged.
1943+
*/
1944+
static int virtio_mem_sbm_unplug_any_sb(struct virtio_mem *vm,
1945+
unsigned long mb_id,
1946+
uint64_t *nb_sb)
1947+
{
1948+
const int old_state = virtio_mem_sbm_get_mb_state(vm, mb_id);
1949+
1950+
switch (old_state) {
1951+
case VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL:
1952+
case VIRTIO_MEM_SBM_MB_ONLINE:
1953+
return virtio_mem_sbm_unplug_any_sb_online(vm, mb_id, nb_sb);
1954+
case VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL:
1955+
case VIRTIO_MEM_SBM_MB_OFFLINE:
1956+
return virtio_mem_sbm_unplug_any_sb_offline(vm, mb_id, nb_sb);
1957+
}
1958+
return -EINVAL;
1959+
}
1960+
19321961
static int virtio_mem_sbm_unplug_request(struct virtio_mem *vm, uint64_t diff)
19331962
{
1963+
const int mb_states[] = {
1964+
VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL,
1965+
VIRTIO_MEM_SBM_MB_OFFLINE,
1966+
VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL,
1967+
VIRTIO_MEM_SBM_MB_ONLINE,
1968+
};
19341969
uint64_t nb_sb = diff / vm->sbm.sb_size;
19351970
unsigned long mb_id;
1936-
int rc;
1971+
int rc, i;
19371972

19381973
if (!nb_sb)
19391974
return 0;
@@ -1945,47 +1980,23 @@ static int virtio_mem_sbm_unplug_request(struct virtio_mem *vm, uint64_t diff)
19451980
*/
19461981
mutex_lock(&vm->hotplug_mutex);
19471982

1948-
/* Try to unplug subblocks of partially plugged offline blocks. */
1949-
virtio_mem_sbm_for_each_mb_rev(vm, mb_id,
1950-
VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL) {
1951-
rc = virtio_mem_sbm_unplug_any_sb_offline(vm, mb_id, &nb_sb);
1952-
if (rc || !nb_sb)
1953-
goto out_unlock;
1954-
cond_resched();
1955-
}
1956-
1957-
/* Try to unplug subblocks of plugged offline blocks. */
1958-
virtio_mem_sbm_for_each_mb_rev(vm, mb_id, VIRTIO_MEM_SBM_MB_OFFLINE) {
1959-
rc = virtio_mem_sbm_unplug_any_sb_offline(vm, mb_id, &nb_sb);
1960-
if (rc || !nb_sb)
1961-
goto out_unlock;
1962-
cond_resched();
1963-
}
1964-
1965-
if (!unplug_online) {
1966-
mutex_unlock(&vm->hotplug_mutex);
1967-
return 0;
1968-
}
1969-
1970-
/* Try to unplug subblocks of partially plugged online blocks. */
1971-
virtio_mem_sbm_for_each_mb_rev(vm, mb_id,
1972-
VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL) {
1973-
rc = virtio_mem_sbm_unplug_any_sb_online(vm, mb_id, &nb_sb);
1974-
if (rc || !nb_sb)
1975-
goto out_unlock;
1976-
mutex_unlock(&vm->hotplug_mutex);
1977-
cond_resched();
1978-
mutex_lock(&vm->hotplug_mutex);
1979-
}
1980-
1981-
/* Try to unplug subblocks of plugged online blocks. */
1982-
virtio_mem_sbm_for_each_mb_rev(vm, mb_id, VIRTIO_MEM_SBM_MB_ONLINE) {
1983-
rc = virtio_mem_sbm_unplug_any_sb_online(vm, mb_id, &nb_sb);
1984-
if (rc || !nb_sb)
1985-
goto out_unlock;
1986-
mutex_unlock(&vm->hotplug_mutex);
1987-
cond_resched();
1988-
mutex_lock(&vm->hotplug_mutex);
1983+
/*
1984+
* We try unplug from partially plugged blocks first, to try removing
1985+
* whole memory blocks along with metadata.
1986+
*/
1987+
for (i = 0; i < ARRAY_SIZE(mb_states); i++) {
1988+
virtio_mem_sbm_for_each_mb_rev(vm, mb_id, mb_states[i]) {
1989+
rc = virtio_mem_sbm_unplug_any_sb(vm, mb_id, &nb_sb);
1990+
if (rc || !nb_sb)
1991+
goto out_unlock;
1992+
mutex_unlock(&vm->hotplug_mutex);
1993+
cond_resched();
1994+
mutex_lock(&vm->hotplug_mutex);
1995+
}
1996+
if (!unplug_online && i == 1) {
1997+
mutex_unlock(&vm->hotplug_mutex);
1998+
return 0;
1999+
}
19892000
}
19902001

19912002
mutex_unlock(&vm->hotplug_mutex);

0 commit comments

Comments
 (0)