diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/aoe/aoe.h | 9 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 14 | ||||
-rw-r--r-- | drivers/block/aoe/aoenet.c | 2 | ||||
-rw-r--r-- | drivers/block/cciss.c | 135 | ||||
-rw-r--r-- | drivers/block/floppy.c | 167 | ||||
-rw-r--r-- | drivers/block/loop.c | 2 | ||||
-rw-r--r-- | drivers/block/nbd.c | 114 | ||||
-rw-r--r-- | drivers/block/rd.c | 27 |
8 files changed, 274 insertions, 196 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index ba07f762c4cb..07f02f855ab5 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -48,15 +48,6 @@ struct aoe_hdr { __be32 tag; }; -#ifdef __KERNEL__ -#include <linux/skbuff.h> - -static inline struct aoe_hdr *aoe_hdr(const struct sk_buff *skb) -{ - return (struct aoe_hdr *)skb_mac_header(skb); -} -#endif - struct aoe_atahdr { unsigned char aflags; unsigned char errfeat; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 99672017ca56..4d59d5057734 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -120,7 +120,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) /* initialize the headers & frame */ skb = f->skb; - h = aoe_hdr(skb); + h = (struct aoe_hdr *) skb_mac_header(skb); ah = (struct aoe_atahdr *) (h+1); skb_put(skb, sizeof *h + sizeof *ah); memset(h, 0, skb->len); @@ -209,7 +209,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) skb->dev = ifp; if (sl_tail == NULL) sl_tail = skb; - h = aoe_hdr(skb); + h = (struct aoe_hdr *) skb_mac_header(skb); memset(h, 0, sizeof *h + sizeof *ch); memset(h->dst, 0xff, sizeof h->dst); @@ -304,7 +304,7 @@ rexmit(struct aoedev *d, struct frame *f) aoechr_error(buf); skb = f->skb; - h = aoe_hdr(skb); + h = (struct aoe_hdr *) skb_mac_header(skb); ah = (struct aoe_atahdr *) (h+1); f->tag = n; h->tag = cpu_to_be32(n); @@ -533,7 +533,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) char ebuf[128]; u16 aoemajor; - hin = aoe_hdr(skb); + hin = (struct aoe_hdr *) skb_mac_header(skb); aoemajor = be16_to_cpu(get_unaligned(&hin->major)); d = aoedev_by_aoeaddr(aoemajor, hin->minor); if (d == NULL) { @@ -565,7 +565,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) calc_rttavg(d, tsince(f->tag)); ahin = (struct aoe_atahdr *) (hin+1); - hout = aoe_hdr(f->skb); + hout = (struct aoe_hdr *) skb_mac_header(f->skb); ahout = (struct aoe_atahdr *) (hout+1); buf = f->buf; @@ -699,7 +699,7 @@ aoecmd_ata_id(struct aoedev *d) /* initialize the headers & frame */ skb = f->skb; - h = aoe_hdr(skb); + h = (struct aoe_hdr *) skb_mac_header(skb); ah = (struct aoe_atahdr *) (h+1); skb_put(skb, sizeof *h + sizeof *ah); memset(h, 0, skb->len); @@ -730,7 +730,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) enum { MAXFRAMES = 16 }; u16 n; - h = aoe_hdr(skb); + h = (struct aoe_hdr *) skb_mac_header(skb); ch = (struct aoe_cfghdr *) (h+1); /* diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 4dc0fb7da94b..4e6deb7f5c24 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -127,7 +127,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, goto exit; skb_push(skb, ETH_HLEN); /* (1) */ - h = aoe_hdr(skb); + h = (struct aoe_hdr *) skb_mac_header(skb); n = be32_to_cpu(get_unaligned(&h->tag)); if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31)) goto exit; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e330c26c5ad9..7c2cfde08f18 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1582,38 +1582,36 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, * allows us to delete disk zero but keep the controller registered. */ if (h->gendisk[0] != disk) { - if (disk) { - struct request_queue *q = disk->queue; - if (disk->flags & GENHD_FL_UP) - del_gendisk(disk); - if (q) { - blk_cleanup_queue(q); - /* Set drv->queue to NULL so that we do not try - * to call blk_start_queue on this queue in the - * interrupt handler - */ - drv->queue = NULL; - } - /* If clear_all is set then we are deleting the logical - * drive, not just refreshing its info. For drives - * other than disk 0 we will call put_disk. We do not - * do this for disk 0 as we need it to be able to - * configure the controller. + struct request_queue *q = disk->queue; + if (disk->flags & GENHD_FL_UP) + del_gendisk(disk); + if (q) { + blk_cleanup_queue(q); + /* Set drv->queue to NULL so that we do not try + * to call blk_start_queue on this queue in the + * interrupt handler + */ + drv->queue = NULL; + } + /* If clear_all is set then we are deleting the logical + * drive, not just refreshing its info. For drives + * other than disk 0 we will call put_disk. We do not + * do this for disk 0 as we need it to be able to + * configure the controller. + */ + if (clear_all){ + /* This isn't pretty, but we need to find the + * disk in our array and NULL our the pointer. + * This is so that we will call alloc_disk if + * this index is used again later. */ - if (clear_all){ - /* This isn't pretty, but we need to find the - * disk in our array and NULL our the pointer. - * This is so that we will call alloc_disk if - * this index is used again later. - */ - for (i=0; i < CISS_MAX_LUN; i++){ - if(h->gendisk[i] == disk){ - h->gendisk[i] = NULL; - break; - } + for (i=0; i < CISS_MAX_LUN; i++){ + if(h->gendisk[i] == disk){ + h->gendisk[i] = NULL; + break; } - put_disk(disk); } + put_disk(disk); } } else { set_capacity(disk, 0); @@ -2365,30 +2363,55 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c) start_io(h); } +static inline unsigned int make_status_bytes(unsigned int scsi_status_byte, + unsigned int msg_byte, unsigned int host_byte, + unsigned int driver_byte) +{ + /* inverse of macros in scsi.h */ + return (scsi_status_byte & 0xff) | + ((msg_byte & 0xff) << 8) | + ((host_byte & 0xff) << 16) | + ((driver_byte & 0xff) << 24); +} + static inline int evaluate_target_status(CommandList_struct *cmd) { unsigned char sense_key; - int error_count = 1; + unsigned char status_byte, msg_byte, host_byte, driver_byte; + int error_value; + + /* If we get in here, it means we got "target status", that is, scsi status */ + status_byte = cmd->err_info->ScsiStatus; + driver_byte = DRIVER_OK; + msg_byte = cmd->err_info->CommandStatus; /* correct? seems too device specific */ + + if (blk_pc_request(cmd->rq)) + host_byte = DID_PASSTHROUGH; + else + host_byte = DID_OK; + + error_value = make_status_bytes(status_byte, msg_byte, + host_byte, driver_byte); - if (cmd->err_info->ScsiStatus != 0x02) { /* not check condition? */ + if (cmd->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) { if (!blk_pc_request(cmd->rq)) printk(KERN_WARNING "cciss: cmd %p " "has SCSI Status 0x%x\n", cmd, cmd->err_info->ScsiStatus); - return error_count; + return error_value; } /* check the sense key */ sense_key = 0xf & cmd->err_info->SenseInfo[2]; /* no status or recovered error */ - if ((sense_key == 0x0) || (sense_key == 0x1)) - error_count = 0; + if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq)) + error_value = 0; if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ - if (error_count != 0) + if (error_value != 0) printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" " sense key = 0x%x\n", cmd, sense_key); - return error_count; + return error_value; } /* SG_IO or similar, copy sense data back */ @@ -2400,7 +2423,7 @@ static inline int evaluate_target_status(CommandList_struct *cmd) } else cmd->rq->sense_len = 0; - return error_count; + return error_value; } /* checks the status of the job and calls complete buffers to mark all @@ -2416,7 +2439,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, rq->errors = 0; if (timeout) - rq->errors = 1; + rq->errors = make_status_bytes(0, 0, 0, DRIVER_TIMEOUT); if (cmd->err_info->CommandStatus == 0) /* no error has occurred */ goto after_error_processing; @@ -2442,32 +2465,44 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, case CMD_INVALID: printk(KERN_WARNING "cciss: cmd %p is " "reported invalid\n", cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); break; case CMD_PROTOCOL_ERR: printk(KERN_WARNING "cciss: cmd %p has " "protocol error \n", cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); break; case CMD_HARDWARE_ERR: printk(KERN_WARNING "cciss: cmd %p had " " hardware error\n", cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); break; case CMD_CONNECTION_LOST: printk(KERN_WARNING "cciss: cmd %p had " "connection lost\n", cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); break; case CMD_ABORTED: printk(KERN_WARNING "cciss: cmd %p was " "aborted\n", cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT); break; case CMD_ABORT_FAILED: printk(KERN_WARNING "cciss: cmd %p reports " "abort failed\n", cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); break; case CMD_UNSOLICITED_ABORT: printk(KERN_WARNING "cciss%d: unsolicited " @@ -2481,17 +2516,23 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, printk(KERN_WARNING "cciss%d: %p retried too " "many times\n", h->ctlr, cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT); break; case CMD_TIMEOUT: printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); break; default: printk(KERN_WARNING "cciss: cmd %p returned " "unknown status %x\n", cmd, cmd->err_info->CommandStatus); - rq->errors = 1; + rq->errors = make_status_bytes(SAM_STAT_GOOD, + cmd->err_info->CommandStatus, DRIVER_OK, + blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); } after_error_processing: diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 80483aac4cc9..639ed14bb08d 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -5,6 +5,7 @@ * Copyright (C) 1993, 1994 Alain Knaff * Copyright (C) 1998 Alan Cox */ + /* * 02.12.91 - Changed to static variables to indicate need for reset * and recalibrate. This makes some things easier (output_byte reset @@ -149,7 +150,7 @@ #define REALLY_SLOW_IO #define DEBUGT 2 -#define DCL_DEBUG /* debug disk change line */ +#define DCL_DEBUG /* debug disk change line */ /* do print messages for unexpected interrupts */ static int print_unex = 1; @@ -161,10 +162,8 @@ static int print_unex = 1; #include <linux/workqueue.h> #define FDPATCHES #include <linux/fdreg.h> - #include <linux/fd.h> #include <linux/hdreg.h> - #include <linux/errno.h> #include <linux/slab.h> #include <linux/mm.h> @@ -274,8 +273,7 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) return; /* we have the memory */ if (can_use_virtual_dma != 2) return; /* no fallback allowed */ - printk - ("DMA memory shortage. Temporarily falling back on virtual DMA\n"); + printk("DMA memory shortage. Temporarily falling back on virtual DMA\n"); *addr = (char *)nodma_mem_alloc(l); #else return; @@ -291,8 +289,8 @@ static int initialising = 1; #define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) #define UNIT(x) ((x) & 0x03) /* drive on fdc */ #define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ + /* reverse mapping from unit and fdc to drive */ #define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) - /* reverse mapping from unit and fdc to drive */ #define DP (&drive_params[current_drive]) #define DRS (&drive_state[current_drive]) #define DRWE (&write_errors[current_drive]) @@ -356,7 +354,6 @@ static int inr; /* size of reply buffer, when called from interrupt */ #define R_HEAD (reply_buffer[4]) #define R_SECTOR (reply_buffer[5]) #define R_SIZECODE (reply_buffer[6]) - #define SEL_DLY (2*HZ/100) /* @@ -472,8 +469,8 @@ static struct floppy_struct floppy_type[32] = { { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */ { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */ { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */ - { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */ + { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */ { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ }; @@ -539,12 +536,12 @@ static char *floppy_track_buffer; static int max_buffer_sectors; static int *errors; -typedef void (*done_f) (int); +typedef void (*done_f)(int); static struct cont_t { - void (*interrupt) (void); /* this is called after the interrupt of the + void (*interrupt)(void); /* this is called after the interrupt of the * main command */ - void (*redo) (void); /* this is called to retry the operation */ - void (*error) (void); /* this is called to tally an error */ + void (*redo)(void); /* this is called to retry the operation */ + void (*error)(void); /* this is called to tally an error */ done_f done; /* this is called to say if the operation has * succeeded/failed */ } *cont; @@ -694,7 +691,6 @@ static void reschedule_timeout(int drive, const char *message, int marg) } #define INFBOUND(a,b) (a)=max_t(int, a, b) - #define SUPBOUND(a,b) (a)=min_t(int, a, b) /* @@ -733,6 +729,7 @@ static void reschedule_timeout(int drive, const char *message, int marg) static int disk_change(int drive) { int fdc = FDC(drive); + #ifdef FLOPPY_SANITY_CHECK if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) DPRINT("WARNING disk change called early\n"); @@ -771,7 +768,6 @@ static int disk_change(int drive) floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1; } - /*USETF(FD_DISK_NEWCHANGE); */ return 1; } else { UDRS->last_checked = jiffies; @@ -787,7 +783,10 @@ static inline int is_selected(int dor, int unit) static int set_dor(int fdc, char mask, char data) { - register unsigned char drive, unit, newdor, olddor; + unsigned char unit; + unsigned char drive; + unsigned char newdor; + unsigned char olddor; if (FDCS->address == -1) return -1; @@ -892,7 +891,6 @@ static int _lock_fdc(int drive, int interruptible, int line) set_current_state(TASK_RUNNING); remove_wait_queue(&fdc_wait, &wait); - flush_scheduled_work(); } command_status = FD_COMMAND_NONE; @@ -942,7 +940,7 @@ static void motor_off_callback(unsigned long nr) static void floppy_off(unsigned int drive) { unsigned long volatile delta; - register int fdc = FDC(drive); + int fdc = FDC(drive); if (!(FDCS->dor & (0x10 << UNIT(drive)))) return; @@ -968,7 +966,9 @@ static void floppy_off(unsigned int drive) */ static void scandrives(void) { - int i, drive, saved_drive; + int i; + int drive; + int saved_drive; if (DP->select_delay) return; @@ -1146,7 +1146,9 @@ static void show_floppy(void); /* waits until the fdc becomes ready */ static int wait_til_ready(void) { - int counter, status; + int status; + int counter; + if (FDCS->reset) return -1; for (counter = 0; counter < 10000; counter++) { @@ -1193,7 +1195,8 @@ static int output_byte(char byte) /* gets the response from the fdc */ static int result(void) { - int i, status = 0; + int i; + int status = 0; for (i = 0; i < MAX_REPLIES; i++) { if ((status = wait_til_ready()) < 0) @@ -1226,6 +1229,7 @@ static int result(void) static int need_more_output(void) { int status; + if ((status = wait_til_ready()) < 0) return -1; if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) @@ -1309,8 +1313,11 @@ static int fdc_configure(void) */ static void fdc_specify(void) { - unsigned char spec1, spec2; - unsigned long srt, hlt, hut; + unsigned char spec1; + unsigned char spec2; + unsigned long srt; + unsigned long hlt; + unsigned long hut; unsigned long dtr = NOMINAL_DTR; unsigned long scale_dtr = NOMINAL_DTR; int hlt_max_code = 0x7f; @@ -1319,7 +1326,6 @@ static void fdc_specify(void) if (FDCS->need_configure && FDCS->version >= FDC_82072A) { fdc_configure(); FDCS->need_configure = 0; - /*DPRINT("FIFO enabled\n"); */ } switch (raw_cmd->rate & 0x03) { @@ -1472,7 +1478,6 @@ static int interpret_errors(void) tell_sector(); } printk("\n"); - } if (ST2 & ST2_WC || ST2 & ST2_BC) /* wrong cylinder => recal */ @@ -1498,7 +1503,10 @@ static int interpret_errors(void) */ static void setup_rw_floppy(void) { - int i, r, flags, dflags; + int i; + int r; + int flags; + int dflags; unsigned long ready_date; timeout_fn function; @@ -1728,9 +1736,9 @@ static void print_result(char *message, int inr) /* interrupt handler. Note that this can be called externally on the Sparc */ irqreturn_t floppy_interrupt(int irq, void *dev_id) { - void (*handler) (void) = do_floppy; int do_print; unsigned long f; + void (*handler)(void) = do_floppy; lasthandler = handler; interruptjiffies = jiffies; @@ -1912,12 +1920,11 @@ static void floppy_shutdown(unsigned long data) is_alive("floppy shutdown"); } -/*typedef void (*timeout_fn)(unsigned long);*/ - /* start motor, check media-changed condition and write protection */ -static int start_motor(void (*function) (void)) +static int start_motor(void (*function)(void)) { - int mask, data; + int mask; + int data; mask = 0xfc; data = UNIT(current_drive); @@ -2020,17 +2027,17 @@ static struct cont_t wakeup_cont = { .interrupt = empty, .redo = do_wakeup, .error = empty, - .done = (done_f) empty + .done = (done_f)empty }; static struct cont_t intr_cont = { .interrupt = empty, .redo = process_fd_request, .error = empty, - .done = (done_f) empty + .done = (done_f)empty }; -static int wait_til_done(void (*handler) (void), int interruptible) +static int wait_til_done(void (*handler)(void), int interruptible) { int ret; @@ -2049,7 +2056,6 @@ static int wait_til_done(void (*handler) (void), int interruptible) break; is_alive("wait_til_done"); - schedule(); } @@ -2141,6 +2147,7 @@ static void bad_flp_intr(void) static void set_floppy(int drive) { int type = ITYPE(UDRS->fd_device); + if (type) _floppy = floppy_type + type; else @@ -2169,11 +2176,14 @@ static void format_interrupt(void) #define CT(x) ((x) | 0xc0) static void setup_format_params(int track) { + int n; + int il; + int count; + int head_shift; + int track_shift; struct fparm { unsigned char track, head, sect, size; } *here = (struct fparm *)floppy_track_buffer; - int il, n; - int count, head_shift, track_shift; raw_cmd = &default_raw_cmd; raw_cmd->track = track; @@ -2344,7 +2354,10 @@ static void request_done(int uptodate) /* Interrupt handler evaluating the result of the r/w operation */ static void rw_interrupt(void) { - int nr_sectors, ssize, eoc, heads; + int eoc; + int ssize; + int heads; + int nr_sectors; if (R_HEAD >= 2) { /* some Toshiba floppy controllers occasionnally seem to @@ -2476,7 +2489,8 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) { int remaining; /* number of transferred 512-byte sectors */ struct bio_vec *bv; - char *buffer, *dma_buffer; + char *buffer; + char *dma_buffer; int size; struct req_iterator iter; @@ -2556,19 +2570,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) #endif } -#if 0 -static inline int check_dma_crossing(char *start, - unsigned long length, char *message) -{ - if (CROSS_64KB(start, length)) { - printk("DMA xfer crosses 64KB boundary in %s %p-%p\n", - message, start, start + length); - return 1; - } else - return 0; -} -#endif - /* work around a bug in pseudo DMA * (on some FDCs) pseudo DMA does not stop when the CPU stops * sending data. Hence we need a different way to signal the @@ -2578,7 +2579,8 @@ static inline int check_dma_crossing(char *start, */ static void virtualdmabug_workaround(void) { - int hard_sectors, end_sector; + int hard_sectors; + int end_sector; if (CT(COMMAND) == FD_WRITE) { COMMAND &= ~0x80; /* switch off multiple track mode */ @@ -2610,7 +2612,10 @@ static void virtualdmabug_workaround(void) static int make_raw_rw_request(void) { int aligned_sector_t; - int max_sector, max_size, tracksize, ssize; + int max_sector; + int max_size; + int tracksize; + int ssize; if (max_buffer_sectors == 0) { printk("VFS: Block I/O scheduled on unopened device\n"); @@ -2762,9 +2767,7 @@ static int make_raw_rw_request(void) */ if (!direct || (indirect * 2 > direct * 3 && - *errors < DP->max_errors.read_track && - /*!TESTF(FD_NEED_TWADDLE) && */ - ((!probing + *errors < DP->max_errors.read_track && ((!probing || (DP->read_track & (1 << DRS->probed_format)))))) { max_size = current_req->nr_sectors; } else { @@ -2777,10 +2780,6 @@ static int make_raw_rw_request(void) indirect, direct, fsector_t); return 0; } -/* check_dma_crossing(raw_cmd->kernel_data, - raw_cmd->length, - "end of make_raw_request [1]");*/ - virtualdmabug_workaround(); return 2; } @@ -2830,8 +2829,6 @@ static int make_raw_rw_request(void) raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; raw_cmd->length <<= 9; #ifdef FLOPPY_SANITY_CHECK - /*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length, - "end of make_raw_request"); */ if ((raw_cmd->length < current_count_sectors << 9) || (raw_cmd->kernel_data != current_req->buffer && CT(COMMAND) == FD_WRITE && @@ -3011,6 +3008,7 @@ static struct cont_t poll_cont = { static int poll_drive(int interruptible, int flag) { int ret; + /* no auto-sense, just clear dcl */ raw_cmd = &default_raw_cmd; raw_cmd->flags = flag; @@ -3173,7 +3171,8 @@ static inline int raw_cmd_copyout(int cmd, char __user *param, static void raw_cmd_free(struct floppy_raw_cmd **ptr) { - struct floppy_raw_cmd *next, *this; + struct floppy_raw_cmd *next; + struct floppy_raw_cmd *this; this = *ptr; *ptr = NULL; @@ -3245,8 +3244,10 @@ static inline int raw_cmd_copyin(int cmd, char __user *param, static int raw_cmd_ioctl(int cmd, void __user *param) { - int drive, ret, ret2; struct floppy_raw_cmd *my_raw_cmd; + int drive; + int ret2; + int ret; if (FDCS->rawcmd <= 1) FDCS->rawcmd = 1; @@ -3453,7 +3454,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 int drive = (long)inode->i_bdev->bd_disk->private_data; - int i, type = ITYPE(UDRS->fd_device); + int type = ITYPE(UDRS->fd_device); + int i; int ret; int size; union inparam { @@ -3619,8 +3621,7 @@ static void __init config_types(void) if (!UDP->cmos && FLOPPY1_TYPE) UDP->cmos = FLOPPY1_TYPE; - /* XXX */ - /* additional physical CMOS drive detection should go here */ + /* FIXME: additional physical CMOS drive detection should go here */ for (drive = 0; drive < N_DRIVE; drive++) { unsigned int type = UDP->cmos; @@ -3903,13 +3904,13 @@ static int floppy_revalidate(struct gendisk *disk) } static struct block_device_operations floppy_fops = { - .owner = THIS_MODULE, - .open = floppy_open, - .release = floppy_release, - .ioctl = fd_ioctl, - .getgeo = fd_getgeo, - .media_changed = check_floppy_change, - .revalidate_disk = floppy_revalidate, + .owner = THIS_MODULE, + .open = floppy_open, + .release = floppy_release, + .ioctl = fd_ioctl, + .getgeo = fd_getgeo, + .media_changed = check_floppy_change, + .revalidate_disk = floppy_revalidate, }; /* @@ -4388,11 +4389,15 @@ static int floppy_grab_irq_and_dma(void) if (fd_request_dma()) { DPRINT("Unable to grab DMA%d for the floppy driver\n", FLOPPY_DMA); - fd_free_irq(); - spin_lock_irqsave(&floppy_usage_lock, flags); - usage_count--; - spin_unlock_irqrestore(&floppy_usage_lock, flags); - return -1; + if (can_use_virtual_dma & 2) + use_virtual_dma = can_use_virtual_dma = 1; + if (!(can_use_virtual_dma & 1)) { + fd_free_irq(); + spin_lock_irqsave(&floppy_usage_lock, flags); + usage_count--; + spin_unlock_irqrestore(&floppy_usage_lock, flags); + return -1; + } } for (fdc = 0; fdc < N_FDC; fdc++) { @@ -4424,8 +4429,8 @@ static int floppy_grab_irq_and_dma(void) if (FDCS->address != -1) fd_outb(FDCS->dor, FD_DOR); /* - * The driver will try and free resources and relies on us - * to know if they were allocated or not. + * The driver will try and free resources and relies on us + * to know if they were allocated or not. */ fdc = 0; irqdma_allocated = 1; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e5a051577a5e..589cbbd9cd4f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1285,7 +1285,6 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a struct loop_device *lo = inode->i_bdev->bd_disk->private_data; int err; - lock_kernel(); switch(cmd) { case LOOP_SET_STATUS: mutex_lock(&lo->lo_ctl_mutex); @@ -1311,7 +1310,6 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a err = -ENOIOCTLCMD; break; } - unlock_kernel(); return err; } #endif diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index be5ec3a9b1fc..cb136a919f2a 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -113,12 +113,42 @@ static void nbd_end_request(struct request *req) spin_unlock_irqrestore(q->queue_lock, flags); } +static void sock_shutdown(struct nbd_device *lo, int lock) +{ + /* Forcibly shutdown the socket causing all listeners + * to error + * + * FIXME: This code is duplicated from sys_shutdown, but + * there should be a more generic interface rather than + * calling socket ops directly here */ + if (lock) + mutex_lock(&lo->tx_lock); + if (lo->sock) { + printk(KERN_WARNING "%s: shutting down socket\n", + lo->disk->disk_name); + lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN); + lo->sock = NULL; + } + if (lock) + mutex_unlock(&lo->tx_lock); +} + +static void nbd_xmit_timeout(unsigned long arg) +{ + struct task_struct *task = (struct task_struct *)arg; + + printk(KERN_WARNING "nbd: killing hung xmit (%s, pid: %d)\n", + task->comm, task->pid); + force_sig(SIGKILL, task); +} + /* * Send or receive packet. */ -static int sock_xmit(struct socket *sock, int send, void *buf, int size, +static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size, int msg_flags) { + struct socket *sock = lo->sock; int result; struct msghdr msg; struct kvec iov; @@ -139,9 +169,20 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, msg.msg_controllen = 0; msg.msg_flags = msg_flags | MSG_NOSIGNAL; - if (send) + if (send) { + struct timer_list ti; + + if (lo->xmit_timeout) { + init_timer(&ti); + ti.function = nbd_xmit_timeout; + ti.data = (unsigned long)current; + ti.expires = jiffies + lo->xmit_timeout; + add_timer(&ti); + } result = kernel_sendmsg(sock, &msg, &iov, 1, size); - else + if (lo->xmit_timeout) + del_timer_sync(&ti); + } else result = kernel_recvmsg(sock, &msg, &iov, 1, size, 0); if (signal_pending(current)) { @@ -150,6 +191,7 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, current->pid, current->comm, dequeue_signal_lock(current, ¤t->blocked, &info)); result = -EINTR; + sock_shutdown(lo, !send); break; } @@ -167,23 +209,22 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, return result; } -static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec, +static inline int sock_send_bvec(struct nbd_device *lo, struct bio_vec *bvec, int flags) { int result; void *kaddr = kmap(bvec->bv_page); - result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len, - flags); + result = sock_xmit(lo, 1, kaddr + bvec->bv_offset, bvec->bv_len, flags); kunmap(bvec->bv_page); return result; } +/* always call with the tx_lock held */ static int nbd_send_req(struct nbd_device *lo, struct request *req) { int result, flags; struct nbd_request request; unsigned long size = req->nr_sectors << 9; - struct socket *sock = lo->sock; request.magic = htonl(NBD_REQUEST_MAGIC); request.type = htonl(nbd_cmd(req)); @@ -196,8 +237,8 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) nbdcmd_to_ascii(nbd_cmd(req)), (unsigned long long)req->sector << 9, req->nr_sectors << 9); - result = sock_xmit(sock, 1, &request, sizeof(request), - (nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0); + result = sock_xmit(lo, 1, &request, sizeof(request), + (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0); if (result <= 0) { printk(KERN_ERR "%s: Send control failed (result %d)\n", lo->disk->disk_name, result); @@ -217,7 +258,7 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) flags = MSG_MORE; dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", lo->disk->disk_name, req, bvec->bv_len); - result = sock_send_bvec(sock, bvec, flags); + result = sock_send_bvec(lo, bvec, flags); if (result <= 0) { printk(KERN_ERR "%s: Send data failed (result %d)\n", lo->disk->disk_name, result); @@ -231,22 +272,18 @@ error_out: return 1; } -static struct request *nbd_find_request(struct nbd_device *lo, char *handle) +static struct request *nbd_find_request(struct nbd_device *lo, + struct request *xreq) { - struct request *req; - struct list_head *tmp; - struct request *xreq; + struct request *req, *tmp; int err; - memcpy(&xreq, handle, sizeof(xreq)); - err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq); if (unlikely(err)) goto out; spin_lock(&lo->queue_lock); - list_for_each(tmp, &lo->queue_head) { - req = list_entry(tmp, struct request, queuelist); + list_for_each_entry_safe(req, tmp, &lo->queue_head, queuelist) { if (req != xreq) continue; list_del_init(&req->queuelist); @@ -261,11 +298,11 @@ out: return ERR_PTR(err); } -static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec) +static inline int sock_recv_bvec(struct nbd_device *lo, struct bio_vec *bvec) { int result; void *kaddr = kmap(bvec->bv_page); - result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len, + result = sock_xmit(lo, 0, kaddr + bvec->bv_offset, bvec->bv_len, MSG_WAITALL); kunmap(bvec->bv_page); return result; @@ -277,10 +314,9 @@ static struct request *nbd_read_stat(struct nbd_device *lo) int result; struct nbd_reply reply; struct request *req; - struct socket *sock = lo->sock; reply.magic = 0; - result = sock_xmit(sock, 0, &reply, sizeof(reply), MSG_WAITALL); + result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL); if (result <= 0) { printk(KERN_ERR "%s: Receive control failed (result %d)\n", lo->disk->disk_name, result); @@ -295,7 +331,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo) goto harderror; } - req = nbd_find_request(lo, reply.handle); + req = nbd_find_request(lo, *(struct request **)reply.handle); if (unlikely(IS_ERR(req))) { result = PTR_ERR(req); if (result != -ENOENT) @@ -321,7 +357,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo) struct bio_vec *bvec; rq_for_each_segment(bvec, req, iter) { - result = sock_recv_bvec(sock, bvec); + result = sock_recv_bvec(lo, bvec); if (result <= 0) { printk(KERN_ERR "%s: Receive data failed (result %d)\n", lo->disk->disk_name, result); @@ -396,6 +432,7 @@ static void nbd_clear_que(struct nbd_device *lo) } } + /* * We always wait for result of write, for now. It would be nice to make it optional * in future @@ -504,7 +541,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file, sreq.nr_sectors = 0; if (!lo->sock) return -EINVAL; + mutex_lock(&lo->tx_lock); nbd_send_req(lo, &sreq); + mutex_unlock(&lo->tx_lock); return 0; case NBD_CLEAR_SOCK: @@ -548,6 +587,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file, set_blocksize(inode->i_bdev, lo->blksize); set_capacity(lo->disk, lo->bytesize >> 9); return 0; + case NBD_SET_TIMEOUT: + lo->xmit_timeout = arg * HZ; + return 0; case NBD_SET_SIZE_BLOCKS: lo->bytesize = ((u64) arg) * lo->blksize; inode->i_bdev->bd_inode->i_size = lo->bytesize; @@ -560,28 +602,16 @@ static int nbd_ioctl(struct inode *inode, struct file *file, error = nbd_do_it(lo); if (error) return error; - /* on return tidy up in case we have a signal */ - /* Forcibly shutdown the socket causing all listeners - * to error - * - * FIXME: This code is duplicated from sys_shutdown, but - * there should be a more generic interface rather than - * calling socket ops directly here */ - mutex_lock(&lo->tx_lock); - if (lo->sock) { - printk(KERN_WARNING "%s: shutting down socket\n", - lo->disk->disk_name); - lo->sock->ops->shutdown(lo->sock, - SEND_SHUTDOWN|RCV_SHUTDOWN); - lo->sock = NULL; - } - mutex_unlock(&lo->tx_lock); + sock_shutdown(lo, 1); file = lo->file; lo->file = NULL; nbd_clear_que(lo); printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name); if (file) fput(file); + lo->bytesize = 0; + inode->i_bdev->bd_inode->i_size = 0; + set_capacity(lo->disk, 0); return lo->harderror; case NBD_CLEAR_QUE: /* @@ -659,14 +689,14 @@ static int __init nbd_init(void) mutex_init(&nbd_dev[i].tx_lock); init_waitqueue_head(&nbd_dev[i].active_wq); nbd_dev[i].blksize = 1024; - nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */ + nbd_dev[i].bytesize = 0; disk->major = NBD_MAJOR; disk->first_minor = i; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; sprintf(disk->disk_name, "nbd%d", i); - set_capacity(disk, 0x7ffffc00ULL << 1); /* 2 TB */ + set_capacity(disk, 0); add_disk(disk); } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 701ea77f62e9..08176d23a46c 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -411,6 +411,9 @@ static void __exit rd_cleanup(void) blk_cleanup_queue(rd_queue[i]); } unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); + + bdi_destroy(&rd_file_backing_dev_info); + bdi_destroy(&rd_backing_dev_info); } /* @@ -419,7 +422,19 @@ static void __exit rd_cleanup(void) static int __init rd_init(void) { int i; - int err = -ENOMEM; + int err; + + err = bdi_init(&rd_backing_dev_info); + if (err) + goto out2; + + err = bdi_init(&rd_file_backing_dev_info); + if (err) { + bdi_destroy(&rd_backing_dev_info); + goto out2; + } + + err = -ENOMEM; if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || (rd_blocksize & (rd_blocksize-1))) { @@ -473,6 +488,9 @@ out: put_disk(rd_disks[i]); blk_cleanup_queue(rd_queue[i]); } + bdi_destroy(&rd_backing_dev_info); + bdi_destroy(&rd_file_backing_dev_info); +out2: return err; } @@ -486,17 +504,12 @@ static int __init ramdisk_size(char *str) rd_size = simple_strtol(str,NULL,0); return 1; } -static int __init ramdisk_size2(char *str) /* kludge */ -{ - return ramdisk_size(str); -} static int __init ramdisk_blocksize(char *str) { rd_blocksize = simple_strtol(str,NULL,0); return 1; } -__setup("ramdisk=", ramdisk_size); -__setup("ramdisk_size=", ramdisk_size2); +__setup("ramdisk_size=", ramdisk_size); __setup("ramdisk_blocksize=", ramdisk_blocksize); #endif |