Skip to content

Commit

Permalink
Merge tag 'for-linus-20180830' of git://git.kernel.dk/linux-block
Browse files Browse the repository at this point in the history
Pull block fixes from Jens Axboe:
 "Small collection of fixes that should go into this series. This pull
  contains:

   - NVMe pull request with three small fixes (via Christoph)

   - Kill useless NULL check before kmem_cache_destroy (Chengguang Xu)

   - Xen block driver pull request with persistent grant flushing fixes
     (Juergen Gross)

   - Final wbt fixes, wrapping up the changes for this series. These
     have been heavily tested (me)

   - cdrom info leak fix (Scott Bauer)

   - ATA dma quirk for SQ201 (Linus Walleij)

   - Straight forward bsg refcount_t conversion (John Pittman)"

* tag 'for-linus-20180830' of git://git.kernel.dk/linux-block:
  cdrom: Fix info leak/OOB read in cdrom_ioctl_drive_status
  nvmet: free workqueue object if module init fails
  nvme-fcloop: Fix dropped LS's to removed target port
  nvme-pci: add a memory barrier to nvme_dbbuf_update_and_check_event
  block: bsg: move atomic_t ref_count variable to refcount API
  block: remove unnecessary condition check
  ata: ftide010: Add a quirk for SQ201
  blk-wbt: remove dead code
  blk-wbt: improve waking of tasks
  blk-wbt: abstract out end IO completion handler
  xen/blkback: remove unused pers_gnts_lock from struct xen_blkif_ring
  xen/blkback: move persistent grants flags to bool
  xen/blkfront: reorder tests in xlblk_init()
  xen/blkfront: cleanup stale persistent grants
  xen/blkback: don't keep persistent grants too long
  • Loading branch information
torvalds committed Aug 30, 2018
2 parents 9f8f16c + 52bd456 commit fb64638
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 108 deletions.
10 changes: 10 additions & 0 deletions Documentation/ABI/testing/sysfs-driver-xen-blkback
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,13 @@ Description:
blkback. If the frontend tries to use more than
max_persistent_grants, the LRU kicks in and starts
removing 5% of max_persistent_grants every 100ms.

What: /sys/module/xen_blkback/parameters/persistent_grant_unused_seconds
Date: August 2018
KernelVersion: 4.19
Contact: Roger Pau Monné <[email protected]>
Description:
How long a persistent grant is allowed to remain
allocated without being in use. The time is in
seconds, 0 means indefinitely long.
The default is 60 seconds.
89 changes: 70 additions & 19 deletions block/blk-wbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,11 @@ static void rwb_wake_all(struct rq_wb *rwb)
}
}

static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct)
static void wbt_rqw_done(struct rq_wb *rwb, struct rq_wait *rqw,
enum wbt_flags wb_acct)
{
struct rq_wb *rwb = RQWB(rqos);
struct rq_wait *rqw;
int inflight, limit;

if (!(wb_acct & WBT_TRACKED))
return;

rqw = get_rq_wait(rwb, wb_acct);
inflight = atomic_dec_return(&rqw->inflight);

/*
Expand Down Expand Up @@ -166,10 +161,22 @@ static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct)
int diff = limit - inflight;

if (!inflight || diff >= rwb->wb_background / 2)
wake_up(&rqw->wait);
wake_up_all(&rqw->wait);
}
}

static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct)
{
struct rq_wb *rwb = RQWB(rqos);
struct rq_wait *rqw;

if (!(wb_acct & WBT_TRACKED))
return;

rqw = get_rq_wait(rwb, wb_acct);
wbt_rqw_done(rwb, rqw, wb_acct);
}

/*
* Called on completion of a request. Note that it's also called when
* a request is merged, when the request gets freed.
Expand Down Expand Up @@ -481,6 +488,34 @@ static inline unsigned int get_limit(struct rq_wb *rwb, unsigned long rw)
return limit;
}

struct wbt_wait_data {
struct wait_queue_entry wq;
struct task_struct *task;
struct rq_wb *rwb;
struct rq_wait *rqw;
unsigned long rw;
bool got_token;
};

static int wbt_wake_function(struct wait_queue_entry *curr, unsigned int mode,
int wake_flags, void *key)
{
struct wbt_wait_data *data = container_of(curr, struct wbt_wait_data,
wq);

/*
* If we fail to get a budget, return -1 to interrupt the wake up
* loop in __wake_up_common.
*/
if (!rq_wait_inc_below(data->rqw, get_limit(data->rwb, data->rw)))
return -1;

data->got_token = true;
list_del_init(&curr->entry);
wake_up_process(data->task);
return 1;
}

/*
* Block if we will exceed our limit, or if we are currently waiting for
* the timer to kick off queuing again.
Expand All @@ -491,31 +526,52 @@ static void __wbt_wait(struct rq_wb *rwb, enum wbt_flags wb_acct,
__acquires(lock)
{
struct rq_wait *rqw = get_rq_wait(rwb, wb_acct);
DECLARE_WAITQUEUE(wait, current);
struct wbt_wait_data data = {
.wq = {
.func = wbt_wake_function,
.entry = LIST_HEAD_INIT(data.wq.entry),
},
.task = current,
.rwb = rwb,
.rqw = rqw,
.rw = rw,
};
bool has_sleeper;

has_sleeper = wq_has_sleeper(&rqw->wait);
if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
return;

add_wait_queue_exclusive(&rqw->wait, &wait);
prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE);
do {
set_current_state(TASK_UNINTERRUPTIBLE);
if (data.got_token)
break;

if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
if (!has_sleeper &&
rq_wait_inc_below(rqw, get_limit(rwb, rw))) {
finish_wait(&rqw->wait, &data.wq);

/*
* We raced with wbt_wake_function() getting a token,
* which means we now have two. Put our local token
* and wake anyone else potentially waiting for one.
*/
if (data.got_token)
wbt_rqw_done(rwb, rqw, wb_acct);
break;
}

if (lock) {
spin_unlock_irq(lock);
io_schedule();
spin_lock_irq(lock);
} else
io_schedule();

has_sleeper = false;
} while (1);

__set_current_state(TASK_RUNNING);
remove_wait_queue(&rqw->wait, &wait);
finish_wait(&rqw->wait, &data.wq);
}

static inline bool wbt_should_throttle(struct rq_wb *rwb, struct bio *bio)
Expand Down Expand Up @@ -580,11 +636,6 @@ static void wbt_wait(struct rq_qos *rqos, struct bio *bio, spinlock_t *lock)
return;
}

if (current_is_kswapd())
flags |= WBT_KSWAPD;
if (bio_op(bio) == REQ_OP_DISCARD)
flags |= WBT_DISCARD;

__wbt_wait(rwb, flags, bio->bi_opf, lock);

if (!blk_stat_is_active(rwb->cb))
Expand Down
8 changes: 4 additions & 4 deletions block/bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct bsg_device {
struct request_queue *queue;
spinlock_t lock;
struct hlist_node dev_list;
atomic_t ref_count;
refcount_t ref_count;
char name[20];
int max_queue;
};
Expand Down Expand Up @@ -252,7 +252,7 @@ static int bsg_put_device(struct bsg_device *bd)

mutex_lock(&bsg_mutex);

if (!atomic_dec_and_test(&bd->ref_count)) {
if (!refcount_dec_and_test(&bd->ref_count)) {
mutex_unlock(&bsg_mutex);
return 0;
}
Expand Down Expand Up @@ -290,7 +290,7 @@ static struct bsg_device *bsg_add_device(struct inode *inode,

bd->queue = rq;

atomic_set(&bd->ref_count, 1);
refcount_set(&bd->ref_count, 1);
hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));

strncpy(bd->name, dev_name(rq->bsg_dev.class_dev), sizeof(bd->name) - 1);
Expand All @@ -308,7 +308,7 @@ static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)

hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) {
if (bd->queue == q) {
atomic_inc(&bd->ref_count);
refcount_inc(&bd->ref_count);
goto found;
}
}
Expand Down
3 changes: 1 addition & 2 deletions block/elevator.c
Original file line number Diff line number Diff line change
Expand Up @@ -895,8 +895,7 @@ int elv_register(struct elevator_type *e)
spin_lock(&elv_list_lock);
if (elevator_find(e->elevator_name, e->uses_mq)) {
spin_unlock(&elv_list_lock);
if (e->icq_cache)
kmem_cache_destroy(e->icq_cache);
kmem_cache_destroy(e->icq_cache);
return -EBUSY;
}
list_add_tail(&e->list, &elv_list);
Expand Down
27 changes: 17 additions & 10 deletions drivers/ata/pata_ftide010.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,12 @@ static struct ata_port_operations pata_ftide010_port_ops = {
.qc_issue = ftide010_qc_issue,
};

static struct ata_port_info ftide010_port_info[] = {
{
.flags = ATA_FLAG_SLAVE_POSS,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.pio_mask = ATA_PIO4,
.port_ops = &pata_ftide010_port_ops,
},
static struct ata_port_info ftide010_port_info = {
.flags = ATA_FLAG_SLAVE_POSS,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.pio_mask = ATA_PIO4,
.port_ops = &pata_ftide010_port_ops,
};

#if IS_ENABLED(CONFIG_SATA_GEMINI)
Expand Down Expand Up @@ -349,6 +347,7 @@ static int pata_ftide010_gemini_cable_detect(struct ata_port *ap)
}

static int pata_ftide010_gemini_init(struct ftide010 *ftide,
struct ata_port_info *pi,
bool is_ata1)
{
struct device *dev = ftide->dev;
Expand All @@ -373,7 +372,13 @@ static int pata_ftide010_gemini_init(struct ftide010 *ftide,

/* Flag port as SATA-capable */
if (gemini_sata_bridge_enabled(sg, is_ata1))
ftide010_port_info[0].flags |= ATA_FLAG_SATA;
pi->flags |= ATA_FLAG_SATA;

/* This device has broken DMA, only PIO works */
if (of_machine_is_compatible("itian,sq201")) {
pi->mwdma_mask = 0;
pi->udma_mask = 0;
}

/*
* We assume that a simple 40-wire cable is used in the PATA mode.
Expand Down Expand Up @@ -435,6 +440,7 @@ static int pata_ftide010_gemini_init(struct ftide010 *ftide,
}
#else
static int pata_ftide010_gemini_init(struct ftide010 *ftide,
struct ata_port_info *pi,
bool is_ata1)
{
return -ENOTSUPP;
Expand All @@ -446,7 +452,7 @@ static int pata_ftide010_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
const struct ata_port_info pi = ftide010_port_info[0];
struct ata_port_info pi = ftide010_port_info;
const struct ata_port_info *ppi[] = { &pi, NULL };
struct ftide010 *ftide;
struct resource *res;
Expand Down Expand Up @@ -490,6 +496,7 @@ static int pata_ftide010_probe(struct platform_device *pdev)
* are ATA0. This will also set up the cable types.
*/
ret = pata_ftide010_gemini_init(ftide,
&pi,
(res->start == 0x63400000));
if (ret)
goto err_dis_clk;
Expand Down
Loading

0 comments on commit fb64638

Please sign in to comment.