1. Fixed bug - Task frame type setting.
[mirror/scst/.git] / scst / src / dev_handlers / scst_vdisk.c
1 /*
2  *  scst_vdisk.c
3  *
4  *  Copyright (C) 2004 - 2009 Vladislav Bolkhovitin <vst@vlnb.net>
5  *  Copyright (C) 2004 - 2005 Leonid Stoljar
6  *  Copyright (C) 2007 Ming Zhang <blackmagic02881 at gmail dot com>
7  *  Copyright (C) 2007 Ross Walker <rswwalker at hotmail dot com>
8  *  Copyright (C) 2007 - 2009 ID7 Ltd.
9  *
10  *  SCSI disk (type 0) and CDROM (type 5) dev handler using files
11  *  on file systems or block devices (VDISK)
12  *
13  *  This program is free software; you can redistribute it and/or
14  *  modify it under the terms of the GNU General Public License
15  *  as published by the Free Software Foundation, version 2
16  *  of the License.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  *  GNU General Public License for more details.
22  */
23
24 #include <linux/file.h>
25 #include <linux/fs.h>
26 #include <linux/string.h>
27 #include <linux/types.h>
28 #include <linux/unistd.h>
29 #include <linux/smp_lock.h>
30 #include <linux/spinlock.h>
31 #include <linux/init.h>
32 #include <linux/uio.h>
33 #include <linux/proc_fs.h>
34 #include <linux/list.h>
35 #include <linux/ctype.h>
36 #include <linux/writeback.h>
37 #include <linux/vmalloc.h>
38 #include <asm/atomic.h>
39 #include <linux/kthread.h>
40 #include <linux/sched.h>
41 #include <linux/version.h>
42 #include <asm/div64.h>
43
44 #define LOG_PREFIX                      "dev_vdisk"
45
46 #include "scst.h"
47
48 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
49
50 #define TRACE_ORDER     0x80000000
51
52 static struct scst_proc_log vdisk_proc_local_trace_tbl[] =
53 {
54     { TRACE_ORDER,              "order" },
55     { 0,                        NULL }
56 };
57 #define trace_log_tbl   vdisk_proc_local_trace_tbl
58
59 #endif
60
61 #include "scst_dev_handler.h"
62
63 /* 8 byte ASCII Vendor */
64 #define SCST_FIO_VENDOR                 "SCST_FIO"
65 #define SCST_BIO_VENDOR                 "SCST_BIO"
66 /* 4 byte ASCII Product Revision Level - left aligned */
67 #define SCST_FIO_REV                    " 102"
68
69 #define MAX_USN_LEN                     (20+1) /* For '\0' */
70
71 #define INQ_BUF_SZ                      128
72 #define EVPD                            0x01
73 #define CMDDT                           0x02
74
75 #define MSENSE_BUF_SZ                   256
76 #define DBD                             0x08    /* disable block descriptor */
77 #define WP                              0x80    /* write protect */
78 #define DPOFUA                          0x10    /* DPOFUA bit */
79 #define WCE                             0x04    /* write cache enable */
80
81 #define PF                              0x10    /* page format */
82 #define SP                              0x01    /* save pages */
83 #define PS                              0x80    /* parameter saveable */
84
85 #define BYTE                            8
86 #define DEF_DISK_BLOCKSIZE_SHIFT        9
87 #define DEF_DISK_BLOCKSIZE              (1 << DEF_DISK_BLOCKSIZE_SHIFT)
88 #define DEF_CDROM_BLOCKSIZE_SHIFT       11
89 #define DEF_CDROM_BLOCKSIZE             (1 << DEF_CDROM_BLOCKSIZE_SHIFT)
90 #define DEF_SECTORS                     56
91 #define DEF_HEADS                       255
92 #define LEN_MEM                         (32 * 1024)
93 #define VDISK_NAME                      "vdisk"
94 #define VCDROM_NAME                     "vcdrom"
95
96 #define VDISK_NULLIO_SIZE               (3LL*1024*1024*1024*1024/2)
97
98 #define DEF_TST                         SCST_CONTR_MODE_SEP_TASK_SETS
99 /*
100  * Since we can't control backstorage device's reordering, we have to always
101  * report unrestricted reordering.
102  */
103 #define DEF_QUEUE_ALG_WT        SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER
104 #define DEF_QUEUE_ALG           SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER
105 #define DEF_SWP                 0
106 #define DEF_TAS                 0
107
108 #define DEF_DSENSE              SCST_CONTR_MODE_FIXED_SENSE
109
110 #define VDISK_PROC_HELP         "help"
111
112 static unsigned int random_values[256] = {
113             9862592UL,  3744545211UL,  2348289082UL,  4036111983UL,
114           435574201UL,  3110343764UL,  2383055570UL,  1826499182UL,
115          4076766377UL,  1549935812UL,  3696752161UL,  1200276050UL,
116          3878162706UL,  1783530428UL,  2291072214UL,   125807985UL,
117          3407668966UL,   547437109UL,  3961389597UL,   969093968UL,
118            56006179UL,  2591023451UL,     1849465UL,  1614540336UL,
119          3699757935UL,   479961779UL,  3768703953UL,  2529621525UL,
120          4157893312UL,  3673555386UL,  4091110867UL,  2193909423UL,
121          2800464448UL,  3052113233UL,   450394455UL,  3424338713UL,
122          2113709130UL,  4082064373UL,  3708640918UL,  3841182218UL,
123          3141803315UL,  1032476030UL,  1166423150UL,  1169646901UL,
124          2686611738UL,   575517645UL,  2829331065UL,  1351103339UL,
125          2856560215UL,  2402488288UL,   867847666UL,     8524618UL,
126           704790297UL,  2228765657UL,   231508411UL,  1425523814UL,
127          2146764591UL,  1287631730UL,  4142687914UL,  3879884598UL,
128           729945311UL,   310596427UL,  2263511876UL,  1983091134UL,
129          3500916580UL,  1642490324UL,  3858376049UL,   695342182UL,
130           780528366UL,  1372613640UL,  1100993200UL,  1314818946UL,
131           572029783UL,  3775573540UL,   776262915UL,  2684520905UL,
132          1007252738UL,  3505856396UL,  1974886670UL,  3115856627UL,
133          4194842288UL,  2135793908UL,  3566210707UL,     7929775UL,
134          1321130213UL,  2627281746UL,  3587067247UL,  2025159890UL,
135          2587032000UL,  3098513342UL,  3289360258UL,   130594898UL,
136          2258149812UL,  2275857755UL,  3966929942UL,  1521739999UL,
137          4191192765UL,   958953550UL,  4153558347UL,  1011030335UL,
138           524382185UL,  4099757640UL,   498828115UL,  2396978754UL,
139           328688935UL,   826399828UL,  3174103611UL,  3921966365UL,
140          2187456284UL,  2631406787UL,  3930669674UL,  4282803915UL,
141          1776755417UL,   374959755UL,  2483763076UL,   844956392UL,
142          2209187588UL,  3647277868UL,   291047860UL,  3485867047UL,
143          2223103546UL,  2526736133UL,  3153407604UL,  3828961796UL,
144          3355731910UL,  2322269798UL,  2752144379UL,   519897942UL,
145          3430536488UL,  1801511593UL,  1953975728UL,  3286944283UL,
146          1511612621UL,  1050133852UL,   409321604UL,  1037601109UL,
147          3352316843UL,  4198371381UL,   617863284UL,   994672213UL,
148          1540735436UL,  2337363549UL,  1242368492UL,   665473059UL,
149          2330728163UL,  3443103219UL,  2291025133UL,  3420108120UL,
150          2663305280UL,  1608969839UL,  2278959931UL,  1389747794UL,
151          2226946970UL,  2131266900UL,  3856979144UL,  1894169043UL,
152          2692697628UL,  3797290626UL,  3248126844UL,  3922786277UL,
153           343705271UL,  3739749888UL,  2191310783UL,  2962488787UL,
154          4119364141UL,  1403351302UL,  2984008923UL,  3822407178UL,
155          1932139782UL,  2323869332UL,  2793574182UL,  1852626483UL,
156          2722460269UL,  1136097522UL,  1005121083UL,  1805201184UL,
157          2212824936UL,  2979547931UL,  4133075915UL,  2585731003UL,
158          2431626071UL,   134370235UL,  3763236829UL,  1171434827UL,
159          2251806994UL,  1289341038UL,  3616320525UL,   392218563UL,
160          1544502546UL,  2993937212UL,  1957503701UL,  3579140080UL,
161          4270846116UL,  2030149142UL,  1792286022UL,   366604999UL,
162          2625579499UL,   790898158UL,   770833822UL,   815540197UL,
163          2747711781UL,  3570468835UL,  3976195842UL,  1257621341UL,
164          1198342980UL,  1860626190UL,  3247856686UL,   351473955UL,
165           993440563UL,   340807146UL,  1041994520UL,  3573925241UL,
166           480246395UL,  2104806831UL,  1020782793UL,  3362132583UL,
167          2272911358UL,  3440096248UL,  2356596804UL,   259492703UL,
168          3899500740UL,   252071876UL,  2177024041UL,  4284810959UL,
169          2775999888UL,  2653420445UL,  2876046047UL,  1025771859UL,
170          1994475651UL,  3564987377UL,  4112956647UL,  1821511719UL,
171          3113447247UL,   455315102UL,  1585273189UL,  2311494568UL,
172           774051541UL,  1898115372UL,  2637499516UL,   247231365UL,
173          1475014417UL,   803585727UL,  3911097303UL,  1714292230UL,
174           476579326UL,  2496900974UL,  3397613314UL,   341202244UL,
175           807790202UL,  4221326173UL,   499979741UL,  1301488547UL,
176          1056807896UL,  3525009458UL,  1174811641UL,  3049738746UL,
177 };
178
179 struct scst_vdisk_dev {
180         uint32_t block_size;
181         uint64_t nblocks;
182         int block_shift;
183         loff_t file_size;       /* in bytes */
184
185         /*
186          * This lock can be taken on both SIRQ and thread context, but in
187          * all cases for each particular instance it's taken consistenly either
188          * on SIRQ or thread context. Mix of them is impossible.
189          */
190         spinlock_t flags_lock;
191
192         /*
193          * Below flags are protected by flags_lock or suspended activity
194          * with scst_vdisk_mutex.
195          */
196         unsigned int rd_only_flag:1;
197         unsigned int wt_flag:1;
198         unsigned int nv_cache:1;
199         unsigned int o_direct_flag:1;
200         unsigned int media_changed:1;
201         unsigned int prevent_allow_medium_removal:1;
202         unsigned int nullio:1;
203         unsigned int blockio:1;
204         unsigned int cdrom_empty:1;
205         unsigned int removable:1;
206         int virt_id;
207         char name[16+1];        /* Name of virtual device,
208                                    must be <= SCSI Model + 1 */
209         char *file_name;        /* File name */
210         char usn[MAX_USN_LEN];
211         struct scst_device *dev;
212         struct list_head vdisk_dev_list_entry;
213 };
214
215 struct scst_vdisk_tgt_dev {
216         /*
217          * Used without locking since SCST core ensures that only commands
218          * with the same ORDERED type per tgt_dev can be processed
219          * simultaneously.
220          */
221         enum scst_cmd_queue_type last_write_cmd_queue_type;
222 };
223
224 struct scst_vdisk_thr {
225         struct scst_thr_data_hdr hdr;
226         struct file *fd;
227         struct block_device *bdev;
228         struct iovec *iv;
229         int iv_count;
230 };
231
232 static struct kmem_cache *vdisk_thr_cachep;
233 static struct kmem_cache *blockio_work_cachep;
234
235 #define DEF_NUM_THREADS         5
236 static int num_threads = DEF_NUM_THREADS;
237
238 module_param_named(num_threads, num_threads, int, 0);
239 MODULE_PARM_DESC(num_threads, "vdisk threads count");
240
241 static int vdisk_attach(struct scst_device *dev);
242 static void vdisk_detach(struct scst_device *dev);
243 static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev);
244 static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev);
245 static int vdisk_parse(struct scst_cmd *);
246 static int vdisk_do_job(struct scst_cmd *cmd);
247 static int vcdrom_parse(struct scst_cmd *);
248 static int vcdrom_exec(struct scst_cmd *cmd);
249 static void vdisk_exec_read(struct scst_cmd *cmd,
250         struct scst_vdisk_thr *thr, loff_t loff);
251 static void vdisk_exec_write(struct scst_cmd *cmd,
252         struct scst_vdisk_thr *thr, loff_t loff);
253 static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
254         u64 lba_start, int write);
255 static void vdisk_exec_verify(struct scst_cmd *cmd,
256         struct scst_vdisk_thr *thr, loff_t loff);
257 static void vdisk_exec_read_capacity(struct scst_cmd *cmd);
258 static void vdisk_exec_read_capacity16(struct scst_cmd *cmd);
259 static void vdisk_exec_inquiry(struct scst_cmd *cmd);
260 static void vdisk_exec_request_sense(struct scst_cmd *cmd);
261 static void vdisk_exec_mode_sense(struct scst_cmd *cmd);
262 static void vdisk_exec_mode_select(struct scst_cmd *cmd);
263 static void vdisk_exec_log(struct scst_cmd *cmd);
264 static void vdisk_exec_read_toc(struct scst_cmd *cmd);
265 static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd);
266 static int vdisk_fsync(struct scst_vdisk_thr *thr,
267         loff_t loff, loff_t len, struct scst_cmd *cmd);
268 static int vdisk_read_proc(struct seq_file *seq,
269         struct scst_dev_type *dev_type);
270 static int vdisk_write_proc(char *buffer, char **start, off_t offset,
271         int length, int *eof, struct scst_dev_type *dev_type);
272 static int vcdrom_read_proc(struct seq_file *seq,
273         struct scst_dev_type *dev_type);
274 static int vcdrom_write_proc(char *buffer, char **start, off_t offset,
275         int length, int *eof, struct scst_dev_type *dev_type);
276 static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
277         struct scst_tgt_dev *tgt_dev);
278
279 /*
280  * Name of FILEIO vdisk can't be changed from "vdisk", since it is the name
281  * of the corresponding /proc/scsi_tgt entry, hence a part of user space ABI.
282  */
283
284 #define VDISK_TYPE {                                    \
285         .name =                 VDISK_NAME,             \
286         .type =                 TYPE_DISK,              \
287         .exec_sync =            1,                      \
288         .threads_num =          -1,                     \
289         .parse_atomic =         1,                      \
290         .exec_atomic =          0,                      \
291         .dev_done_atomic =      1,                      \
292         .attach =               vdisk_attach,           \
293         .detach =               vdisk_detach,           \
294         .attach_tgt =           vdisk_attach_tgt,       \
295         .detach_tgt =           vdisk_detach_tgt,       \
296         .parse =                vdisk_parse,            \
297         .exec =                 vdisk_do_job,           \
298         .read_proc =            vdisk_read_proc,        \
299         .write_proc =           vdisk_write_proc,       \
300         .task_mgmt_fn =         vdisk_task_mgmt_fn,     \
301 }
302
303 #define VDISK_BLK_TYPE {                                \
304         .name =                 VDISK_NAME "_blk",      \
305         .type =                 TYPE_DISK,              \
306         .threads_num =          0,                      \
307         .parse_atomic =         1,                      \
308         .exec_atomic =          0,                      \
309         .dev_done_atomic =      1,                      \
310         .no_proc =              1,                      \
311         .attach =               vdisk_attach,           \
312         .detach =               vdisk_detach,           \
313         .attach_tgt =           vdisk_attach_tgt,       \
314         .detach_tgt =           vdisk_detach_tgt,       \
315         .parse =                vdisk_parse,            \
316         .exec =                 vdisk_do_job,           \
317         .task_mgmt_fn =         vdisk_task_mgmt_fn,     \
318 }
319
320 #define VDISK_NULL_TYPE {                               \
321         .name =                 VDISK_NAME "_null",     \
322         .type =                 TYPE_DISK,              \
323         .threads_num =          0,                      \
324         .parse_atomic =         1,                      \
325         .exec_atomic =          1,                      \
326         .dev_done_atomic =      1,                      \
327         .no_proc =              1,                      \
328         .attach =               vdisk_attach,           \
329         .detach =               vdisk_detach,           \
330         .attach_tgt =           vdisk_attach_tgt,       \
331         .detach_tgt =           vdisk_detach_tgt,       \
332         .parse =                vdisk_parse,            \
333         .exec =                 vdisk_do_job,           \
334         .task_mgmt_fn =         vdisk_task_mgmt_fn,     \
335 }
336
337 #define VCDROM_TYPE {                                   \
338         .name =                 VCDROM_NAME,            \
339         .type =                 TYPE_ROM,               \
340         .exec_sync =            1,                      \
341         .threads_num =          -1,                     \
342         .parse_atomic =         1,                      \
343         .exec_atomic =          0,                      \
344         .dev_done_atomic =      1,                      \
345         .attach =               vdisk_attach,           \
346         .detach =               vdisk_detach,           \
347         .attach_tgt =           vdisk_attach_tgt,       \
348         .detach_tgt =           vdisk_detach_tgt,       \
349         .parse =                vcdrom_parse,           \
350         .exec =                 vcdrom_exec,            \
351         .read_proc =            vcdrom_read_proc,       \
352         .write_proc =           vcdrom_write_proc,      \
353         .task_mgmt_fn =         vdisk_task_mgmt_fn,     \
354 }
355
356 static DEFINE_MUTEX(scst_vdisk_mutex);
357 static LIST_HEAD(vdisk_dev_list);
358 static LIST_HEAD(vcdrom_dev_list);
359
360 static struct scst_dev_type vdisk_file_devtype = VDISK_TYPE;
361 static struct scst_dev_type vdisk_blk_devtype = VDISK_BLK_TYPE;
362 static struct scst_dev_type vdisk_null_devtype = VDISK_NULL_TYPE;
363 static struct scst_dev_type vcdrom_devtype = VCDROM_TYPE;
364
365 static struct scst_vdisk_thr nullio_thr_data;
366
367 static char *vdisk_proc_help_string =
368         "echo \"open|close|resync_size NAME [FILE_NAME [BLOCK_SIZE] "
369         "[WRITE_THROUGH READ_ONLY O_DIRECT NULLIO NV_CACHE BLOCKIO]]\" "
370         ">/proc/scsi_tgt/" VDISK_NAME "/" VDISK_NAME "\n";
371
372 static char *vcdrom_proc_help_string =
373         "echo \"open|change|close NAME [FILE_NAME]\" "
374         ">/proc/scsi_tgt/" VCDROM_NAME "/" VCDROM_NAME "\n";
375
376 static int scst_vdisk_ID;
377
378 module_param_named(scst_vdisk_ID, scst_vdisk_ID, int, 0);
379 MODULE_PARM_DESC(scst_vdisk_ID, "SCST virtual disk subsystem ID");
380
381
382 /**************************************************************
383  *  Function:  vdisk_open
384  *
385  *  Argument:
386  *
387  *  Returns :  fd, use IS_ERR(fd) to get error status
388  *
389  *  Description:
390  *************************************************************/
391 static struct file *vdisk_open(const struct scst_vdisk_dev *virt_dev)
392 {
393         int open_flags = 0;
394         struct file *fd;
395
396         TRACE_ENTRY();
397
398         if (virt_dev->rd_only_flag)
399                 open_flags |= O_RDONLY;
400         else
401                 open_flags |= O_RDWR;
402         if (virt_dev->o_direct_flag)
403                 open_flags |= O_DIRECT;
404         if (virt_dev->wt_flag && !virt_dev->nv_cache)
405                 open_flags |= O_SYNC;
406         TRACE_DBG("Opening file %s, flags 0x%x",
407                   virt_dev->file_name, open_flags);
408         fd = filp_open(virt_dev->file_name, O_LARGEFILE | open_flags, 0600);
409
410         TRACE_EXIT();
411         return fd;
412 }
413
414 /**************************************************************
415  *  Function:  vdisk_get_file_size
416  *
417  *  Argument:
418  *
419  *  Returns :  0 on success and file size in *file_size,
420  *             error code otherwise
421  *
422  *  Description:
423  *************************************************************/
424 static int vdisk_get_check_file_size(const char *file_name, bool blockio,
425         loff_t *file_size)
426 {
427         struct inode *inode;
428         int res = 0;
429         struct file *fd;
430
431         TRACE_ENTRY();
432
433         *file_size = 0;
434
435         fd = filp_open(file_name, O_LARGEFILE | O_RDONLY, 0600);
436         if (IS_ERR(fd)) {
437                 res = PTR_ERR(fd);
438                 PRINT_ERROR("filp_open(%s) returned error %d", file_name, res);
439                 goto out;
440         }
441
442 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
443         if ((fd->f_op == NULL) ||
444             (fd->f_op->readv == NULL) ||
445             (fd->f_op->writev == NULL)) {
446 #else
447         if ((fd->f_op == NULL) ||
448             (fd->f_op->aio_read == NULL) ||
449             (fd->f_op->aio_write == NULL)) {
450 #endif
451                 PRINT_ERROR("%s", "Wrong f_op or FS doesn't have required "
452                         "capabilities");
453                 res = -EINVAL;
454                 goto out_close;
455         }
456
457         inode = fd->f_dentry->d_inode;
458
459         if (blockio && !S_ISBLK(inode->i_mode)) {
460                 PRINT_ERROR("File %s is NOT a block device", file_name);
461                 res = -EINVAL;
462                 goto out_close;
463         }
464
465         if (S_ISREG(inode->i_mode))
466                 /* Nothing to do*/;
467         else if (S_ISBLK(inode->i_mode))
468                 inode = inode->i_bdev->bd_inode;
469         else {
470                 res = -EINVAL;
471                 goto out_close;
472         }
473
474         *file_size = inode->i_size;
475
476 out_close:
477         filp_close(fd, NULL);
478
479 out:
480         TRACE_EXIT_RES(res);
481         return res;
482 }
483
484 /**************************************************************
485  *  Function:  vdisk_attach
486  *
487  *  Argument:
488  *
489  *  Returns :  1 if attached, error code otherwise
490  *
491  *  Description:
492  *************************************************************/
493 static int vdisk_attach(struct scst_device *dev)
494 {
495         int res = 0;
496         loff_t err;
497         struct scst_vdisk_dev *virt_dev = NULL, *vv;
498         struct list_head *vd;
499
500         TRACE_ENTRY();
501
502         TRACE_DBG("virt_id %d (%s)", dev->virt_id, dev->virt_name);
503
504         if (dev->virt_id == 0) {
505                 PRINT_ERROR("%s", "Not a virtual device");
506                 res = -EINVAL;
507                 goto out;
508         }
509
510         vd = (dev->type == TYPE_DISK) ?
511                                 &vdisk_dev_list :
512                                 &vcdrom_dev_list;
513
514         /*
515          * scst_vdisk_mutex must be already taken before
516          * scst_register_virtual_device()
517          */
518         list_for_each_entry(vv, vd, vdisk_dev_list_entry) {
519                 if (strcmp(vv->name, dev->virt_name) == 0) {
520                         virt_dev = vv;
521                         break;
522                 }
523         }
524
525         if (virt_dev == NULL) {
526                 PRINT_ERROR("Device %s not found", dev->virt_name);
527                 res = -EINVAL;
528                 goto out;
529         }
530
531         virt_dev->dev = dev;
532
533         if (dev->type == TYPE_ROM)
534                 virt_dev->rd_only_flag = 1;
535
536         if (!virt_dev->cdrom_empty) {
537                 if (virt_dev->nullio)
538                         err = VDISK_NULLIO_SIZE;
539                 else {
540                         res = vdisk_get_check_file_size(virt_dev->file_name,
541                                 virt_dev->blockio, &err);
542                         if (res != 0)
543                                 goto out;
544                 }
545                 virt_dev->file_size = err;
546                 TRACE_DBG("size of file: %lld", (long long unsigned int)err);
547         } else
548                 virt_dev->file_size = 0;
549
550         if (dev->type == TYPE_DISK) {
551                 virt_dev->nblocks =
552                         virt_dev->file_size >> virt_dev->block_shift;
553         } else {
554                 virt_dev->block_size = DEF_CDROM_BLOCKSIZE;
555                 virt_dev->block_shift = DEF_CDROM_BLOCKSIZE_SHIFT;
556                 virt_dev->nblocks =
557                         virt_dev->file_size >> DEF_CDROM_BLOCKSIZE_SHIFT;
558         }
559
560         if (!virt_dev->cdrom_empty) {
561                 PRINT_INFO("Attached SCSI target virtual %s %s "
562                       "(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld,"
563                       " cyln=%lld%s)",
564                       (dev->type == TYPE_DISK) ? "disk" : "cdrom",
565                       virt_dev->name, virt_dev->file_name,
566                       virt_dev->file_size >> 20, virt_dev->block_size,
567                       (long long unsigned int)virt_dev->nblocks,
568                       (long long unsigned int)virt_dev->nblocks/64/32,
569                       virt_dev->nblocks < 64*32
570                       ? " !WARNING! cyln less than 1" : "");
571         } else {
572                 PRINT_INFO("Attached empty SCSI target virtual cdrom %s",
573                         virt_dev->name);
574         }
575
576         dev->dh_priv = virt_dev;
577
578         dev->tst = DEF_TST;
579         dev->d_sense = DEF_DSENSE;
580         if (virt_dev->wt_flag && !virt_dev->nv_cache)
581                 dev->queue_alg = DEF_QUEUE_ALG_WT;
582         else
583                 dev->queue_alg = DEF_QUEUE_ALG;
584         dev->swp = DEF_SWP;
585         dev->tas = DEF_TAS;
586
587 out:
588         TRACE_EXIT();
589         return res;
590 }
591
592 /************************************************************
593  *  Function:  vdisk_detach
594  *
595  *  Argument:
596  *
597  *  Returns :  None
598  *
599  *  Description:  Called to detach this device type driver
600  ************************************************************/
601 static void vdisk_detach(struct scst_device *dev)
602 {
603         struct scst_vdisk_dev *virt_dev =
604             (struct scst_vdisk_dev *)dev->dh_priv;
605
606         TRACE_ENTRY();
607
608         TRACE_DBG("virt_id %d", dev->virt_id);
609
610         PRINT_INFO("Detached SCSI target virtual device %s (\"%s\")",
611                       virt_dev->name, virt_dev->file_name);
612
613         /* virt_dev will be freed by the caller */
614         dev->dh_priv = NULL;
615
616         TRACE_EXIT();
617         return;
618 }
619
620 static void vdisk_free_thr_data(struct scst_thr_data_hdr *d)
621 {
622         struct scst_vdisk_thr *thr =
623                 container_of(d, struct scst_vdisk_thr, hdr);
624
625         TRACE_ENTRY();
626
627         if (thr->fd)
628                 filp_close(thr->fd, NULL);
629
630         kfree(thr->iv);
631
632         kmem_cache_free(vdisk_thr_cachep, thr);
633
634         TRACE_EXIT();
635         return;
636 }
637
638 static struct scst_vdisk_thr *vdisk_init_thr_data(
639         struct scst_tgt_dev *tgt_dev)
640 {
641         struct scst_vdisk_thr *res;
642         struct scst_vdisk_dev *virt_dev =
643             (struct scst_vdisk_dev *)tgt_dev->dev->dh_priv;
644
645         TRACE_ENTRY();
646
647         EXTRACHECKS_BUG_ON(virt_dev->nullio);
648
649 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
650         res = kmem_cache_alloc(vdisk_thr_cachep, GFP_KERNEL);
651         if (res != NULL)
652                 memset(res, 0, sizeof(*res));
653 #else
654         res = kmem_cache_zalloc(vdisk_thr_cachep, GFP_KERNEL);
655 #endif
656         if (res == NULL) {
657                 TRACE(TRACE_OUT_OF_MEM, "%s", "Unable to allocate struct "
658                         "scst_vdisk_thr");
659                 goto out;
660         }
661
662         if (!virt_dev->cdrom_empty) {
663                 res->fd = vdisk_open(virt_dev);
664                 if (IS_ERR(res->fd)) {
665                         PRINT_ERROR("filp_open(%s) returned an error %ld",
666                                 virt_dev->file_name, PTR_ERR(res->fd));
667                         goto out_free;
668                 }
669                 if (virt_dev->blockio)
670                         res->bdev = res->fd->f_dentry->d_inode->i_bdev;
671                 else
672                         res->bdev = NULL;
673         } else
674                 res->fd = NULL;
675
676         scst_add_thr_data(tgt_dev, &res->hdr, vdisk_free_thr_data);
677
678 out:
679         TRACE_EXIT_HRES((unsigned long)res);
680         return res;
681
682 out_free:
683         kmem_cache_free(vdisk_thr_cachep, res);
684         res = NULL;
685         goto out;
686 }
687
688 static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev)
689 {
690         struct scst_vdisk_tgt_dev *ftgt_dev;
691         int res = 0;
692
693         TRACE_ENTRY();
694
695         ftgt_dev = kzalloc(sizeof(*ftgt_dev), GFP_KERNEL);
696         if (ftgt_dev == NULL) {
697                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of per-session "
698                         "virtual device failed");
699                 res = -ENOMEM;
700                 goto out;
701         }
702
703         tgt_dev->dh_priv = ftgt_dev;
704
705 out:
706         TRACE_EXIT_RES(res);
707         return res;
708 }
709
710 static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev)
711 {
712         struct scst_vdisk_tgt_dev *ftgt_dev =
713                 (struct scst_vdisk_tgt_dev *)tgt_dev->dh_priv;
714
715         TRACE_ENTRY();
716
717         scst_del_all_thr_data(tgt_dev);
718
719         kfree(ftgt_dev);
720         tgt_dev->dh_priv = NULL;
721
722         TRACE_EXIT();
723         return;
724 }
725
726 static inline int vdisk_sync_queue_type(enum scst_cmd_queue_type qt)
727 {
728         switch (qt) {
729         case SCST_CMD_QUEUE_ORDERED:
730         case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
731                 return 1;
732         default:
733                 return 0;
734         }
735 }
736
737 static inline int vdisk_need_pre_sync(enum scst_cmd_queue_type cur,
738         enum scst_cmd_queue_type last)
739 {
740         if (vdisk_sync_queue_type(cur))
741                 if (!vdisk_sync_queue_type(last))
742                         return 1;
743         return 0;
744 }
745
746 static int vdisk_do_job(struct scst_cmd *cmd)
747 {
748         int rc, res;
749         uint64_t lba_start = 0;
750         loff_t data_len = 0;
751         uint8_t *cdb = cmd->cdb;
752         int opcode = cdb[0];
753         loff_t loff;
754         struct scst_device *dev = cmd->dev;
755         struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
756         struct scst_vdisk_dev *virt_dev =
757                 (struct scst_vdisk_dev *)dev->dh_priv;
758         struct scst_thr_data_hdr *d;
759         struct scst_vdisk_thr *thr = NULL;
760         int fua = 0;
761
762         TRACE_ENTRY();
763
764         switch (cmd->queue_type) {
765         case SCST_CMD_QUEUE_ORDERED:
766                 TRACE(TRACE_ORDER, "ORDERED cmd %p", cmd);
767                 break;
768         case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
769                 TRACE(TRACE_ORDER, "HQ cmd %p", cmd);
770                 break;
771         default:
772                 break;
773         }
774
775         rc = scst_check_local_events(cmd);
776         if (unlikely(rc != 0))
777                 goto out_done;
778
779         cmd->status = 0;
780         cmd->msg_status = 0;
781         cmd->host_status = DID_OK;
782         cmd->driver_status = 0;
783
784         if (!virt_dev->nullio) {
785                 d = scst_find_thr_data(tgt_dev);
786                 if (unlikely(d == NULL)) {
787                         thr = vdisk_init_thr_data(tgt_dev);
788                         if (thr == NULL) {
789                                 scst_set_busy(cmd);
790                                 goto out_compl;
791                         }
792                         scst_thr_data_get(&thr->hdr);
793                 } else
794                         thr = container_of(d, struct scst_vdisk_thr, hdr);
795         } else {
796                 thr = &nullio_thr_data;
797                 scst_thr_data_get(&thr->hdr);
798         }
799
800         switch (opcode) {
801         case READ_6:
802         case WRITE_6:
803         case VERIFY_6:
804                 lba_start = (((cdb[1] & 0x1f) << (BYTE * 2)) +
805                              (cdb[2] << (BYTE * 1)) +
806                              (cdb[3] << (BYTE * 0)));
807                 data_len = cmd->bufflen;
808                 break;
809         case READ_10:
810         case READ_12:
811         case WRITE_10:
812         case WRITE_12:
813         case VERIFY:
814         case WRITE_VERIFY:
815         case WRITE_VERIFY_12:
816         case VERIFY_12:
817                 lba_start |= ((u64)cdb[2]) << 24;
818                 lba_start |= ((u64)cdb[3]) << 16;
819                 lba_start |= ((u64)cdb[4]) << 8;
820                 lba_start |= ((u64)cdb[5]);
821                 data_len = cmd->bufflen;
822                 break;
823         case READ_16:
824         case WRITE_16:
825         case WRITE_VERIFY_16:
826         case VERIFY_16:
827                 lba_start |= ((u64)cdb[2]) << 56;
828                 lba_start |= ((u64)cdb[3]) << 48;
829                 lba_start |= ((u64)cdb[4]) << 40;
830                 lba_start |= ((u64)cdb[5]) << 32;
831                 lba_start |= ((u64)cdb[6]) << 24;
832                 lba_start |= ((u64)cdb[7]) << 16;
833                 lba_start |= ((u64)cdb[8]) << 8;
834                 lba_start |= ((u64)cdb[9]);
835                 data_len = cmd->bufflen;
836                 break;
837         case SYNCHRONIZE_CACHE:
838                 lba_start |= ((u64)cdb[2]) << 24;
839                 lba_start |= ((u64)cdb[3]) << 16;
840                 lba_start |= ((u64)cdb[4]) << 8;
841                 lba_start |= ((u64)cdb[5]);
842                 data_len = ((cdb[7] << (BYTE * 1)) + (cdb[8] << (BYTE * 0)))
843                                 << virt_dev->block_shift;
844                 if (data_len == 0)
845                         data_len = virt_dev->file_size -
846                                 ((loff_t)lba_start << virt_dev->block_shift);
847                 break;
848         }
849
850         loff = (loff_t)lba_start << virt_dev->block_shift;
851         TRACE_DBG("cmd %p, lba_start %lld, loff %lld, data_len %lld", cmd,
852                   (long long unsigned int)lba_start,
853                   (long long unsigned int)loff,
854                   (long long unsigned int)data_len);
855         if (unlikely(loff < 0) || unlikely(data_len < 0) ||
856             unlikely((loff + data_len) > virt_dev->file_size)) {
857                 PRINT_INFO("Access beyond the end of the device "
858                         "(%lld of %lld, len %lld)",
859                            (long long unsigned int)loff,
860                            (long long unsigned int)virt_dev->file_size,
861                            (long long unsigned int)data_len);
862                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
863                                         scst_sense_block_out_range_error));
864                 goto out_compl;
865         }
866
867         switch (opcode) {
868         case WRITE_10:
869         case WRITE_12:
870         case WRITE_16:
871                 fua = (cdb[1] & 0x8);
872                 if (fua) {
873                         TRACE(TRACE_ORDER, "FUA: loff=%lld, "
874                                 "data_len=%lld", (long long unsigned int)loff,
875                                 (long long unsigned int)data_len);
876                 }
877                 break;
878         }
879
880         switch (opcode) {
881         case READ_6:
882         case READ_10:
883         case READ_12:
884         case READ_16:
885                 if (virt_dev->blockio) {
886                         blockio_exec_rw(cmd, thr, lba_start, 0);
887                         goto out_thr;
888                 } else
889                         vdisk_exec_read(cmd, thr, loff);
890                 break;
891         case WRITE_6:
892         case WRITE_10:
893         case WRITE_12:
894         case WRITE_16:
895                 if (likely(!virt_dev->rd_only_flag)) {
896                         int do_fsync = vdisk_sync_queue_type(cmd->queue_type);
897                         struct scst_vdisk_tgt_dev *ftgt_dev =
898                                 (struct scst_vdisk_tgt_dev *)
899                                         tgt_dev->dh_priv;
900                         enum scst_cmd_queue_type last_queue_type =
901                                 ftgt_dev->last_write_cmd_queue_type;
902                         ftgt_dev->last_write_cmd_queue_type = cmd->queue_type;
903                         if (vdisk_need_pre_sync(cmd->queue_type,
904                                                 last_queue_type)) {
905                                 TRACE(TRACE_ORDER, "ORDERED "
906                                       "WRITE(%d): loff=%lld, data_len=%lld",
907                                       cmd->queue_type,
908                                       (long long unsigned int)loff,
909                                       (long long unsigned int)data_len);
910                                 do_fsync = 1;
911                                 if (vdisk_fsync(thr, 0, 0, cmd) != 0)
912                                         goto out_compl;
913                         }
914                         if (virt_dev->blockio) {
915                                 blockio_exec_rw(cmd, thr, lba_start, 1);
916                                 goto out_thr;
917                         } else
918                                 vdisk_exec_write(cmd, thr, loff);
919                         /* O_SYNC flag is used for WT devices */
920                         if (do_fsync || fua)
921                                 vdisk_fsync(thr, loff, data_len, cmd);
922                 } else {
923                         PRINT_WARNING("Attempt of write access to read-only "
924                                 "device %s: initiator %s, op %x",
925                                 virt_dev->name, cmd->sess->initiator_name,
926                                 cmd->cdb[0]);
927                         scst_set_cmd_error(cmd,
928                                    SCST_LOAD_SENSE(scst_sense_data_protect));
929                 }
930                 break;
931         case WRITE_VERIFY:
932         case WRITE_VERIFY_12:
933         case WRITE_VERIFY_16:
934                 if (likely(!virt_dev->rd_only_flag)) {
935                         int do_fsync = vdisk_sync_queue_type(cmd->queue_type);
936                         struct scst_vdisk_tgt_dev *ftgt_dev =
937                                 (struct scst_vdisk_tgt_dev *)
938                                         tgt_dev->dh_priv;
939                         enum scst_cmd_queue_type last_queue_type =
940                                 ftgt_dev->last_write_cmd_queue_type;
941                         ftgt_dev->last_write_cmd_queue_type = cmd->queue_type;
942                         if (vdisk_need_pre_sync(cmd->queue_type,
943                                                 last_queue_type)) {
944                                 TRACE(TRACE_ORDER, "ORDERED "
945                                       "WRITE_VERIFY(%d): loff=%lld,"
946                                       " data_len=%lld", cmd->queue_type,
947                                       (long long unsigned int)loff,
948                                       (long long unsigned int)data_len);
949                                 do_fsync = 1;
950                                 if (vdisk_fsync(thr, 0, 0, cmd) != 0)
951                                         goto out_compl;
952                         }
953                         /* ToDo: BLOCKIO VERIFY */
954                         vdisk_exec_write(cmd, thr, loff);
955                         /* O_SYNC flag is used for WT devices */
956                         if (scsi_status_is_good(cmd->status))
957                                 vdisk_exec_verify(cmd, thr, loff);
958                         else if (do_fsync)
959                                 vdisk_fsync(thr, loff, data_len, cmd);
960                 } else {
961                         PRINT_WARNING("Attempt of write access to read-only "
962                                 "device %s: initiator %s, op %x",
963                                 virt_dev->name, cmd->sess->initiator_name,
964                                 cmd->cdb[0]);
965                         scst_set_cmd_error(cmd,
966                                 SCST_LOAD_SENSE(scst_sense_data_protect));
967                 }
968                 break;
969         case SYNCHRONIZE_CACHE:
970         {
971                 int immed = cdb[1] & 0x2;
972                 TRACE(TRACE_ORDER, "SYNCHRONIZE_CACHE: "
973                         "loff=%lld, data_len=%lld, immed=%d",
974                         (long long unsigned int)loff,
975                         (long long unsigned int)data_len, immed);
976                 if (immed) {
977                         scst_cmd_get(cmd);
978                         cmd->completed = 1;
979                         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT,
980                                 SCST_CONTEXT_SAME);
981                         vdisk_fsync(thr, loff, data_len, NULL);
982                         /* ToDo: vdisk_fsync() error processing */
983                         scst_cmd_put(cmd);
984                         goto out_thr;
985                 } else {
986                         vdisk_fsync(thr, loff, data_len, cmd);
987                         break;
988                 }
989         }
990         case VERIFY_6:
991         case VERIFY:
992         case VERIFY_12:
993         case VERIFY_16:
994                 vdisk_exec_verify(cmd, thr, loff);
995                 break;
996         case MODE_SENSE:
997         case MODE_SENSE_10:
998                 vdisk_exec_mode_sense(cmd);
999                 break;
1000         case MODE_SELECT:
1001         case MODE_SELECT_10:
1002                 vdisk_exec_mode_select(cmd);
1003                 break;
1004         case LOG_SELECT:
1005         case LOG_SENSE:
1006                 vdisk_exec_log(cmd);
1007                 break;
1008         case ALLOW_MEDIUM_REMOVAL:
1009                 vdisk_exec_prevent_allow_medium_removal(cmd);
1010                 break;
1011         case READ_TOC:
1012                 vdisk_exec_read_toc(cmd);
1013                 break;
1014         case START_STOP:
1015                 vdisk_fsync(thr, 0, virt_dev->file_size, cmd);
1016                 break;
1017         case RESERVE:
1018         case RESERVE_10:
1019         case RELEASE:
1020         case RELEASE_10:
1021         case TEST_UNIT_READY:
1022                 break;
1023         case INQUIRY:
1024                 vdisk_exec_inquiry(cmd);
1025                 break;
1026         case REQUEST_SENSE:
1027                 vdisk_exec_request_sense(cmd);
1028                 break;
1029         case READ_CAPACITY:
1030                 vdisk_exec_read_capacity(cmd);
1031                 break;
1032         case SERVICE_ACTION_IN:
1033                 if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
1034                         vdisk_exec_read_capacity16(cmd);
1035                         break;
1036                 }
1037                 /* else go through */
1038         case REPORT_LUNS:
1039         default:
1040                 TRACE_DBG("Invalid opcode %d", opcode);
1041                 scst_set_cmd_error(cmd,
1042                     SCST_LOAD_SENSE(scst_sense_invalid_opcode));
1043         }
1044
1045 out_compl:
1046         cmd->completed = 1;
1047
1048 out_done:
1049         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
1050
1051 out_thr:
1052         if (likely(thr != NULL))
1053                 scst_thr_data_put(&thr->hdr);
1054
1055         res = SCST_EXEC_COMPLETED;
1056
1057         TRACE_EXIT_RES(res);
1058         return res;
1059 }
1060
1061 static int vdisk_get_block_shift(struct scst_cmd *cmd)
1062 {
1063         struct scst_vdisk_dev *virt_dev =
1064             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1065         return virt_dev->block_shift;
1066 }
1067
1068 /********************************************************************
1069  *  Function:  vdisk_parse
1070  *
1071  *  Argument:
1072  *
1073  *  Returns :  The state of the command
1074  *
1075  *  Description:  This does the parsing of the command
1076  *
1077  *  Note:  Not all states are allowed on return
1078  ********************************************************************/
1079 static int vdisk_parse(struct scst_cmd *cmd)
1080 {
1081         scst_sbc_generic_parse(cmd, vdisk_get_block_shift);
1082         return SCST_CMD_STATE_DEFAULT;
1083 }
1084
1085 /********************************************************************
1086  *  Function:  vcdrom_parse
1087  *
1088  *  Argument:
1089  *
1090  *  Returns :  The state of the command
1091  *
1092  *  Description:  This does the parsing of the command
1093  *
1094  *  Note:  Not all states are allowed on return
1095  ********************************************************************/
1096 static int vcdrom_parse(struct scst_cmd *cmd)
1097 {
1098         scst_cdrom_generic_parse(cmd, vdisk_get_block_shift);
1099         return SCST_CMD_STATE_DEFAULT;
1100 }
1101
1102 /********************************************************************
1103  *  Function:  vcdrom_exec
1104  *
1105  *  Argument:
1106  *
1107  *  Returns :
1108  *
1109  *  Description:
1110  ********************************************************************/
1111 static int vcdrom_exec(struct scst_cmd *cmd)
1112 {
1113         int res = SCST_EXEC_COMPLETED;
1114         int opcode = cmd->cdb[0];
1115         struct scst_vdisk_dev *virt_dev =
1116             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1117
1118         TRACE_ENTRY();
1119
1120         cmd->status = 0;
1121         cmd->msg_status = 0;
1122         cmd->host_status = DID_OK;
1123         cmd->driver_status = 0;
1124
1125         if (virt_dev->cdrom_empty && (opcode != INQUIRY)) {
1126                 TRACE_DBG("%s", "CDROM empty");
1127                 scst_set_cmd_error(cmd,
1128                         SCST_LOAD_SENSE(scst_sense_not_ready));
1129                 goto out_done;
1130         }
1131
1132         if (virt_dev->media_changed && (cmd->cdb[0] != INQUIRY) &&
1133             (cmd->cdb[0] != REQUEST_SENSE) && (cmd->cdb[0] != REPORT_LUNS)) {
1134                 spin_lock(&virt_dev->flags_lock);
1135                 if (virt_dev->media_changed) {
1136                         virt_dev->media_changed = 0;
1137                         TRACE_DBG("%s", "Reporting media changed");
1138                         scst_set_cmd_error(cmd,
1139                                 SCST_LOAD_SENSE(scst_sense_medium_changed_UA));
1140                         spin_unlock(&virt_dev->flags_lock);
1141                         goto out_done;
1142                 }
1143                 spin_unlock(&virt_dev->flags_lock);
1144         }
1145
1146         res = vdisk_do_job(cmd);
1147
1148 out:
1149         TRACE_EXIT_RES(res);
1150         return res;
1151
1152 out_done:
1153         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
1154         goto out;
1155 }
1156
1157 static uint64_t vdisk_gen_dev_id_num(struct scst_vdisk_dev *virt_dev)
1158 {
1159         unsigned int dev_id_num, i;
1160
1161         for (dev_id_num = 0, i = 0; i < strlen(virt_dev->name); i++) {
1162                 unsigned int rv = random_values[(int)(virt_dev->name[i])];
1163                 /* Do some rotating of the bits */
1164                 dev_id_num ^= ((rv << i) | (rv >> (32 - i)));
1165         }
1166
1167         return ((uint64_t)scst_vdisk_ID << 32) | dev_id_num;
1168 }
1169
1170 static void vdisk_exec_inquiry(struct scst_cmd *cmd)
1171 {
1172         int32_t length, i, resp_len = 0;
1173         uint8_t *address;
1174         uint8_t *buf;
1175         struct scst_vdisk_dev *virt_dev =
1176             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1177
1178         /* ToDo: Performance Boost:
1179          * 1. remove kzalloc, buf
1180          * 2. do all checks before touching *address
1181          * 3. zero *address
1182          * 4. write directly to *address
1183          */
1184
1185         TRACE_ENTRY();
1186
1187         buf = kzalloc(INQ_BUF_SZ,
1188                 scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
1189         if (buf == NULL) {
1190                 scst_set_busy(cmd);
1191                 goto out;
1192         }
1193
1194         length = scst_get_buf_first(cmd, &address);
1195         TRACE_DBG("length %d", length);
1196         if (unlikely(length <= 0)) {
1197                 if (length < 0) {
1198                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1199                         scst_set_cmd_error(cmd,
1200                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1201                 }
1202                 goto out_free;
1203         }
1204
1205         if (cmd->cdb[1] & CMDDT) {
1206                 TRACE_DBG("%s", "INQUIRY: CMDDT is unsupported");
1207                 scst_set_cmd_error(cmd,
1208                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1209                 goto out_put;
1210         }
1211
1212         buf[0] = cmd->dev->type;      /* type dev */
1213         if ((buf[0] == TYPE_ROM) || virt_dev->removable)
1214                 buf[1] = 0x80;      /* removable */
1215         /* Vital Product */
1216         if (cmd->cdb[1] & EVPD) {
1217                 uint64_t dev_id_num;
1218                 int dev_id_len;
1219                 char dev_id_str[17];
1220
1221                 dev_id_num = vdisk_gen_dev_id_num(virt_dev);
1222                 dev_id_len = scnprintf(dev_id_str, sizeof(dev_id_str), "%llx",
1223                                         dev_id_num);
1224                 TRACE_DBG("dev_id num %lld, str %s, len %d", dev_id_num,
1225                         dev_id_str, dev_id_len);
1226                 if (0 == cmd->cdb[2]) {
1227                         /* supported vital product data pages */
1228                         buf[3] = 3;
1229                         buf[4] = 0x0; /* this page */
1230                         buf[5] = 0x80; /* unit serial number */
1231                         buf[6] = 0x83; /* device identification */
1232                         resp_len = buf[3] + 4;
1233                 } else if (0x80 == cmd->cdb[2]) {
1234                         /* unit serial number */
1235                         int usn_len = strlen(virt_dev->usn);
1236                         buf[1] = 0x80;
1237                         buf[3] = usn_len;
1238                         strncpy(&buf[4], virt_dev->usn, usn_len);
1239                         resp_len = buf[3] + 4;
1240                 } else if (0x83 == cmd->cdb[2]) {
1241                         /* device identification */
1242                         int num = 4;
1243
1244                         buf[1] = 0x83;
1245                         /* T10 vendor identifier field format (faked) */
1246                         buf[num + 0] = 0x2;     /* ASCII */
1247                         buf[num + 1] = 0x1;     /* Vendor ID */
1248                         if (virt_dev->blockio)
1249                                 memcpy(&buf[num + 4], SCST_BIO_VENDOR, 8);
1250                         else
1251                                 memcpy(&buf[num + 4], SCST_FIO_VENDOR, 8);
1252
1253                         i = strlen(virt_dev->name) + 1; /* for ' ' */
1254                         memset(&buf[num + 12], ' ', i + dev_id_len);
1255                         memcpy(&buf[num + 12], virt_dev->name, i-1);
1256                         memcpy(&buf[num + 12 + i], dev_id_str, dev_id_len);
1257                         buf[num + 3] = 8 + i + dev_id_len;
1258                         num += buf[num + 3];
1259
1260 #if 0 /* This isn't required and can be misleading, so let's disable it */
1261                         num += 4;
1262
1263                         /* NAA IEEE registered identifier (faked) */
1264                         buf[num] = 0x1; /* binary */
1265                         buf[num + 1] = 0x3;
1266                         buf[num + 2] = 0x0;
1267                         buf[num + 3] = 0x8;
1268                         buf[num + 4] = 0x51; /* IEEE OUI=0x123456 (faked) */
1269                         buf[num + 5] = 0x23;
1270                         buf[num + 6] = 0x45;
1271                         buf[num + 7] = 0x60;
1272                         buf[num + 8] = (dev_id_num >> 24);
1273                         buf[num + 9] = (dev_id_num >> 16) & 0xff;
1274                         buf[num + 10] = (dev_id_num >> 8) & 0xff;
1275                         buf[num + 11] = dev_id_num & 0xff;
1276                         num = num + 12 - 4;
1277 #endif
1278
1279                         resp_len = num;
1280                         buf[2] = (resp_len >> 8) & 0xFF;
1281                         buf[3] = resp_len & 0xFF;
1282                         resp_len += 4;
1283                 } else {
1284                         TRACE_DBG("INQUIRY: Unsupported EVPD page %x",
1285                                 cmd->cdb[2]);
1286                         scst_set_cmd_error(cmd,
1287                             SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1288                         goto out_put;
1289                 }
1290         } else {
1291                 int len;
1292
1293                 if (cmd->cdb[2] != 0) {
1294                         TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
1295                         scst_set_cmd_error(cmd,
1296                             SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1297                         goto out_put;
1298                 }
1299
1300                 buf[2] = 4; /* Device complies to this standard - SPC-2  */
1301                 buf[3] = 0x12;  /* HiSup + data in format specified in SPC-2 */
1302                 buf[4] = 31;/* n - 4 = 35 - 4 = 31 for full 36 byte data */
1303                 buf[6] = 1; /* MultiP 1 */
1304                 buf[7] = 2; /* CMDQUE 1, BQue 0 => commands queuing supported */
1305
1306                 /*
1307                  * 8 byte ASCII Vendor Identification of the target
1308                  * - left aligned.
1309                  */
1310                 if (virt_dev->blockio)
1311                         memcpy(&buf[8], SCST_BIO_VENDOR, 8);
1312                 else
1313                         memcpy(&buf[8], SCST_FIO_VENDOR, 8);
1314
1315                 /*
1316                  * 16 byte ASCII Product Identification of the target - left
1317                  * aligned.
1318                  */
1319                 memset(&buf[16], ' ', 16);
1320                 len = min(strlen(virt_dev->name), (size_t)16);
1321                 memcpy(&buf[16], virt_dev->name, len);
1322
1323                 /*
1324                  * 4 byte ASCII Product Revision Level of the target - left
1325                  * aligned.
1326                  */
1327                 memcpy(&buf[32], SCST_FIO_REV, 4);
1328                 resp_len = buf[4] + 5;
1329         }
1330
1331         sBUG_ON(resp_len >= INQ_BUF_SZ);
1332         if (length > resp_len)
1333                 length = resp_len;
1334         memcpy(address, buf, length);
1335
1336 out_put:
1337         scst_put_buf(cmd, address);
1338         if (length < cmd->resp_data_len)
1339                 scst_set_resp_data_len(cmd, length);
1340
1341 out_free:
1342         kfree(buf);
1343
1344 out:
1345         TRACE_EXIT();
1346         return;
1347 }
1348
1349 static void vdisk_exec_request_sense(struct scst_cmd *cmd)
1350 {
1351         int32_t length;
1352         uint8_t *address;
1353
1354         TRACE_ENTRY();
1355
1356         length = scst_get_buf_first(cmd, &address);
1357         TRACE_DBG("length %d", length);
1358         if (unlikely(length < SCST_STANDARD_SENSE_LEN)) {
1359                 if (length != 0) {
1360                         PRINT_ERROR("scst_get_buf_first() failed or too small "
1361                                 "requested buffer (returned %d)", length);
1362                         scst_set_cmd_error(cmd,
1363                                 SCST_LOAD_SENSE(
1364                                         scst_sense_invalid_field_in_parm_list));
1365                 }
1366                 if (length > 0)
1367                         goto out_put;
1368                 else
1369                         goto out;
1370         }
1371
1372         scst_set_sense(address, length, cmd->dev->d_sense,
1373                 SCST_LOAD_SENSE(scst_sense_no_sense));
1374
1375 out_put:
1376         scst_put_buf(cmd, address);
1377
1378 out:
1379         TRACE_EXIT();
1380         return;
1381 }
1382
1383 /*
1384  * <<Following mode pages info copied from ST318451LW with some corrections>>
1385  *
1386  * ToDo: revise them
1387  */
1388 static int vdisk_err_recov_pg(unsigned char *p, int pcontrol,
1389                                struct scst_vdisk_dev *virt_dev)
1390 {       /* Read-Write Error Recovery page for mode_sense */
1391         const unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1392                                               5, 0, 0xff, 0xff};
1393
1394         memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1395         if (1 == pcontrol)
1396                 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1397         return sizeof(err_recov_pg);
1398 }
1399
1400 static int vdisk_disconnect_pg(unsigned char *p, int pcontrol,
1401                                 struct scst_vdisk_dev *virt_dev)
1402 {       /* Disconnect-Reconnect page for mode_sense */
1403         const unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1404                                                0, 0, 0, 0, 0, 0, 0, 0};
1405
1406         memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1407         if (1 == pcontrol)
1408                 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1409         return sizeof(disconnect_pg);
1410 }
1411
1412 static int vdisk_rigid_geo_pg(unsigned char *p, int pcontrol,
1413         struct scst_vdisk_dev *virt_dev)
1414 {
1415         unsigned char geo_m_pg[] = {0x04, 0x16, 0, 0, 0, DEF_HEADS, 0, 0,
1416                                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1417                                     0x3a, 0x98/* 15K RPM */, 0, 0};
1418         int32_t ncyl, n, rem;
1419         uint64_t dividend;
1420
1421         memcpy(p, geo_m_pg, sizeof(geo_m_pg));
1422         /*
1423          * Divide virt_dev->nblocks by (DEF_HEADS * DEF_SECTORS) and store
1424          * the quotient in ncyl and the remainder in rem.
1425          */
1426         dividend = virt_dev->nblocks;
1427         rem = do_div(dividend, DEF_HEADS * DEF_SECTORS);
1428         ncyl = dividend;
1429         if (rem != 0)
1430                 ncyl++;
1431         memcpy(&n, p + 2, sizeof(u32));
1432         n = n | (cpu_to_be32(ncyl) >> 8);
1433         memcpy(p + 2, &n, sizeof(u32));
1434         if (1 == pcontrol)
1435                 memset(p + 2, 0, sizeof(geo_m_pg) - 2);
1436         return sizeof(geo_m_pg);
1437 }
1438
1439 static int vdisk_format_pg(unsigned char *p, int pcontrol,
1440                             struct scst_vdisk_dev *virt_dev)
1441 {       /* Format device page for mode_sense */
1442         const unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1443                                            0, 0, 0, 0, 0, 0, 0, 0,
1444                                            0, 0, 0, 0, 0x40, 0, 0, 0};
1445
1446         memcpy(p, format_pg, sizeof(format_pg));
1447         p[10] = (DEF_SECTORS >> 8) & 0xff;
1448         p[11] = DEF_SECTORS & 0xff;
1449         p[12] = (virt_dev->block_size >> 8) & 0xff;
1450         p[13] = virt_dev->block_size & 0xff;
1451         if (1 == pcontrol)
1452                 memset(p + 2, 0, sizeof(format_pg) - 2);
1453         return sizeof(format_pg);
1454 }
1455
1456 static int vdisk_caching_pg(unsigned char *p, int pcontrol,
1457                              struct scst_vdisk_dev *virt_dev)
1458 {       /* Caching page for mode_sense */
1459         const unsigned char caching_pg[] = {0x8, 18, 0x10, 0, 0xff, 0xff, 0, 0,
1460                 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1461
1462         memcpy(p, caching_pg, sizeof(caching_pg));
1463         p[2] |= !(virt_dev->wt_flag || virt_dev->nv_cache) ? WCE : 0;
1464         if (1 == pcontrol)
1465                 memset(p + 2, 0, sizeof(caching_pg) - 2);
1466         return sizeof(caching_pg);
1467 }
1468
1469 static int vdisk_ctrl_m_pg(unsigned char *p, int pcontrol,
1470                             struct scst_vdisk_dev *virt_dev)
1471 {       /* Control mode page for mode_sense */
1472         const unsigned char ctrl_m_pg[] = {0xa, 0xa, 0, 0, 0, 0, 0, 0,
1473                                            0, 0, 0x2, 0x4b};
1474
1475         memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1476         switch (pcontrol) {
1477         case 0:
1478                 p[2] |= virt_dev->dev->tst << 5;
1479                 p[2] |= virt_dev->dev->d_sense << 2;
1480                 p[3] |= virt_dev->dev->queue_alg << 4;
1481                 p[4] |= virt_dev->dev->swp << 3;
1482                 p[5] |= virt_dev->dev->tas << 6;
1483                 break;
1484         case 1:
1485                 memset(p + 2, 0, sizeof(ctrl_m_pg) - 2);
1486 #if 0   /*
1487          * It's too early to implement it, since we can't control the
1488          * backstorage device parameters. ToDo
1489          */
1490                 p[2] |= 7 << 5;         /* TST */
1491                 p[3] |= 0xF << 4;       /* QUEUE ALGORITHM MODIFIER */
1492 #endif
1493                 p[2] |= 1 << 2;         /* D_SENSE */
1494                 p[4] |= 1 << 3;         /* SWP */
1495                 p[5] |= 1 << 6;         /* TAS */
1496                 break;
1497         case 2:
1498                 p[2] |= DEF_TST << 5;
1499                 p[2] |= DEF_DSENSE << 2;
1500                 if (virt_dev->wt_flag || virt_dev->nv_cache)
1501                         p[3] |= DEF_QUEUE_ALG_WT << 4;
1502                 else
1503                         p[3] |= DEF_QUEUE_ALG << 4;
1504                 p[4] |= DEF_SWP << 3;
1505                 p[5] |= DEF_TAS << 6;
1506                 break;
1507         default:
1508                 sBUG();
1509         }
1510         return sizeof(ctrl_m_pg);
1511 }
1512
1513 static int vdisk_iec_m_pg(unsigned char *p, int pcontrol,
1514                            struct scst_vdisk_dev *virt_dev)
1515 {       /* Informational Exceptions control mode page for mode_sense */
1516         const unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1517                                           0, 0, 0x0, 0x0};
1518         memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1519         if (1 == pcontrol)
1520                 memset(p + 2, 0, sizeof(iec_m_pg) - 2);
1521         return sizeof(iec_m_pg);
1522 }
1523
1524 static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
1525 {
1526         int32_t length;
1527         uint8_t *address;
1528         uint8_t *buf;
1529         struct scst_vdisk_dev *virt_dev;
1530         uint32_t blocksize;
1531         uint64_t nblocks;
1532         unsigned char dbd, type;
1533         int pcontrol, pcode, subpcode;
1534         unsigned char dev_spec;
1535         int msense_6, offset = 0, len;
1536         unsigned char *bp;
1537
1538         TRACE_ENTRY();
1539
1540         buf = kzalloc(MSENSE_BUF_SZ,
1541                 scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
1542         if (buf == NULL) {
1543                 scst_set_busy(cmd);
1544                 goto out;
1545         }
1546
1547         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1548         blocksize = virt_dev->block_size;
1549         nblocks = virt_dev->nblocks;
1550
1551         type = cmd->dev->type;    /* type dev */
1552         dbd = cmd->cdb[1] & DBD;
1553         pcontrol = (cmd->cdb[2] & 0xc0) >> 6;
1554         pcode = cmd->cdb[2] & 0x3f;
1555         subpcode = cmd->cdb[3];
1556         msense_6 = (MODE_SENSE == cmd->cdb[0]);
1557         dev_spec = (virt_dev->rd_only_flag ? WP : 0) | DPOFUA;
1558
1559         length = scst_get_buf_first(cmd, &address);
1560         if (unlikely(length <= 0)) {
1561                 if (length < 0) {
1562                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1563                         scst_set_cmd_error(cmd,
1564                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1565                 }
1566                 goto out_free;
1567         }
1568
1569         if (0x3 == pcontrol) {
1570                 TRACE_DBG("%s", "MODE SENSE: Saving values not supported");
1571                 scst_set_cmd_error(cmd,
1572                     SCST_LOAD_SENSE(scst_sense_saving_params_unsup));
1573                 goto out_put;
1574         }
1575
1576         if (msense_6) {
1577                 buf[1] = type;
1578                 buf[2] = dev_spec;
1579                 offset = 4;
1580         } else {
1581                 buf[2] = type;
1582                 buf[3] = dev_spec;
1583                 offset = 8;
1584         }
1585
1586         if (0 != subpcode) {
1587                 /* TODO: Control Extension page */
1588                 TRACE_DBG("%s", "MODE SENSE: Only subpage 0 is supported");
1589                 scst_set_cmd_error(cmd,
1590                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1591                 goto out_put;
1592         }
1593
1594         if (!dbd) {
1595                 /* Create block descriptor */
1596                 buf[offset - 1] = 0x08;         /* block descriptor length */
1597                 if (nblocks >> 32) {
1598                         buf[offset + 0] = 0xFF;
1599                         buf[offset + 1] = 0xFF;
1600                         buf[offset + 2] = 0xFF;
1601                         buf[offset + 3] = 0xFF;
1602                 } else {
1603                         /* num blks */
1604                         buf[offset + 0] = (nblocks >> (BYTE * 3)) & 0xFF;
1605                         buf[offset + 1] = (nblocks >> (BYTE * 2)) & 0xFF;
1606                         buf[offset + 2] = (nblocks >> (BYTE * 1)) & 0xFF;
1607                         buf[offset + 3] = (nblocks >> (BYTE * 0)) & 0xFF;
1608                 }
1609                 buf[offset + 4] = 0;                    /* density code */
1610                 buf[offset + 5] = (blocksize >> (BYTE * 2)) & 0xFF;/* blklen */
1611                 buf[offset + 6] = (blocksize >> (BYTE * 1)) & 0xFF;
1612                 buf[offset + 7] = (blocksize >> (BYTE * 0)) & 0xFF;
1613
1614                 offset += 8;                    /* increment offset */
1615         }
1616
1617         bp = buf + offset;
1618
1619         switch (pcode) {
1620         case 0x1:       /* Read-Write error recovery page, direct access */
1621                 len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
1622                 break;
1623         case 0x2:       /* Disconnect-Reconnect page, all devices */
1624                 len = vdisk_disconnect_pg(bp, pcontrol, virt_dev);
1625                 break;
1626         case 0x3:       /* Format device page, direct access */
1627                 len = vdisk_format_pg(bp, pcontrol, virt_dev);
1628                 break;
1629         case 0x4:       /* Rigid disk geometry */
1630                 len = vdisk_rigid_geo_pg(bp, pcontrol, virt_dev);
1631                 break;
1632         case 0x8:       /* Caching page, direct access */
1633                 len = vdisk_caching_pg(bp, pcontrol, virt_dev);
1634                 break;
1635         case 0xa:       /* Control Mode page, all devices */
1636                 len = vdisk_ctrl_m_pg(bp, pcontrol, virt_dev);
1637                 break;
1638         case 0x1c:      /* Informational Exceptions Mode page, all devices */
1639                 len = vdisk_iec_m_pg(bp, pcontrol, virt_dev);
1640                 break;
1641         case 0x3f:      /* Read all Mode pages */
1642                 len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
1643                 len += vdisk_disconnect_pg(bp + len, pcontrol, virt_dev);
1644                 len += vdisk_format_pg(bp + len, pcontrol, virt_dev);
1645                 len += vdisk_caching_pg(bp + len, pcontrol, virt_dev);
1646                 len += vdisk_ctrl_m_pg(bp + len, pcontrol, virt_dev);
1647                 len += vdisk_iec_m_pg(bp + len, pcontrol, virt_dev);
1648                 len += vdisk_rigid_geo_pg(bp + len, pcontrol, virt_dev);
1649                 break;
1650         default:
1651                 TRACE_DBG("MODE SENSE: Unsupported page %x", pcode);
1652                 scst_set_cmd_error(cmd,
1653                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1654                 goto out_put;
1655         }
1656
1657         offset += len;
1658
1659         if (msense_6)
1660                 buf[0] = offset - 1;
1661         else {
1662                 buf[0] = ((offset - 2) >> 8) & 0xff;
1663                 buf[1] = (offset - 2) & 0xff;
1664         }
1665
1666         if (offset > length)
1667                 offset = length;
1668         memcpy(address, buf, offset);
1669
1670 out_put:
1671         scst_put_buf(cmd, address);
1672         if (offset < cmd->resp_data_len)
1673                 scst_set_resp_data_len(cmd, offset);
1674
1675 out_free:
1676         kfree(buf);
1677
1678 out:
1679         TRACE_EXIT();
1680         return;
1681 }
1682
1683 static int vdisk_set_wt(struct scst_vdisk_dev *virt_dev, int wt)
1684 {
1685         int res = 0;
1686
1687         TRACE_ENTRY();
1688
1689         if ((virt_dev->wt_flag == wt) || virt_dev->nullio || virt_dev->nv_cache)
1690                 goto out;
1691
1692         spin_lock(&virt_dev->flags_lock);
1693         virt_dev->wt_flag = wt;
1694         spin_unlock(&virt_dev->flags_lock);
1695
1696         scst_dev_del_all_thr_data(virt_dev->dev);
1697
1698 out:
1699         TRACE_EXIT_RES(res);
1700         return res;
1701 }
1702
1703 static void vdisk_ctrl_m_pg_select(unsigned char *p,
1704         struct scst_vdisk_dev *virt_dev)
1705 {
1706         struct scst_device *dev = virt_dev->dev;
1707         int old_swp = dev->swp, old_tas = dev->tas, old_dsense = dev->d_sense;
1708
1709 #if 0
1710         /* Not implemented yet, see comment in vdisk_ctrl_m_pg() */
1711         dev->tst = p[2] >> 5;
1712         dev->queue_alg = p[3] >> 4;
1713 #endif
1714         dev->swp = (p[4] & 0x8) >> 3;
1715         dev->tas = (p[5] & 0x40) >> 6;
1716         dev->d_sense = (p[2] & 0x4) >> 2;
1717
1718         PRINT_INFO("Device %s: new control mode page parameters: SWP %x "
1719                 "(was %x), TAS %x (was %x), D_SENSE %d (was %d)",
1720                 virt_dev->name, dev->swp, old_swp, dev->tas, old_tas,
1721                 dev->d_sense, old_dsense);
1722         return;
1723 }
1724
1725 static void vdisk_exec_mode_select(struct scst_cmd *cmd)
1726 {
1727         int32_t length;
1728         uint8_t *address;
1729         struct scst_vdisk_dev *virt_dev;
1730         int mselect_6, offset;
1731
1732         TRACE_ENTRY();
1733
1734         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1735         mselect_6 = (MODE_SELECT == cmd->cdb[0]);
1736
1737         length = scst_get_buf_first(cmd, &address);
1738         if (unlikely(length <= 0)) {
1739                 if (length < 0) {
1740                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1741                         scst_set_cmd_error(cmd,
1742                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1743                 }
1744                 goto out;
1745         }
1746
1747         if (!(cmd->cdb[1] & PF) || (cmd->cdb[1] & SP)) {
1748                 TRACE(TRACE_MINOR|TRACE_SCSI, "MODE SELECT: Unsupported "
1749                         "value(s) of PF and/or SP bits (cdb[1]=%x)",
1750                         cmd->cdb[1]);
1751                 scst_set_cmd_error(cmd,
1752                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1753                 goto out_put;
1754         }
1755
1756         if (mselect_6)
1757                 offset = 4;
1758         else
1759                 offset = 8;
1760
1761         if (address[offset - 1] == 8) {
1762                 offset += 8;
1763         } else if (address[offset - 1] != 0) {
1764                 PRINT_ERROR("%s", "MODE SELECT: Wrong parameters list "
1765                         "lenght");
1766                 scst_set_cmd_error(cmd,
1767                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
1768                 goto out_put;
1769         }
1770
1771         while (length > offset + 2) {
1772                 if (address[offset] & PS) {
1773                         PRINT_ERROR("%s", "MODE SELECT: Illegal PS bit");
1774                         scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1775                                 scst_sense_invalid_field_in_parm_list));
1776                         goto out_put;
1777                 }
1778                 if ((address[offset] & 0x3f) == 0x8) {
1779                         /* Caching page */
1780                         if (address[offset + 1] != 18) {
1781                                 PRINT_ERROR("%s", "MODE SELECT: Invalid "
1782                                         "caching page request");
1783                                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1784                                     scst_sense_invalid_field_in_parm_list));
1785                                 goto out_put;
1786                         }
1787                         if (vdisk_set_wt(virt_dev,
1788                               (address[offset + 2] & WCE) ? 0 : 1) != 0) {
1789                                 scst_set_cmd_error(cmd,
1790                                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1791                                 goto out_put;
1792                         }
1793                         break;
1794                 } else if ((address[offset] & 0x3f) == 0xA) {
1795                         /* Control page */
1796                         if (address[offset + 1] != 0xA) {
1797                                 PRINT_ERROR("%s", "MODE SELECT: Invalid "
1798                                         "control page request");
1799                                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1800                                     scst_sense_invalid_field_in_parm_list));
1801                                 goto out_put;
1802                         }
1803                         vdisk_ctrl_m_pg_select(&address[offset], virt_dev);
1804                 } else {
1805                         PRINT_ERROR("MODE SELECT: Invalid request %x",
1806                                 address[offset] & 0x3f);
1807                         scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1808                             scst_sense_invalid_field_in_parm_list));
1809                         goto out_put;
1810                 }
1811                 offset += address[offset + 1];
1812         }
1813
1814 out_put:
1815         scst_put_buf(cmd, address);
1816
1817 out:
1818         TRACE_EXIT();
1819         return;
1820 }
1821
1822 static void vdisk_exec_log(struct scst_cmd *cmd)
1823 {
1824         TRACE_ENTRY();
1825
1826         /* No log pages are supported */
1827         scst_set_cmd_error(cmd,
1828                 SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1829
1830         TRACE_EXIT();
1831         return;
1832 }
1833
1834 static void vdisk_exec_read_capacity(struct scst_cmd *cmd)
1835 {
1836         int32_t length;
1837         uint8_t *address;
1838         struct scst_vdisk_dev *virt_dev;
1839         uint32_t blocksize;
1840         uint64_t nblocks;
1841         uint8_t buffer[READ_CAP_LEN];
1842
1843         TRACE_ENTRY();
1844
1845         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1846         blocksize = virt_dev->block_size;
1847         nblocks = virt_dev->nblocks;
1848
1849         /* last block on the virt_dev is (nblocks-1) */
1850         memset(buffer, 0, sizeof(buffer));
1851         if (nblocks >> 32) {
1852                 buffer[0] = 0xFF;
1853                 buffer[1] = 0xFF;
1854                 buffer[2] = 0xFF;
1855                 buffer[3] = 0xFF;
1856         } else {
1857                 buffer[0] = ((nblocks - 1) >> (BYTE * 3)) & 0xFF;
1858                 buffer[1] = ((nblocks - 1) >> (BYTE * 2)) & 0xFF;
1859                 buffer[2] = ((nblocks - 1) >> (BYTE * 1)) & 0xFF;
1860                 buffer[3] = ((nblocks - 1) >> (BYTE * 0)) & 0xFF;
1861         }
1862         buffer[4] = (blocksize >> (BYTE * 3)) & 0xFF;
1863         buffer[5] = (blocksize >> (BYTE * 2)) & 0xFF;
1864         buffer[6] = (blocksize >> (BYTE * 1)) & 0xFF;
1865         buffer[7] = (blocksize >> (BYTE * 0)) & 0xFF;
1866
1867         length = scst_get_buf_first(cmd, &address);
1868         if (unlikely(length <= 0)) {
1869                 if (length < 0) {
1870                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1871                         scst_set_cmd_error(cmd,
1872                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1873                 }
1874                 goto out;
1875         }
1876
1877         if (length > READ_CAP_LEN)
1878                 length = READ_CAP_LEN;
1879         memcpy(address, buffer, length);
1880
1881         scst_put_buf(cmd, address);
1882
1883         if (length < cmd->resp_data_len)
1884                 scst_set_resp_data_len(cmd, length);
1885
1886 out:
1887         TRACE_EXIT();
1888         return;
1889 }
1890
1891 static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
1892 {
1893         int32_t length;
1894         uint8_t *address;
1895         struct scst_vdisk_dev *virt_dev;
1896         uint32_t blocksize;
1897         uint64_t nblocks;
1898         uint8_t buffer[READ_CAP16_LEN];
1899
1900         TRACE_ENTRY();
1901
1902         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1903         blocksize = virt_dev->block_size;
1904         nblocks = virt_dev->nblocks - 1;
1905
1906         memset(buffer, 0, sizeof(buffer));
1907
1908         buffer[0] = nblocks >> 56;
1909         buffer[1] = (nblocks >> 48) & 0xFF;
1910         buffer[2] = (nblocks >> 40) & 0xFF;
1911         buffer[3] = (nblocks >> 32) & 0xFF;
1912         buffer[4] = (nblocks >> 24) & 0xFF;
1913         buffer[5] = (nblocks >> 16) & 0xFF;
1914         buffer[6] = (nblocks >> 8) & 0xFF;
1915         buffer[7] = nblocks & 0xFF;
1916
1917         buffer[8] = (blocksize >> (BYTE * 3)) & 0xFF;
1918         buffer[9] = (blocksize >> (BYTE * 2)) & 0xFF;
1919         buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF;
1920         buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF;
1921
1922         switch (blocksize) {
1923         case 512:
1924                 buffer[13] = 3;
1925                 break;
1926         case 1024:
1927                 buffer[13] = 2;
1928                 break;
1929         case 2048:
1930                 buffer[13] = 1;
1931                 break;
1932         default:
1933                 PRINT_ERROR("%s: Unexpected block size %d",
1934                         cmd->op_name, blocksize);
1935                 /* go through */
1936         case 4096:
1937                 buffer[13] = 0;
1938                 break;
1939         }
1940
1941         length = scst_get_buf_first(cmd, &address);
1942         if (unlikely(length <= 0)) {
1943                 if (length < 0) {
1944                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1945                         scst_set_cmd_error(cmd,
1946                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1947                         }
1948                 goto out;
1949         }
1950
1951         if (length > READ_CAP16_LEN)
1952                 length = READ_CAP16_LEN;
1953         memcpy(address, buffer, length);
1954
1955         scst_put_buf(cmd, address);
1956
1957         if (length < cmd->resp_data_len)
1958                 scst_set_resp_data_len(cmd, length);
1959
1960 out:
1961         TRACE_EXIT();
1962         return;
1963 }
1964
1965 static void vdisk_exec_read_toc(struct scst_cmd *cmd)
1966 {
1967         int32_t length, off = 0;
1968         uint8_t *address;
1969         struct scst_vdisk_dev *virt_dev;
1970         uint32_t nblocks;
1971         uint8_t buffer[4+8+8] = { 0x00, 0x0a, 0x01, 0x01, 0x00, 0x14,
1972                                   0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
1973
1974         TRACE_ENTRY();
1975
1976         if (cmd->dev->type != TYPE_ROM) {
1977                 PRINT_ERROR("%s", "READ TOC for non-CDROM device");
1978                 scst_set_cmd_error(cmd,
1979                         SCST_LOAD_SENSE(scst_sense_invalid_opcode));
1980                 goto out;
1981         }
1982
1983         if (cmd->cdb[2] & 0x0e/*Format*/) {
1984                 PRINT_ERROR("%s", "READ TOC: invalid requested data format");
1985                 scst_set_cmd_error(cmd,
1986                         SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1987                 goto out;
1988         }
1989
1990         if ((cmd->cdb[6] != 0 && (cmd->cdb[2] & 0x01)) ||
1991             (cmd->cdb[6] > 1 && cmd->cdb[6] != 0xAA)) {
1992                 PRINT_ERROR("READ TOC: invalid requested track number %x",
1993                         cmd->cdb[6]);
1994                 scst_set_cmd_error(cmd,
1995                         SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1996                 goto out;
1997         }
1998
1999         length = scst_get_buf_first(cmd, &address);
2000         if (unlikely(length <= 0)) {
2001                 if (length < 0) {
2002                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
2003                         scst_set_cmd_error(cmd,
2004                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
2005                 }
2006                 goto out;
2007         }
2008
2009         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2010         /* ToDo when you have > 8TB ROM device. */
2011         nblocks = (uint32_t)virt_dev->nblocks;
2012
2013         /* Header */
2014         memset(buffer, 0, sizeof(buffer));
2015         buffer[2] = 0x01;    /* First Track/Session */
2016         buffer[3] = 0x01;    /* Last Track/Session */
2017         off = 4;
2018         if (cmd->cdb[6] <= 1) {
2019                 /* Fistr TOC Track Descriptor */
2020                 /* ADDR    0x10 - Q Sub-channel encodes current position data
2021                    CONTROL 0x04 - Data track, recoreded uninterrupted */
2022                 buffer[off+1] = 0x14;
2023                 /* Track Number */
2024                 buffer[off+2] = 0x01;
2025                 off += 8;
2026         }
2027         if (!(cmd->cdb[2] & 0x01)) {
2028                 /* Lead-out area TOC Track Descriptor */
2029                 buffer[off+1] = 0x14;
2030                 /* Track Number */
2031                 buffer[off+2] = 0xAA;
2032                 /* Track Start Address */
2033                 buffer[off+4] = (nblocks >> (BYTE * 3)) & 0xFF;
2034                 buffer[off+5] = (nblocks >> (BYTE * 2)) & 0xFF;
2035                 buffer[off+6] = (nblocks >> (BYTE * 1)) & 0xFF;
2036                 buffer[off+7] = (nblocks >> (BYTE * 0)) & 0xFF;
2037                 off += 8;
2038         }
2039
2040         buffer[1] = off - 2;    /* Data  Length */
2041
2042         if (off > length)
2043                 off = length;
2044         memcpy(address, buffer, off);
2045
2046         scst_put_buf(cmd, address);
2047
2048         if (off < cmd->resp_data_len)
2049                 scst_set_resp_data_len(cmd, off);
2050
2051 out:
2052         TRACE_EXIT();
2053         return;
2054 }
2055
2056 static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd)
2057 {
2058         struct scst_vdisk_dev *virt_dev =
2059                 (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2060
2061         TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
2062
2063         if (cmd->dev->type == TYPE_ROM) {
2064                 spin_lock(&virt_dev->flags_lock);
2065                 virt_dev->prevent_allow_medium_removal =
2066                         cmd->cdb[4] & 0x01 ? 1 : 0;
2067                 spin_unlock(&virt_dev->flags_lock);
2068         }
2069
2070         return;
2071 }
2072
2073 static int vdisk_fsync(struct scst_vdisk_thr *thr,
2074         loff_t loff, loff_t len, struct scst_cmd *cmd)
2075 {
2076         int res = 0;
2077         struct scst_vdisk_dev *virt_dev =
2078                 (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2079         struct file *file = thr->fd;
2080         struct inode *inode;
2081         struct address_space *mapping;
2082
2083         TRACE_ENTRY();
2084
2085         /* Hopefully, the compiler will generate the single comparison */
2086         if (virt_dev->nv_cache || virt_dev->blockio || virt_dev->wt_flag ||
2087             virt_dev->rd_only_flag || virt_dev->o_direct_flag ||
2088             virt_dev->nullio)
2089                 goto out;
2090
2091         inode = file->f_dentry->d_inode;
2092         mapping = file->f_mapping;
2093
2094         res = sync_page_range(inode, mapping, loff, len);
2095         if (unlikely(res != 0)) {
2096                 PRINT_ERROR("sync_page_range() failed (%d)", res);
2097                 if (cmd != NULL) {
2098                         scst_set_cmd_error(cmd,
2099                                 SCST_LOAD_SENSE(scst_sense_write_error));
2100                 }
2101         }
2102
2103         /* ToDo: flush the device cache, if needed */
2104
2105 out:
2106         TRACE_EXIT_RES(res);
2107         return res;
2108 }
2109
2110 static struct iovec *vdisk_alloc_iv(struct scst_cmd *cmd,
2111         struct scst_vdisk_thr *thr)
2112 {
2113         int iv_count;
2114
2115         iv_count = scst_get_buf_count(cmd);
2116         if (iv_count > thr->iv_count) {
2117                 kfree(thr->iv);
2118                 /* It can't be called in atomic context */
2119                 thr->iv = kmalloc(sizeof(*thr->iv) * iv_count, GFP_KERNEL);
2120                 if (thr->iv == NULL) {
2121                         PRINT_ERROR("Unable to allocate iv (%d)", iv_count);
2122                         scst_set_busy(cmd);
2123                         goto out;
2124                 }
2125                 thr->iv_count = iv_count;
2126         }
2127
2128 out:
2129         return thr->iv;
2130 }
2131
2132 /*
2133  * copied from <ksrc>/fs/read_write.*
2134  */
2135 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
2136 static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
2137 {
2138         set_current_state(TASK_UNINTERRUPTIBLE);
2139         if (!kiocbIsKicked(iocb))
2140                 schedule();
2141         else
2142                 kiocbClearKicked(iocb);
2143         __set_current_state(TASK_RUNNING);
2144 }
2145
2146 typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
2147                                 unsigned long, loff_t);
2148
2149 static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
2150                 unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
2151 {
2152         struct kiocb kiocb;
2153         ssize_t ret;
2154
2155         init_sync_kiocb(&kiocb, filp);
2156         kiocb.ki_pos = *ppos;
2157         kiocb.ki_left = len;
2158         kiocb.ki_nbytes = len;
2159
2160         for (;;) {
2161                 ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
2162                 if (ret != -EIOCBRETRY)
2163                         break;
2164                 wait_on_retry_sync_kiocb(&kiocb);
2165         }
2166
2167         if (ret == -EIOCBQUEUED)
2168                 ret = wait_on_sync_kiocb(&kiocb);
2169         *ppos = kiocb.ki_pos;
2170         return ret;
2171 }
2172 #endif
2173
2174 static void vdisk_exec_read(struct scst_cmd *cmd,
2175         struct scst_vdisk_thr *thr, loff_t loff)
2176 {
2177         mm_segment_t old_fs;
2178         loff_t err;
2179         ssize_t length, full_len;
2180         uint8_t __user *address;
2181         struct scst_vdisk_dev *virt_dev =
2182             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2183         struct file *fd = thr->fd;
2184         struct iovec *iv;
2185         int iv_count, i;
2186
2187         TRACE_ENTRY();
2188
2189         if (virt_dev->nullio)
2190                 goto out;
2191
2192         iv = vdisk_alloc_iv(cmd, thr);
2193         if (iv == NULL)
2194                 goto out;
2195
2196         iv_count = 0;
2197         full_len = 0;
2198         i = -1;
2199         length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
2200         while (length > 0) {
2201                 full_len += length;
2202                 i++;
2203                 iv_count++;
2204                 iv[i].iov_base = address;
2205                 iv[i].iov_len = length;
2206                 length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
2207         }
2208         if (unlikely(length < 0)) {
2209                 PRINT_ERROR("scst_get_buf_() failed: %zd", length);
2210                 scst_set_cmd_error(cmd,
2211                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2212                 goto out_put;
2213         }
2214
2215         old_fs = get_fs();
2216         set_fs(get_ds());
2217
2218         TRACE_DBG("reading(iv_count %d, full_len %zd)", iv_count, full_len);
2219         /* SEEK */
2220         if (fd->f_op->llseek)
2221                 err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
2222         else
2223                 err = default_llseek(fd, loff, 0/*SEEK_SET*/);
2224         if (err != loff) {
2225                 PRINT_ERROR("lseek trouble %lld != %lld",
2226                             (long long unsigned int)err,
2227                             (long long unsigned int)loff);
2228                 scst_set_cmd_error(cmd,
2229                         SCST_LOAD_SENSE(scst_sense_hardw_error));
2230                 goto out_set_fs;
2231         }
2232
2233         /* READ */
2234 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
2235         err = fd->f_op->readv(fd, iv, iv_count, &fd->f_pos);
2236 #else
2237         err = do_sync_readv_writev(fd, iv, iv_count, full_len,
2238                                    &fd->f_pos, fd->f_op->aio_read);
2239 #endif
2240
2241         if ((err < 0) || (err < full_len)) {
2242                 PRINT_ERROR("readv() returned %lld from %zd",
2243                             (long long unsigned int)err,
2244                             full_len);
2245                 if (err == -EAGAIN)
2246                         scst_set_busy(cmd);
2247                 else {
2248                         scst_set_cmd_error(cmd,
2249                             SCST_LOAD_SENSE(scst_sense_read_error));
2250                 }
2251                 goto out_set_fs;
2252         }
2253
2254 out_set_fs:
2255         set_fs(old_fs);
2256
2257 out_put:
2258         for (; i >= 0; i--)
2259                 scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
2260
2261 out:
2262         TRACE_EXIT();
2263         return;
2264 }
2265
2266 static void vdisk_exec_write(struct scst_cmd *cmd,
2267         struct scst_vdisk_thr *thr, loff_t loff)
2268 {
2269         mm_segment_t old_fs;
2270         loff_t err;
2271         ssize_t length, full_len;
2272         uint8_t __user *address;
2273         struct scst_vdisk_dev *virt_dev =
2274             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2275         struct file *fd = thr->fd;
2276         struct iovec *iv, *eiv;
2277         int iv_count, eiv_count;
2278
2279         TRACE_ENTRY();
2280
2281         if (virt_dev->nullio)
2282                 goto out;
2283
2284         iv = vdisk_alloc_iv(cmd, thr);
2285         if (iv == NULL)
2286                 goto out;
2287
2288         iv_count = 0;
2289         full_len = 0;
2290         length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
2291         while (length > 0) {
2292                 full_len += length;
2293                 iv[iv_count].iov_base = address;
2294                 iv[iv_count].iov_len = length;
2295                 iv_count++;
2296                 length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
2297         }
2298         if (unlikely(length < 0)) {
2299                 PRINT_ERROR("scst_get_buf_() failed: %zd", length);
2300                 scst_set_cmd_error(cmd,
2301                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2302                 goto out_put;
2303         }
2304
2305         old_fs = get_fs();
2306         set_fs(get_ds());
2307
2308         eiv = iv;
2309         eiv_count = iv_count;
2310 restart:
2311         TRACE_DBG("writing(eiv_count %d, full_len %zd)", eiv_count, full_len);
2312
2313         /* SEEK */
2314         if (fd->f_op->llseek)
2315                 err = fd->f_op->llseek(fd, loff, 0 /*SEEK_SET */);
2316         else
2317                 err = default_llseek(fd, loff, 0 /*SEEK_SET */);
2318         if (err != loff) {
2319                 PRINT_ERROR("lseek trouble %lld != %lld",
2320                             (long long unsigned int)err,
2321                             (long long unsigned int)loff);
2322                 scst_set_cmd_error(cmd,
2323                                    SCST_LOAD_SENSE(scst_sense_hardw_error));
2324                 goto out_set_fs;
2325         }
2326
2327         /* WRITE */
2328 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
2329         err = fd->f_op->writev(fd, eiv, eiv_count, &fd->f_pos);
2330 #else
2331         err = do_sync_readv_writev(fd, iv, iv_count, full_len, &fd->f_pos,
2332                                         fd->f_op->aio_write);
2333 #endif
2334
2335         if (err < 0) {
2336                 PRINT_ERROR("write() returned %lld from %zd",
2337                             (long long unsigned int)err,
2338                             full_len);
2339                 if (err == -EAGAIN)
2340                         scst_set_busy(cmd);
2341                 else {
2342                         scst_set_cmd_error(cmd,
2343                             SCST_LOAD_SENSE(scst_sense_write_error));
2344                 }
2345                 goto out_set_fs;
2346         } else if (err < full_len) {
2347                 /*
2348                  * Probably that's wrong, but sometimes write() returns
2349                  * value less, than requested. Let's restart.
2350                  */
2351                 int i, e = eiv_count;
2352                 TRACE_MGMT_DBG("write() returned %d from %zd "
2353                         "(iv_count=%d)", (int)err, full_len,
2354                         eiv_count);
2355                 if (err == 0) {
2356                         PRINT_INFO("Suspicious: write() returned 0 from "
2357                                 "%zd (iv_count=%d)", full_len, eiv_count);
2358                 }
2359                 full_len -= err;
2360                 for (i = 0; i < e; i++) {
2361                         if ((long long)eiv->iov_len < err) {
2362                                 err -= eiv->iov_len;
2363                                 eiv++;
2364                                 eiv_count--;
2365                         } else {
2366                                 eiv->iov_base =
2367                                         (uint8_t __force __user *)eiv->iov_base +
2368                                         err;
2369                                 eiv->iov_len -= err;
2370                                 break;
2371                         }
2372                 }
2373                 goto restart;
2374         }
2375
2376 out_set_fs:
2377         set_fs(old_fs);
2378
2379 out_put:
2380         while (iv_count > 0) {
2381                 scst_put_buf(cmd, (void __force *)(iv[iv_count-1].iov_base));
2382                 iv_count--;
2383         }
2384
2385 out:
2386         TRACE_EXIT();
2387         return;
2388 }
2389
2390 struct scst_blockio_work {
2391         atomic_t bios_inflight;
2392         struct scst_cmd *cmd;
2393 };
2394
2395 static inline void blockio_check_finish(struct scst_blockio_work *blockio_work)
2396 {
2397         /* Decrement the bios in processing, and if zero signal completion */
2398         if (atomic_dec_and_test(&blockio_work->bios_inflight)) {
2399                 blockio_work->cmd->completed = 1;
2400                 blockio_work->cmd->scst_cmd_done(blockio_work->cmd,
2401                         SCST_CMD_STATE_DEFAULT, scst_estimate_context());
2402                 kmem_cache_free(blockio_work_cachep, blockio_work);
2403         }
2404         return;
2405 }
2406
2407 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
2408 static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error)
2409 #else
2410 static void blockio_endio(struct bio *bio, int error)
2411 #endif
2412 {
2413         struct scst_blockio_work *blockio_work = bio->bi_private;
2414
2415 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
2416         if (bio->bi_size)
2417                 return 1;
2418 #endif
2419
2420         error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO;
2421
2422         if (unlikely(error != 0)) {
2423                 PRINT_ERROR("cmd %p returned error %d", blockio_work->cmd,
2424                         error);
2425                 /*
2426                  * The race with other such bio's doesn't matter, since all
2427                  * scst_set_cmd_error() calls do the same local to this cmd
2428                  * operations.
2429                  */
2430                 if (bio->bi_rw & WRITE)
2431                         scst_set_cmd_error(blockio_work->cmd,
2432                                 SCST_LOAD_SENSE(scst_sense_write_error));
2433                 else
2434                         scst_set_cmd_error(blockio_work->cmd,
2435                                 SCST_LOAD_SENSE(scst_sense_read_error));
2436         }
2437
2438         blockio_check_finish(blockio_work);
2439
2440         bio_put(bio);
2441 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
2442         return 0;
2443 #else
2444         return;
2445 #endif
2446 }
2447
2448 static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
2449         u64 lba_start, int write)
2450 {
2451         struct scst_vdisk_dev *virt_dev =
2452                 (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2453         struct block_device *bdev = thr->bdev;
2454         struct request_queue *q = bdev_get_queue(bdev);
2455         int length, max_nr_vecs = 0;
2456         uint8_t *address;
2457         struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
2458         int need_new_bio;
2459         struct scst_blockio_work *blockio_work;
2460         int bios = 0;
2461
2462         TRACE_ENTRY();
2463
2464         if (virt_dev->nullio)
2465                 goto out;
2466
2467         /* Allocate and initialize blockio_work struct */
2468         blockio_work = kmem_cache_alloc(blockio_work_cachep, GFP_KERNEL);
2469         if (blockio_work == NULL)
2470                 goto out_no_mem;
2471
2472         blockio_work->cmd = cmd;
2473
2474         if (q)
2475                 max_nr_vecs = min(bio_get_nr_vecs(bdev), BIO_MAX_PAGES);
2476         else
2477                 max_nr_vecs = 1;
2478
2479         need_new_bio = 1;
2480
2481         length = scst_get_buf_first(cmd, &address);
2482         while (length > 0) {
2483                 int len, bytes, off, thislen;
2484                 uint8_t *addr;
2485                 u64 lba_start0;
2486
2487                 addr = address;
2488                 off = offset_in_page(addr);
2489                 len = length;
2490                 thislen = 0;
2491                 lba_start0 = lba_start;
2492
2493                 while (len > 0) {
2494                         int rc;
2495                         struct page *page = virt_to_page(addr);
2496
2497                         if (need_new_bio) {
2498                                 bio = bio_alloc(GFP_KERNEL, max_nr_vecs);
2499                                 if (!bio) {
2500                                         PRINT_ERROR("Failed to create bio "
2501                                                 "for data segment= %d cmd %p",
2502                                                 cmd->get_sg_buf_entry_num, cmd);
2503                                         goto out_no_bio;
2504                                 }
2505
2506                                 bios++;
2507                                 need_new_bio = 0;
2508                                 bio->bi_end_io = blockio_endio;
2509                                 bio->bi_sector = lba_start0 <<
2510                                         (virt_dev->block_shift - 9);
2511                                 bio->bi_bdev = bdev;
2512                                 bio->bi_private = blockio_work;
2513 #if 0 /* It could be win, but could be not, so a performance study is needed */
2514                                 bio->bi_rw |= 1 << BIO_RW_SYNC;
2515 #endif
2516                                 if (!hbio)
2517                                         hbio = tbio = bio;
2518                                 else
2519                                         tbio = tbio->bi_next = bio;
2520                         }
2521
2522                         bytes = min_t(unsigned int, len, PAGE_SIZE - off);
2523
2524                         rc = bio_add_page(bio, page, bytes, off);
2525                         if (rc < bytes) {
2526                                 sBUG_ON(rc != 0);
2527                                 need_new_bio = 1;
2528                                 lba_start0 += thislen >> virt_dev->block_shift;
2529                                 thislen = 0;
2530                                 continue;
2531                         }
2532
2533                         addr += PAGE_SIZE;
2534                         thislen += bytes;
2535                         len -= bytes;
2536                         off = 0;
2537                 }
2538
2539                 lba_start += length >> virt_dev->block_shift;
2540
2541                 scst_put_buf(cmd, address);
2542                 length = scst_get_buf_next(cmd, &address);
2543         }
2544
2545         /* +1 to prevent erroneous too early command completion */
2546         atomic_set(&blockio_work->bios_inflight, bios+1);
2547
2548         while (hbio) {
2549                 bio = hbio;
2550                 hbio = hbio->bi_next;
2551                 bio->bi_next = NULL;
2552                 submit_bio(write, bio);
2553         }
2554
2555         if (q && q->unplug_fn)
2556                 q->unplug_fn(q);
2557
2558         blockio_check_finish(blockio_work);
2559
2560 out:
2561         TRACE_EXIT();
2562         return;
2563
2564 out_no_bio:
2565         while (hbio) {
2566                 bio = hbio;
2567                 hbio = hbio->bi_next;
2568                 bio_put(bio);
2569         }
2570         kmem_cache_free(blockio_work_cachep, blockio_work);
2571
2572 out_no_mem:
2573         scst_set_busy(cmd);
2574         goto out;
2575 }
2576
2577 static void vdisk_exec_verify(struct scst_cmd *cmd,
2578         struct scst_vdisk_thr *thr, loff_t loff)
2579 {
2580         mm_segment_t old_fs;
2581         loff_t err;
2582         ssize_t length, len_mem = 0;
2583         uint8_t *address_sav, *address;
2584         int compare;
2585         struct scst_vdisk_dev *virt_dev =
2586             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2587         struct file *fd = thr->fd;
2588         uint8_t *mem_verify = NULL;
2589
2590         TRACE_ENTRY();
2591
2592         if (vdisk_fsync(thr, loff, cmd->bufflen, cmd) != 0)
2593                 goto out;
2594
2595         /*
2596          * Until the cache is cleared prior the verifying, there is not
2597          * much point in this code. ToDo.
2598          *
2599          * Nevertherless, this code is valuable if the data have not read
2600          * from the file/disk yet.
2601          */
2602
2603         /* SEEK */
2604         old_fs = get_fs();
2605         set_fs(get_ds());
2606
2607         if (!virt_dev->nullio) {
2608                 if (fd->f_op->llseek)
2609                         err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
2610                 else
2611                         err = default_llseek(fd, loff, 0/*SEEK_SET*/);
2612                 if (err != loff) {
2613                         PRINT_ERROR("lseek trouble %lld != %lld",
2614                                     (long long unsigned int)err,
2615                                     (long long unsigned int)loff);
2616                         scst_set_cmd_error(cmd,
2617                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
2618                         goto out_set_fs;
2619                 }
2620         }
2621
2622         mem_verify = vmalloc(LEN_MEM);
2623         if (mem_verify == NULL) {
2624                 PRINT_ERROR("Unable to allocate memory %d for verify",
2625                                LEN_MEM);
2626                 scst_set_cmd_error(cmd,
2627                                    SCST_LOAD_SENSE(scst_sense_hardw_error));
2628                 goto out_set_fs;
2629         }
2630
2631         length = scst_get_buf_first(cmd, &address);
2632         address_sav = address;
2633         if (!length && cmd->data_len) {
2634                 length = cmd->data_len;
2635                 compare = 0;
2636         } else
2637                 compare = 1;
2638
2639         while (length > 0) {
2640                 len_mem = (length > LEN_MEM) ? LEN_MEM : length;
2641                 TRACE_DBG("Verify: length %zd - len_mem %zd", length, len_mem);
2642
2643                 if (!virt_dev->nullio)
2644                         err = fd->f_op->read(fd,
2645                                 (char __force __user *)mem_verify, len_mem,
2646                                 &fd->f_pos);
2647                 else
2648                         err = len_mem;
2649                 if ((err < 0) || (err < len_mem)) {
2650                         PRINT_ERROR("verify() returned %lld from %zd",
2651                                     (long long unsigned int)err, len_mem);
2652                         if (err == -EAGAIN)
2653                                 scst_set_busy(cmd);
2654                         else {
2655                                 scst_set_cmd_error(cmd,
2656                                     SCST_LOAD_SENSE(scst_sense_read_error));
2657                         }
2658                         if (compare)
2659                                 scst_put_buf(cmd, address_sav);
2660                         goto out_set_fs;
2661                 }
2662                 if (compare && memcmp(address, mem_verify, len_mem) != 0) {
2663                         TRACE_DBG("Verify: error memcmp length %zd", length);
2664                         scst_set_cmd_error(cmd,
2665                             SCST_LOAD_SENSE(scst_sense_miscompare_error));
2666                         scst_put_buf(cmd, address_sav);
2667                         goto out_set_fs;
2668                 }
2669                 length -= len_mem;
2670                 address += len_mem;
2671                 if (compare && length <= 0) {
2672                         scst_put_buf(cmd, address_sav);
2673                         length = scst_get_buf_next(cmd, &address);
2674                         address_sav = address;
2675                 }
2676         }
2677
2678         if (length < 0) {
2679                 PRINT_ERROR("scst_get_buf_() failed: %zd", length);
2680                 scst_set_cmd_error(cmd,
2681                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2682         }
2683
2684 out_set_fs:
2685         set_fs(old_fs);
2686         if (mem_verify)
2687                 vfree(mem_verify);
2688
2689 out:
2690         TRACE_EXIT();
2691         return;
2692 }
2693
2694 static inline struct scst_vdisk_dev *vdisk_alloc_dev(void)
2695 {
2696         struct scst_vdisk_dev *dev;
2697         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2698         if (dev == NULL) {
2699                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of virtual "
2700                         "device failed");
2701                 goto out;
2702         }
2703         spin_lock_init(&dev->flags_lock);
2704 out:
2705         return dev;
2706 }
2707
2708 static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
2709         struct scst_tgt_dev *tgt_dev)
2710 {
2711         TRACE_ENTRY();
2712
2713         if ((mcmd->fn == SCST_LUN_RESET) || (mcmd->fn == SCST_TARGET_RESET)) {
2714                 /* Restore default values */
2715                 struct scst_device *dev = tgt_dev->dev;
2716                 struct scst_vdisk_dev *virt_dev =
2717                         (struct scst_vdisk_dev *)dev->dh_priv;
2718                 dev->tst = DEF_TST;
2719                 dev->d_sense = DEF_DSENSE;
2720                 if (virt_dev->wt_flag && !virt_dev->nv_cache)
2721                         dev->queue_alg = DEF_QUEUE_ALG_WT;
2722                 else
2723                         dev->queue_alg = DEF_QUEUE_ALG;
2724                 dev->swp = DEF_SWP;
2725                 dev->tas = DEF_TAS;
2726         }
2727
2728         TRACE_EXIT();
2729         return SCST_DEV_TM_NOT_COMPLETED;
2730 }
2731
2732 /*
2733  * Called when a file in the /proc/VDISK_NAME/VDISK_NAME is read
2734  */
2735 static int vdisk_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type)
2736 {
2737         int res = 0;
2738         struct scst_vdisk_dev *virt_dev;
2739
2740         TRACE_ENTRY();
2741
2742         if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
2743                 res = -EINTR;
2744                 goto out;
2745         }
2746
2747         seq_printf(seq, "%-17s %-11s %-11s %-15s %s\n",
2748                    "Name", "Size(MB)", "Block size", "Options", "File name");
2749
2750         list_for_each_entry(virt_dev, &vdisk_dev_list, vdisk_dev_list_entry) {
2751                 int c;
2752                 seq_printf(seq, "%-17s %-11d %-12d", virt_dev->name,
2753                         (uint32_t)(virt_dev->file_size >> 20),
2754                         virt_dev->block_size);
2755                 c = 0;
2756                 if (virt_dev->wt_flag) {
2757                         seq_printf(seq, "WT ");
2758                         c += 3;
2759                 }
2760                 if (virt_dev->nv_cache) {
2761                         seq_printf(seq, "NV ");
2762                         c += 3;
2763                 }
2764                 if (virt_dev->rd_only_flag) {
2765                         seq_printf(seq, "RO ");
2766                         c += 3;
2767                 }
2768                 if (virt_dev->o_direct_flag) {
2769                         seq_printf(seq, "DR ");
2770                         c += 3;
2771                 }
2772                 if (virt_dev->nullio) {
2773                         seq_printf(seq, "NIO ");
2774                         c += 4;
2775                 }
2776                 if (virt_dev->blockio) {
2777                         seq_printf(seq, "BIO ");
2778                         c += 4;
2779                 }
2780                 if (virt_dev->removable) {
2781                         seq_printf(seq, "RM ");
2782                         c += 4;
2783                 }
2784                 while (c < 16) {
2785                         seq_printf(seq, " ");
2786                         c++;
2787                 }
2788                 seq_printf(seq, "%s\n", virt_dev->file_name);
2789         }
2790         mutex_unlock(&scst_vdisk_mutex);
2791 out:
2792         TRACE_EXIT_RES(res);
2793         return res;
2794 }
2795
2796 static void vdisk_report_registering(const char *type,
2797         const struct scst_vdisk_dev *virt_dev)
2798 {
2799         char buf[128];
2800         int i, j;
2801
2802         i = snprintf(buf, sizeof(buf), "Registering virtual %s device %s ",
2803                 type, virt_dev->name);
2804         j = i;
2805
2806         if (virt_dev->wt_flag)
2807                 i += snprintf(&buf[i], sizeof(buf) - i, "(WRITE_THROUGH");
2808
2809         if (virt_dev->nv_cache)
2810                 i += snprintf(&buf[i], sizeof(buf) - i, "%sNV_CACHE",
2811                         (j == i) ? "(" : ", ");
2812
2813         if (virt_dev->rd_only_flag)
2814                 i += snprintf(&buf[i], sizeof(buf) - i, "%sREAD_ONLY",
2815                         (j == i) ? "(" : ", ");
2816
2817         if (virt_dev->o_direct_flag)
2818                 i += snprintf(&buf[i], sizeof(buf) - i, "%sO_DIRECT",
2819                         (j == i) ? "(" : ", ");
2820
2821         if (virt_dev->nullio)
2822                 i += snprintf(&buf[i], sizeof(buf) - i, "%sNULLIO",
2823                         (j == i) ? "(" : ", ");
2824
2825         if (virt_dev->blockio)
2826                 i += snprintf(&buf[i], sizeof(buf) - i, "%sBLOCKIO",
2827                         (j == i) ? "(" : ", ");
2828
2829         if (virt_dev->removable)
2830                 i += snprintf(&buf[i], sizeof(buf) - i, "%sREMOVABLE",
2831                         (j == i) ? "(" : ", ");
2832
2833         if (j == i)
2834                 PRINT_INFO("%s", buf);
2835         else
2836                 PRINT_INFO("%s)", buf);
2837
2838         return;
2839 }
2840
2841 /* scst_vdisk_mutex supposed to be held */
2842 static int vdisk_resync_size(struct scst_vdisk_dev *virt_dev)
2843 {
2844         loff_t err;
2845         int res = 0;
2846
2847         if (!virt_dev->nullio) {
2848                 res = vdisk_get_check_file_size(virt_dev->file_name,
2849                                 virt_dev->blockio, &err);
2850                 if (res != 0)
2851                         goto out;
2852         } else
2853                 err = VDISK_NULLIO_SIZE;
2854
2855         res = scst_suspend_activity(true);
2856         if (res != 0)
2857                 goto out;
2858
2859         virt_dev->file_size = err;
2860         virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
2861
2862         scst_dev_del_all_thr_data(virt_dev->dev);
2863
2864         PRINT_INFO("New size of SCSI target virtual disk %s "
2865                 "(fs=%lldMB, bs=%d, nblocks=%lld, cyln=%lld%s)",
2866                 virt_dev->name, virt_dev->file_size >> 20,
2867                 virt_dev->block_size,
2868                 (long long unsigned int)virt_dev->nblocks,
2869                 (long long unsigned int)virt_dev->nblocks/64/32,
2870                 virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
2871                                                 "than 1" : "");
2872
2873         scst_capacity_data_changed(virt_dev->dev);
2874
2875         scst_resume_activity();
2876
2877 out:
2878         return res;
2879 }
2880
2881 /*
2882  * Called when a file in the /proc/VDISK_NAME/VDISK_NAME is written
2883  */
2884 static int vdisk_write_proc(char *buffer, char **start, off_t offset,
2885         int length, int *eof, struct scst_dev_type *dev_type)
2886 {
2887         int res = 0, action;
2888         char *p, *name, *file_name;
2889         struct scst_vdisk_dev *virt_dev, *vv;
2890         uint32_t block_size = DEF_DISK_BLOCKSIZE;
2891         int block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
2892         size_t len;
2893
2894         TRACE_ENTRY();
2895
2896         /* VERY UGLY code. You can rewrite it if you want */
2897
2898         if (buffer[0] == '\0')
2899                 goto out;
2900
2901         if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
2902                 res = -EINTR;
2903                 goto out;
2904         }
2905
2906         p = buffer;
2907         if (p[strlen(p) - 1] == '\n')
2908                 p[strlen(p) - 1] = '\0';
2909         if (!strncmp("close ", p, 6)) {
2910                 p += 6;
2911                 action = 0;
2912         } else if (!strncmp("open ", p, 5)) {
2913                 p += 5;
2914                 action = 1;
2915         } else if (!strncmp("resync_size ", p, 12)) {
2916                 p += 12;
2917                 action = 2;
2918         } else {
2919                 PRINT_ERROR("Unknown action \"%s\"", p);
2920                 res = -EINVAL;
2921                 goto out_up;
2922         }
2923
2924         while (isspace(*p) && *p != '\0')
2925                 p++;
2926         name = p;
2927         while (!isspace(*p) && *p != '\0')
2928                 p++;
2929         *p++ = '\0';
2930         if (*name == '\0') {
2931                 PRINT_ERROR("%s", "Name required");
2932                 res = -EINVAL;
2933                 goto out_up;
2934         } else if (strlen(name) >= sizeof(virt_dev->name)) {
2935                 PRINT_ERROR("Name is too long (max %zd "
2936                         "characters)", sizeof(virt_dev->name)-1);
2937                 res = -EINVAL;
2938                 goto out_up;
2939         }
2940
2941         if (action == 1) {
2942                 /* open */
2943                 virt_dev = NULL;
2944                 list_for_each_entry(vv, &vdisk_dev_list,
2945                                         vdisk_dev_list_entry) {
2946                         if (strcmp(vv->name, name) == 0) {
2947                                 virt_dev = vv;
2948                                 break;
2949                         }
2950                 }
2951                 if (virt_dev) {
2952                         PRINT_ERROR("Virtual device with name "
2953                                    "%s already exist", name);
2954                         res = -EINVAL;
2955                         goto out_up;
2956                 }
2957
2958                 while (isspace(*p) && *p != '\0')
2959                         p++;
2960                 file_name = p;
2961                 while (!isspace(*p) && *p != '\0')
2962                         p++;
2963                 *p++ = '\0';
2964                 if (*file_name == '\0') {
2965                         PRINT_ERROR("%s", "File name required");
2966                         res = -EINVAL;
2967                         goto out_up;
2968                 }
2969
2970                 virt_dev = vdisk_alloc_dev();
2971                 if (virt_dev == NULL) {
2972                         TRACE(TRACE_OUT_OF_MEM, "%s",
2973                                   "Allocation of virt_dev failed");
2974                         res = -ENOMEM;
2975                         goto out_up;
2976                 }
2977
2978                 while (isspace(*p) && *p != '\0')
2979                         p++;
2980
2981                 if (isdigit(*p)) {
2982                         char *pp;
2983                         block_size = simple_strtoul(p, &pp, 0);
2984                         p = pp;
2985                         if ((*p != '\0') && !isspace(*p)) {
2986                                 PRINT_ERROR("Parse error: \"%s\"", p);
2987                                 res = -EINVAL;
2988                                 goto out_free_vdev;
2989                         }
2990                         while (isspace(*p) && *p != '\0')
2991                                 p++;
2992
2993                         block_shift = scst_calc_block_shift(block_size);
2994                         if (block_shift < 9) {
2995                                 res = -EINVAL;
2996                                 goto out_free_vdev;
2997                         }
2998                 }
2999                 virt_dev->block_size = block_size;
3000                 virt_dev->block_shift = block_shift;
3001
3002                 while (*p != '\0') {
3003                         if (!strncmp("WRITE_THROUGH", p, 13)) {
3004                                 p += 13;
3005                                 virt_dev->wt_flag = 1;
3006                                 TRACE_DBG("%s", "WRITE_THROUGH");
3007                         } else if (!strncmp("NV_CACHE", p, 8)) {
3008                                 p += 8;
3009                                 virt_dev->nv_cache = 1;
3010                                 TRACE_DBG("%s", "NON-VOLATILE CACHE");
3011                         } else if (!strncmp("READ_ONLY", p, 9)) {
3012                                 p += 9;
3013                                 virt_dev->rd_only_flag = 1;
3014                                 TRACE_DBG("%s", "READ_ONLY");
3015                         } else if (!strncmp("O_DIRECT", p, 8)) {
3016                                 p += 8;
3017 #if 0
3018
3019                                 virt_dev->o_direct_flag = 1;
3020                                 TRACE_DBG("%s", "O_DIRECT");
3021 #else
3022                                 PRINT_INFO("%s flag doesn't currently"
3023                                         " work, ignoring it, use fileio_tgt "
3024                                         "in O_DIRECT mode instead", "O_DIRECT");
3025 #endif
3026                         } else if (!strncmp("NULLIO", p, 6)) {
3027                                 p += 6;
3028                                 virt_dev->nullio = 1;
3029                                 TRACE_DBG("%s", "NULLIO");
3030                         } else if (!strncmp("BLOCKIO", p, 7)) {
3031                                 p += 7;
3032                                 virt_dev->blockio = 1;
3033                                 TRACE_DBG("%s", "BLOCKIO");
3034                         } else if (!strncmp("REMOVABLE", p, 9)) {
3035                                 p += 9;
3036                                 virt_dev->removable = 1;
3037                                 TRACE_DBG("%s", "REMOVABLE");
3038                         } else {
3039                                 PRINT_ERROR("Unknown flag \"%s\"", p);
3040                                 res = -EINVAL;
3041                                 goto out_free_vdev;
3042                         }
3043                         while (isspace(*p) && *p != '\0')
3044                                 p++;
3045                 }
3046
3047                 if (!virt_dev->nullio && (*file_name != '/')) {
3048                         PRINT_ERROR("File path \"%s\" is not "
3049                                 "absolute", file_name);
3050                         res = -EINVAL;
3051                         goto out_up;
3052                 }
3053
3054                 strcpy(virt_dev->name, name);
3055
3056                 scnprintf(virt_dev->usn, sizeof(virt_dev->usn), "%llx",
3057                                 vdisk_gen_dev_id_num(virt_dev));
3058                 TRACE_DBG("usn %s", virt_dev->usn);
3059
3060                 len = strlen(file_name) + 1;
3061                 virt_dev->file_name = kmalloc(len, GFP_KERNEL);
3062                 if (virt_dev->file_name == NULL) {
3063                         TRACE(TRACE_OUT_OF_MEM, "%s",
3064                                   "Allocation of file_name failed");
3065                         res = -ENOMEM;
3066                         goto out_free_vdev;
3067                 }
3068                 strncpy(virt_dev->file_name, file_name, len);
3069
3070                 list_add_tail(&virt_dev->vdisk_dev_list_entry,
3071                                   &vdisk_dev_list);
3072
3073                 if (virt_dev->blockio) {
3074                         vdisk_report_registering("BLOCKIO", virt_dev);
3075                         virt_dev->virt_id =
3076                                 scst_register_virtual_device(&vdisk_blk_devtype,
3077                                                          virt_dev->name);
3078                 } else if (virt_dev->nullio) {
3079                         vdisk_report_registering("NULLIO", virt_dev);
3080                         virt_dev->virt_id =
3081                                scst_register_virtual_device(&vdisk_null_devtype,
3082                                                          virt_dev->name);
3083                 } else {
3084                         vdisk_report_registering("FILEIO", virt_dev);
3085                         virt_dev->virt_id =
3086                                scst_register_virtual_device(&vdisk_file_devtype,
3087                                                          virt_dev->name);
3088                 }
3089                 if (virt_dev->virt_id < 0) {
3090                         res = virt_dev->virt_id;
3091                         goto out_free_vpath;
3092                 }
3093                 TRACE_DBG("Added virt_dev (name %s, file name %s, "
3094                         "id %d, block size %d) to "
3095                         "vdisk_dev_list", virt_dev->name,
3096                         virt_dev->file_name, virt_dev->virt_id,
3097                         virt_dev->block_size);
3098         } else if (action == 0) {       /* close */
3099                 virt_dev = NULL;
3100                 list_for_each_entry(vv, &vdisk_dev_list,
3101                                         vdisk_dev_list_entry) {
3102                         if (strcmp(vv->name, name) == 0) {
3103                                 virt_dev = vv;
3104                                 break;
3105                         }
3106                 }
3107                 if (virt_dev == NULL) {
3108                         PRINT_ERROR("Device %s not found", name);
3109                         res = -EINVAL;
3110                         goto out_up;
3111                 }
3112                 scst_unregister_virtual_device(virt_dev->virt_id);
3113                 PRINT_INFO("Virtual device %s unregistered",
3114                         virt_dev->name);
3115                 TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
3116
3117                 list_del(&virt_dev->vdisk_dev_list_entry);
3118
3119                 kfree(virt_dev->file_name);
3120                 kfree(virt_dev);
3121         } else {        /* resync_size */
3122                 virt_dev = NULL;
3123                 list_for_each_entry(vv, &vdisk_dev_list,
3124                                         vdisk_dev_list_entry) {
3125                         if (strcmp(vv->name, name) == 0) {
3126                                 virt_dev = vv;
3127                                 break;
3128                         }
3129                 }
3130                 if (virt_dev == NULL) {
3131                         PRINT_ERROR("Device %s not found", name);
3132                         res = -EINVAL;
3133                         goto out_up;
3134                 }
3135
3136                 res = vdisk_resync_size(virt_dev);
3137                 if (res != 0)
3138                         goto out_up;
3139         }
3140         res = length;
3141
3142 out_up:
3143         mutex_unlock(&scst_vdisk_mutex);
3144
3145 out:
3146         TRACE_EXIT_RES(res);
3147         return res;
3148
3149 out_free_vpath:
3150         list_del(&virt_dev->vdisk_dev_list_entry);
3151         kfree(virt_dev->file_name);
3152
3153 out_free_vdev:
3154         kfree(virt_dev);
3155         goto out_up;
3156 }
3157
3158 /* scst_vdisk_mutex supposed to be held */
3159 static int vcdrom_open(char *p, char *name)
3160 {
3161         struct scst_vdisk_dev *virt_dev, *vv;
3162         char *file_name;
3163         int len;
3164         int res = 0;
3165         int cdrom_empty;
3166
3167         virt_dev = NULL;
3168         list_for_each_entry(vv, &vcdrom_dev_list, vdisk_dev_list_entry)
3169         {
3170                 if (strcmp(vv->name, name) == 0) {
3171                         virt_dev = vv;
3172                         break;
3173                 }
3174         }
3175         if (virt_dev) {
3176                 PRINT_ERROR("Virtual device with name "
3177                        "%s already exist", name);
3178                 res = -EINVAL;
3179                 goto out;
3180         }
3181
3182         while (isspace(*p) && *p != '\0')
3183                 p++;
3184         file_name = p;
3185         while (!isspace(*p) && *p != '\0')
3186                 p++;
3187         *p++ = '\0';
3188         if (*file_name == '\0') {
3189                 cdrom_empty = 1;
3190                 TRACE_DBG("%s", "No media");
3191         } else if (*file_name != '/') {
3192                 PRINT_ERROR("File path \"%s\" is not "
3193                         "absolute", file_name);
3194                 res = -EINVAL;
3195                 goto out;
3196         } else
3197                 cdrom_empty = 0;
3198
3199         virt_dev = vdisk_alloc_dev();
3200         if (virt_dev == NULL) {
3201                 TRACE(TRACE_OUT_OF_MEM, "%s",
3202                       "Allocation of virt_dev failed");
3203                 res = -ENOMEM;
3204                 goto out;
3205         }
3206         virt_dev->cdrom_empty = cdrom_empty;
3207
3208         strcpy(virt_dev->name, name);
3209
3210         scnprintf(virt_dev->usn, sizeof(virt_dev->usn), "%llx",
3211                         vdisk_gen_dev_id_num(virt_dev));
3212         TRACE_DBG("usn %s", virt_dev->usn);
3213
3214         if (!virt_dev->cdrom_empty) {
3215                 len = strlen(file_name) + 1;
3216                 virt_dev->file_name = kmalloc(len, GFP_KERNEL);
3217                 if (virt_dev->file_name == NULL) {
3218                         TRACE(TRACE_OUT_OF_MEM, "%s",
3219                               "Allocation of file_name failed");
3220                         res = -ENOMEM;
3221                         goto out_free_vdev;
3222                 }
3223                 strncpy(virt_dev->file_name, file_name, len);
3224         }
3225
3226         list_add_tail(&virt_dev->vdisk_dev_list_entry,
3227                       &vcdrom_dev_list);
3228
3229         PRINT_INFO("Registering virtual CDROM %s", name);
3230
3231         virt_dev->virt_id =
3232             scst_register_virtual_device(&vcdrom_devtype,
3233                                          virt_dev->name);
3234         if (virt_dev->virt_id < 0) {
3235                 res = virt_dev->virt_id;
3236                 goto out_free_vpath;
3237         }
3238         TRACE_DBG("Added virt_dev (name %s file_name %s id %d) "
3239                   "to vcdrom_dev_list", virt_dev->name,
3240                   virt_dev->file_name, virt_dev->virt_id);
3241
3242 out:
3243         return res;
3244
3245 out_free_vpath:
3246         list_del(&virt_dev->vdisk_dev_list_entry);
3247         kfree(virt_dev->file_name);
3248
3249 out_free_vdev:
3250         kfree(virt_dev);
3251         goto out;
3252 }
3253
3254 /* scst_vdisk_mutex supposed to be held */
3255 static int vcdrom_close(char *name)
3256 {
3257         struct scst_vdisk_dev *virt_dev, *vv;
3258         int res = 0;
3259
3260         virt_dev = NULL;
3261         list_for_each_entry(vv, &vcdrom_dev_list,
3262                             vdisk_dev_list_entry)
3263         {
3264                 if (strcmp(vv->name, name) == 0) {
3265                         virt_dev = vv;
3266                         break;
3267                 }
3268         }
3269         if (virt_dev == NULL) {
3270                 PRINT_ERROR("Virtual device with name "
3271                        "%s not found", name);
3272                 res = -EINVAL;
3273                 goto out;
3274         }
3275         scst_unregister_virtual_device(virt_dev->virt_id);
3276         PRINT_INFO("Virtual device %s unregistered",
3277                 virt_dev->name);
3278         TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
3279
3280         list_del(&virt_dev->vdisk_dev_list_entry);
3281
3282         kfree(virt_dev->file_name);
3283         kfree(virt_dev);
3284
3285 out:
3286         return res;
3287 }
3288
3289 /* scst_vdisk_mutex supposed to be held */
3290 static int vcdrom_change(char *p, char *name)
3291 {
3292         loff_t err;
3293         struct scst_vdisk_dev *virt_dev, *vv;
3294         char *file_name, *fn = NULL, *old_fn;
3295         int len;
3296         int res = 0;
3297
3298         virt_dev = NULL;
3299         list_for_each_entry(vv, &vcdrom_dev_list,
3300                             vdisk_dev_list_entry) {
3301                 if (strcmp(vv->name, name) == 0) {
3302                         virt_dev = vv;
3303                         break;
3304                 }
3305         }
3306         if (virt_dev == NULL) {
3307                 PRINT_ERROR("Virtual device with name "
3308                        "%s not found", name);
3309                 res = -EINVAL;
3310                 goto out;
3311         }
3312
3313         while (isspace(*p) && *p != '\0')
3314                 p++;
3315         file_name = p;
3316         while (!isspace(*p) && *p != '\0')
3317                 p++;
3318         *p++ = '\0';
3319         if (*file_name == '\0') {
3320                 virt_dev->cdrom_empty = 1;
3321                 TRACE_DBG("%s", "No media");
3322         } else if (*file_name != '/') {
3323                 PRINT_ERROR("File path \"%s\" is not "
3324                         "absolute", file_name);
3325                 res = -EINVAL;
3326                 goto out;
3327         } else
3328                 virt_dev->cdrom_empty = 0;
3329
3330         old_fn = virt_dev->file_name;
3331
3332         if (!virt_dev->cdrom_empty && !virt_dev->nullio) {
3333                 len = strlen(file_name) + 1;
3334                 fn = kmalloc(len, GFP_KERNEL);
3335                 if (fn == NULL) {
3336                         TRACE(TRACE_OUT_OF_MEM, "%s",
3337                                 "Allocation of file_name failed");
3338                         res = -ENOMEM;
3339                         goto out;
3340                 }
3341
3342                 strncpy(fn, file_name, len);
3343                 virt_dev->file_name = fn;
3344
3345                 res = vdisk_get_check_file_size(virt_dev->file_name,
3346                                 virt_dev->blockio, &err);
3347                 if (res != 0)
3348                         goto out_free;
3349         } else {
3350                 err = 0;
3351                 virt_dev->file_name = NULL;
3352         }
3353
3354          if (virt_dev->nullio)
3355                 err = VDISK_NULLIO_SIZE;
3356
3357         res = scst_suspend_activity(true);
3358         if (res != 0)
3359                 goto out_free;
3360
3361         if (virt_dev->prevent_allow_medium_removal) {
3362                 PRINT_ERROR("Prevent medium removal for "
3363                         "virtual device with name %s", name);
3364                 res = -EINVAL;
3365                 goto out_free_resume;
3366         }
3367
3368         virt_dev->file_size = err;
3369         virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
3370         if (!virt_dev->cdrom_empty)
3371                 virt_dev->media_changed = 1;
3372
3373         scst_dev_del_all_thr_data(virt_dev->dev);
3374
3375         if (!virt_dev->cdrom_empty) {
3376                 PRINT_INFO("Changed SCSI target virtual cdrom %s "
3377                         "(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld,"
3378                         " cyln=%lld%s)", virt_dev->name, virt_dev->file_name,
3379                         virt_dev->file_size >> 20, virt_dev->block_size,
3380                         (long long unsigned int)virt_dev->nblocks,
3381                         (long long unsigned int)virt_dev->nblocks/64/32,
3382                         virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
3383                                                         "than 1" : "");
3384         } else {
3385                 PRINT_INFO("Removed media from SCSI target virtual cdrom %s",
3386                         virt_dev->name);
3387         }
3388
3389         kfree(old_fn);
3390
3391 out_resume:
3392         scst_resume_activity();
3393
3394 out:
3395         return res;
3396
3397 out_free:
3398         virt_dev->file_name = old_fn;
3399         kfree(fn);
3400         goto out;
3401
3402 out_free_resume:
3403         virt_dev->file_name = old_fn;
3404         kfree(fn);
3405         goto out_resume;
3406 }
3407
3408 /*
3409  * Called when a file in the /proc/VCDROM_NAME/VCDROM_NAME is read
3410  */
3411 static int vcdrom_read_proc(struct seq_file *seq,
3412                             struct scst_dev_type *dev_type)
3413 {
3414         int res = 0;
3415         struct scst_vdisk_dev *virt_dev;
3416
3417         TRACE_ENTRY();
3418
3419         if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
3420                 res = -EINTR;
3421                 goto out;
3422         }
3423
3424<