Skip to content

Commit

Permalink
Merge branch 'for-3.19/drivers' of git://git.kernel.dk/linux-block
Browse files Browse the repository at this point in the history
Pull block layer driver updates from Jens Axboe:

 - NVMe updates:
        - The blk-mq conversion from Matias (and others)

        - A stack of NVMe bug fixes from the nvme tree, mostly from Keith.

        - Various bug fixes from me, fixing issues in both the blk-mq
          conversion and generic bugs.

        - Abort and CPU online fix from Sam.

        - Hot add/remove fix from Indraneel.

 - A couple of drbd fixes from the drbd team (Andreas, Lars, Philipp)

 - With the generic IO stat accounting from 3.19/core, converting md,
   bcache, and rsxx to use those.  From Gu Zheng.

 - Boundary check for queue/irq mode for null_blk from Matias.  Fixes
   cases where invalid values could be given, causing the device to hang.

 - The xen blkfront pull request, with two bug fixes from Vitaly.

* 'for-3.19/drivers' of git://git.kernel.dk/linux-block: (56 commits)
  NVMe: fix race condition in nvme_submit_sync_cmd()
  NVMe: fix retry/error logic in nvme_queue_rq()
  NVMe: Fix FS mount issue (hot-remove followed by hot-add)
  NVMe: fix error return checking from blk_mq_alloc_request()
  NVMe: fix freeing of wrong request in abort path
  xen/blkfront: remove redundant flush_op
  xen/blkfront: improve protection against issuing unsupported REQ_FUA
  NVMe: Fix command setup on IO retry
  null_blk: boundary check queue_mode and irqmode
  block/rsxx: use generic io stats accounting functions to simplify io stat accounting
  md: use generic io stats accounting functions to simplify io stat accounting
  drbd: use generic io stats accounting functions to simplify io stat accounting
  md/bcache: use generic io stats accounting functions to simplify io stat accounting
  NVMe: Update module version major number
  NVMe: fail pci initialization if the device doesn't have any BARs
  NVMe: add ->exit_hctx() hook
  NVMe: make setup work for devices that don't do INTx
  NVMe: enable IO stats by default
  NVMe: nvme_submit_async_admin_req() must use atomic rq allocation
  NVMe: replace blk_put_request() with blk_mq_free_request()
  ...
  • Loading branch information
Linus Torvalds committed Dec 13, 2014
2 parents caf292a + 849c6e7 commit 9ea18f8
Show file tree
Hide file tree
Showing 20 changed files with 1,009 additions and 1,199 deletions.
3 changes: 1 addition & 2 deletions drivers/block/drbd/drbd_actlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,8 +827,7 @@ static int update_sync_bits(struct drbd_device *device,
*
*/
int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size,
enum update_sync_bits_mode mode,
const char *file, const unsigned int line)
enum update_sync_bits_mode mode)
{
/* Is called from worker and receiver context _only_ */
unsigned long sbnr, ebnr, lbnr;
Expand Down
39 changes: 8 additions & 31 deletions drivers/block/drbd/drbd_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,6 @@ extern int is_valid_ar_handle(struct drbd_request *, sector_t);


/* drbd_nl.c */
extern int drbd_msg_put_info(struct sk_buff *skb, const char *info);
extern void drbd_suspend_io(struct drbd_device *device);
extern void drbd_resume_io(struct drbd_device *device);
extern char *ppsize(char *buf, unsigned long long size);
Expand Down Expand Up @@ -1558,52 +1557,31 @@ extern void drbd_set_recv_tcq(struct drbd_device *device, int tcq_enabled);
extern void _drbd_clear_done_ee(struct drbd_device *device, struct list_head *to_be_freed);
extern int drbd_connected(struct drbd_peer_device *);

/* Yes, there is kernel_setsockopt, but only since 2.6.18.
* So we have our own copy of it here. */
static inline int drbd_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
mm_segment_t oldfs = get_fs();
char __user *uoptval;
int err;

uoptval = (char __user __force *)optval;

set_fs(KERNEL_DS);
if (level == SOL_SOCKET)
err = sock_setsockopt(sock, level, optname, uoptval, optlen);
else
err = sock->ops->setsockopt(sock, level, optname, uoptval,
optlen);
set_fs(oldfs);
return err;
}

static inline void drbd_tcp_cork(struct socket *sock)
{
int val = 1;
(void) drbd_setsockopt(sock, SOL_TCP, TCP_CORK,
(void) kernel_setsockopt(sock, SOL_TCP, TCP_CORK,
(char*)&val, sizeof(val));
}

static inline void drbd_tcp_uncork(struct socket *sock)
{
int val = 0;
(void) drbd_setsockopt(sock, SOL_TCP, TCP_CORK,
(void) kernel_setsockopt(sock, SOL_TCP, TCP_CORK,
(char*)&val, sizeof(val));
}

static inline void drbd_tcp_nodelay(struct socket *sock)
{
int val = 1;
(void) drbd_setsockopt(sock, SOL_TCP, TCP_NODELAY,
(void) kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
(char*)&val, sizeof(val));
}

static inline void drbd_tcp_quickack(struct socket *sock)
{
int val = 2;
(void) drbd_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
(void) kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
(char*)&val, sizeof(val));
}

Expand Down Expand Up @@ -1662,14 +1640,13 @@ extern void drbd_advance_rs_marks(struct drbd_device *device, unsigned long stil

enum update_sync_bits_mode { RECORD_RS_FAILED, SET_OUT_OF_SYNC, SET_IN_SYNC };
extern int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size,
enum update_sync_bits_mode mode,
const char *file, const unsigned int line);
enum update_sync_bits_mode mode);
#define drbd_set_in_sync(device, sector, size) \
__drbd_change_sync(device, sector, size, SET_IN_SYNC, __FILE__, __LINE__)
__drbd_change_sync(device, sector, size, SET_IN_SYNC)
#define drbd_set_out_of_sync(device, sector, size) \
__drbd_change_sync(device, sector, size, SET_OUT_OF_SYNC, __FILE__, __LINE__)
__drbd_change_sync(device, sector, size, SET_OUT_OF_SYNC)
#define drbd_rs_failed_io(device, sector, size) \
__drbd_change_sync(device, sector, size, RECORD_RS_FAILED, __FILE__, __LINE__)
__drbd_change_sync(device, sector, size, RECORD_RS_FAILED)
extern void drbd_al_shrink(struct drbd_device *device);
extern int drbd_initialize_al(struct drbd_device *, void *);

Expand Down
23 changes: 6 additions & 17 deletions drivers/block/drbd/drbd_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2532,10 +2532,6 @@ int set_resource_options(struct drbd_resource *resource, struct res_opts *res_op

if (!zalloc_cpumask_var(&new_cpu_mask, GFP_KERNEL))
return -ENOMEM;
/*
retcode = ERR_NOMEM;
drbd_msg_put_info("unable to allocate cpumask");
*/

/* silently ignore cpu mask on UP kernel */
if (nr_cpu_ids > 1 && res_opts->cpu_mask[0] != 0) {
Expand Down Expand Up @@ -2731,7 +2727,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig

device = minor_to_device(minor);
if (device)
return ERR_MINOR_EXISTS;
return ERR_MINOR_OR_VOLUME_EXISTS;

/* GFP_KERNEL, we are outside of all write-out paths */
device = kzalloc(sizeof(struct drbd_device), GFP_KERNEL);
Expand Down Expand Up @@ -2793,20 +2789,16 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig

id = idr_alloc(&drbd_devices, device, minor, minor + 1, GFP_KERNEL);
if (id < 0) {
if (id == -ENOSPC) {
err = ERR_MINOR_EXISTS;
drbd_msg_put_info(adm_ctx->reply_skb, "requested minor exists already");
}
if (id == -ENOSPC)
err = ERR_MINOR_OR_VOLUME_EXISTS;
goto out_no_minor_idr;
}
kref_get(&device->kref);

id = idr_alloc(&resource->devices, device, vnr, vnr + 1, GFP_KERNEL);
if (id < 0) {
if (id == -ENOSPC) {
err = ERR_MINOR_EXISTS;
drbd_msg_put_info(adm_ctx->reply_skb, "requested minor exists already");
}
if (id == -ENOSPC)
err = ERR_MINOR_OR_VOLUME_EXISTS;
goto out_idr_remove_minor;
}
kref_get(&device->kref);
Expand All @@ -2825,18 +2817,15 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig

id = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL);
if (id < 0) {
if (id == -ENOSPC) {
if (id == -ENOSPC)
err = ERR_INVALID_REQUEST;
drbd_msg_put_info(adm_ctx->reply_skb, "requested volume exists already");
}
goto out_idr_remove_from_resource;
}
kref_get(&connection->kref);
}

if (init_submitter(device)) {
err = ERR_NOMEM;
drbd_msg_put_info(adm_ctx->reply_skb, "unable to create submit workqueue");
goto out_idr_remove_vol;
}

Expand Down
64 changes: 28 additions & 36 deletions drivers/block/drbd/drbd_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static void drbd_adm_send_reply(struct sk_buff *skb, struct genl_info *info)

/* Used on a fresh "drbd_adm_prepare"d reply_skb, this cannot fail: The only
* reason it could fail was no space in skb, and there are 4k available. */
int drbd_msg_put_info(struct sk_buff *skb, const char *info)
static int drbd_msg_put_info(struct sk_buff *skb, const char *info)
{
struct nlattr *nla;
int err = -EMSGSIZE;
Expand Down Expand Up @@ -588,7 +588,7 @@ drbd_set_role(struct drbd_device *const device, enum drbd_role new_role, int for
val.i = 0; val.role = new_role;

while (try++ < max_tries) {
rv = _drbd_request_state(device, mask, val, CS_WAIT_COMPLETE);
rv = _drbd_request_state_holding_state_mutex(device, mask, val, CS_WAIT_COMPLETE);

/* in case we first succeeded to outdate,
* but now suddenly could establish a connection */
Expand Down Expand Up @@ -2052,7 +2052,7 @@ check_net_options(struct drbd_connection *connection, struct net_conf *new_net_c
rv = _check_net_options(connection, rcu_dereference(connection->net_conf), new_net_conf);
rcu_read_unlock();

/* connection->volumes protected by genl_lock() here */
/* connection->peer_devices protected by genl_lock() here */
idr_for_each_entry(&connection->peer_devices, peer_device, i) {
struct drbd_device *device = peer_device->device;
if (!device->bitmap) {
Expand Down Expand Up @@ -3483,7 +3483,7 @@ int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info)
* that first_peer_device(device)->connection and device->vnr match the request. */
if (adm_ctx.device) {
if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
retcode = ERR_MINOR_EXISTS;
retcode = ERR_MINOR_OR_VOLUME_EXISTS;
/* else: still NO_ERROR */
goto out;
}
Expand Down Expand Up @@ -3530,6 +3530,27 @@ int drbd_adm_del_minor(struct sk_buff *skb, struct genl_info *info)
return 0;
}

static int adm_del_resource(struct drbd_resource *resource)
{
struct drbd_connection *connection;

for_each_connection(connection, resource) {
if (connection->cstate > C_STANDALONE)
return ERR_NET_CONFIGURED;
}
if (!idr_is_empty(&resource->devices))
return ERR_RES_IN_USE;

list_del_rcu(&resource->resources);
/* Make sure all threads have actually stopped: state handling only
* does drbd_thread_stop_nowait(). */
list_for_each_entry(connection, &resource->connections, connections)
drbd_thread_stop(&connection->worker);
synchronize_rcu();
drbd_free_resource(resource);
return NO_ERROR;
}

int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
{
struct drbd_config_context adm_ctx;
Expand Down Expand Up @@ -3575,14 +3596,6 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
}
}

/* If we reach this, all volumes (of this connection) are Secondary,
* Disconnected, Diskless, aka Unconfigured. Make sure all threads have
* actually stopped, state handling only does drbd_thread_stop_nowait(). */
for_each_connection(connection, resource)
drbd_thread_stop(&connection->worker);

/* Now, nothing can fail anymore */

/* delete volumes */
idr_for_each_entry(&resource->devices, device, i) {
retcode = adm_del_minor(device);
Expand All @@ -3593,10 +3606,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
}
}

list_del_rcu(&resource->resources);
synchronize_rcu();
drbd_free_resource(resource);
retcode = NO_ERROR;
retcode = adm_del_resource(resource);
out:
mutex_unlock(&resource->adm_mutex);
finish:
Expand All @@ -3608,35 +3618,17 @@ int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
{
struct drbd_config_context adm_ctx;
struct drbd_resource *resource;
struct drbd_connection *connection;
enum drbd_ret_code retcode;

retcode = drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE);
if (!adm_ctx.reply_skb)
return retcode;
if (retcode != NO_ERROR)
goto finish;

resource = adm_ctx.resource;
mutex_lock(&resource->adm_mutex);
for_each_connection(connection, resource) {
if (connection->cstate > C_STANDALONE) {
retcode = ERR_NET_CONFIGURED;
goto out;
}
}
if (!idr_is_empty(&resource->devices)) {
retcode = ERR_RES_IN_USE;
goto out;
}

list_del_rcu(&resource->resources);
for_each_connection(connection, resource)
drbd_thread_stop(&connection->worker);
synchronize_rcu();
drbd_free_resource(resource);
retcode = NO_ERROR;
out:
mutex_lock(&resource->adm_mutex);
retcode = adm_del_resource(resource);
mutex_unlock(&resource->adm_mutex);
finish:
drbd_adm_finish(&adm_ctx, info, retcode);
Expand Down
2 changes: 1 addition & 1 deletion drivers/block/drbd/drbd_receiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -2482,7 +2482,7 @@ bool drbd_rs_c_min_rate_throttle(struct drbd_device *device)
atomic_read(&device->rs_sect_ev);

if (atomic_read(&device->ap_actlog_cnt)
|| !device->rs_last_events || curr_events - device->rs_last_events > 64) {
|| curr_events - device->rs_last_events > 64) {
unsigned long rs_left;
int i;

Expand Down
25 changes: 6 additions & 19 deletions drivers/block/drbd/drbd_req.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,15 @@ static bool drbd_may_do_local_read(struct drbd_device *device, sector_t sector,
/* Update disk stats at start of I/O request */
static void _drbd_start_io_acct(struct drbd_device *device, struct drbd_request *req)
{
const int rw = bio_data_dir(req->master_bio);
int cpu;
cpu = part_stat_lock();
part_round_stats(cpu, &device->vdisk->part0);
part_stat_inc(cpu, &device->vdisk->part0, ios[rw]);
part_stat_add(cpu, &device->vdisk->part0, sectors[rw], req->i.size >> 9);
(void) cpu; /* The macro invocations above want the cpu argument, I do not like
the compiler warning about cpu only assigned but never used... */
part_inc_in_flight(&device->vdisk->part0, rw);
part_stat_unlock();
generic_start_io_acct(bio_data_dir(req->master_bio), req->i.size >> 9,
&device->vdisk->part0);
}

/* Update disk stats when completing request upwards */
static void _drbd_end_io_acct(struct drbd_device *device, struct drbd_request *req)
{
int rw = bio_data_dir(req->master_bio);
unsigned long duration = jiffies - req->start_jif;
int cpu;
cpu = part_stat_lock();
part_stat_add(cpu, &device->vdisk->part0, ticks[rw], duration);
part_round_stats(cpu, &device->vdisk->part0);
part_dec_in_flight(&device->vdisk->part0, rw);
part_stat_unlock();
generic_end_io_acct(bio_data_dir(req->master_bio),
&device->vdisk->part0, req->start_jif);
}

static struct drbd_request *drbd_req_new(struct drbd_device *device,
Expand Down Expand Up @@ -1545,6 +1531,7 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
struct request_queue * const b =
device->ldev->backing_bdev->bd_disk->queue;
if (b->merge_bvec_fn) {
bvm->bi_bdev = device->ldev->backing_bdev;
backing_limit = b->merge_bvec_fn(b, bvm, bvec);
limit = min(limit, backing_limit);
}
Expand Down Expand Up @@ -1628,7 +1615,7 @@ void request_timer_fn(unsigned long data)
time_after(now, req_peer->pre_send_jif + ent) &&
!time_in_range(now, connection->last_reconnect_jif, connection->last_reconnect_jif + ent)) {
drbd_warn(device, "Remote failed to finish a request within ko-count * timeout\n");
_drbd_set_state(_NS(device, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
_conn_request_state(connection, NS(conn, C_TIMEOUT), CS_VERBOSE | CS_HARD);
}
if (dt && oldest_submit_jif != now &&
time_after(now, oldest_submit_jif + dt) &&
Expand Down
Loading

0 comments on commit 9ea18f8

Please sign in to comment.