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