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