- Memory barriers cleanup. Comments for them improved
[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_tgt_dev *tgt_dev = cmd->tgt_dev;
716         struct scst_vdisk_dev *virt_dev =
717                 (struct scst_vdisk_dev *)dev->dh_priv;
718         struct scst_thr_data_hdr *d;
719         struct scst_vdisk_thr *thr = NULL;
720         int fua = 0;
721
722         TRACE_ENTRY();
723
724         switch (cmd->queue_type) {
725         case SCST_CMD_QUEUE_ORDERED:
726                 TRACE(TRACE_ORDER, "ORDERED cmd %p", cmd);
727                 break;
728         case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
729                 TRACE(TRACE_ORDER, "HQ cmd %p", cmd);
730                 break;
731         default:
732                 break;
733         }
734
735         rc = scst_check_local_events(cmd);
736         if (unlikely(rc != 0))
737                 goto out_done;
738
739         cmd->status = 0;
740         cmd->msg_status = 0;
741         cmd->host_status = DID_OK;
742         cmd->driver_status = 0;
743
744         if (!virt_dev->nullio) {
745                 d = scst_find_thr_data(tgt_dev);
746                 if (unlikely(d == NULL)) {
747                         thr = vdisk_init_thr_data(tgt_dev);
748                         if (thr == NULL) {
749                                 scst_set_busy(cmd);
750                                 goto out_compl;
751                         }
752                         scst_thr_data_get(&thr->hdr);
753                 } else
754                         thr = container_of(d, struct scst_vdisk_thr, hdr);
755         } else {
756                 thr = &nullio_thr_data;
757                 scst_thr_data_get(&thr->hdr);
758         }
759
760         switch (opcode) {
761         case READ_6:
762         case WRITE_6:
763         case VERIFY_6:
764                 lba_start = (((cdb[1] & 0x1f) << (BYTE * 2)) +
765                              (cdb[2] << (BYTE * 1)) +
766                              (cdb[3] << (BYTE * 0)));
767                 data_len = cmd->bufflen;
768                 break;
769         case READ_10:
770         case READ_12:
771         case WRITE_10:
772         case WRITE_12:
773         case VERIFY:
774         case WRITE_VERIFY:
775         case WRITE_VERIFY_12:
776         case VERIFY_12:
777                 lba_start |= ((u64)cdb[2]) << 24;
778                 lba_start |= ((u64)cdb[3]) << 16;
779                 lba_start |= ((u64)cdb[4]) << 8;
780                 lba_start |= ((u64)cdb[5]);
781                 data_len = cmd->bufflen;
782                 break;
783         case READ_16:
784         case WRITE_16:
785         case WRITE_VERIFY_16:
786         case VERIFY_16:
787                 lba_start |= ((u64)cdb[2]) << 56;
788                 lba_start |= ((u64)cdb[3]) << 48;
789                 lba_start |= ((u64)cdb[4]) << 40;
790                 lba_start |= ((u64)cdb[5]) << 32;
791                 lba_start |= ((u64)cdb[6]) << 24;
792                 lba_start |= ((u64)cdb[7]) << 16;
793                 lba_start |= ((u64)cdb[8]) << 8;
794                 lba_start |= ((u64)cdb[9]);
795                 data_len = cmd->bufflen;
796                 break;
797         case SYNCHRONIZE_CACHE:
798                 lba_start |= ((u64)cdb[2]) << 24;
799                 lba_start |= ((u64)cdb[3]) << 16;
800                 lba_start |= ((u64)cdb[4]) << 8;
801                 lba_start |= ((u64)cdb[5]);
802                 data_len = ((cdb[7] << (BYTE * 1)) + (cdb[8] << (BYTE * 0)))
803                                 << virt_dev->block_shift;
804                 if (data_len == 0)
805                         data_len = virt_dev->file_size -
806                                 ((loff_t)lba_start << virt_dev->block_shift);
807                 break;
808         }
809
810         loff = (loff_t)lba_start << virt_dev->block_shift;
811         TRACE_DBG("cmd %p, lba_start %lld, loff %lld, data_len %lld", cmd,
812                   (long long unsigned int)lba_start,
813                   (long long unsigned int)loff,
814                   (long long unsigned int)data_len);
815         if (unlikely(loff < 0) || unlikely(data_len < 0) ||
816             unlikely((loff + data_len) > virt_dev->file_size)) {
817                 PRINT_INFO("Access beyond the end of the device "
818                         "(%lld of %lld, len %lld)",
819                            (long long unsigned int)loff,
820                            (long long unsigned int)virt_dev->file_size,
821                            (long long unsigned int)data_len);
822                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
823                                         scst_sense_block_out_range_error));
824                 goto out_compl;
825         }
826
827         switch (opcode) {
828         case WRITE_10:
829         case WRITE_12:
830         case WRITE_16:
831                 fua = (cdb[1] & 0x8);
832                 if (fua) {
833                         TRACE(TRACE_ORDER, "FUA: loff=%lld, "
834                                 "data_len=%lld", (long long unsigned int)loff,
835                                 (long long unsigned int)data_len);
836                 }
837                 break;
838         }
839
840         switch (opcode) {
841         case READ_6:
842         case READ_10:
843         case READ_12:
844         case READ_16:
845                 if (virt_dev->blockio) {
846                         blockio_exec_rw(cmd, thr, lba_start, 0);
847                         goto out_thr;
848                 } else
849                         vdisk_exec_read(cmd, thr, loff);
850                 break;
851         case WRITE_6:
852         case WRITE_10:
853         case WRITE_12:
854         case WRITE_16:
855                 if (likely(!virt_dev->rd_only_flag)) {
856                         int do_fsync = vdisk_sync_queue_type(cmd->queue_type);
857                         struct scst_vdisk_tgt_dev *ftgt_dev =
858                                 (struct scst_vdisk_tgt_dev *)
859                                         tgt_dev->dh_priv;
860                         enum scst_cmd_queue_type last_queue_type =
861                                 ftgt_dev->last_write_cmd_queue_type;
862                         ftgt_dev->last_write_cmd_queue_type = cmd->queue_type;
863                         if (vdisk_need_pre_sync(cmd->queue_type,
864                                                 last_queue_type)) {
865                                 TRACE(TRACE_ORDER, "ORDERED "
866                                       "WRITE(%d): loff=%lld, data_len=%lld",
867                                       cmd->queue_type,
868                                       (long long unsigned int)loff,
869                                       (long long unsigned int)data_len);
870                                 do_fsync = 1;
871                                 if (vdisk_fsync(thr, 0, 0, cmd) != 0)
872                                         goto out_compl;
873                         }
874                         if (virt_dev->blockio) {
875                                 blockio_exec_rw(cmd, thr, lba_start, 1);
876                                 goto out_thr;
877                         } else
878                                 vdisk_exec_write(cmd, thr, loff);
879                         /* O_SYNC flag is used for WT devices */
880                         if (do_fsync || fua)
881                                 vdisk_fsync(thr, loff, data_len, cmd);
882                 } else {
883                         TRACE(TRACE_MINOR, "Attempt to write to read-only "
884                               "device %s", virt_dev->name);
885                         scst_set_cmd_error(cmd,
886                                    SCST_LOAD_SENSE(scst_sense_data_protect));
887                 }
888                 break;
889         case WRITE_VERIFY:
890         case WRITE_VERIFY_12:
891         case WRITE_VERIFY_16:
892                 if (likely(!virt_dev->rd_only_flag)) {
893                         int do_fsync = vdisk_sync_queue_type(cmd->queue_type);
894                         struct scst_vdisk_tgt_dev *ftgt_dev =
895                                 (struct scst_vdisk_tgt_dev *)
896                                         tgt_dev->dh_priv;
897                         enum scst_cmd_queue_type last_queue_type =
898                                 ftgt_dev->last_write_cmd_queue_type;
899                         ftgt_dev->last_write_cmd_queue_type = cmd->queue_type;
900                         if (vdisk_need_pre_sync(cmd->queue_type,
901                                                 last_queue_type)) {
902                                 TRACE(TRACE_ORDER, "ORDERED "
903                                       "WRITE_VERIFY(%d): loff=%lld,"
904                                       " data_len=%lld", cmd->queue_type,
905                                       (long long unsigned int)loff,
906                                       (long long unsigned int)data_len);
907                                 do_fsync = 1;
908                                 if (vdisk_fsync(thr, 0, 0, cmd) != 0)
909                                         goto out_compl;
910                         }
911                         /* ToDo: BLOCKIO VERIFY */
912                         vdisk_exec_write(cmd, thr, loff);
913                         /* O_SYNC flag is used for WT devices */
914                         if (scsi_status_is_good(cmd->status))
915                                 vdisk_exec_verify(cmd, thr, loff);
916                         else if (do_fsync)
917                                 vdisk_fsync(thr, loff, data_len, cmd);
918                 } else {
919                         TRACE(TRACE_MINOR, "Attempt to write to read-only "
920                                 "device %s", virt_dev->name);
921                         scst_set_cmd_error(cmd,
922                                 SCST_LOAD_SENSE(scst_sense_data_protect));
923                 }
924                 break;
925         case SYNCHRONIZE_CACHE:
926         {
927                 int immed = cdb[1] & 0x2;
928                 TRACE(TRACE_ORDER, "SYNCHRONIZE_CACHE: "
929                         "loff=%lld, data_len=%lld, immed=%d",
930                         (long long unsigned int)loff,
931                         (long long unsigned int)data_len, immed);
932                 if (immed) {
933                         scst_cmd_get(cmd);
934                         cmd->completed = 1;
935                         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT,
936                                 SCST_CONTEXT_SAME);
937                         vdisk_fsync(thr, loff, data_len, NULL);
938                         /* ToDo: vdisk_fsync() error processing */
939                         scst_cmd_put(cmd);
940                         goto out_thr;
941                 } else {
942                         vdisk_fsync(thr, loff, data_len, cmd);
943                         break;
944                 }
945         }
946         case VERIFY_6:
947         case VERIFY:
948         case VERIFY_12:
949         case VERIFY_16:
950                 vdisk_exec_verify(cmd, thr, loff);
951                 break;
952         case MODE_SENSE:
953         case MODE_SENSE_10:
954                 vdisk_exec_mode_sense(cmd);
955                 break;
956         case MODE_SELECT:
957         case MODE_SELECT_10:
958                 vdisk_exec_mode_select(cmd);
959                 break;
960         case LOG_SELECT:
961         case LOG_SENSE:
962                 vdisk_exec_log(cmd);
963                 break;
964         case ALLOW_MEDIUM_REMOVAL:
965                 vdisk_exec_prevent_allow_medium_removal(cmd);
966                 break;
967         case READ_TOC:
968                 vdisk_exec_read_toc(cmd);
969                 break;
970         case START_STOP:
971                 vdisk_fsync(thr, 0, virt_dev->file_size, cmd);
972                 break;
973         case RESERVE:
974         case RESERVE_10:
975         case RELEASE:
976         case RELEASE_10:
977         case TEST_UNIT_READY:
978                 break;
979         case INQUIRY:
980                 vdisk_exec_inquiry(cmd);
981                 break;
982         case REQUEST_SENSE:
983                 vdisk_exec_request_sense(cmd);
984                 break;
985         case READ_CAPACITY:
986                 vdisk_exec_read_capacity(cmd);
987                 break;
988         case SERVICE_ACTION_IN:
989                 if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
990                         vdisk_exec_read_capacity16(cmd);
991                         break;
992                 }
993                 /* else go through */
994         case REPORT_LUNS:
995         default:
996                 TRACE_DBG("Invalid opcode %d", opcode);
997                 scst_set_cmd_error(cmd,
998                     SCST_LOAD_SENSE(scst_sense_invalid_opcode));
999         }
1000
1001 out_compl:
1002         cmd->completed = 1;
1003
1004 out_done:
1005         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
1006
1007 out_thr:
1008         if (likely(thr != NULL))
1009                 scst_thr_data_put(&thr->hdr);
1010
1011         res = SCST_EXEC_COMPLETED;
1012
1013         TRACE_EXIT_RES(res);
1014         return res;
1015 }
1016
1017 static int vdisk_get_block_shift(struct scst_cmd *cmd)
1018 {
1019         struct scst_vdisk_dev *virt_dev =
1020             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1021         return virt_dev->block_shift;
1022 }
1023
1024 /********************************************************************
1025  *  Function:  vdisk_parse
1026  *
1027  *  Argument:
1028  *
1029  *  Returns :  The state of the command
1030  *
1031  *  Description:  This does the parsing of the command
1032  *
1033  *  Note:  Not all states are allowed on return
1034  ********************************************************************/
1035 static int vdisk_parse(struct scst_cmd *cmd)
1036 {
1037         scst_sbc_generic_parse(cmd, vdisk_get_block_shift);
1038         return SCST_CMD_STATE_DEFAULT;
1039 }
1040
1041 /********************************************************************
1042  *  Function:  vcdrom_parse
1043  *
1044  *  Argument:
1045  *
1046  *  Returns :  The state of the command
1047  *
1048  *  Description:  This does the parsing of the command
1049  *
1050  *  Note:  Not all states are allowed on return
1051  ********************************************************************/
1052 static int vcdrom_parse(struct scst_cmd *cmd)
1053 {
1054         scst_cdrom_generic_parse(cmd, vdisk_get_block_shift);
1055         return SCST_CMD_STATE_DEFAULT;
1056 }
1057
1058 /********************************************************************
1059  *  Function:  vcdrom_exec
1060  *
1061  *  Argument:
1062  *
1063  *  Returns :
1064  *
1065  *  Description:
1066  ********************************************************************/
1067 static int vcdrom_exec(struct scst_cmd *cmd)
1068 {
1069         int res = SCST_EXEC_COMPLETED;
1070         int opcode = cmd->cdb[0];
1071         struct scst_vdisk_dev *virt_dev =
1072             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1073
1074         TRACE_ENTRY();
1075
1076         cmd->status = 0;
1077         cmd->msg_status = 0;
1078         cmd->host_status = DID_OK;
1079         cmd->driver_status = 0;
1080
1081         if (virt_dev->cdrom_empty && (opcode != INQUIRY)) {
1082                 TRACE_DBG("%s", "CDROM empty");
1083                 scst_set_cmd_error(cmd,
1084                         SCST_LOAD_SENSE(scst_sense_not_ready));
1085                 goto out_done;
1086         }
1087
1088         if (virt_dev->media_changed && (cmd->cdb[0] != INQUIRY) &&
1089             (cmd->cdb[0] != REQUEST_SENSE) && (cmd->cdb[0] != REPORT_LUNS)) {
1090                 spin_lock(&virt_dev->flags_lock);
1091                 if (virt_dev->media_changed) {
1092                         virt_dev->media_changed = 0;
1093                         TRACE_DBG("%s", "Reporting media changed");
1094                         scst_set_cmd_error(cmd,
1095                                 SCST_LOAD_SENSE(scst_sense_medium_changed_UA));
1096                         spin_unlock(&virt_dev->flags_lock);
1097                         goto out_done;
1098                 }
1099                 spin_unlock(&virt_dev->flags_lock);
1100         }
1101
1102         res = vdisk_do_job(cmd);
1103
1104 out:
1105         TRACE_EXIT_RES(res);
1106         return res;
1107
1108 out_done:
1109         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
1110         goto out;
1111 }
1112
1113 static void vdisk_exec_inquiry(struct scst_cmd *cmd)
1114 {
1115         int32_t length, len, i, resp_len = 0;
1116         uint8_t *address;
1117         uint8_t *buf;
1118         struct scst_vdisk_dev *virt_dev =
1119             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1120
1121         /* ToDo: Performance Boost:
1122          * 1. remove kzalloc, buf
1123          * 2. do all checks before touching *address
1124          * 3. zero *address
1125          * 4. write directly to *address
1126          */
1127
1128         TRACE_ENTRY();
1129
1130         buf = kzalloc(INQ_BUF_SZ,
1131                 scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
1132         if (buf == NULL) {
1133                 scst_set_busy(cmd);
1134                 goto out;
1135         }
1136
1137         length = scst_get_buf_first(cmd, &address);
1138         TRACE_DBG("length %d", length);
1139         if (unlikely(length <= 0)) {
1140                 if (length < 0) {
1141                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1142                         scst_set_cmd_error(cmd,
1143                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1144                 }
1145                 goto out_free;
1146         }
1147
1148         if (cmd->cdb[1] & CMDDT) {
1149                 TRACE_DBG("%s", "INQUIRY: CMDDT is unsupported");
1150                 scst_set_cmd_error(cmd,
1151                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1152                 goto out_put;
1153         }
1154
1155         buf[0] = cmd->dev->handler->type;      /* type dev */
1156         if ((buf[0] == TYPE_ROM) || virt_dev->removable)
1157                 buf[1] = 0x80;      /* removable */
1158         /* Vital Product */
1159         if (cmd->cdb[1] & EVPD) {
1160                 int dev_id_num;
1161                 char dev_id_str[6];
1162
1163                 for (dev_id_num = 0, i = 0; i < (int)strlen(virt_dev->name);
1164                      i++) {
1165                         unsigned int rv =
1166                                 random_values[(int)(virt_dev->name[i])];
1167                         /*
1168                          * Device name maximum length = 16,
1169                          * do some rotating of the bits.
1170                          */
1171                         dev_id_num ^= ((rv << i) | (rv >> (32 - i)));
1172                 }
1173
1174                 dev_id_num += scst_vdisk_ID;
1175
1176                 len = scnprintf(dev_id_str, 6, "%d", dev_id_num);
1177                 TRACE_DBG("num %d, str <%s>, len %d",
1178                            dev_id_num, dev_id_str, len);
1179                 if (0 == cmd->cdb[2]) {
1180                         /* supported vital product data pages */
1181                         buf[3] = 3;
1182                         buf[4] = 0x0; /* this page */
1183                         buf[5] = 0x80; /* unit serial number */
1184                         buf[6] = 0x83; /* device identification */
1185                         resp_len = buf[3] + 4;
1186                 } else if (0x80 == cmd->cdb[2]) {
1187                         /* unit serial number */
1188                         buf[1] = 0x80;
1189                         if (virt_dev->usn == NULL) {
1190                                 buf[3] = MAX_USN_LEN;
1191                                 memset(&buf[4], 0x20, MAX_USN_LEN);
1192                         } else {
1193                                 int usn_len;
1194
1195                                 if (strlen(virt_dev->usn) > MAX_USN_LEN)
1196                                         usn_len = MAX_USN_LEN;
1197                                 else
1198                                         usn_len = strlen(virt_dev->usn);
1199                                 buf[3] = usn_len;
1200                                 strncpy(&buf[4], virt_dev->usn, usn_len);
1201                         }
1202                         resp_len = buf[3] + 4;
1203                 } else if (0x83 == cmd->cdb[2]) {
1204                         /* device identification */
1205                         int num = 4;
1206
1207                         buf[1] = 0x83;
1208                         /* Two identification descriptors: */
1209                         /* T10 vendor identifier field format (faked) */
1210                         buf[num + 0] = 0x2;     /* ASCII */
1211                         buf[num + 1] = 0x1;
1212                         buf[num + 2] = 0x0;
1213                         if (virt_dev->blockio)
1214                                 memcpy(&buf[num + 4], SCST_BIO_VENDOR, 8);
1215                         else
1216                                 memcpy(&buf[num + 4], SCST_FIO_VENDOR, 8);
1217                         memset(&buf[num + 12], ' ', 16);
1218                         i = strlen(virt_dev->name);
1219                         i = i < 16 ? i : 16;
1220                         memcpy(&buf[num + 12], virt_dev->name, i);
1221                         memcpy(&buf[num + 28], dev_id_str, i);
1222                         buf[num + 3] = 8 + 16 + i;
1223                         num += buf[num + 3] + 4;
1224                         /* NAA IEEE registered identifier (faked) */
1225                         buf[num] = 0x1; /* binary */
1226                         buf[num + 1] = 0x3;
1227                         buf[num + 2] = 0x0;
1228                         buf[num + 3] = 0x8;
1229                         buf[num + 4] = 0x51; /* IEEE OUI=0x123456 (faked) */
1230                         buf[num + 5] = 0x23;
1231                         buf[num + 6] = 0x45;
1232                         buf[num + 7] = 0x60;
1233                         buf[num + 8] = (dev_id_num >> 24);
1234                         buf[num + 9] = (dev_id_num >> 16) & 0xff;
1235                         buf[num + 10] = (dev_id_num >> 8) & 0xff;
1236                         buf[num + 11] = dev_id_num & 0xff;
1237
1238                         resp_len = num + 12 - 4;
1239                         buf[2] = (resp_len >> 8) & 0xFF;
1240                         buf[3] = resp_len & 0xFF;
1241                         resp_len += 4;
1242                 } else {
1243                         TRACE_DBG("INQUIRY: Unsupported EVPD page %x",
1244                                 cmd->cdb[2]);
1245                         scst_set_cmd_error(cmd,
1246                             SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1247                         goto out_put;
1248                 }
1249         } else {
1250                 if (cmd->cdb[2] != 0) {
1251                         TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
1252                         scst_set_cmd_error(cmd,
1253                             SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1254                         goto out_put;
1255                 }
1256
1257                 buf[2] = 4;     /* Device complies to this standard - SPC-2  */
1258                 buf[3] = 0x12;  /* HiSup + data in format specified in SPC-2 */
1259                 buf[4] = 31;    /* n - 4 = 35 - 4 = 31 for full 36 byte data */
1260                 /* BQue = 0, CMDQUE = 1 commands queuing supported */
1261                 buf[6] = 0; buf[7] = 2;
1262
1263                 /*
1264                  * 8 byte ASCII Vendor Identification of the target
1265                  * - left aligned.
1266                  */
1267                 if (virt_dev->blockio)
1268                         memcpy(&buf[8], SCST_BIO_VENDOR, 8);
1269                 else
1270                         memcpy(&buf[8], SCST_FIO_VENDOR, 8);
1271
1272                 /*
1273                  * 16 byte ASCII Product Identification of the target - left
1274                  * aligned.
1275                  */
1276                 memset(&buf[16], ' ', 16);
1277                 len = strlen(virt_dev->name);
1278                 len = len < 16 ? len : 16;
1279                 memcpy(&buf[16], virt_dev->name, len);
1280
1281                 /*
1282                  * 4 byte ASCII Product Revision Level of the target - left
1283                  * aligned.
1284                  */
1285                 memcpy(&buf[32], SCST_FIO_REV, 4);
1286                 resp_len = buf[4] + 5;
1287         }
1288
1289         sBUG_ON(resp_len >= INQ_BUF_SZ);
1290         if (length > resp_len)
1291                 length = resp_len;
1292         memcpy(address, buf, length);
1293
1294 out_put:
1295         scst_put_buf(cmd, address);
1296         if (length < cmd->resp_data_len)
1297                 scst_set_resp_data_len(cmd, length);
1298
1299 out_free:
1300         kfree(buf);
1301
1302 out:
1303         TRACE_EXIT();
1304         return;
1305 }
1306
1307 static void vdisk_exec_request_sense(struct scst_cmd *cmd)
1308 {
1309         int32_t length;
1310         uint8_t *address;
1311
1312         TRACE_ENTRY();
1313
1314         length = scst_get_buf_first(cmd, &address);
1315         TRACE_DBG("length %d", length);
1316         if (unlikely(length < SCST_STANDARD_SENSE_LEN)) {
1317                 if (length != 0) {
1318                         PRINT_ERROR("scst_get_buf_first() failed or too small "
1319                                 "requested buffer (returned %d)", length);
1320                         scst_set_cmd_error(cmd,
1321                                 SCST_LOAD_SENSE(
1322                                         scst_sense_invalid_field_in_parm_list));
1323                 }
1324                 if (length > 0)
1325                         goto out_put;
1326                 else
1327                         goto out;
1328         }
1329
1330         scst_set_sense(address, length, SCST_LOAD_SENSE(scst_sense_no_sense));
1331
1332 out_put:
1333         scst_put_buf(cmd, address);
1334
1335 out:
1336         TRACE_EXIT();
1337         return;
1338 }
1339
1340 /*
1341  * <<Following mode pages info copied from ST318451LW with some corrections>>
1342  *
1343  * ToDo: revise them
1344  */
1345
1346 static int vdisk_err_recov_pg(unsigned char *p, int pcontrol,
1347                                struct scst_vdisk_dev *virt_dev)
1348 {       /* Read-Write Error Recovery page for mode_sense */
1349         const unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1350                                               5, 0, 0xff, 0xff};
1351
1352         memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1353         if (1 == pcontrol)
1354                 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1355         return sizeof(err_recov_pg);
1356 }
1357
1358 static int vdisk_disconnect_pg(unsigned char *p, int pcontrol,
1359                                 struct scst_vdisk_dev *virt_dev)
1360 {       /* Disconnect-Reconnect page for mode_sense */
1361         const unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1362                                                0, 0, 0, 0, 0, 0, 0, 0};
1363
1364         memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1365         if (1 == pcontrol)
1366                 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1367         return sizeof(disconnect_pg);
1368 }
1369
1370 static int vdisk_format_pg(unsigned char *p, int pcontrol,
1371                             struct scst_vdisk_dev *virt_dev)
1372 {       /* Format device page for mode_sense */
1373         const unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1374                                            0, 0, 0, 0, 0, 0, 0, 0,
1375                                            0, 0, 0, 0, 0x40, 0, 0, 0};
1376
1377         memcpy(p, format_pg, sizeof(format_pg));
1378         p[10] = (DEF_SECTORS_PER >> 8) & 0xff;
1379         p[11] = DEF_SECTORS_PER & 0xff;
1380         p[12] = (virt_dev->block_size >> 8) & 0xff;
1381         p[13] = virt_dev->block_size & 0xff;
1382         if (1 == pcontrol)
1383                 memset(p + 2, 0, sizeof(format_pg) - 2);
1384         return sizeof(format_pg);
1385 }
1386
1387 static int vdisk_caching_pg(unsigned char *p, int pcontrol,
1388                              struct scst_vdisk_dev *virt_dev)
1389 {       /* Caching page for mode_sense */
1390         const unsigned char caching_pg[] = {0x8, 18, 0x10, 0, 0xff, 0xff, 0, 0,
1391                 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1392
1393         memcpy(p, caching_pg, sizeof(caching_pg));
1394         p[2] |= !(virt_dev->wt_flag || virt_dev->nv_cache) ? WCE : 0;
1395         if (1 == pcontrol)
1396                 memset(p + 2, 0, sizeof(caching_pg) - 2);
1397         return sizeof(caching_pg);
1398 }
1399
1400 static int vdisk_ctrl_m_pg(unsigned char *p, int pcontrol,
1401                             struct scst_vdisk_dev *virt_dev)
1402 {       /* Control mode page for mode_sense */
1403         const unsigned char ctrl_m_pg[] = {0xa, 0xa, 0, 0, 0, 0, 0, 0,
1404                                            0, 0, 0x2, 0x4b};
1405
1406         memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1407         switch (pcontrol) {
1408         case 0:
1409                 p[2] |= virt_dev->dev->tst << 5;
1410                 p[3] |= virt_dev->dev->queue_alg << 4;
1411                 p[4] |= virt_dev->dev->swp << 3;
1412                 p[5] |= virt_dev->dev->tas << 6;
1413                 break;
1414         case 1:
1415                 memset(p + 2, 0, sizeof(ctrl_m_pg) - 2);
1416 #if 0   /*
1417          * It's too early to implement it, since we can't control the
1418          * backstorage device parameters. ToDo
1419          */
1420                 p[2] |= 7 << 5;         /* TST */
1421                 p[3] |= 0xF << 4;       /* QUEUE ALGORITHM MODIFIER */
1422 #endif
1423                 p[4] |= 1 << 3;         /* SWP */
1424                 p[5] |= 1 << 6;         /* TAS */
1425                 break;
1426         case 2:
1427                 p[2] |= DEF_TST << 5;
1428                 if (virt_dev->wt_flag || virt_dev->nv_cache)
1429                         p[3] |= DEF_QUEUE_ALG_WT << 4;
1430                 else
1431                         p[3] |= DEF_QUEUE_ALG << 4;
1432                 p[4] |= DEF_SWP << 3;
1433                 p[5] |= DEF_TAS << 6;
1434                 break;
1435         default:
1436                 sBUG();
1437         }
1438         return sizeof(ctrl_m_pg);
1439 }
1440
1441 static int vdisk_iec_m_pg(unsigned char *p, int pcontrol,
1442                            struct scst_vdisk_dev *virt_dev)
1443 {       /* Informational Exceptions control mode page for mode_sense */
1444         const unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1445                                           0, 0, 0x0, 0x0};
1446         memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1447         if (1 == pcontrol)
1448                 memset(p + 2, 0, sizeof(iec_m_pg) - 2);
1449         return sizeof(iec_m_pg);
1450 }
1451
1452 static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
1453 {
1454         int32_t length;
1455         uint8_t *address;
1456         uint8_t *buf;
1457         struct scst_vdisk_dev *virt_dev;
1458         uint32_t blocksize;
1459         uint64_t nblocks;
1460         unsigned char dbd, type;
1461         int pcontrol, pcode, subpcode;
1462         unsigned char dev_spec;
1463         int msense_6, offset = 0, len;
1464         unsigned char *bp;
1465
1466         TRACE_ENTRY();
1467
1468         buf = kzalloc(MSENSE_BUF_SZ,
1469                 scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
1470         if (buf == NULL) {
1471                 scst_set_busy(cmd);
1472                 goto out;
1473         }
1474
1475         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1476         blocksize = virt_dev->block_size;
1477         nblocks = virt_dev->nblocks;
1478
1479         type = cmd->dev->handler->type;    /* type dev */
1480         dbd = cmd->cdb[1] & DBD;
1481         pcontrol = (cmd->cdb[2] & 0xc0) >> 6;
1482         pcode = cmd->cdb[2] & 0x3f;
1483         subpcode = cmd->cdb[3];
1484         msense_6 = (MODE_SENSE == cmd->cdb[0]);
1485         dev_spec = (virt_dev->rd_only_flag ? WP : 0) | DPOFUA;
1486
1487         length = scst_get_buf_first(cmd, &address);
1488         if (unlikely(length <= 0)) {
1489                 if (length < 0) {
1490                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1491                         scst_set_cmd_error(cmd,
1492                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1493                 }
1494                 goto out_free;
1495         }
1496
1497         if (0x3 == pcontrol) {
1498                 TRACE_DBG("%s", "MODE SENSE: Saving values not supported");
1499                 scst_set_cmd_error(cmd,
1500                     SCST_LOAD_SENSE(scst_sense_saving_params_unsup));
1501                 goto out_put;
1502         }
1503
1504         if (msense_6) {
1505                 buf[1] = type;
1506                 buf[2] = dev_spec;
1507                 offset = 4;
1508         } else {
1509                 buf[2] = type;
1510                 buf[3] = dev_spec;
1511                 offset = 8;
1512         }
1513
1514         if (0 != subpcode) {
1515                 /* TODO: Control Extension page */
1516                 TRACE_DBG("%s", "MODE SENSE: Only subpage 0 is supported");
1517                 scst_set_cmd_error(cmd,
1518                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1519                 goto out_put;
1520         }
1521
1522         if (!dbd) {
1523                 /* Create block descriptor */
1524                 buf[offset - 1] = 0x08;         /* block descriptor length */
1525                 if (nblocks >> 32) {
1526                         buf[offset + 0] = 0xFF;
1527                         buf[offset + 1] = 0xFF;
1528                         buf[offset + 2] = 0xFF;
1529                         buf[offset + 3] = 0xFF;
1530                 } else {
1531                         /* num blks */
1532                         buf[offset + 0] = (nblocks >> (BYTE * 3)) & 0xFF;
1533                         buf[offset + 1] = (nblocks >> (BYTE * 2)) & 0xFF;
1534                         buf[offset + 2] = (nblocks >> (BYTE * 1)) & 0xFF;
1535                         buf[offset + 3] = (nblocks >> (BYTE * 0)) & 0xFF;
1536                 }
1537                 buf[offset + 4] = 0;                    /* density code */
1538                 buf[offset + 5] = (blocksize >> (BYTE * 2)) & 0xFF;/* blklen */
1539                 buf[offset + 6] = (blocksize >> (BYTE * 1)) & 0xFF;
1540                 buf[offset + 7] = (blocksize >> (BYTE * 0)) & 0xFF;
1541
1542                 offset += 8;                    /* increment offset */
1543         }
1544
1545         bp = buf + offset;
1546
1547         switch (pcode) {
1548         case 0x1:       /* Read-Write error recovery page, direct access */
1549                 len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
1550                 offset += len;
1551                 break;
1552         case 0x2:       /* Disconnect-Reconnect page, all devices */
1553                 len = vdisk_disconnect_pg(bp, pcontrol, virt_dev);
1554                 offset += len;
1555                 break;
1556         case 0x3:       /* Format device page, direct access */
1557                 len = vdisk_format_pg(bp, pcontrol, virt_dev);
1558                 offset += len;
1559                 break;
1560         case 0x8:       /* Caching page, direct access */
1561                 len = vdisk_caching_pg(bp, pcontrol, virt_dev);
1562                 offset += len;
1563                 break;
1564         case 0xa:       /* Control Mode page, all devices */
1565                 len = vdisk_ctrl_m_pg(bp, pcontrol, virt_dev);
1566                 offset += len;
1567                 break;
1568         case 0x1c:      /* Informational Exceptions Mode page, all devices */
1569                 len = vdisk_iec_m_pg(bp, pcontrol, virt_dev);
1570                 offset += len;
1571                 break;
1572         case 0x3f:      /* Read all Mode pages */
1573                 len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
1574                 len += vdisk_disconnect_pg(bp + len, pcontrol, virt_dev);
1575                 len += vdisk_format_pg(bp + len, pcontrol, virt_dev);
1576                 len += vdisk_caching_pg(bp + len, pcontrol, virt_dev);
1577                 len += vdisk_ctrl_m_pg(bp + len, pcontrol, virt_dev);
1578                 len += vdisk_iec_m_pg(bp + len, pcontrol, virt_dev);
1579                 offset += len;
1580                 break;
1581         default:
1582                 TRACE_DBG("MODE SENSE: Unsupported page %x", pcode);
1583                 scst_set_cmd_error(cmd,
1584                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1585                 goto out_put;
1586         }
1587         if (msense_6)
1588                 buf[0] = offset - 1;
1589         else {
1590                 buf[0] = ((offset - 2) >> 8) & 0xff;
1591                 buf[1] = (offset - 2) & 0xff;
1592         }
1593
1594         if (offset > length)
1595                 offset = length;
1596         memcpy(address, buf, offset);
1597
1598 out_put:
1599         scst_put_buf(cmd, address);
1600         if (offset < cmd->resp_data_len)
1601                 scst_set_resp_data_len(cmd, offset);
1602
1603 out_free:
1604         kfree(buf);
1605
1606 out:
1607         TRACE_EXIT();
1608         return;
1609 }
1610
1611 static int vdisk_set_wt(struct scst_vdisk_dev *virt_dev, int wt)
1612 {
1613         int res = 0;
1614
1615         TRACE_ENTRY();
1616
1617         if ((virt_dev->wt_flag == wt) || virt_dev->nullio || virt_dev->nv_cache)
1618                 goto out;
1619
1620         spin_lock(&virt_dev->flags_lock);
1621         virt_dev->wt_flag = wt;
1622         spin_unlock(&virt_dev->flags_lock);
1623
1624         scst_dev_del_all_thr_data(virt_dev->dev);
1625
1626 out:
1627         TRACE_EXIT_RES(res);
1628         return res;
1629 }
1630
1631 static void vdisk_ctrl_m_pg_select(unsigned char *p,
1632         struct scst_vdisk_dev *virt_dev)
1633 {
1634         struct scst_device *dev = virt_dev->dev;
1635         int old_swp = dev->swp, old_tas = dev->tas;
1636
1637 #if 0
1638         /* Not implemented yet, see comment in vdisk_ctrl_m_pg() */
1639         dev->tst = p[2] >> 5;
1640         dev->queue_alg = p[3] >> 4;
1641 #endif
1642         dev->swp = (p[4] & 0x8) >> 3;
1643         dev->tas = (p[5] & 0x40) >> 6;
1644
1645         PRINT_INFO("Device %s: new control mode page parameters: SWP %x "
1646                 "(was %x), TAS %x (was %x)", virt_dev->name, dev->swp,
1647                 old_swp, dev->tas, old_tas);
1648         return;
1649 }
1650
1651 static void vdisk_exec_mode_select(struct scst_cmd *cmd)
1652 {
1653         int32_t length;
1654         uint8_t *address;
1655         struct scst_vdisk_dev *virt_dev;
1656         int mselect_6, offset;
1657
1658         TRACE_ENTRY();
1659
1660         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1661         mselect_6 = (MODE_SELECT == cmd->cdb[0]);
1662
1663         length = scst_get_buf_first(cmd, &address);
1664         if (unlikely(length <= 0)) {
1665                 if (length < 0) {
1666                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1667                         scst_set_cmd_error(cmd,
1668                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1669                 }
1670                 goto out;
1671         }
1672
1673         if (!(cmd->cdb[1] & PF) || (cmd->cdb[1] & SP)) {
1674                 TRACE(TRACE_MINOR|TRACE_SCSI, "MODE SELECT: Unsupported "
1675                         "value(s) of PF and/or SP bits (cdb[1]=%x)",
1676                         cmd->cdb[1]);
1677                 scst_set_cmd_error(cmd,
1678                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1679                 goto out_put;
1680         }
1681
1682         if (mselect_6)
1683                 offset = 4;
1684         else
1685                 offset = 8;
1686
1687         if (address[offset - 1] == 8) {
1688                 offset += 8;
1689         } else if (address[offset - 1] != 0) {
1690                 PRINT_ERROR("%s", "MODE SELECT: Wrong parameters list "
1691                         "lenght");
1692                 scst_set_cmd_error(cmd,
1693                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
1694                 goto out_put;
1695         }
1696
1697         while (length > offset + 2) {
1698                 if (address[offset] & PS) {
1699                         PRINT_ERROR("%s", "MODE SELECT: Illegal PS bit");
1700                         scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1701                                 scst_sense_invalid_field_in_parm_list));
1702                         goto out_put;
1703                 }
1704                 if ((address[offset] & 0x3f) == 0x8) {
1705                         /* Caching page */
1706                         if (address[offset + 1] != 18) {
1707                                 PRINT_ERROR("%s", "MODE SELECT: Invalid "
1708                                         "caching page request");
1709                                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1710                                     scst_sense_invalid_field_in_parm_list));
1711                                 goto out_put;
1712                         }
1713                         if (vdisk_set_wt(virt_dev,
1714                               (address[offset + 2] & WCE) ? 0 : 1) != 0) {
1715                                 scst_set_cmd_error(cmd,
1716                                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1717                                 goto out_put;
1718                         }
1719                         break;
1720                 } else if ((address[offset] & 0x3f) == 0xA) {
1721                         /* Control page */
1722                         if (address[offset + 1] != 0xA) {
1723                                 PRINT_ERROR("%s", "MODE SELECT: Invalid "
1724                                         "control page request");
1725                                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1726                                     scst_sense_invalid_field_in_parm_list));
1727                                 goto out_put;
1728                         }
1729                         vdisk_ctrl_m_pg_select(&address[offset], virt_dev);
1730                 } else {
1731                         PRINT_ERROR("MODE SELECT: Invalid request %x",
1732                                 address[offset] & 0x3f);
1733                         scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1734                             scst_sense_invalid_field_in_parm_list));
1735                         goto out_put;
1736                 }
1737                 offset += address[offset + 1];
1738         }
1739
1740 out_put:
1741         scst_put_buf(cmd, address);
1742
1743 out:
1744         TRACE_EXIT();
1745         return;
1746 }
1747
1748 static void vdisk_exec_log(struct scst_cmd *cmd)
1749 {
1750         TRACE_ENTRY();
1751
1752         /* No log pages are supported */
1753         scst_set_cmd_error(cmd,
1754                 SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1755
1756         TRACE_EXIT();
1757         return;
1758 }
1759
1760 static void vdisk_exec_read_capacity(struct scst_cmd *cmd)
1761 {
1762         int32_t length;
1763         uint8_t *address;
1764         struct scst_vdisk_dev *virt_dev;
1765         uint32_t blocksize;
1766         uint64_t nblocks;
1767         uint8_t buffer[READ_CAP_LEN];
1768
1769         TRACE_ENTRY();
1770
1771         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1772         blocksize = virt_dev->block_size;
1773         nblocks = virt_dev->nblocks;
1774
1775         /* last block on the virt_dev is (nblocks-1) */
1776         memset(buffer, 0, sizeof(buffer));
1777         if (nblocks >> 32) {
1778                 buffer[0] = 0xFF;
1779                 buffer[1] = 0xFF;
1780                 buffer[2] = 0xFF;
1781                 buffer[3] = 0xFF;
1782         } else {
1783                 buffer[0] = ((nblocks - 1) >> (BYTE * 3)) & 0xFF;
1784                 buffer[1] = ((nblocks - 1) >> (BYTE * 2)) & 0xFF;
1785                 buffer[2] = ((nblocks - 1) >> (BYTE * 1)) & 0xFF;
1786                 buffer[3] = ((nblocks - 1) >> (BYTE * 0)) & 0xFF;
1787         }
1788         buffer[4] = (blocksize >> (BYTE * 3)) & 0xFF;
1789         buffer[5] = (blocksize >> (BYTE * 2)) & 0xFF;
1790         buffer[6] = (blocksize >> (BYTE * 1)) & 0xFF;
1791         buffer[7] = (blocksize >> (BYTE * 0)) & 0xFF;
1792
1793         length = scst_get_buf_first(cmd, &address);
1794         if (unlikely(length <= 0)) {
1795                 if (length < 0) {
1796                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1797                         scst_set_cmd_error(cmd,
1798                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1799                 }
1800                 goto out;
1801         }
1802
1803         if (length > READ_CAP_LEN)
1804                 length = READ_CAP_LEN;
1805         memcpy(address, buffer, length);
1806
1807         scst_put_buf(cmd, address);
1808
1809         if (length < cmd->resp_data_len)
1810                 scst_set_resp_data_len(cmd, length);
1811
1812 out:
1813         TRACE_EXIT();
1814         return;
1815 }
1816
1817 static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
1818 {
1819         int32_t length;
1820         uint8_t *address;
1821         struct scst_vdisk_dev *virt_dev;
1822         uint32_t blocksize;
1823         uint64_t nblocks;
1824         uint8_t buffer[READ_CAP16_LEN];
1825
1826         TRACE_ENTRY();
1827
1828         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1829         blocksize = virt_dev->block_size;
1830         nblocks = virt_dev->nblocks - 1;
1831
1832         memset(buffer, 0, sizeof(buffer));
1833         buffer[0] = nblocks >> 56;
1834         buffer[1] = (nblocks >> 48) & 0xFF;
1835         buffer[2] = (nblocks >> 40) & 0xFF;
1836         buffer[3] = (nblocks >> 32) & 0xFF;
1837         buffer[4] = (nblocks >> 24) & 0xFF;
1838         buffer[5] = (nblocks >> 16) & 0xFF;
1839         buffer[6] = (nblocks >> 8) & 0xFF;
1840         buffer[7] = nblocks & 0xFF;
1841
1842         buffer[8] = (blocksize >> (BYTE * 3)) & 0xFF;
1843         buffer[9] = (blocksize >> (BYTE * 2)) & 0xFF;
1844         buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF;
1845         buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF;
1846
1847         length = scst_get_buf_first(cmd, &address);
1848         if (unlikely(length <= 0)) {
1849                 if (length < 0) {
1850                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1851                         scst_set_cmd_error(cmd,
1852                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1853                         }
1854                 goto out;
1855         }
1856
1857         if (length > READ_CAP16_LEN)
1858                 length = READ_CAP16_LEN;
1859         memcpy(address, buffer, length);
1860
1861         scst_put_buf(cmd, address);
1862
1863         if (length < cmd->resp_data_len)
1864                 scst_set_resp_data_len(cmd, length);
1865
1866 out:
1867         TRACE_EXIT();
1868         return;
1869 }
1870
1871 static void vdisk_exec_read_toc(struct scst_cmd *cmd)
1872 {
1873         int32_t length, off = 0;
1874         uint8_t *address;
1875         struct scst_vdisk_dev *virt_dev;
1876         uint32_t nblocks;
1877         uint8_t buffer[4+8+8] = { 0x00, 0x0a, 0x01, 0x01, 0x00, 0x14,
1878                                   0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
1879
1880         TRACE_ENTRY();
1881
1882         if (cmd->dev->handler->type != TYPE_ROM) {
1883                 PRINT_ERROR("%s", "READ TOC for non-CDROM device");
1884                 scst_set_cmd_error(cmd,
1885                         SCST_LOAD_SENSE(scst_sense_invalid_opcode));
1886                 goto out;
1887         }
1888
1889         if (cmd->cdb[2] & 0x0e/*Format*/) {
1890                 PRINT_ERROR("%s", "READ TOC: invalid requested data format");
1891                 scst_set_cmd_error(cmd,
1892                         SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1893                 goto out;
1894         }
1895
1896         if ((cmd->cdb[6] != 0 && (cmd->cdb[2] & 0x01)) ||
1897             (cmd->cdb[6] > 1 && cmd->cdb[6] != 0xAA)) {
1898                 PRINT_ERROR("READ TOC: invalid requested track number %x",
1899                         cmd->cdb[6]);
1900                 scst_set_cmd_error(cmd,
1901                         SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1902                 goto out;
1903         }
1904
1905         length = scst_get_buf_first(cmd, &address);
1906         if (unlikely(length <= 0)) {
1907                 if (length < 0) {
1908                         PRINT_ERROR("scst_get_buf_first() failed: %d", length);
1909                         scst_set_cmd_error(cmd,
1910                                 SCST_LOAD_SENSE(scst_sense_hardw_error));
1911                 }
1912                 goto out;
1913         }
1914
1915         virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1916         /* ToDo when you have > 8TB ROM device. */
1917         nblocks = (uint32_t)virt_dev->nblocks;
1918
1919         /* Header */
1920         memset(buffer, 0, sizeof(buffer));
1921         buffer[2] = 0x01;    /* First Track/Session */
1922         buffer[3] = 0x01;    /* Last Track/Session */
1923         off = 4;
1924         if (cmd->cdb[6] <= 1) {
1925                 /* Fistr TOC Track Descriptor */
1926                 /* ADDR    0x10 - Q Sub-channel encodes current position data
1927                    CONTROL 0x04 - Data track, recoreded uninterrupted */
1928                 buffer[off+1] = 0x14;
1929                 /* Track Number */
1930                 buffer[off+2] = 0x01;
1931                 off += 8;
1932         }
1933         if (!(cmd->cdb[2] & 0x01)) {
1934                 /* Lead-out area TOC Track Descriptor */
1935                 buffer[off+1] = 0x14;
1936                 /* Track Number */
1937                 buffer[off+2] = 0xAA;
1938                 /* Track Start Address */
1939                 buffer[off+4] = (nblocks >> (BYTE * 3)) & 0xFF;
1940                 buffer[off+5] = (nblocks >> (BYTE * 2)) & 0xFF;
1941                 buffer[off+6] = (nblocks >> (BYTE * 1)) & 0xFF;
1942                 buffer[off+7] = (nblocks >> (BYTE * 0)) & 0xFF;
1943                 off += 8;
1944         }
1945
1946         buffer[1] = off - 2;    /* Data  Length */
1947
1948         if (off > length)
1949                 off = length;
1950         memcpy(address, buffer, off);
1951
1952         scst_put_buf(cmd, address);
1953
1954         if (off < cmd->resp_data_len)
1955                 scst_set_resp_data_len(cmd, off);
1956
1957 out:
1958         TRACE_EXIT();
1959         return;
1960 }
1961
1962 static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd)
1963 {
1964         struct scst_vdisk_dev *virt_dev =
1965                 (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1966
1967         TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
1968
1969         if (cmd->dev->handler->type == TYPE_ROM) {
1970                 spin_lock(&virt_dev->flags_lock);
1971                 virt_dev->prevent_allow_medium_removal =
1972                         cmd->cdb[4] & 0x01 ? 1 : 0;
1973                 spin_unlock(&virt_dev->flags_lock);
1974         }
1975
1976         return;
1977 }
1978
1979 static int vdisk_fsync(struct scst_vdisk_thr *thr,
1980         loff_t loff, loff_t len, struct scst_cmd *cmd)
1981 {
1982         int res = 0;
1983         struct scst_vdisk_dev *virt_dev =
1984                 (struct scst_vdisk_dev *)cmd->dev->dh_priv;
1985         struct file *file = thr->fd;
1986         struct inode *inode;
1987         struct address_space *mapping;
1988
1989         TRACE_ENTRY();
1990
1991         /* Hopefully, the compiler will generate the single comparison */
1992         if (virt_dev->nv_cache || virt_dev->blockio || virt_dev->wt_flag ||
1993             virt_dev->rd_only_flag || virt_dev->o_direct_flag ||
1994             virt_dev->nullio)
1995                 goto out;
1996
1997         inode = file->f_dentry->d_inode;
1998         mapping = file->f_mapping;
1999
2000         res = sync_page_range(inode, mapping, loff, len);
2001         if (unlikely(res != 0)) {
2002                 PRINT_ERROR("sync_page_range() failed (%d)", res);
2003                 if (cmd != NULL) {
2004                         scst_set_cmd_error(cmd,
2005                                 SCST_LOAD_SENSE(scst_sense_write_error));
2006                 }
2007         }
2008
2009         /* ToDo: flush the device cache, if needed */
2010
2011 out:
2012         TRACE_EXIT_RES(res);
2013         return res;
2014 }
2015
2016 static struct iovec *vdisk_alloc_iv(struct scst_cmd *cmd,
2017         struct scst_vdisk_thr *thr)
2018 {
2019         int iv_count;
2020
2021         iv_count = scst_get_buf_count(cmd);
2022         if (iv_count > thr->iv_count) {
2023                 kfree(thr->iv);
2024                 /* It can't be called in atomic context */
2025                 thr->iv = kmalloc(sizeof(*thr->iv) * iv_count, GFP_KERNEL);
2026                 if (thr->iv == NULL) {
2027                         PRINT_ERROR("Unable to allocate iv (%d)", iv_count);
2028                         scst_set_busy(cmd);
2029                         goto out;
2030                 }
2031                 thr->iv_count = iv_count;
2032         }
2033
2034 out:
2035         return thr->iv;
2036 }
2037
2038 /*
2039  * copied from <ksrc>/fs/read_write.*
2040  */
2041 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
2042 static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
2043 {
2044         set_current_state(TASK_UNINTERRUPTIBLE);
2045         if (!kiocbIsKicked(iocb))
2046                 schedule();
2047         else
2048                 kiocbClearKicked(iocb);
2049         __set_current_state(TASK_RUNNING);
2050 }
2051
2052 typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
2053                                 unsigned long, loff_t);
2054
2055 static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
2056                 unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
2057 {
2058         struct kiocb kiocb;
2059         ssize_t ret;
2060
2061         init_sync_kiocb(&kiocb, filp);
2062         kiocb.ki_pos = *ppos;
2063         kiocb.ki_left = len;
2064         kiocb.ki_nbytes = len;
2065
2066         for (;;) {
2067                 ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
2068                 if (ret != -EIOCBRETRY)
2069                         break;
2070                 wait_on_retry_sync_kiocb(&kiocb);
2071         }
2072
2073         if (ret == -EIOCBQUEUED)
2074                 ret = wait_on_sync_kiocb(&kiocb);
2075         *ppos = kiocb.ki_pos;
2076         return ret;
2077 }
2078 #endif
2079
2080 static void vdisk_exec_read(struct scst_cmd *cmd,
2081         struct scst_vdisk_thr *thr, loff_t loff)
2082 {
2083         mm_segment_t old_fs;
2084         loff_t err;
2085         ssize_t length, full_len;
2086         uint8_t __user *address;
2087         struct scst_vdisk_dev *virt_dev =
2088             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2089         struct file *fd = thr->fd;
2090         struct iovec *iv;
2091         int iv_count, i;
2092
2093         TRACE_ENTRY();
2094
2095         if (virt_dev->nullio)
2096                 goto out;
2097
2098         iv = vdisk_alloc_iv(cmd, thr);
2099         if (iv == NULL)
2100                 goto out;
2101
2102         iv_count = 0;
2103         full_len = 0;
2104         i = -1;
2105         length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
2106         while (length > 0) {
2107                 full_len += length;
2108                 i++;
2109                 iv_count++;
2110                 iv[i].iov_base = address;
2111                 iv[i].iov_len = length;
2112                 length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
2113         }
2114         if (unlikely(length < 0)) {
2115                 PRINT_ERROR("scst_get_buf_() failed: %zd", length);
2116                 scst_set_cmd_error(cmd,
2117                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2118                 goto out_put;
2119         }
2120
2121         old_fs = get_fs();
2122         set_fs(get_ds());
2123
2124         TRACE_DBG("reading(iv_count %d, full_len %zd)", iv_count, full_len);
2125         /* SEEK */
2126         if (fd->f_op->llseek)
2127                 err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
2128         else
2129                 err = default_llseek(fd, loff, 0/*SEEK_SET*/);
2130         if (err != loff) {
2131                 PRINT_ERROR("lseek trouble %lld != %lld",
2132                             (long long unsigned int)err,
2133                             (long long unsigned int)loff);
2134                 scst_set_cmd_error(cmd,
2135                         SCST_LOAD_SENSE(scst_sense_hardw_error));
2136                 goto out_set_fs;
2137         }
2138
2139         /* READ */
2140 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
2141         err = fd->f_op->readv(fd, iv, iv_count, &fd->f_pos);
2142 #else
2143         err = do_sync_readv_writev(fd, iv, iv_count, full_len,
2144                                    &fd->f_pos, fd->f_op->aio_read);
2145 #endif
2146
2147         if ((err < 0) || (err < full_len)) {
2148                 PRINT_ERROR("readv() returned %lld from %zd",
2149                             (long long unsigned int)err,
2150                             full_len);
2151                 if (err == -EAGAIN)
2152                         scst_set_busy(cmd);
2153                 else {
2154                         scst_set_cmd_error(cmd,
2155                             SCST_LOAD_SENSE(scst_sense_read_error));
2156                 }
2157                 goto out_set_fs;
2158         }
2159
2160 out_set_fs:
2161         set_fs(old_fs);
2162
2163 out_put:
2164         for (; i >= 0; i--)
2165                 scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
2166
2167 out:
2168         TRACE_EXIT();
2169         return;
2170 }
2171
2172 static void vdisk_exec_write(struct scst_cmd *cmd,
2173         struct scst_vdisk_thr *thr, loff_t loff)
2174 {
2175         mm_segment_t old_fs;
2176         loff_t err;
2177         ssize_t length, full_len;
2178         uint8_t __user *address;
2179         struct scst_vdisk_dev *virt_dev =
2180             (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2181         struct file *fd = thr->fd;
2182         struct iovec *iv, *eiv;
2183         int iv_count, eiv_count;
2184
2185         TRACE_ENTRY();
2186
2187         if (virt_dev->nullio)
2188                 goto out;
2189
2190         iv = vdisk_alloc_iv(cmd, thr);
2191         if (iv == NULL)
2192                 goto out;
2193
2194         iv_count = 0;
2195         full_len = 0;
2196         length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
2197         while (length > 0) {
2198                 full_len += length;
2199                 iv[iv_count].iov_base = address;
2200                 iv[iv_count].iov_len = length;
2201                 iv_count++;
2202                 length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
2203         }
2204         if (unlikely(length < 0)) {
2205                 PRINT_ERROR("scst_get_buf_() failed: %zd", length);
2206                 scst_set_cmd_error(cmd,
2207                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2208                 goto out_put;
2209         }
2210
2211         old_fs = get_fs();
2212         set_fs(get_ds());
2213
2214         eiv = iv;
2215         eiv_count = iv_count;
2216 restart:
2217         TRACE_DBG("writing(eiv_count %d, full_len %zd)", eiv_count, full_len);
2218
2219         /* SEEK */
2220         if (fd->f_op->llseek)
2221                 err = fd->f_op->llseek(fd, loff, 0 /*SEEK_SET */);
2222         else
2223                 err = default_llseek(fd, loff, 0 /*SEEK_SET */);
2224         if (err != loff) {
2225                 PRINT_ERROR("lseek trouble %lld != %lld",
2226                             (long long unsigned int)err,
2227                             (long long unsigned int)loff);
2228                 scst_set_cmd_error(cmd,
2229                                    SCST_LOAD_SENSE(scst_sense_hardw_error));
2230                 goto out_set_fs;
2231         }
2232
2233         /* WRITE */
2234 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
2235         err = fd->f_op->writev(fd, eiv, eiv_count, &fd->f_pos);
2236 #else
2237         err = do_sync_readv_writev(fd, iv, iv_count, full_len, &fd->f_pos,
2238                                         fd->f_op->aio_write);
2239 #endif
2240
2241         if (err < 0) {
2242                 PRINT_ERROR("write() returned %lld from %zd",
2243                             (long long unsigned int)err,
2244                             full_len);
2245                 if (err == -EAGAIN)
2246                         scst_set_busy(cmd);
2247                 else {
2248                         scst_set_cmd_error(cmd,
2249                             SCST_LOAD_SENSE(scst_sense_write_error));
2250                 }
2251                 goto out_set_fs;
2252         } else if (err < full_len) {
2253                 /*
2254                  * Probably that's wrong, but sometimes write() returns
2255                  * value less, than requested. Let's restart.
2256                  */
2257                 int i, e = eiv_count;
2258                 TRACE_MGMT_DBG("write() returned %d from %zd "
2259                         "(iv_count=%d)", (int)err, full_len,
2260                         eiv_count);
2261                 if (err == 0) {
2262                         PRINT_INFO("Suspicious: write() returned 0 from "
2263                                 "%zd (iv_count=%d)", full_len, eiv_count);
2264                 }
2265                 full_len -= err;
2266                 for (i = 0; i < e; i++) {
2267                         if ((long long)eiv->iov_len < err) {
2268                                 err -= eiv->iov_len;
2269                                 eiv++;
2270                                 eiv_count--;
2271                         } else {
2272                                 eiv->iov_base =
2273                                         (uint8_t __force __user *)eiv->iov_base +
2274                                         err;
2275                                 eiv->iov_len -= err;
2276                                 break;
2277                         }
2278                 }
2279                 goto restart;
2280         }
2281
2282 out_set_fs:
2283         set_fs(old_fs);
2284
2285 out_put:
2286         while (iv_count > 0) {
2287                 scst_put_buf(cmd, (void __force *)(iv[iv_count-1].iov_base));
2288                 iv_count--;
2289         }
2290
2291 out:
2292         TRACE_EXIT();
2293         return;
2294 }
2295
2296 struct blockio_work {
2297         atomic_t bios_inflight;
2298         struct scst_cmd *cmd;
2299 };
2300
2301 static inline void blockio_check_finish(struct blockio_work *blockio_work)
2302 {
2303         /* Decrement the bios in processing, and if zero signal completion */
2304         if (atomic_dec_and_test(&blockio_work->bios_inflight)) {
2305                 blockio_work->cmd->completed = 1;
2306                 blockio_work->cmd->scst_cmd_done(blockio_work->cmd,
2307                         SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_DIRECT_ATOMIC);
2308                 kfree(blockio_work);
2309         }
2310         return;
2311 }
2312
2313 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
2314 static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error)
2315 #else
2316 static void blockio_endio(struct bio *bio, int error)
2317 #endif
2318 {
2319         struct blockio_work *blockio_work = bio->bi_private;
2320
2321 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
2322         if (bio->bi_size)
2323                 return 1;
2324 #endif
2325
2326         error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO;
2327
2328         if (unlikely(error != 0)) {
2329                 PRINT_ERROR("cmd %p returned error %d", blockio_work->cmd,
2330                         error);
2331                 /*
2332                  * The race with other such bio's doesn't matter, since all
2333                  * scst_set_cmd_error() calls do the same local to this cmd
2334                  * operations.
2335                  */
2336                 if (bio->bi_rw & WRITE)
2337                         scst_set_cmd_error(blockio_work->cmd,
2338                                 SCST_LOAD_SENSE(scst_sense_write_error));
2339                 else
2340                         scst_set_cmd_error(blockio_work->cmd,
2341                                 SCST_LOAD_SENSE(scst_sense_read_error));
2342         }
2343
2344         blockio_check_finish(blockio_work);
2345
2346         bio_put(bio);
2347 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
2348         return 0;
2349 #else
2350         return;
2351 #endif
2352 }
2353
2354 static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
2355         u64 lba_start, int write)
2356 {
2357         struct scst_vdisk_dev *virt_dev =
2358                 (struct scst_vdisk_dev *)cmd->dev->dh_priv;
2359         struct block_device *bdev = thr->bdev;
2360         struct request_queue *q = bdev_get_queue(bdev);
2361         int length, max_nr_vecs = 0;
2362         uint8_t *address;
2363         struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
2364         int need_new_bio;
2365         struct blockio_work *blockio_work;
2366         int bios = 0;
2367
2368         TRACE_ENTRY();
2369
2370         if (virt_dev->nullio)
2371                 goto out;
2372
2373         /* Allocate and initialize blockio_work struct */
2374         blockio_work = kmalloc(sizeof(*blockio_work), GFP_KERNEL);
2375         if (blockio_work == NULL)
2376                 goto out_no_mem;
2377
2378         blockio_work->cmd = cmd;
2379
2380         if (q)
2381                 max_nr_vecs = min(bio_get_nr_vecs(bdev), BIO_MAX_PAGES);
2382         else
2383                 max_nr_vecs = 1;
2384
2385         need_new_bio = 1;
2386
2387         length = scst_get_buf_first(cmd, &address);
2388         while (length > 0) {
2389                 int len, bytes, off, thislen;
2390                 uint8_t *addr;
2391                 u64 lba_start0;
2392
2393                 addr = address;
2394                 off = offset_in_page(addr);
2395                 len = length;
2396                 thislen = 0;
2397                 lba_start0 = lba_start;
2398
2399                 while (len > 0) {
2400                         int rc;
2401                         struct page *page = virt_to_page(addr);
2402
2403                         if (need_new_bio) {
2404                                 bio = bio_alloc(GFP_KERNEL, max_nr_vecs);
2405                                 if (!bio) {
2406                                         PRINT_ERROR("Failed to create bio "
2407                                                 "for data segment= %d cmd %p",
2408                                                 cmd->get_sg_buf_entry_num, cmd);
2409                                         goto out_no_bio;
2410                                 }
2411
2412                                 bios++;
2413                                 need_new_bio = 0;
2414                                 bio->bi_end_io = blockio_endio;
2415                                 bio->bi_sector = lba_start0 <<
2416                                         (virt_dev->block_shift - 9);
2417                                 bio->bi_bdev = bdev;
2418                                 bio->bi_private = blockio_work;
2419 #if 0 /* It could be win, but could be not, so a performance study is needed */
2420                                 bio->bi_rw |= 1 << BIO_RW_SYNC;
2421 #endif
2422                                 if (!hbio)
2423                                         hbio = tbio = bio;
2424                                 else
2425                                         tbio = tbio->bi_next = bio;
2426                         }
2427
2428                         bytes = min_t(unsigned int, len, PAGE_SIZE - off);
2429
2430                         rc = bio_add_page(bio, page, bytes, off);
2431                         if (rc < bytes) {
2432                                 sBUG_ON(rc != 0);
2433                                 need_new_bio = 1;
2434                                 lba_start0 += thislen >> virt_dev->block_shift;
2435                                 thislen = 0;
2436                                 continue;
2437                         }
2438
2439                         addr += PAGE_SIZE;
2440                         thislen += bytes;
2441                         len -= bytes;
2442                         off = 0;
2443                 }
2444
2445                 lba_start += length >> virt_dev->block_shift;
2446
2447                 scst_put_buf(cmd, address);
2448                 length = scst_get_buf_next(cmd, &address);
2449         }
2450
2451         /* +1 to prevent erroneous too early command completion */
2452         atomic_set(&blockio_work->bios_inflight, bios+1);
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;
3397 }
3398
3399 static struct scst_proc_data vdisk_help_proc_data = {
3400         SCST_DEF_RW_SEQ_OP(NULL)
3401         .show = vdisk_help_info_show,
3402 };
3403
3404 static int vdisk_proc_help_build(struct scst_dev_type *dev_type)
3405 {