From 8e234f882490f5f771bbba26f891e09223c59db1 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 23 Oct 2008 12:06:39 +0000 Subject: [PATCH] Fixes problems spotted by lockdep git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@534 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_vdisk.c | 139 ++++++++++++++++------------- 1 file changed, 77 insertions(+), 62 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 4eb1e5634..050ad2add 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -174,7 +174,14 @@ struct scst_vdisk_dev { uint64_t nblocks; int block_shift; loff_t file_size; /* in bytes */ + + /* + * This lock can be taken on both SIRQ and thread context, but in + * all cases for each particular instance it's taken consistenly either + * on SIRQ or thread context. Mix of them is impossible. + */ spinlock_t flags_lock; + /* * Below flags are protected by flags_lock or suspended activity * with scst_vdisk_mutex. @@ -213,7 +220,6 @@ struct scst_vdisk_thr { struct block_device *bdev; struct iovec *iv; int iv_count; - struct scst_vdisk_dev *virt_dev; }; static struct kmem_cache *vdisk_thr_cachep; @@ -342,6 +348,8 @@ static struct scst_dev_type vdisk_blk_devtype = VDISK_BLK_TYPE; static struct scst_dev_type vdisk_null_devtype = VDISK_NULL_TYPE; static struct scst_dev_type vcdrom_devtype = VCDROM_TYPE; +static struct scst_vdisk_thr nullio_thr_data; + static char *vdisk_proc_help_string = "echo \"open|close NAME [FILE_NAME [BLOCK_SIZE] [WRITE_THROUGH " "READ_ONLY O_DIRECT NULLIO NV_CACHE BLOCKIO]]\" >/proc/scsi_tgt/" @@ -594,6 +602,8 @@ static struct scst_vdisk_thr *vdisk_init_thr_data( TRACE_ENTRY(); + EXTRACHECKS_BUG_ON(virt_dev->nullio); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) res = kmem_cache_alloc(vdisk_thr_cachep, atomic ? GFP_ATOMIC : GFP_KERNEL); @@ -609,9 +619,7 @@ static struct scst_vdisk_thr *vdisk_init_thr_data( goto out; } - res->virt_dev = virt_dev; - - if (!virt_dev->cdrom_empty && !virt_dev->nullio) { + if (!virt_dev->cdrom_empty) { res->fd = vdisk_open(virt_dev); if (IS_ERR(res->fd)) { PRINT_ERROR("filp_open(%s) returned an error %ld", @@ -732,16 +740,21 @@ static int vdisk_do_job(struct scst_cmd *cmd) cmd->host_status = DID_OK; cmd->driver_status = 0; - d = scst_find_thr_data(cmd->tgt_dev); - if (unlikely(d == NULL)) { - thr = vdisk_init_thr_data(cmd->tgt_dev, scst_cmd_atomic(cmd)); - if (thr == NULL) { - scst_set_busy(cmd); - goto out_compl; - } + if (!virt_dev->nullio) { + d = scst_find_thr_data(cmd->tgt_dev); + if (unlikely(d == NULL)) { + thr = vdisk_init_thr_data(cmd->tgt_dev, scst_cmd_atomic(cmd)); + if (thr == NULL) { + scst_set_busy(cmd); + goto out_compl; + } + scst_thr_data_get(&thr->hdr); + } else + thr = container_of(d, struct scst_vdisk_thr, hdr); + } else { + thr = &nullio_thr_data; scst_thr_data_get(&thr->hdr); - } else - thr = container_of(d, struct scst_vdisk_thr, hdr); + } switch (opcode) { case READ_6: @@ -1946,7 +1959,8 @@ static int vdisk_fsync(struct scst_vdisk_thr *thr, loff_t loff, loff_t len, struct scst_cmd *cmd) { int res = 0; - struct scst_vdisk_dev *virt_dev = thr->virt_dev; + struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; struct file *file = thr->fd; struct inode *inode; struct address_space *mapping; @@ -2057,6 +2071,9 @@ static void vdisk_exec_read(struct scst_cmd *cmd, TRACE_ENTRY(); + if (virt_dev->nullio) + goto out; + iv = vdisk_alloc_iv(cmd, thr); if (iv == NULL) goto out; @@ -2084,31 +2101,28 @@ static void vdisk_exec_read(struct scst_cmd *cmd, set_fs(get_ds()); TRACE_DBG("reading(iv_count %d, full_len %zd)", iv_count, full_len); - if (virt_dev->nullio) - err = full_len; - else { - /* SEEK */ - if (fd->f_op->llseek) - err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/); - else - err = default_llseek(fd, loff, 0/*SEEK_SET*/); - if (err != loff) { - PRINT_ERROR("lseek trouble %lld != %lld", - (long long unsigned int)err, - (long long unsigned int)loff); - scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); - goto out_set_fs; - } - /* READ */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - err = fd->f_op->readv(fd, iv, iv_count, &fd->f_pos); -#else - err = do_sync_readv_writev(fd, iv, iv_count, full_len, - &fd->f_pos, fd->f_op->aio_read); -#endif + /* SEEK */ + if (fd->f_op->llseek) + err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/); + else + err = default_llseek(fd, loff, 0/*SEEK_SET*/); + if (err != loff) { + PRINT_ERROR("lseek trouble %lld != %lld", + (long long unsigned int)err, + (long long unsigned int)loff); + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_hardw_error)); + goto out_set_fs; } + /* READ */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) + err = fd->f_op->readv(fd, iv, iv_count, &fd->f_pos); +#else + err = do_sync_readv_writev(fd, iv, iv_count, full_len, + &fd->f_pos, fd->f_op->aio_read); +#endif + if ((err < 0) || (err < full_len)) { PRINT_ERROR("readv() returned %lld from %zd", (long long unsigned int)err, @@ -2149,6 +2163,9 @@ static void vdisk_exec_write(struct scst_cmd *cmd, TRACE_ENTRY(); + if (virt_dev->nullio) + goto out; + iv = vdisk_alloc_iv(cmd, thr); if (iv == NULL) goto out; @@ -2178,32 +2195,27 @@ static void vdisk_exec_write(struct scst_cmd *cmd, restart: TRACE_DBG("writing(eiv_count %d, full_len %zd)", eiv_count, full_len); - if (virt_dev->nullio) - err = full_len; - else { - /* SEEK */ - if (fd->f_op->llseek) - err = fd->f_op->llseek(fd, loff, 0 /*SEEK_SET */); - else - err = default_llseek(fd, loff, 0 /*SEEK_SET */); - if (err != loff) { - PRINT_ERROR("lseek trouble %lld != %lld", - (long long unsigned int)err, - (long long unsigned int)loff); - scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); - goto out_set_fs; - } - - /* WRITE */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - err = fd->f_op->writev(fd, eiv, eiv_count, &fd->f_pos); -#else - err = do_sync_readv_writev(fd, iv, iv_count, full_len, - &fd->f_pos, fd->f_op->aio_write); -#endif + /* SEEK */ + if (fd->f_op->llseek) + err = fd->f_op->llseek(fd, loff, 0 /*SEEK_SET */); + else + err = default_llseek(fd, loff, 0 /*SEEK_SET */); + if (err != loff) { + PRINT_ERROR("lseek trouble %lld != %lld", + (long long unsigned int)err, + (long long unsigned int)loff); + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + goto out_set_fs; } + /* WRITE */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) + err = fd->f_op->writev(fd, eiv, eiv_count, &fd->f_pos); +#else + err = do_sync_readv_writev(fd, iv, iv_count, full_len, &fd->f_pos, + fd->f_op->aio_write); +#endif + if (err < 0) { PRINT_ERROR("write() returned %lld from %zd", (long long unsigned int)err, @@ -2318,7 +2330,8 @@ static void blockio_endio(struct bio *bio, int error) static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr, u64 lba_start, int write) { - struct scst_vdisk_dev *virt_dev = thr->virt_dev; + struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; struct block_device *bdev = thr->bdev; struct request_queue *q = bdev_get_queue(bdev); int length, max_nr_vecs = 0; @@ -3487,6 +3500,8 @@ static int __init init_scst_vdisk_driver(void) vdisk_file_devtype.threads_num = num_threads; vcdrom_devtype.threads_num = num_threads; + atomic_set(&nullio_thr_data.hdr.ref, 1); /* never destroy it */ + res = init_scst_vdisk(&vdisk_file_devtype); if (res != 0) goto out_free_slab;