Merge branch 'for-4.6/drivers' of git://git.kernel.dk/linux-block
Pull block driver updates from Jens Axboe:
"This is the block driver pull request for this merge window. It sits
on top of for-4.6/core, that was just sent out.
This contains:
- A set of fixes for lightnvm. One from Alan, fixing an overflow,
and the rest from the usual suspects, Javier and Matias.
- A set of fixes for nbd from Markus and Dan, and a fixup from Arnd
for correct usage of the signed 64-bit divider.
- A set of bug fixes for the Micron mtip32xx, from Asai.
- A fix for the brd discard handling from Bart.
- Update the maintainers entry for cciss, since that hardware has
transferred ownership.
- Three bug fixes for bcache from Eric Wheeler.
- Set of fixes for xen-blk{back,front} from Jan and Konrad.
- Removal of the cpqarray driver. It has been disabled in Kconfig
since 2013, and we were initially scheduled to remove it in 3.15.
- Various updates and fixes for NVMe, with the most important being:
- Removal of the per-device NVMe thread, replacing that with a
watchdog timer instead. From Christoph.
- Exposing the namespace WWID through sysfs, from Keith.
- Set of cleanups from Ming Lin.
- Logging the controller device name instead of the underlying
PCI device name, from Sagi.
- And a bunch of fixes and optimizations from the usual suspects
in this area"
* 'for-4.6/drivers' of git://git.kernel.dk/linux-block: (49 commits)
NVMe: Expose ns wwid through single sysfs entry
drivers:block: cpqarray clean up
brd: Fix discard request processing
cpqarray: remove it from the kernel
cciss: update MAINTAINERS
NVMe: Remove unused sq_head read in completion path
bcache: fix cache_set_flush() NULL pointer dereference on OOM
bcache: cleaned up error handling around register_cache()
bcache: fix race of writeback thread starting before complete initialization
NVMe: Create discard zero quirk white list
nbd: use correct div_s64 helper
mtip32xx: remove unneeded variable in mtip_cmd_timeout()
lightnvm: generalize rrpc ppa calculations
lightnvm: remove struct nvm_dev->total_blocks
lightnvm: rename ->nr_pages to ->nr_sects
lightnvm: update closed list outside of intr context
xen/blback: Fit the important information of the thread in 17 characters
lightnvm: fold get bb tbl when using dual/quad plane mode
lightnvm: fix up nonsensical configure overrun checking
xen-blkback: advertise indirect segment support earlier
...
This commit is contained in:
@@ -110,16 +110,6 @@ source "drivers/block/mtip32xx/Kconfig"
|
||||
|
||||
source "drivers/block/zram/Kconfig"
|
||||
|
||||
config BLK_CPQ_DA
|
||||
tristate "Compaq SMART2 support"
|
||||
depends on PCI && VIRT_TO_BUS && 0
|
||||
help
|
||||
This is the driver for Compaq Smart Array controllers. Everyone
|
||||
using these boards should say Y here. See the file
|
||||
<file:Documentation/blockdev/cpqarray.txt> for the current list of
|
||||
boards supported by this driver, and for further information on the
|
||||
use of this driver.
|
||||
|
||||
config BLK_CPQ_CISS_DA
|
||||
tristate "Compaq Smart Array 5xxx support"
|
||||
depends on PCI
|
||||
|
||||
@@ -15,7 +15,6 @@ obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
|
||||
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
|
||||
obj-$(CONFIG_BLK_DEV_RAM) += brd.o
|
||||
obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
|
||||
obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
|
||||
obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
|
||||
obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
|
||||
obj-$(CONFIG_XILINX_SYSACE) += xsysace.o
|
||||
|
||||
@@ -341,7 +341,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
|
||||
|
||||
if (unlikely(bio->bi_rw & REQ_DISCARD)) {
|
||||
if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) ||
|
||||
bio->bi_iter.bi_size & PAGE_MASK)
|
||||
bio->bi_iter.bi_size & ~PAGE_MASK)
|
||||
goto io_error;
|
||||
discard_from_brd(brd, sector, bio->bi_iter.bi_size);
|
||||
goto out;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Disk Array driver for Compaq SMART2 Controllers
|
||||
* Copyright 1998 Compaq Computer Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
|
||||
*
|
||||
* If you want to make changes, improve or add functionality to this
|
||||
* driver, you'll probably need the Compaq Array Controller Interface
|
||||
* Specificiation (Document number ECG086/1198)
|
||||
*/
|
||||
#ifndef CPQARRAY_H
|
||||
#define CPQARRAY_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/timer.h>
|
||||
#endif
|
||||
|
||||
#include "ida_cmd.h"
|
||||
|
||||
#define IO_OK 0
|
||||
#define IO_ERROR 1
|
||||
#define NWD 16
|
||||
#define NWD_SHIFT 4
|
||||
|
||||
#define IDA_TIMER (5*HZ)
|
||||
#define IDA_TIMEOUT (10*HZ)
|
||||
|
||||
#define MISC_NONFATAL_WARN 0x01
|
||||
|
||||
typedef struct {
|
||||
unsigned blk_size;
|
||||
unsigned nr_blks;
|
||||
unsigned cylinders;
|
||||
unsigned heads;
|
||||
unsigned sectors;
|
||||
int usage_count;
|
||||
} drv_info_t;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct ctlr_info;
|
||||
typedef struct ctlr_info ctlr_info_t;
|
||||
|
||||
struct access_method {
|
||||
void (*submit_command)(ctlr_info_t *h, cmdlist_t *c);
|
||||
void (*set_intr_mask)(ctlr_info_t *h, unsigned long val);
|
||||
unsigned long (*fifo_full)(ctlr_info_t *h);
|
||||
unsigned long (*intr_pending)(ctlr_info_t *h);
|
||||
unsigned long (*command_completed)(ctlr_info_t *h);
|
||||
};
|
||||
|
||||
struct board_type {
|
||||
__u32 board_id;
|
||||
char *product_name;
|
||||
struct access_method *access;
|
||||
};
|
||||
|
||||
struct ctlr_info {
|
||||
int ctlr;
|
||||
char devname[8];
|
||||
__u32 log_drv_map;
|
||||
__u32 drv_assign_map;
|
||||
__u32 drv_spare_map;
|
||||
__u32 mp_failed_drv_map;
|
||||
|
||||
char firm_rev[4];
|
||||
int ctlr_sig;
|
||||
|
||||
int log_drives;
|
||||
int phys_drives;
|
||||
|
||||
struct pci_dev *pci_dev; /* NULL if EISA */
|
||||
__u32 board_id;
|
||||
char *product_name;
|
||||
|
||||
void __iomem *vaddr;
|
||||
unsigned long paddr;
|
||||
unsigned long io_mem_addr;
|
||||
unsigned long io_mem_length;
|
||||
int intr;
|
||||
int usage_count;
|
||||
drv_info_t drv[NWD];
|
||||
struct proc_dir_entry *proc;
|
||||
|
||||
struct access_method access;
|
||||
|
||||
cmdlist_t *reqQ;
|
||||
cmdlist_t *cmpQ;
|
||||
cmdlist_t *cmd_pool;
|
||||
dma_addr_t cmd_pool_dhandle;
|
||||
unsigned long *cmd_pool_bits;
|
||||
struct request_queue *queue;
|
||||
spinlock_t lock;
|
||||
|
||||
unsigned int Qdepth;
|
||||
unsigned int maxQsinceinit;
|
||||
|
||||
unsigned int nr_requests;
|
||||
unsigned int nr_allocs;
|
||||
unsigned int nr_frees;
|
||||
struct timer_list timer;
|
||||
unsigned int misc_tflags;
|
||||
};
|
||||
|
||||
#define IDA_LOCK(i) (&hba[i]->lock)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CPQARRAY_H */
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* Disk Array driver for Compaq SMART2 Controllers
|
||||
* Copyright 1998 Compaq Computer Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
|
||||
*
|
||||
*/
|
||||
#ifndef ARRAYCMD_H
|
||||
#define ARRAYCMD_H
|
||||
|
||||
#include <asm/types.h>
|
||||
#if 0
|
||||
#include <linux/blkdev.h>
|
||||
#endif
|
||||
|
||||
/* for the Smart Array 42XX cards */
|
||||
#define S42XX_REQUEST_PORT_OFFSET 0x40
|
||||
#define S42XX_REPLY_INTR_MASK_OFFSET 0x34
|
||||
#define S42XX_REPLY_PORT_OFFSET 0x44
|
||||
#define S42XX_INTR_STATUS 0x30
|
||||
|
||||
#define S42XX_INTR_OFF 0x08
|
||||
#define S42XX_INTR_PENDING 0x08
|
||||
|
||||
#define COMMAND_FIFO 0x04
|
||||
#define COMMAND_COMPLETE_FIFO 0x08
|
||||
#define INTR_MASK 0x0C
|
||||
#define INTR_STATUS 0x10
|
||||
#define INTR_PENDING 0x14
|
||||
|
||||
#define FIFO_NOT_EMPTY 0x01
|
||||
#define FIFO_NOT_FULL 0x02
|
||||
|
||||
#define BIG_PROBLEM 0x40
|
||||
#define LOG_NOT_CONF 2
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
__u32 size;
|
||||
__u32 addr;
|
||||
} sg_t;
|
||||
|
||||
#define RCODE_NONFATAL 0x02
|
||||
#define RCODE_FATAL 0x04
|
||||
#define RCODE_INVREQ 0x10
|
||||
typedef struct {
|
||||
__u16 next;
|
||||
__u8 cmd;
|
||||
__u8 rcode;
|
||||
__u32 blk;
|
||||
__u16 blk_cnt;
|
||||
__u8 sg_cnt;
|
||||
__u8 reserved;
|
||||
} rhdr_t;
|
||||
|
||||
#define SG_MAX 32
|
||||
typedef struct {
|
||||
rhdr_t hdr;
|
||||
sg_t sg[SG_MAX];
|
||||
__u32 bp;
|
||||
} rblk_t;
|
||||
|
||||
typedef struct {
|
||||
__u8 unit;
|
||||
__u8 prio;
|
||||
__u16 size;
|
||||
} chdr_t;
|
||||
|
||||
#define CMD_RWREQ 0x00
|
||||
#define CMD_IOCTL_PEND 0x01
|
||||
#define CMD_IOCTL_DONE 0x02
|
||||
|
||||
typedef struct cmdlist {
|
||||
chdr_t hdr;
|
||||
rblk_t req;
|
||||
__u32 size;
|
||||
int retry_cnt;
|
||||
__u32 busaddr;
|
||||
int ctlr;
|
||||
struct cmdlist *prev;
|
||||
struct cmdlist *next;
|
||||
struct request *rq;
|
||||
int type;
|
||||
} cmdlist_t;
|
||||
|
||||
#define ID_CTLR 0x11
|
||||
typedef struct {
|
||||
__u8 nr_drvs;
|
||||
__u32 cfg_sig;
|
||||
__u8 firm_rev[4];
|
||||
__u8 rom_rev[4];
|
||||
__u8 hw_rev;
|
||||
__u32 bb_rev;
|
||||
__u32 drv_present_map;
|
||||
__u32 ext_drv_map;
|
||||
__u32 board_id;
|
||||
__u8 cfg_error;
|
||||
__u32 non_disk_bits;
|
||||
__u8 bad_ram_addr;
|
||||
__u8 cpu_rev;
|
||||
__u8 pdpi_rev;
|
||||
__u8 epic_rev;
|
||||
__u8 wcxc_rev;
|
||||
__u8 marketing_rev;
|
||||
__u8 ctlr_flags;
|
||||
__u8 host_flags;
|
||||
__u8 expand_dis;
|
||||
__u8 scsi_chips;
|
||||
__u32 max_req_blocks;
|
||||
__u32 ctlr_clock;
|
||||
__u8 drvs_per_bus;
|
||||
__u16 big_drv_present_map[8];
|
||||
__u16 big_ext_drv_map[8];
|
||||
__u16 big_non_disk_map[8];
|
||||
__u16 task_flags;
|
||||
__u8 icl_bus;
|
||||
__u8 red_modes;
|
||||
__u8 cur_red_mode;
|
||||
__u8 red_ctlr_stat;
|
||||
__u8 red_fail_reason;
|
||||
__u8 reserved[403];
|
||||
} id_ctlr_t;
|
||||
|
||||
typedef struct {
|
||||
__u16 cyl;
|
||||
__u8 heads;
|
||||
__u8 xsig;
|
||||
__u8 psectors;
|
||||
__u16 wpre;
|
||||
__u8 maxecc;
|
||||
__u8 drv_ctrl;
|
||||
__u16 pcyls;
|
||||
__u8 pheads;
|
||||
__u16 landz;
|
||||
__u8 sect_per_track;
|
||||
__u8 cksum;
|
||||
} drv_param_t;
|
||||
|
||||
#define ID_LOG_DRV 0x10
|
||||
typedef struct {
|
||||
__u16 blk_size;
|
||||
__u32 nr_blks;
|
||||
drv_param_t drv;
|
||||
__u8 fault_tol;
|
||||
__u8 reserved;
|
||||
__u8 bios_disable;
|
||||
} id_log_drv_t;
|
||||
|
||||
#define ID_LOG_DRV_EXT 0x18
|
||||
typedef struct {
|
||||
__u32 log_drv_id;
|
||||
__u8 log_drv_label[64];
|
||||
__u8 reserved[418];
|
||||
} id_log_drv_ext_t;
|
||||
|
||||
#define SENSE_LOG_DRV_STAT 0x12
|
||||
typedef struct {
|
||||
__u8 status;
|
||||
__u32 fail_map;
|
||||
__u16 read_err[32];
|
||||
__u16 write_err[32];
|
||||
__u8 drv_err_data[256];
|
||||
__u8 drq_timeout[32];
|
||||
__u32 blks_to_recover;
|
||||
__u8 drv_recovering;
|
||||
__u16 remap_cnt[32];
|
||||
__u32 replace_drv_map;
|
||||
__u32 act_spare_map;
|
||||
__u8 spare_stat;
|
||||
__u8 spare_repl_map[32];
|
||||
__u32 repl_ok_map;
|
||||
__u8 media_exch;
|
||||
__u8 cache_fail;
|
||||
__u8 expn_fail;
|
||||
__u8 unit_flags;
|
||||
__u16 big_fail_map[8];
|
||||
__u16 big_remap_map[128];
|
||||
__u16 big_repl_map[8];
|
||||
__u16 big_act_spare_map[8];
|
||||
__u8 big_spar_repl_map[128];
|
||||
__u16 big_repl_ok_map[8];
|
||||
__u8 big_drv_rebuild;
|
||||
__u8 reserved[36];
|
||||
} sense_log_drv_stat_t;
|
||||
|
||||
#define START_RECOVER 0x13
|
||||
|
||||
#define ID_PHYS_DRV 0x15
|
||||
typedef struct {
|
||||
__u8 scsi_bus;
|
||||
__u8 scsi_id;
|
||||
__u16 blk_size;
|
||||
__u32 nr_blks;
|
||||
__u32 rsvd_blks;
|
||||
__u8 drv_model[40];
|
||||
__u8 drv_sn[40];
|
||||
__u8 drv_fw[8];
|
||||
__u8 scsi_iq_bits;
|
||||
__u8 compaq_drv_stmp;
|
||||
__u8 last_fail;
|
||||
__u8 phys_drv_flags;
|
||||
__u8 phys_drv_flags1;
|
||||
__u8 scsi_lun;
|
||||
__u8 phys_drv_flags2;
|
||||
__u8 reserved;
|
||||
__u32 spi_speed_rules;
|
||||
__u8 phys_connector[2];
|
||||
__u8 phys_box_on_bus;
|
||||
__u8 phys_bay_in_box;
|
||||
} id_phys_drv_t;
|
||||
|
||||
#define BLINK_DRV_LEDS 0x16
|
||||
typedef struct {
|
||||
__u32 blink_duration;
|
||||
__u32 reserved;
|
||||
__u8 blink[256];
|
||||
__u8 reserved1[248];
|
||||
} blink_drv_leds_t;
|
||||
|
||||
#define SENSE_BLINK_LEDS 0x17
|
||||
typedef struct {
|
||||
__u32 blink_duration;
|
||||
__u32 btime_elap;
|
||||
__u8 blink[256];
|
||||
__u8 reserved1[248];
|
||||
} sense_blink_leds_t;
|
||||
|
||||
#define IDA_READ 0x20
|
||||
#define IDA_WRITE 0x30
|
||||
#define IDA_WRITE_MEDIA 0x31
|
||||
#define RESET_TO_DIAG 0x40
|
||||
#define DIAG_PASS_THRU 0x41
|
||||
|
||||
#define SENSE_CONFIG 0x50
|
||||
#define SET_CONFIG 0x51
|
||||
typedef struct {
|
||||
__u32 cfg_sig;
|
||||
__u16 compat_port;
|
||||
__u8 data_dist_mode;
|
||||
__u8 surf_an_ctrl;
|
||||
__u16 ctlr_phys_drv;
|
||||
__u16 log_unit_phys_drv;
|
||||
__u16 fault_tol_mode;
|
||||
__u8 phys_drv_param[16];
|
||||
drv_param_t drv;
|
||||
__u32 drv_asgn_map;
|
||||
__u16 dist_factor;
|
||||
__u32 spare_asgn_map;
|
||||
__u8 reserved[6];
|
||||
__u16 os;
|
||||
__u8 ctlr_order;
|
||||
__u8 extra_info;
|
||||
__u32 data_offs;
|
||||
__u8 parity_backedout_write_drvs;
|
||||
__u8 parity_dist_mode;
|
||||
__u8 parity_shift_fact;
|
||||
__u8 bios_disable_flag;
|
||||
__u32 blks_on_vol;
|
||||
__u32 blks_per_drv;
|
||||
__u8 scratch[16];
|
||||
__u16 big_drv_map[8];
|
||||
__u16 big_spare_map[8];
|
||||
__u8 ss_source_vol;
|
||||
__u8 mix_drv_cap_range;
|
||||
struct {
|
||||
__u16 big_drv_map[8];
|
||||
__u32 blks_per_drv;
|
||||
__u16 fault_tol_mode;
|
||||
__u16 dist_factor;
|
||||
} MDC_range[4];
|
||||
__u8 reserved1[248];
|
||||
} config_t;
|
||||
|
||||
#define BYPASS_VOL_STATE 0x52
|
||||
#define SS_CREATE_VOL 0x53
|
||||
#define CHANGE_CONFIG 0x54
|
||||
#define SENSE_ORIG_CONF 0x55
|
||||
#define REORDER_LOG_DRV 0x56
|
||||
typedef struct {
|
||||
__u8 old_units[32];
|
||||
} reorder_log_drv_t;
|
||||
|
||||
#define LABEL_LOG_DRV 0x57
|
||||
typedef struct {
|
||||
__u8 log_drv_label[64];
|
||||
} label_log_drv_t;
|
||||
|
||||
#define SS_TO_VOL 0x58
|
||||
|
||||
#define SET_SURF_DELAY 0x60
|
||||
typedef struct {
|
||||
__u16 delay;
|
||||
__u8 reserved[510];
|
||||
} surf_delay_t;
|
||||
|
||||
#define SET_OVERHEAT_DELAY 0x61
|
||||
typedef struct {
|
||||
__u16 delay;
|
||||
} overhead_delay_t;
|
||||
|
||||
#define SET_MP_DELAY
|
||||
typedef struct {
|
||||
__u16 delay;
|
||||
__u8 reserved[510];
|
||||
} mp_delay_t;
|
||||
|
||||
#define PASSTHRU_A 0x91
|
||||
typedef struct {
|
||||
__u8 target;
|
||||
__u8 bus;
|
||||
__u8 lun;
|
||||
__u32 timeout;
|
||||
__u32 flags;
|
||||
__u8 status;
|
||||
__u8 error;
|
||||
__u8 cdb_len;
|
||||
__u8 sense_error;
|
||||
__u8 sense_key;
|
||||
__u32 sense_info;
|
||||
__u8 sense_code;
|
||||
__u8 sense_qual;
|
||||
__u32 residual;
|
||||
__u8 reserved[4];
|
||||
__u8 cdb[12];
|
||||
} scsi_param_t;
|
||||
|
||||
#define RESUME_BACKGROUND_ACTIVITY 0x99
|
||||
#define SENSE_CONTROLLER_PERFORMANCE 0xa8
|
||||
#define FLUSH_CACHE 0xc2
|
||||
#define COLLECT_BUFFER 0xd2
|
||||
#define READ_FLASH_ROM 0xf6
|
||||
#define WRITE_FLASH_ROM 0xf7
|
||||
#pragma pack()
|
||||
|
||||
#endif /* ARRAYCMD_H */
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Disk Array driver for Compaq SMART2 Controllers
|
||||
* Copyright 1998 Compaq Computer Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
|
||||
*
|
||||
*/
|
||||
#ifndef IDA_IOCTL_H
|
||||
#define IDA_IOCTL_H
|
||||
|
||||
#include "ida_cmd.h"
|
||||
#include "cpqarray.h"
|
||||
|
||||
#define IDAGETDRVINFO 0x27272828
|
||||
#define IDAPASSTHRU 0x28282929
|
||||
#define IDAGETCTLRSIG 0x29293030
|
||||
#define IDAREVALIDATEVOLS 0x30303131
|
||||
#define IDADRIVERVERSION 0x31313232
|
||||
#define IDAGETPCIINFO 0x32323333
|
||||
|
||||
typedef struct _ida_pci_info_struct
|
||||
{
|
||||
unsigned char bus;
|
||||
unsigned char dev_fn;
|
||||
__u32 board_id;
|
||||
} ida_pci_info_struct;
|
||||
/*
|
||||
* Normally, the ioctl determines the logical unit for this command by
|
||||
* the major,minor number of the fd passed to ioctl. If you need to send
|
||||
* a command to a different/nonexistant unit (such as during config), you
|
||||
* can override the normal behavior by setting the unit valid bit. (Normally,
|
||||
* it should be zero) The controller the command is sent to is still
|
||||
* determined by the major number of the open device.
|
||||
*/
|
||||
|
||||
#define UNITVALID 0x80
|
||||
typedef struct {
|
||||
__u8 cmd;
|
||||
__u8 rcode;
|
||||
__u8 unit;
|
||||
__u32 blk;
|
||||
__u16 blk_cnt;
|
||||
|
||||
/* currently, sg_cnt is assumed to be 1: only the 0th element of sg is used */
|
||||
struct {
|
||||
void __user *addr;
|
||||
size_t size;
|
||||
} sg[SG_MAX];
|
||||
int sg_cnt;
|
||||
|
||||
union ctlr_cmds {
|
||||
drv_info_t drv;
|
||||
unsigned char buf[1024];
|
||||
|
||||
id_ctlr_t id_ctlr;
|
||||
drv_param_t drv_param;
|
||||
id_log_drv_t id_log_drv;
|
||||
id_log_drv_ext_t id_log_drv_ext;
|
||||
sense_log_drv_stat_t sense_log_drv_stat;
|
||||
id_phys_drv_t id_phys_drv;
|
||||
blink_drv_leds_t blink_drv_leds;
|
||||
sense_blink_leds_t sense_blink_leds;
|
||||
config_t config;
|
||||
reorder_log_drv_t reorder_log_drv;
|
||||
label_log_drv_t label_log_drv;
|
||||
surf_delay_t surf_delay;
|
||||
overhead_delay_t overhead_delay;
|
||||
mp_delay_t mp_delay;
|
||||
scsi_param_t scsi_param;
|
||||
} c;
|
||||
} ida_ioctl_t;
|
||||
|
||||
#endif /* IDA_IOCTL_H */
|
||||
@@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd)
|
||||
{
|
||||
struct request *rq;
|
||||
|
||||
if (mtip_check_surprise_removal(dd->pdev))
|
||||
return NULL;
|
||||
|
||||
rq = blk_mq_alloc_request(dd->queue, 0, BLK_MQ_REQ_RESERVED);
|
||||
if (IS_ERR(rq))
|
||||
return NULL;
|
||||
|
||||
return blk_mq_rq_to_pdu(rq);
|
||||
}
|
||||
|
||||
@@ -233,15 +239,9 @@ static void mtip_async_complete(struct mtip_port *port,
|
||||
"Command tag %d failed due to TFE\n", tag);
|
||||
}
|
||||
|
||||
/* Unmap the DMA scatter list entries */
|
||||
dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction);
|
||||
|
||||
rq = mtip_rq_from_tag(dd, tag);
|
||||
|
||||
if (unlikely(cmd->unaligned))
|
||||
up(&port->cmd_slot_unal);
|
||||
|
||||
blk_mq_end_request(rq, status ? -EIO : 0);
|
||||
blk_mq_complete_request(rq, status);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -581,6 +581,8 @@ static void mtip_completion(struct mtip_port *port,
|
||||
dev_warn(&port->dd->pdev->dev,
|
||||
"Internal command %d completed with TFE\n", tag);
|
||||
|
||||
command->comp_func = NULL;
|
||||
command->comp_data = NULL;
|
||||
complete(waiting);
|
||||
}
|
||||
|
||||
@@ -618,8 +620,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
||||
|
||||
port = dd->port;
|
||||
|
||||
set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
||||
|
||||
if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
|
||||
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
||||
dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n");
|
||||
@@ -628,7 +628,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
||||
cmd->comp_func(port, MTIP_TAG_INTERNAL,
|
||||
cmd, PORT_IRQ_TF_ERR);
|
||||
}
|
||||
goto handle_tfe_exit;
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear the tag accumulator */
|
||||
@@ -701,7 +701,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
||||
fail_reason = "thermal shutdown";
|
||||
}
|
||||
if (buf[288] == 0xBF) {
|
||||
set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag);
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
|
||||
dev_info(&dd->pdev->dev,
|
||||
"Drive indicates rebuild has failed. Secure erase required.\n");
|
||||
fail_all_ncq_cmds = 1;
|
||||
@@ -771,11 +771,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
||||
}
|
||||
}
|
||||
print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
|
||||
|
||||
handle_tfe_exit:
|
||||
/* clear eh_active */
|
||||
clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
||||
wake_up_interruptible(&port->svc_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1007,6 +1002,7 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
||||
(fis->features == 0x27 || fis->features == 0x72 ||
|
||||
fis->features == 0x62 || fis->features == 0x26))) {
|
||||
clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
|
||||
clear_bit(MTIP_DDF_REBUILD_FAILED_BIT, &port->dd->dd_flag);
|
||||
/* Com reset after secure erase or lowlevel format */
|
||||
mtip_restart_port(port);
|
||||
clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
|
||||
@@ -1021,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
||||
*
|
||||
* @port Pointer to port data structure
|
||||
* @timeout Max duration to wait (ms)
|
||||
* @atomic gfp_t flag to indicate blockable context or not
|
||||
*
|
||||
* return value
|
||||
* 0 Success
|
||||
* -EBUSY Commands still active
|
||||
*/
|
||||
static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
|
||||
static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout,
|
||||
gfp_t atomic)
|
||||
{
|
||||
unsigned long to;
|
||||
unsigned int n;
|
||||
@@ -1037,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
|
||||
to = jiffies + msecs_to_jiffies(timeout);
|
||||
do {
|
||||
if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) &&
|
||||
test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
|
||||
test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) &&
|
||||
atomic == GFP_KERNEL) {
|
||||
msleep(20);
|
||||
continue; /* svc thd is actively issuing commands */
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
if (atomic == GFP_KERNEL)
|
||||
msleep(100);
|
||||
else {
|
||||
cpu_relax();
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (mtip_check_surprise_removal(port->dd->pdev))
|
||||
goto err_fault;
|
||||
if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
|
||||
goto err_fault;
|
||||
|
||||
/*
|
||||
* Ignore s_active bit 0 of array element 0.
|
||||
@@ -1099,6 +1102,7 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
||||
struct mtip_cmd *int_cmd;
|
||||
struct driver_data *dd = port->dd;
|
||||
int rv = 0;
|
||||
unsigned long start;
|
||||
|
||||
/* Make sure the buffer is 8 byte aligned. This is asic specific. */
|
||||
if (buffer & 0x00000007) {
|
||||
@@ -1107,6 +1111,10 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
||||
}
|
||||
|
||||
int_cmd = mtip_get_int_command(dd);
|
||||
if (!int_cmd) {
|
||||
dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
|
||||
|
||||
@@ -1119,7 +1127,7 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
||||
if (fis->command != ATA_CMD_STANDBYNOW1) {
|
||||
/* wait for io to complete if non atomic */
|
||||
if (mtip_quiesce_io(port,
|
||||
MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) {
|
||||
MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) {
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Failed to quiesce IO\n");
|
||||
mtip_put_int_command(dd, int_cmd);
|
||||
@@ -1162,6 +1170,8 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
||||
/* Populate the command header */
|
||||
int_cmd->command_header->byte_count = 0;
|
||||
|
||||
start = jiffies;
|
||||
|
||||
/* Issue the command to the hardware */
|
||||
mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
|
||||
|
||||
@@ -1170,10 +1180,12 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
||||
if ((rv = wait_for_completion_interruptible_timeout(
|
||||
&wait,
|
||||
msecs_to_jiffies(timeout))) <= 0) {
|
||||
|
||||
if (rv == -ERESTARTSYS) { /* interrupted */
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Internal command [%02X] was interrupted after %lu ms\n",
|
||||
fis->command, timeout);
|
||||
"Internal command [%02X] was interrupted after %u ms\n",
|
||||
fis->command,
|
||||
jiffies_to_msecs(jiffies - start));
|
||||
rv = -EINTR;
|
||||
goto exec_ic_exit;
|
||||
} else if (rv == 0) /* timeout */
|
||||
@@ -2890,6 +2902,42 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static void mtip_softirq_done_fn(struct request *rq)
|
||||
{
|
||||
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
struct driver_data *dd = rq->q->queuedata;
|
||||
|
||||
/* Unmap the DMA scatter list entries */
|
||||
dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents,
|
||||
cmd->direction);
|
||||
|
||||
if (unlikely(cmd->unaligned))
|
||||
up(&dd->port->cmd_slot_unal);
|
||||
|
||||
blk_mq_end_request(rq, rq->errors);
|
||||
}
|
||||
|
||||
static void mtip_abort_cmd(struct request *req, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = data;
|
||||
|
||||
dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag);
|
||||
|
||||
clear_bit(req->tag, dd->port->cmds_to_issue);
|
||||
req->errors = -EIO;
|
||||
mtip_softirq_done_fn(req);
|
||||
}
|
||||
|
||||
static void mtip_queue_cmd(struct request *req, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = data;
|
||||
|
||||
set_bit(req->tag, dd->port->cmds_to_issue);
|
||||
blk_abort_request(req);
|
||||
}
|
||||
|
||||
/*
|
||||
* service thread to issue queued commands
|
||||
*
|
||||
@@ -2902,7 +2950,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
|
||||
static int mtip_service_thread(void *data)
|
||||
{
|
||||
struct driver_data *dd = (struct driver_data *)data;
|
||||
unsigned long slot, slot_start, slot_wrap;
|
||||
unsigned long slot, slot_start, slot_wrap, to;
|
||||
unsigned int num_cmd_slots = dd->slot_groups * 32;
|
||||
struct mtip_port *port = dd->port;
|
||||
|
||||
@@ -2917,9 +2965,7 @@ static int mtip_service_thread(void *data)
|
||||
* is in progress nor error handling is active
|
||||
*/
|
||||
wait_event_interruptible(port->svc_wait, (port->flags) &&
|
||||
!(port->flags & MTIP_PF_PAUSE_IO));
|
||||
|
||||
set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
|
||||
(port->flags & MTIP_PF_SVC_THD_WORK));
|
||||
|
||||
if (kthread_should_stop() ||
|
||||
test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
|
||||
@@ -2929,6 +2975,8 @@ static int mtip_service_thread(void *data)
|
||||
&dd->dd_flag)))
|
||||
goto st_out;
|
||||
|
||||
set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
|
||||
|
||||
restart_eh:
|
||||
/* Demux bits: start with error handling */
|
||||
if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) {
|
||||
@@ -2939,6 +2987,32 @@ restart_eh:
|
||||
if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags))
|
||||
goto restart_eh;
|
||||
|
||||
if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) {
|
||||
to = jiffies + msecs_to_jiffies(5000);
|
||||
|
||||
do {
|
||||
mdelay(100);
|
||||
} while (atomic_read(&dd->irq_workers_active) != 0 &&
|
||||
time_before(jiffies, to));
|
||||
|
||||
if (atomic_read(&dd->irq_workers_active) != 0)
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Completion workers still active!");
|
||||
|
||||
spin_lock(dd->queue->queue_lock);
|
||||
blk_mq_all_tag_busy_iter(*dd->tags.tags,
|
||||
mtip_queue_cmd, dd);
|
||||
spin_unlock(dd->queue->queue_lock);
|
||||
|
||||
set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags);
|
||||
|
||||
if (mtip_device_reset(dd))
|
||||
blk_mq_all_tag_busy_iter(*dd->tags.tags,
|
||||
mtip_abort_cmd, dd);
|
||||
|
||||
clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags);
|
||||
}
|
||||
|
||||
if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
|
||||
slot = 1;
|
||||
/* used to restrict the loop to one iteration */
|
||||
@@ -2971,10 +3045,8 @@ restart_eh:
|
||||
}
|
||||
|
||||
if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) {
|
||||
if (mtip_ftl_rebuild_poll(dd) < 0)
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT,
|
||||
&dd->dd_flag);
|
||||
clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
|
||||
if (mtip_ftl_rebuild_poll(dd) == 0)
|
||||
clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3089,7 +3161,7 @@ static int mtip_hw_get_identify(struct driver_data *dd)
|
||||
if (buf[288] == 0xBF) {
|
||||
dev_info(&dd->pdev->dev,
|
||||
"Drive indicates rebuild has failed.\n");
|
||||
/* TODO */
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3263,20 +3335,25 @@ out1:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_standby_drive(struct driver_data *dd)
|
||||
static int mtip_standby_drive(struct driver_data *dd)
|
||||
{
|
||||
if (dd->sr)
|
||||
return;
|
||||
int rv = 0;
|
||||
|
||||
if (dd->sr || !dd->port)
|
||||
return -ENODEV;
|
||||
/*
|
||||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags) &&
|
||||
!test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))
|
||||
if (mtip_standby_immediate(dd->port))
|
||||
!test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag) &&
|
||||
!test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) {
|
||||
rv = mtip_standby_immediate(dd->port);
|
||||
if (rv)
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"STANDBY IMMEDIATE failed\n");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3289,10 +3366,6 @@ static void mtip_standby_drive(struct driver_data *dd)
|
||||
*/
|
||||
static int mtip_hw_exit(struct driver_data *dd)
|
||||
{
|
||||
/*
|
||||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!dd->sr) {
|
||||
/* de-initialize the port. */
|
||||
mtip_deinit_port(dd->port);
|
||||
@@ -3334,8 +3407,7 @@ static int mtip_hw_shutdown(struct driver_data *dd)
|
||||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!dd->sr && dd->port)
|
||||
mtip_standby_immediate(dd->port);
|
||||
mtip_standby_drive(dd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3358,7 +3430,7 @@ static int mtip_hw_suspend(struct driver_data *dd)
|
||||
* Send standby immediate (E0h) to the drive
|
||||
* so that it saves its state.
|
||||
*/
|
||||
if (mtip_standby_immediate(dd->port) != 0) {
|
||||
if (mtip_standby_drive(dd) != 0) {
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Failed standby-immediate command\n");
|
||||
return -EFAULT;
|
||||
@@ -3596,6 +3668,28 @@ static int mtip_block_getgeo(struct block_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtip_block_open(struct block_device *dev, fmode_t mode)
|
||||
{
|
||||
struct driver_data *dd;
|
||||
|
||||
if (dev && dev->bd_disk) {
|
||||
dd = (struct driver_data *) dev->bd_disk->private_data;
|
||||
|
||||
if (dd) {
|
||||
if (test_bit(MTIP_DDF_REMOVAL_BIT,
|
||||
&dd->dd_flag)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void mtip_block_release(struct gendisk *disk, fmode_t mode)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Block device operation function.
|
||||
*
|
||||
@@ -3603,6 +3697,8 @@ static int mtip_block_getgeo(struct block_device *dev,
|
||||
* layer.
|
||||
*/
|
||||
static const struct block_device_operations mtip_block_ops = {
|
||||
.open = mtip_block_open,
|
||||
.release = mtip_block_release,
|
||||
.ioctl = mtip_block_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = mtip_block_compat_ioctl,
|
||||
@@ -3664,10 +3760,9 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq)
|
||||
rq_data_dir(rq))) {
|
||||
return -ENODATA;
|
||||
}
|
||||
if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)))
|
||||
if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag) ||
|
||||
test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)))
|
||||
return -ENODATA;
|
||||
if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (rq->cmd_flags & REQ_DISCARD) {
|
||||
@@ -3779,11 +3874,32 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = req->q->queuedata;
|
||||
|
||||
if (reserved)
|
||||
goto exit_handler;
|
||||
|
||||
if (test_bit(req->tag, dd->port->cmds_to_issue))
|
||||
goto exit_handler;
|
||||
|
||||
if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags))
|
||||
goto exit_handler;
|
||||
|
||||
wake_up_interruptible(&dd->port->svc_wait);
|
||||
exit_handler:
|
||||
return BLK_EH_RESET_TIMER;
|
||||
}
|
||||
|
||||
static struct blk_mq_ops mtip_mq_ops = {
|
||||
.queue_rq = mtip_queue_rq,
|
||||
.map_queue = blk_mq_map_queue,
|
||||
.init_request = mtip_init_cmd,
|
||||
.exit_request = mtip_free_cmd,
|
||||
.complete = mtip_softirq_done_fn,
|
||||
.timeout = mtip_cmd_timeout,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3850,7 +3966,6 @@ static int mtip_block_initialize(struct driver_data *dd)
|
||||
|
||||
mtip_hw_debugfs_init(dd);
|
||||
|
||||
skip_create_disk:
|
||||
memset(&dd->tags, 0, sizeof(dd->tags));
|
||||
dd->tags.ops = &mtip_mq_ops;
|
||||
dd->tags.nr_hw_queues = 1;
|
||||
@@ -3860,12 +3975,13 @@ skip_create_disk:
|
||||
dd->tags.numa_node = dd->numa_node;
|
||||
dd->tags.flags = BLK_MQ_F_SHOULD_MERGE;
|
||||
dd->tags.driver_data = dd;
|
||||
dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS;
|
||||
|
||||
rv = blk_mq_alloc_tag_set(&dd->tags);
|
||||
if (rv) {
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Unable to allocate request queue\n");
|
||||
goto block_queue_alloc_init_error;
|
||||
goto block_queue_alloc_tag_error;
|
||||
}
|
||||
|
||||
/* Allocate the request queue. */
|
||||
@@ -3880,6 +3996,7 @@ skip_create_disk:
|
||||
dd->disk->queue = dd->queue;
|
||||
dd->queue->queuedata = dd;
|
||||
|
||||
skip_create_disk:
|
||||
/* Initialize the protocol layer. */
|
||||
wait_for_rebuild = mtip_hw_get_identify(dd);
|
||||
if (wait_for_rebuild < 0) {
|
||||
@@ -3976,8 +4093,9 @@ kthread_run_error:
|
||||
read_capacity_error:
|
||||
init_hw_cmds_error:
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
block_queue_alloc_init_error:
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
block_queue_alloc_tag_error:
|
||||
mtip_hw_debugfs_exit(dd);
|
||||
disk_index_error:
|
||||
spin_lock(&rssd_index_lock);
|
||||
@@ -3994,6 +4112,22 @@ protocol_init_error:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv)
|
||||
{
|
||||
struct driver_data *dd = (struct driver_data *)data;
|
||||
struct mtip_cmd *cmd;
|
||||
|
||||
if (likely(!reserv))
|
||||
blk_mq_complete_request(rq, -ENODEV);
|
||||
else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) {
|
||||
|
||||
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
||||
if (cmd->comp_func)
|
||||
cmd->comp_func(dd->port, MTIP_TAG_INTERNAL,
|
||||
cmd, -ENODEV);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Block layer deinitialization function.
|
||||
*
|
||||
@@ -4025,12 +4159,23 @@ static int mtip_block_remove(struct driver_data *dd)
|
||||
}
|
||||
}
|
||||
|
||||
if (!dd->sr)
|
||||
mtip_standby_drive(dd);
|
||||
if (!dd->sr) {
|
||||
/*
|
||||
* Explicitly wait here for IOs to quiesce,
|
||||
* as mtip_standby_drive usually won't wait for IOs.
|
||||
*/
|
||||
if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS,
|
||||
GFP_KERNEL))
|
||||
mtip_standby_drive(dd);
|
||||
}
|
||||
else
|
||||
dev_info(&dd->pdev->dev, "device %s surprise removal\n",
|
||||
dd->disk->disk_name);
|
||||
|
||||
blk_mq_freeze_queue_start(dd->queue);
|
||||
blk_mq_stop_hw_queues(dd->queue);
|
||||
blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd);
|
||||
|
||||
/*
|
||||
* Delete our gendisk structure. This also removes the device
|
||||
* from /dev
|
||||
@@ -4040,7 +4185,8 @@ static int mtip_block_remove(struct driver_data *dd)
|
||||
dd->bdev = NULL;
|
||||
}
|
||||
if (dd->disk) {
|
||||
del_gendisk(dd->disk);
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
|
||||
del_gendisk(dd->disk);
|
||||
if (dd->disk->queue) {
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
@@ -4081,7 +4227,8 @@ static int mtip_block_shutdown(struct driver_data *dd)
|
||||
dev_info(&dd->pdev->dev,
|
||||
"Shutting down %s ...\n", dd->disk->disk_name);
|
||||
|
||||
del_gendisk(dd->disk);
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
|
||||
del_gendisk(dd->disk);
|
||||
if (dd->disk->queue) {
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
@@ -4426,7 +4573,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
||||
struct driver_data *dd = pci_get_drvdata(pdev);
|
||||
unsigned long flags, to;
|
||||
|
||||
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
||||
set_bit(MTIP_DDF_REMOVAL_BIT, &dd->dd_flag);
|
||||
|
||||
spin_lock_irqsave(&dev_lock, flags);
|
||||
list_del_init(&dd->online_list);
|
||||
@@ -4443,12 +4590,17 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
||||
} while (atomic_read(&dd->irq_workers_active) != 0 &&
|
||||
time_before(jiffies, to));
|
||||
|
||||
if (!dd->sr)
|
||||
fsync_bdev(dd->bdev);
|
||||
|
||||
if (atomic_read(&dd->irq_workers_active) != 0) {
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Completion workers still active!\n");
|
||||
}
|
||||
|
||||
blk_mq_stop_hw_queues(dd->queue);
|
||||
blk_set_queue_dying(dd->queue);
|
||||
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
||||
|
||||
/* Clean up the block layer. */
|
||||
mtip_block_remove(dd);
|
||||
|
||||
|
||||
@@ -134,16 +134,24 @@ enum {
|
||||
MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */
|
||||
MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */
|
||||
MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */
|
||||
MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */
|
||||
MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_EH_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_SE_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_DM_ACTIVE_BIT)),
|
||||
(1 << MTIP_PF_DM_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_TO_ACTIVE_BIT)),
|
||||
|
||||
MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
|
||||
MTIP_PF_ISSUE_CMDS_BIT = 5,
|
||||
MTIP_PF_REBUILD_BIT = 6,
|
||||
MTIP_PF_SVC_THD_STOP_BIT = 8,
|
||||
|
||||
MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_ISSUE_CMDS_BIT) |
|
||||
(1 << MTIP_PF_REBUILD_BIT) |
|
||||
(1 << MTIP_PF_SVC_THD_STOP_BIT) |
|
||||
(1 << MTIP_PF_TO_ACTIVE_BIT)),
|
||||
|
||||
/* below are bit numbers in 'dd_flag' defined in driver_data */
|
||||
MTIP_DDF_SEC_LOCK_BIT = 0,
|
||||
MTIP_DDF_REMOVE_PENDING_BIT = 1,
|
||||
@@ -153,6 +161,7 @@ enum {
|
||||
MTIP_DDF_RESUME_BIT = 6,
|
||||
MTIP_DDF_INIT_DONE_BIT = 7,
|
||||
MTIP_DDF_REBUILD_FAILED_BIT = 8,
|
||||
MTIP_DDF_REMOVAL_BIT = 9,
|
||||
|
||||
MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
|
||||
(1 << MTIP_DDF_SEC_LOCK_BIT) |
|
||||
|
||||
@@ -57,10 +57,12 @@ struct nbd_device {
|
||||
int blksize;
|
||||
loff_t bytesize;
|
||||
int xmit_timeout;
|
||||
bool timedout;
|
||||
bool disconnect; /* a disconnect has been requested by user */
|
||||
|
||||
struct timer_list timeout_timer;
|
||||
spinlock_t tasks_lock;
|
||||
/* protects initialization and shutdown of the socket */
|
||||
spinlock_t sock_lock;
|
||||
struct task_struct *task_recv;
|
||||
struct task_struct *task_send;
|
||||
|
||||
@@ -98,6 +100,11 @@ static inline struct device *nbd_to_dev(struct nbd_device *nbd)
|
||||
return disk_to_dev(nbd->disk);
|
||||
}
|
||||
|
||||
static bool nbd_is_connected(struct nbd_device *nbd)
|
||||
{
|
||||
return !!nbd->task_recv;
|
||||
}
|
||||
|
||||
static const char *nbdcmd_to_ascii(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
@@ -110,6 +117,42 @@ static const char *nbdcmd_to_ascii(int cmd)
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev)
|
||||
{
|
||||
bdev->bd_inode->i_size = 0;
|
||||
set_capacity(nbd->disk, 0);
|
||||
kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev)
|
||||
{
|
||||
if (!nbd_is_connected(nbd))
|
||||
return;
|
||||
|
||||
bdev->bd_inode->i_size = nbd->bytesize;
|
||||
set_capacity(nbd->disk, nbd->bytesize >> 9);
|
||||
kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
|
||||
}
|
||||
|
||||
static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
|
||||
int blocksize, int nr_blocks)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = set_blocksize(bdev, blocksize);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nbd->blksize = blocksize;
|
||||
nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks;
|
||||
|
||||
nbd_size_update(nbd, bdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nbd_end_request(struct nbd_device *nbd, struct request *req)
|
||||
{
|
||||
int error = req->errors ? -EIO : 0;
|
||||
@@ -129,13 +172,20 @@ static void nbd_end_request(struct nbd_device *nbd, struct request *req)
|
||||
*/
|
||||
static void sock_shutdown(struct nbd_device *nbd)
|
||||
{
|
||||
if (!nbd->sock)
|
||||
spin_lock_irq(&nbd->sock_lock);
|
||||
|
||||
if (!nbd->sock) {
|
||||
spin_unlock_irq(&nbd->sock_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
|
||||
kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
|
||||
sockfd_put(nbd->sock);
|
||||
nbd->sock = NULL;
|
||||
del_timer_sync(&nbd->timeout_timer);
|
||||
spin_unlock_irq(&nbd->sock_lock);
|
||||
|
||||
del_timer(&nbd->timeout_timer);
|
||||
}
|
||||
|
||||
static void nbd_xmit_timeout(unsigned long arg)
|
||||
@@ -146,19 +196,16 @@ static void nbd_xmit_timeout(unsigned long arg)
|
||||
if (list_empty(&nbd->queue_head))
|
||||
return;
|
||||
|
||||
nbd->disconnect = true;
|
||||
spin_lock_irqsave(&nbd->sock_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&nbd->tasks_lock, flags);
|
||||
nbd->timedout = true;
|
||||
|
||||
if (nbd->task_recv)
|
||||
force_sig(SIGKILL, nbd->task_recv);
|
||||
if (nbd->sock)
|
||||
kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
|
||||
|
||||
if (nbd->task_send)
|
||||
force_sig(SIGKILL, nbd->task_send);
|
||||
spin_unlock_irqrestore(&nbd->sock_lock, flags);
|
||||
|
||||
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
|
||||
|
||||
dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
|
||||
dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -171,7 +218,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
|
||||
int result;
|
||||
struct msghdr msg;
|
||||
struct kvec iov;
|
||||
sigset_t blocked, oldset;
|
||||
unsigned long pflags = current->flags;
|
||||
|
||||
if (unlikely(!sock)) {
|
||||
@@ -181,11 +227,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allow interception of SIGKILL only
|
||||
* Don't allow other signals to interrupt the transmission */
|
||||
siginitsetinv(&blocked, sigmask(SIGKILL));
|
||||
sigprocmask(SIG_SETMASK, &blocked, &oldset);
|
||||
|
||||
current->flags |= PF_MEMALLOC;
|
||||
do {
|
||||
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
|
||||
@@ -212,7 +253,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
|
||||
buf += result;
|
||||
} while (size > 0);
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
tsk_restore_flags(current, pflags, PF_MEMALLOC);
|
||||
|
||||
if (!send && nbd->xmit_timeout)
|
||||
@@ -402,31 +442,28 @@ static struct device_attribute pid_attr = {
|
||||
.show = pid_show,
|
||||
};
|
||||
|
||||
static int nbd_thread_recv(struct nbd_device *nbd)
|
||||
static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
|
||||
{
|
||||
struct request *req;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(nbd->magic != NBD_MAGIC);
|
||||
|
||||
sk_set_memalloc(nbd->sock->sk);
|
||||
|
||||
spin_lock_irqsave(&nbd->tasks_lock, flags);
|
||||
nbd->task_recv = current;
|
||||
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
|
||||
|
||||
ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
|
||||
if (ret) {
|
||||
dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
|
||||
|
||||
spin_lock_irqsave(&nbd->tasks_lock, flags);
|
||||
nbd->task_recv = NULL;
|
||||
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
nbd_size_update(nbd, bdev);
|
||||
|
||||
while (1) {
|
||||
req = nbd_read_stat(nbd);
|
||||
if (IS_ERR(req)) {
|
||||
@@ -437,21 +474,11 @@ static int nbd_thread_recv(struct nbd_device *nbd)
|
||||
nbd_end_request(nbd, req);
|
||||
}
|
||||
|
||||
nbd_size_clear(nbd, bdev);
|
||||
|
||||
device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
|
||||
|
||||
spin_lock_irqsave(&nbd->tasks_lock, flags);
|
||||
nbd->task_recv = NULL;
|
||||
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
|
||||
|
||||
if (signal_pending(current)) {
|
||||
ret = kernel_dequeue_signal(NULL);
|
||||
dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
|
||||
task_pid_nr(current), current->comm, ret);
|
||||
mutex_lock(&nbd->tx_lock);
|
||||
sock_shutdown(nbd);
|
||||
mutex_unlock(&nbd->tx_lock);
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -544,11 +571,8 @@ static int nbd_thread_send(void *data)
|
||||
{
|
||||
struct nbd_device *nbd = data;
|
||||
struct request *req;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&nbd->tasks_lock, flags);
|
||||
nbd->task_send = current;
|
||||
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
|
||||
|
||||
set_user_nice(current, MIN_NICE);
|
||||
while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
|
||||
@@ -557,17 +581,6 @@ static int nbd_thread_send(void *data)
|
||||
kthread_should_stop() ||
|
||||
!list_empty(&nbd->waiting_queue));
|
||||
|
||||
if (signal_pending(current)) {
|
||||
int ret = kernel_dequeue_signal(NULL);
|
||||
|
||||
dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
|
||||
task_pid_nr(current), current->comm, ret);
|
||||
mutex_lock(&nbd->tx_lock);
|
||||
sock_shutdown(nbd);
|
||||
mutex_unlock(&nbd->tx_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
/* extract request */
|
||||
if (list_empty(&nbd->waiting_queue))
|
||||
continue;
|
||||
@@ -582,13 +595,7 @@ static int nbd_thread_send(void *data)
|
||||
nbd_handle_req(nbd, req);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&nbd->tasks_lock, flags);
|
||||
nbd->task_send = NULL;
|
||||
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
|
||||
|
||||
/* Clear maybe pending signals */
|
||||
if (signal_pending(current))
|
||||
kernel_dequeue_signal(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -618,8 +625,8 @@ static void nbd_request_handler(struct request_queue *q)
|
||||
req, req->cmd_type);
|
||||
|
||||
if (unlikely(!nbd->sock)) {
|
||||
dev_err(disk_to_dev(nbd->disk),
|
||||
"Attempted send on closed socket\n");
|
||||
dev_err_ratelimited(disk_to_dev(nbd->disk),
|
||||
"Attempted send on closed socket\n");
|
||||
req->errors++;
|
||||
nbd_end_request(nbd, req);
|
||||
spin_lock_irq(q->queue_lock);
|
||||
@@ -636,6 +643,61 @@ static void nbd_request_handler(struct request_queue *q)
|
||||
}
|
||||
}
|
||||
|
||||
static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irq(&nbd->sock_lock);
|
||||
|
||||
if (nbd->sock) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nbd->sock = sock;
|
||||
|
||||
out:
|
||||
spin_unlock_irq(&nbd->sock_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset all properties of an NBD device */
|
||||
static void nbd_reset(struct nbd_device *nbd)
|
||||
{
|
||||
nbd->disconnect = false;
|
||||
nbd->timedout = false;
|
||||
nbd->blksize = 1024;
|
||||
nbd->bytesize = 0;
|
||||
set_capacity(nbd->disk, 0);
|
||||
nbd->flags = 0;
|
||||
nbd->xmit_timeout = 0;
|
||||
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
|
||||
del_timer_sync(&nbd->timeout_timer);
|
||||
}
|
||||
|
||||
static void nbd_bdev_reset(struct block_device *bdev)
|
||||
{
|
||||
set_device_ro(bdev, false);
|
||||
bdev->bd_inode->i_size = 0;
|
||||
if (max_part > 0) {
|
||||
blkdev_reread_part(bdev);
|
||||
bdev->bd_invalidated = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev)
|
||||
{
|
||||
if (nbd->flags & NBD_FLAG_READ_ONLY)
|
||||
set_device_ro(bdev, true);
|
||||
if (nbd->flags & NBD_FLAG_SEND_TRIM)
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
|
||||
if (nbd->flags & NBD_FLAG_SEND_FLUSH)
|
||||
blk_queue_flush(nbd->disk->queue, REQ_FLUSH);
|
||||
else
|
||||
blk_queue_flush(nbd->disk->queue, 0);
|
||||
}
|
||||
|
||||
static int nbd_dev_dbg_init(struct nbd_device *nbd);
|
||||
static void nbd_dev_dbg_close(struct nbd_device *nbd);
|
||||
|
||||
@@ -668,48 +730,40 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
case NBD_CLEAR_SOCK: {
|
||||
struct socket *sock = nbd->sock;
|
||||
nbd->sock = NULL;
|
||||
case NBD_CLEAR_SOCK:
|
||||
sock_shutdown(nbd);
|
||||
nbd_clear_que(nbd);
|
||||
BUG_ON(!list_empty(&nbd->queue_head));
|
||||
BUG_ON(!list_empty(&nbd->waiting_queue));
|
||||
kill_bdev(bdev);
|
||||
if (sock)
|
||||
sockfd_put(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case NBD_SET_SOCK: {
|
||||
struct socket *sock;
|
||||
int err;
|
||||
if (nbd->sock)
|
||||
return -EBUSY;
|
||||
sock = sockfd_lookup(arg, &err);
|
||||
if (sock) {
|
||||
nbd->sock = sock;
|
||||
if (max_part > 0)
|
||||
bdev->bd_invalidated = 1;
|
||||
nbd->disconnect = false; /* we're connected now */
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
struct socket *sock = sockfd_lookup(arg, &err);
|
||||
|
||||
if (!sock)
|
||||
return err;
|
||||
|
||||
err = nbd_set_socket(nbd, sock);
|
||||
if (!err && max_part)
|
||||
bdev->bd_invalidated = 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
case NBD_SET_BLKSIZE:
|
||||
nbd->blksize = arg;
|
||||
nbd->bytesize &= ~(nbd->blksize-1);
|
||||
bdev->bd_inode->i_size = nbd->bytesize;
|
||||
set_blocksize(bdev, nbd->blksize);
|
||||
set_capacity(nbd->disk, nbd->bytesize >> 9);
|
||||
return 0;
|
||||
case NBD_SET_BLKSIZE: {
|
||||
loff_t bsize = div_s64(nbd->bytesize, arg);
|
||||
|
||||
return nbd_size_set(nbd, bdev, arg, bsize);
|
||||
}
|
||||
|
||||
case NBD_SET_SIZE:
|
||||
nbd->bytesize = arg & ~(nbd->blksize-1);
|
||||
bdev->bd_inode->i_size = nbd->bytesize;
|
||||
set_blocksize(bdev, nbd->blksize);
|
||||
set_capacity(nbd->disk, nbd->bytesize >> 9);
|
||||
return 0;
|
||||
return nbd_size_set(nbd, bdev, nbd->blksize,
|
||||
arg / nbd->blksize);
|
||||
|
||||
case NBD_SET_SIZE_BLOCKS:
|
||||
return nbd_size_set(nbd, bdev, nbd->blksize, arg);
|
||||
|
||||
case NBD_SET_TIMEOUT:
|
||||
nbd->xmit_timeout = arg * HZ;
|
||||
@@ -725,16 +779,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||
nbd->flags = arg;
|
||||
return 0;
|
||||
|
||||
case NBD_SET_SIZE_BLOCKS:
|
||||
nbd->bytesize = ((u64) arg) * nbd->blksize;
|
||||
bdev->bd_inode->i_size = nbd->bytesize;
|
||||
set_blocksize(bdev, nbd->blksize);
|
||||
set_capacity(nbd->disk, nbd->bytesize >> 9);
|
||||
return 0;
|
||||
|
||||
case NBD_DO_IT: {
|
||||
struct task_struct *thread;
|
||||
struct socket *sock;
|
||||
int error;
|
||||
|
||||
if (nbd->task_recv)
|
||||
@@ -744,15 +790,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||
|
||||
mutex_unlock(&nbd->tx_lock);
|
||||
|
||||
if (nbd->flags & NBD_FLAG_READ_ONLY)
|
||||
set_device_ro(bdev, true);
|
||||
if (nbd->flags & NBD_FLAG_SEND_TRIM)
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
|
||||
nbd->disk->queue);
|
||||
if (nbd->flags & NBD_FLAG_SEND_FLUSH)
|
||||
blk_queue_flush(nbd->disk->queue, REQ_FLUSH);
|
||||
else
|
||||
blk_queue_flush(nbd->disk->queue, 0);
|
||||
nbd_parse_flags(nbd, bdev);
|
||||
|
||||
thread = kthread_run(nbd_thread_send, nbd, "%s",
|
||||
nbd_name(nbd));
|
||||
@@ -762,29 +800,24 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||
}
|
||||
|
||||
nbd_dev_dbg_init(nbd);
|
||||
error = nbd_thread_recv(nbd);
|
||||
error = nbd_thread_recv(nbd, bdev);
|
||||
nbd_dev_dbg_close(nbd);
|
||||
kthread_stop(thread);
|
||||
|
||||
mutex_lock(&nbd->tx_lock);
|
||||
|
||||
sock_shutdown(nbd);
|
||||
sock = nbd->sock;
|
||||
nbd->sock = NULL;
|
||||
nbd_clear_que(nbd);
|
||||
kill_bdev(bdev);
|
||||
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
|
||||
set_device_ro(bdev, false);
|
||||
if (sock)
|
||||
sockfd_put(sock);
|
||||
nbd->flags = 0;
|
||||
nbd->bytesize = 0;
|
||||
bdev->bd_inode->i_size = 0;
|
||||
set_capacity(nbd->disk, 0);
|
||||
if (max_part > 0)
|
||||
blkdev_reread_part(bdev);
|
||||
nbd_bdev_reset(bdev);
|
||||
|
||||
if (nbd->disconnect) /* user requested, ignore socket errors */
|
||||
return 0;
|
||||
error = 0;
|
||||
if (nbd->timedout)
|
||||
error = -ETIMEDOUT;
|
||||
|
||||
nbd_reset(nbd);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -892,50 +925,23 @@ static const struct file_operations nbd_dbg_flags_ops = {
|
||||
static int nbd_dev_dbg_init(struct nbd_device *nbd)
|
||||
{
|
||||
struct dentry *dir;
|
||||
struct dentry *f;
|
||||
|
||||
if (!nbd_dbg_dir)
|
||||
return -EIO;
|
||||
|
||||
dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir);
|
||||
if (IS_ERR_OR_NULL(dir)) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s' (%ld)\n",
|
||||
nbd_name(nbd), PTR_ERR(dir));
|
||||
return PTR_ERR(dir);
|
||||
if (!dir) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s'\n",
|
||||
nbd_name(nbd));
|
||||
return -EIO;
|
||||
}
|
||||
nbd->dbg_dir = dir;
|
||||
|
||||
f = debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
|
||||
if (IS_ERR_OR_NULL(f)) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'tasks', %ld\n",
|
||||
PTR_ERR(f));
|
||||
return PTR_ERR(f);
|
||||
}
|
||||
|
||||
f = debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
|
||||
if (IS_ERR_OR_NULL(f)) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'size_bytes', %ld\n",
|
||||
PTR_ERR(f));
|
||||
return PTR_ERR(f);
|
||||
}
|
||||
|
||||
f = debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout);
|
||||
if (IS_ERR_OR_NULL(f)) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'timeout', %ld\n",
|
||||
PTR_ERR(f));
|
||||
return PTR_ERR(f);
|
||||
}
|
||||
|
||||
f = debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
|
||||
if (IS_ERR_OR_NULL(f)) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'blocksize', %ld\n",
|
||||
PTR_ERR(f));
|
||||
return PTR_ERR(f);
|
||||
}
|
||||
|
||||
f = debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops);
|
||||
if (IS_ERR_OR_NULL(f)) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'flags', %ld\n",
|
||||
PTR_ERR(f));
|
||||
return PTR_ERR(f);
|
||||
}
|
||||
debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
|
||||
debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
|
||||
debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout);
|
||||
debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
|
||||
debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -950,8 +956,8 @@ static int nbd_dbg_init(void)
|
||||
struct dentry *dbg_dir;
|
||||
|
||||
dbg_dir = debugfs_create_dir("nbd", NULL);
|
||||
if (IS_ERR(dbg_dir))
|
||||
return PTR_ERR(dbg_dir);
|
||||
if (!dbg_dir)
|
||||
return -EIO;
|
||||
|
||||
nbd_dbg_dir = dbg_dir;
|
||||
|
||||
@@ -1069,7 +1075,7 @@ static int __init nbd_init(void)
|
||||
nbd_dev[i].magic = NBD_MAGIC;
|
||||
INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
|
||||
spin_lock_init(&nbd_dev[i].queue_lock);
|
||||
spin_lock_init(&nbd_dev[i].tasks_lock);
|
||||
spin_lock_init(&nbd_dev[i].sock_lock);
|
||||
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
|
||||
mutex_init(&nbd_dev[i].tx_lock);
|
||||
init_timer(&nbd_dev[i].timeout_timer);
|
||||
@@ -1077,14 +1083,12 @@ static int __init nbd_init(void)
|
||||
nbd_dev[i].timeout_timer.data = (unsigned long)&nbd_dev[i];
|
||||
init_waitqueue_head(&nbd_dev[i].active_wq);
|
||||
init_waitqueue_head(&nbd_dev[i].waiting_wq);
|
||||
nbd_dev[i].blksize = 1024;
|
||||
nbd_dev[i].bytesize = 0;
|
||||
disk->major = NBD_MAJOR;
|
||||
disk->first_minor = i << part_shift;
|
||||
disk->fops = &nbd_fops;
|
||||
disk->private_data = &nbd_dev[i];
|
||||
sprintf(disk->disk_name, "nbd%d", i);
|
||||
set_capacity(disk, 0);
|
||||
nbd_reset(&nbd_dev[i]);
|
||||
add_disk(disk);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
#include <xen/grant_table.h>
|
||||
#include "common.h"
|
||||
|
||||
/* Enlarge the array size in order to fully show blkback name. */
|
||||
#define BLKBACK_NAME_LEN (20)
|
||||
/* On the XenBus the max length of 'ring-ref%u'. */
|
||||
#define RINGREF_NAME_LEN (20)
|
||||
|
||||
struct backend_info {
|
||||
@@ -76,7 +75,7 @@ static int blkback_name(struct xen_blkif *blkif, char *buf)
|
||||
else
|
||||
devname = devpath;
|
||||
|
||||
snprintf(buf, BLKBACK_NAME_LEN, "blkback.%d.%s", blkif->domid, devname);
|
||||
snprintf(buf, TASK_COMM_LEN, "%d.%s", blkif->domid, devname);
|
||||
kfree(devpath);
|
||||
|
||||
return 0;
|
||||
@@ -85,7 +84,7 @@ static int blkback_name(struct xen_blkif *blkif, char *buf)
|
||||
static void xen_update_blkif_status(struct xen_blkif *blkif)
|
||||
{
|
||||
int err;
|
||||
char name[BLKBACK_NAME_LEN];
|
||||
char name[TASK_COMM_LEN];
|
||||
struct xen_blkif_ring *ring;
|
||||
int i;
|
||||
|
||||
@@ -618,6 +617,14 @@ static int xen_blkbk_probe(struct xenbus_device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = xenbus_printf(XBT_NIL, dev->nodename,
|
||||
"feature-max-indirect-segments", "%u",
|
||||
MAX_INDIRECT_SEGMENTS);
|
||||
if (err)
|
||||
dev_warn(&dev->dev,
|
||||
"writing %s/feature-max-indirect-segments (%d)",
|
||||
dev->nodename, err);
|
||||
|
||||
/* Multi-queue: advertise how many queues are supported by us.*/
|
||||
err = xenbus_printf(XBT_NIL, dev->nodename,
|
||||
"multi-queue-max-queues", "%u", xenblk_max_queues);
|
||||
@@ -849,11 +856,6 @@ again:
|
||||
dev->nodename);
|
||||
goto abort;
|
||||
}
|
||||
err = xenbus_printf(xbt, dev->nodename, "feature-max-indirect-segments", "%u",
|
||||
MAX_INDIRECT_SEGMENTS);
|
||||
if (err)
|
||||
dev_warn(&dev->dev, "writing %s/feature-max-indirect-segments (%d)",
|
||||
dev->nodename, err);
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
|
||||
(unsigned long long)vbd_sz(&be->blkif->vbd));
|
||||
|
||||
@@ -125,8 +125,10 @@ static const struct block_device_operations xlvbd_block_fops;
|
||||
*/
|
||||
|
||||
static unsigned int xen_blkif_max_segments = 32;
|
||||
module_param_named(max, xen_blkif_max_segments, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(max, "Maximum amount of segments in indirect requests (default is 32)");
|
||||
module_param_named(max_indirect_segments, xen_blkif_max_segments, uint,
|
||||
S_IRUGO);
|
||||
MODULE_PARM_DESC(max_indirect_segments,
|
||||
"Maximum amount of segments in indirect requests (default is 32)");
|
||||
|
||||
static unsigned int xen_blkif_max_queues = 4;
|
||||
module_param_named(max_queues, xen_blkif_max_queues, uint, S_IRUGO);
|
||||
|
||||
Reference in New Issue
Block a user