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