From Erik Habbinga <erikhabbinga@inphase-tech.com>
[mirror/scst/.git] / scst / src / dev_handlers / scst_fileio.c
1 /*
2  *  scst_fileio.c
3  *  
4  *  Copyright (C) 2004-2006 Vladislav Bolkhovitin <vst@vlnb.net>
5  *                 and Leonid Stoljar
6  *
7  *  SCSI disk (type 0) and CDROM (type 5) dev handler using files 
8  *  on file systems (FILEIO)
9  *  
10  *  This program is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU General Public License
12  *  as published by the Free Software Foundation, version 2
13  *  of the License.
14  * 
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  *  GNU General Public License for more details.
19  */
20
21 #include <asm/uaccess.h>  
22 #include <linux/file.h>
23 #include <linux/fs.h>
24 #include <linux/string.h>
25 #include <linux/types.h>
26 #include <linux/unistd.h>
27 #include <linux/smp_lock.h>
28 #include <linux/spinlock.h>
29 #include <linux/init.h>
30 #include <linux/uio.h>
31 #include <linux/proc_fs.h>
32 #include <linux/list.h>
33 #include <linux/ctype.h>
34 #include <linux/writeback.h>
35 #include <linux/vmalloc.h>
36 #include <asm/atomic.h>
37
38 #define LOG_PREFIX                      "dev_fileio"
39 #include "scst_debug.h"
40 #include "scsi_tgt.h"
41 #include "scst_dev_handler.h"
42
43 #include "scst_debug.c"
44
45 /* 8 byte ASCII Vendor of the FILE IO target */
46 #define SCST_FIO_VENDOR                 "SCST_FIO"
47 /* 4 byte ASCII Product Revision Level of the FILE IO target - left aligned */
48 #define SCST_FIO_REV                    " 095"
49
50 #define READ_CAP_LEN                    8
51 #define READ_CAP16_LEN                  32
52
53 #define BYTCHK                          0x02
54
55 #define INQ_BUF_SZ                      128
56 #define EVPD                            0x01
57 #define CMDDT                           0x02
58
59 #define MSENSE_BUF_SZ                   256
60 #define DBD                             0x08    /* disable block descriptor */
61 #define WP                              0x80    /* write protect */
62 #define DPOFUA                          0x10    /* DPOFUA bit */
63 #define WCE                             0x04    /* write cache enable */
64
65 #define PF                              0x10    /* page format */
66 #define SP                              0x01    /* save pages */
67 #define PS                              0x80    /* parameter saveable */
68
69 #define BYTE                            8
70 #define DEF_DISK_BLOCKSIZE              512
71 #define DEF_DISK_BLOCKSIZE_SHIFT        9
72 #define DEF_CDROM_BLOCKSIZE             2048
73 #define DEF_CDROM_BLOCKSIZE_SHIFT       11
74 #define DEF_SECTORS_PER                 63
75 #define LEN_MEM                         (32 * 1024)
76 #define DISK_FILEIO_NAME                "disk_fileio"
77 #define CDROM_FILEIO_NAME               "cdrom_fileio"
78
79 #define FILEIO_PROC_HELP                "help"
80
81 #if defined(DEBUG) || defined(TRACING)
82 unsigned long trace_flag = SCST_DEFAULT_DEV_LOG_FLAGS;
83 #endif
84
85 struct scst_fileio_dev {
86         uint32_t block_size;
87         uint64_t nblocks;
88         int block_shift;
89         loff_t file_size;       /* in bytes */
90         unsigned int rd_only_flag:1;
91         unsigned int wt_flag:1;
92         unsigned int nv_cache:1;
93         unsigned int o_direct_flag:1;
94         unsigned int media_changed:1;
95         unsigned int prevent_allow_medium_removal:1;
96         unsigned int nullio:1;
97         unsigned int cdrom_empty:1;
98         int virt_id;
99         char name[16+1];        /* Name of virtual device,
100                                    must be <= SCSI Model + 1 */
101         char *file_name;        /* File name */
102         struct list_head fileio_dev_list_entry;
103         struct list_head ftgt_list;
104         struct semaphore ftgt_list_mutex;
105 };
106
107 struct scst_fileio_tgt_dev {
108         spinlock_t fdev_lock;
109         enum scst_cmd_queue_type last_write_cmd_queue_type;
110         int shutdown;
111         struct file *fd;
112         struct iovec *iv;
113         int iv_count;
114         struct list_head fdev_cmd_list;
115         wait_queue_head_t fdev_waitQ;
116         struct scst_fileio_dev *virt_dev;
117         atomic_t threads_count;
118         struct semaphore shutdown_mutex;
119         struct list_head ftgt_list_entry;
120 };
121
122 static int fileio_attach(struct scst_device *dev);
123 static void fileio_detach(struct scst_device *dev);
124 static int fileio_attach_tgt(struct scst_tgt_dev *tgt_dev);
125 static void fileio_detach_tgt(struct scst_tgt_dev *tgt_dev);
126 static int disk_fileio_parse(struct scst_cmd *, const struct scst_info_cdb *info_cdb);
127 static int disk_fileio_exec(struct scst_cmd *cmd);
128 static int cdrom_fileio_parse(struct scst_cmd *, const struct scst_info_cdb *info_cdb);
129 static int cdrom_fileio_exec(struct scst_cmd *cmd);
130 static void fileio_exec_read(struct scst_cmd *cmd, loff_t loff);
131 static void fileio_exec_write(struct scst_cmd *cmd, loff_t loff);
132 static void fileio_exec_verify(struct scst_cmd *cmd, loff_t loff);
133 static int fileio_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
134         struct scst_tgt_dev *tgt_dev);
135 static void fileio_exec_read_capacity(struct scst_cmd *cmd);
136 static void fileio_exec_read_capacity16(struct scst_cmd *cmd);
137 static void fileio_exec_inquiry(struct scst_cmd *cmd);
138 static void fileio_exec_mode_sense(struct scst_cmd *cmd);
139 static void fileio_exec_mode_select(struct scst_cmd *cmd);
140 static void fileio_exec_read_toc(struct scst_cmd *cmd);
141 static void fileio_exec_prevent_allow_medium_removal(struct scst_cmd *cmd);
142 static int fileio_fsync(struct scst_fileio_tgt_dev *ftgt_dev,
143         loff_t loff, loff_t len, struct scst_cmd *cmd);
144 static int disk_fileio_proc(char *buffer, char **start, off_t offset,
145         int length, int *eof, struct scst_dev_type *dev_type, int inout);
146 static int cdrom_fileio_proc(char *buffer, char **start, off_t offset,
147         int length, int *eof, struct scst_dev_type *dev_type, int inout);
148 static int fileio_proc_help_read(char *buffer, char **start,off_t offset,
149         int length, int *eof, void *data);
150
151 #define DISK_TYPE_FILEIO {              \
152   name:         DISK_FILEIO_NAME,       \
153   type:         TYPE_DISK,              \
154   parse_atomic: 1,                      \
155   exec_atomic:  1,                      \
156   dev_done_atomic: 1,                   \
157   attach:       fileio_attach,          \
158   detach:       fileio_detach,          \
159   attach_tgt:   fileio_attach_tgt,      \
160   detach_tgt:   fileio_detach_tgt,      \
161   parse:        disk_fileio_parse,      \
162   exec:         disk_fileio_exec,       \
163   task_mgmt_fn: fileio_task_mgmt_fn,    \
164   proc_info:    disk_fileio_proc,       \
165 }
166
167 #define CDROM_TYPE_FILEIO {             \
168   name:         CDROM_FILEIO_NAME,      \
169   type:         TYPE_ROM,               \
170   parse_atomic: 1,                      \
171   exec_atomic:  1,                      \
172   dev_done_atomic: 1,                   \
173   attach:       fileio_attach,          \
174   detach:       fileio_detach,          \
175   attach_tgt:   fileio_attach_tgt,      \
176   detach_tgt:   fileio_detach_tgt,      \
177   parse:        cdrom_fileio_parse,     \
178   exec:         cdrom_fileio_exec,      \
179   task_mgmt_fn: fileio_task_mgmt_fn,    \
180   proc_info:    cdrom_fileio_proc,      \
181 }
182
183 DECLARE_MUTEX(scst_fileio_mutex);
184 static LIST_HEAD(disk_fileio_dev_list);
185 static LIST_HEAD(cdrom_fileio_dev_list);
186
187 static struct scst_dev_type disk_devtype_fileio = DISK_TYPE_FILEIO;
188 static struct scst_dev_type cdrom_devtype_fileio = CDROM_TYPE_FILEIO;
189
190 static char *disk_fileio_proc_help_string =
191         "echo \"open|close NAME [FILE_NAME [BLOCK_SIZE] [WRITE_THROUGH "
192         "READ_ONLY O_DIRECT NULLIO NV_CACHE]]\" >/proc/scsi_tgt/" 
193         DISK_FILEIO_NAME "/" DISK_FILEIO_NAME "\n";
194
195 static char *cdrom_fileio_proc_help_string =
196         "echo \"open|change|close NAME [FILE_NAME]\" "
197         ">/proc/scsi_tgt/" CDROM_FILEIO_NAME "/" CDROM_FILEIO_NAME "\n";
198
199 #define FILEIO_THREAD_FLAGS                    CLONE_KERNEL
200
201 /**************************************************************
202  *  Function:  fileio_open
203  *
204  *  Argument:  
205  *
206  *  Returns :  fd, use IS_ERR(fd) to get error status
207  *
208  *  Description:  
209  *************************************************************/
210 static struct file *fileio_open(const struct scst_fileio_dev *virt_dev)
211 {
212         int open_flags = 0;
213         struct file *fd;
214
215         TRACE_ENTRY();
216
217         if (virt_dev->rd_only_flag)
218                 open_flags |= O_RDONLY;
219         else
220                 open_flags |= O_RDWR;
221         if (virt_dev->o_direct_flag)
222                 open_flags |= O_DIRECT;
223         if (virt_dev->wt_flag)
224                 open_flags |= O_SYNC;
225         TRACE_DBG("Opening file %s, flags 0x%x", virt_dev->file_name, open_flags);
226         fd = filp_open(virt_dev->file_name, O_LARGEFILE | open_flags, 0600);
227
228         TRACE_EXIT();
229         return fd;
230 }
231
232 /**************************************************************
233  *  Function:  fileio_attach
234  *
235  *  Argument:  
236  *
237  *  Returns :  1 if attached, error code otherwise
238  *
239  *  Description:  
240  *************************************************************/
241 static int fileio_attach(struct scst_device *dev)
242 {
243         int res = 0;
244         loff_t err;
245         mm_segment_t old_fs;
246         struct file *fd;
247         struct scst_fileio_dev *virt_dev = NULL, *vv;
248         struct list_head *fileio_dev_list;
249
250         TRACE_ENTRY();
251
252         TRACE_DBG("virt_id %d (%s)", dev->virt_id, dev->virt_name);
253
254         if (dev->virt_id == 0) {
255                 PRINT_ERROR_PR("%s", "Not a virtual device");
256                 res = -EINVAL;
257                 goto out;
258         }
259
260         fileio_dev_list = (dev->handler->type == TYPE_DISK) ? 
261                                 &disk_fileio_dev_list :
262                                 &cdrom_fileio_dev_list;
263
264         /* 
265          * scst_fileio_mutex must be already taken before 
266          * scst_register_virtual_device()
267          */
268         list_for_each_entry(vv, fileio_dev_list, fileio_dev_list_entry)
269         {
270                 if (strcmp(vv->name, dev->virt_name) == 0) {
271                         virt_dev = vv;
272                         break;
273                 }
274         }
275         
276         if (virt_dev == NULL) {
277                 PRINT_ERROR_PR("Device %s not found", dev->virt_name);
278                 res = -EINVAL;
279                 goto out;
280         }
281         
282         if (dev->handler->type == TYPE_ROM)
283                 virt_dev->rd_only_flag = 1;
284
285         if (!virt_dev->cdrom_empty) {
286                 fd = fileio_open(virt_dev);
287                 if (IS_ERR(fd)) {
288                         res = PTR_ERR(fd);
289                         PRINT_ERROR_PR("filp_open(%s) returned an error %d",
290                                        virt_dev->file_name, res);
291                         goto out;
292                 }
293
294                 if ((fd->f_op == NULL) || (fd->f_op->readv == NULL) || 
295                     (fd->f_op->writev == NULL))
296                 {
297                         PRINT_ERROR_PR("%s", "Wrong f_op or FS doesn't have "
298                                 "required capabilities");
299                                 res = -EINVAL;
300                         goto out_close_file;
301                 }
302         
303                 /* seek to end */
304                 old_fs = get_fs();
305                 set_fs(get_ds());
306                 if (fd->f_op->llseek) {
307                         err = fd->f_op->llseek(fd, 0, 2/*SEEK_END*/);
308                 } else {
309                         err = default_llseek(fd, 0, 2/*SEEK_END*/);
310                 }
311                 set_fs(old_fs);
312                 if (err < 0) {
313                         res = err;
314                         PRINT_ERROR_PR("llseek %s returned an error %d",
315                                        virt_dev->file_name, res);
316                         goto out_close_file;
317                 }
318                 virt_dev->file_size = err;
319                 TRACE_DBG("size of file: %Ld", (uint64_t)err);
320
321                 filp_close(fd, NULL);
322         } else
323                 virt_dev->file_size = 0;
324
325         if (dev->handler->type == TYPE_DISK) {
326                 virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
327         } else {
328                 virt_dev->block_size = DEF_CDROM_BLOCKSIZE;
329                 virt_dev->block_shift = DEF_CDROM_BLOCKSIZE_SHIFT;
330                 virt_dev->nblocks = virt_dev->file_size >> DEF_CDROM_BLOCKSIZE_SHIFT;
331         }
332
333         if (!virt_dev->cdrom_empty) {
334                 PRINT_INFO_PR("Attached SCSI target virtual %s %s "
335                       "(file=\"%s\", fs=%LdMB, bs=%d, nblocks=%Ld, cyln=%Ld%s)",
336                       (dev->handler->type == TYPE_DISK) ? "disk" : "cdrom",
337                       virt_dev->name, virt_dev->file_name,
338                       virt_dev->file_size >> 20, virt_dev->block_size,
339                       virt_dev->nblocks, virt_dev->nblocks/64/32,
340                       virt_dev->nblocks < 64*32 ? " !WARNING! cyln less than 1" : "");
341         } else {
342                 PRINT_INFO_PR("Attached empty SCSI target virtual cdrom %s",
343                         virt_dev->name);
344         }
345
346         dev->dh_priv = virt_dev;
347
348 out:
349         TRACE_EXIT();
350         return res;
351
352 out_close_file:
353         filp_close(fd, NULL);
354         goto out;
355 }
356
357 /************************************************************
358  *  Function:  fileio_detach
359  *
360  *  Argument: 
361  *
362  *  Returns :  None
363  *
364  *  Description:  Called to detach this device type driver
365  ************************************************************/
366 static void fileio_detach(struct scst_device *dev)
367 {
368         struct scst_fileio_dev *virt_dev =
369             (struct scst_fileio_dev *)dev->dh_priv;
370
371         TRACE_ENTRY();
372
373         TRACE_DBG("virt_id %d", dev->virt_id);
374
375         PRINT_INFO_PR("Detached SCSI target virtual device %s (\"%s\")",
376                       virt_dev->name, virt_dev->file_name);
377
378         /* virt_dev will be freed by the caller */
379         dev->dh_priv = NULL;
380         
381         TRACE_EXIT();
382         return;
383 }
384
385 static inline int fileio_sync_queue_type(enum scst_cmd_queue_type qt)
386 {
387         switch(qt) {
388                 case SCST_CMD_QUEUE_ORDERED:
389                 case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
390                         return 1;
391                 default:
392                         return 0;
393         }
394 }
395
396 static inline int fileio_need_pre_sync(enum scst_cmd_queue_type cwqt,
397         enum scst_cmd_queue_type lwqt)
398 {
399         if (fileio_sync_queue_type(cwqt))
400                 if (!fileio_sync_queue_type(lwqt))
401                         return 1;
402         return 0;
403 }
404
405 static void fileio_do_job(struct scst_cmd *cmd)
406 {
407         uint64_t lba_start;
408         loff_t data_len;
409         int opcode = cmd->cdb[0];
410         loff_t loff;
411         struct scst_device *dev = cmd->dev;
412         struct scst_fileio_dev *virt_dev =
413                 (struct scst_fileio_dev *)dev->dh_priv;
414         int fua = 0;
415
416         TRACE_ENTRY();
417
418         if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
419                 TRACE_MGMT_DBG("Flag ABORTED set for "
420                       "cmd %p (tag %d), skipping", cmd, cmd->tag);
421                 goto done_uncompl;
422         }
423         
424
425         switch (opcode) {
426         case READ_6:
427         case WRITE_6:
428         case VERIFY_6:
429                 lba_start = (((cmd->cdb[1] & 0x1f) << (BYTE * 2)) +
430                              (cmd->cdb[2] << (BYTE * 1)) +
431                              (cmd->cdb[3] << (BYTE * 0)));
432                 data_len = cmd->bufflen;
433                 break;
434         case READ_10:
435         case READ_12:
436         case WRITE_10:
437         case WRITE_12:
438         case VERIFY:
439         case WRITE_VERIFY:
440         case WRITE_VERIFY_12:
441         case VERIFY_12:
442                 lba_start = be32_to_cpu(*(u32 *)&cmd->cdb[2]);
443                 data_len = cmd->bufflen;
444                 break;
445         case SYNCHRONIZE_CACHE:
446                 lba_start = be32_to_cpu(*(u32 *)&cmd->cdb[2]);
447                 data_len = ((cmd->cdb[7] << (BYTE * 1)) +
448                         (cmd->cdb[8] << (BYTE * 0))) << virt_dev->block_shift;
449                 if (data_len == 0)
450                         data_len = virt_dev->file_size - 
451                                 ((loff_t)lba_start << virt_dev->block_shift);
452                 break;
453         case READ_16:
454         case WRITE_16:
455         case WRITE_VERIFY_16:
456         case VERIFY_16:
457                 lba_start = be64_to_cpu(*(u64*)&cmd->cdb[2]);
458                 data_len = cmd->bufflen;
459                 break;
460         default:
461                 lba_start = 0;
462                 data_len = 0;
463         }
464
465         loff = (loff_t)lba_start << virt_dev->block_shift;
466         TRACE_DBG("cmd %p, lba_start %Ld, loff %Ld, data_len %Ld", cmd,
467                 lba_start, (uint64_t)loff, (uint64_t)data_len);
468         if (unlikely(loff < 0) || unlikely(data_len < 0) ||
469             unlikely((loff + data_len) > virt_dev->file_size)) {
470                 PRINT_INFO_PR("Access beyond the end of the device "
471                         "(%lld of %lld, len %Ld)", (uint64_t)loff, 
472                         (uint64_t)virt_dev->file_size, (uint64_t)data_len);
473                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
474                                         scst_sense_block_out_range_error));
475                 goto done;
476         }
477
478         switch (opcode) {
479         case WRITE_10:
480         case WRITE_12:
481         case WRITE_16:
482                 fua = (cmd->cdb[1] & 0x8) && !virt_dev->wt_flag;
483                 if (cmd->cdb[1] & 0x8) {
484                         TRACE(TRACE_SCSI, "FUA(%d): loff=%Ld, "
485                                 "data_len=%Ld", fua, (uint64_t)loff,
486                                 (uint64_t)data_len);
487                 }
488                 break;
489         }
490
491         switch (opcode) {
492         case READ_6:
493         case READ_10:
494         case READ_12:
495         case READ_16:
496                 fileio_exec_read(cmd, loff);
497                 break;
498         case WRITE_6:
499         case WRITE_10:
500         case WRITE_12:
501         case WRITE_16:
502                 if (likely(!virt_dev->rd_only_flag)) {
503                         int do_fsync = 0;
504                         struct scst_fileio_tgt_dev *ftgt_dev =
505                                 (struct scst_fileio_tgt_dev*)
506                                         cmd->tgt_dev->dh_priv;
507                         enum scst_cmd_queue_type last_queue_type =
508                                 ftgt_dev->last_write_cmd_queue_type;
509                         ftgt_dev->last_write_cmd_queue_type = cmd->queue_type;
510                         if (fileio_need_pre_sync(cmd->queue_type, last_queue_type) &&
511                             !virt_dev->wt_flag) {
512                                 TRACE(TRACE_SCSI/*|TRACE_SPECIAL*/, "ORDERED "
513                                         "WRITE(%d): loff=%Ld, data_len=%Ld",
514                                         cmd->queue_type, (uint64_t)loff,
515                                         (uint64_t)data_len);
516                                 do_fsync = 1;
517                                 if (fileio_fsync(ftgt_dev, 0, 0, cmd) != 0)
518                                         goto done;
519                         }
520                         fileio_exec_write(cmd, loff);
521                         /* O_SYNC flag is used for wt_flag devices */
522                         if (do_fsync || fua)
523                                 fileio_fsync(ftgt_dev, loff, data_len, cmd);
524                 } else {
525                         TRACE_DBG("%s", "Attempt to write to read-only device");
526                         scst_set_cmd_error(cmd,
527                                 SCST_LOAD_SENSE(scst_sense_data_protect));
528                 }
529                 break;
530         case WRITE_VERIFY:
531         case WRITE_VERIFY_12:
532         case WRITE_VERIFY_16:
533                 if (likely(!virt_dev->rd_only_flag)) {
534                         int do_fsync = 0;
535                         struct scst_fileio_tgt_dev *ftgt_dev =
536                                 (struct scst_fileio_tgt_dev*)
537                                         cmd->tgt_dev->dh_priv;
538                         enum scst_cmd_queue_type last_queue_type =
539                                 ftgt_dev->last_write_cmd_queue_type;
540                         ftgt_dev->last_write_cmd_queue_type = cmd->queue_type;
541                         if (fileio_need_pre_sync(cmd->queue_type, last_queue_type) && 
542                             !virt_dev->wt_flag) {
543                                 TRACE(TRACE_SCSI/*|TRACE_SPECIAL*/, "ORDERED "
544                                         "WRITE_VERIFY(%d): loff=%Ld, data_len=%Ld",
545                                         cmd->queue_type, (uint64_t)loff,
546                                         (uint64_t)data_len);
547                                 do_fsync = 1;
548                                 if (fileio_fsync(ftgt_dev, 0, 0, cmd) != 0)
549                                         goto done;
550                         }
551                         fileio_exec_write(cmd, loff);
552                         /* O_SYNC flag is used for wt_flag devices */
553                         if (cmd->status == 0)
554                                 fileio_exec_verify(cmd, loff);
555                         else if (do_fsync)
556                                 fileio_fsync(ftgt_dev, loff, data_len, cmd);
557                 } else {
558                         TRACE_DBG("%s", "Attempt to write to read-only device");
559                         scst_set_cmd_error(cmd,
560                                 SCST_LOAD_SENSE(scst_sense_data_protect));
561                 }
562                 break;
563         case SYNCHRONIZE_CACHE:
564         {
565                 int immed = cmd->cdb[1] & 0x2;
566                 struct scst_fileio_tgt_dev *ftgt_dev = 
567                         (struct scst_fileio_tgt_dev*)
568                                 cmd->tgt_dev->dh_priv;
569                 TRACE(TRACE_SCSI, "SYNCHRONIZE_CACHE: "
570                         "loff=%Ld, data_len=%Ld, immed=%d", (uint64_t)loff,
571                         (uint64_t)data_len, immed);
572                 if (immed) {
573                         scst_get();
574                         cmd->completed = 1;
575                         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT);
576                         /* cmd is dead here */
577                         fileio_fsync(ftgt_dev, loff, data_len, NULL);
578                         /* ToDo: fileio_fsync() error processing */
579                         scst_put();
580                         goto out;
581                 } else {
582                         fileio_fsync(ftgt_dev, loff, data_len, cmd);
583                         break;
584                 }
585         }
586         case VERIFY_6:
587         case VERIFY:
588         case VERIFY_12:
589         case VERIFY_16:
590                 fileio_exec_verify(cmd, loff);
591                 break;
592         case MODE_SENSE:
593         case MODE_SENSE_10:
594                 fileio_exec_mode_sense(cmd);
595                 break;
596         case MODE_SELECT:
597         case MODE_SELECT_10:
598                 fileio_exec_mode_select(cmd);
599                 break;
600         case ALLOW_MEDIUM_REMOVAL:
601                 fileio_exec_prevent_allow_medium_removal(cmd);
602                 break;
603         case READ_TOC:
604                 fileio_exec_read_toc(cmd);
605                 break;
606         case START_STOP:
607         case RESERVE:
608         case RESERVE_10:
609         case RELEASE:
610         case RELEASE_10:
611                 break;
612         default:
613                 TRACE_DBG("Invalid opcode %d", opcode);
614                 scst_set_cmd_error(cmd,
615                     SCST_LOAD_SENSE(scst_sense_invalid_opcode));
616         }
617
618 done:
619         cmd->completed = 1;
620
621 done_uncompl:
622         cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT);
623
624 out:
625         TRACE_EXIT();
626         return;
627 }
628
629 static inline int test_cmd_list(struct scst_fileio_tgt_dev *ftgt_dev)
630 {
631         int res = !list_empty(&ftgt_dev->fdev_cmd_list) ||
632                   unlikely(ftgt_dev->shutdown);
633         return res;
634 }
635
636 static int fileio_cmd_thread(void *arg)
637 {
638         struct scst_fileio_tgt_dev *ftgt_dev = (struct scst_fileio_tgt_dev*)arg;
639
640         TRACE_ENTRY();
641
642         daemonize("scst_fileio");
643         recalc_sigpending();
644         set_user_nice(current, 10);
645         current->flags |= PF_NOFREEZE;
646
647         spin_lock_bh(&ftgt_dev->fdev_lock);
648         while (1) {
649                 wait_queue_t wait;
650                 struct scst_cmd *cmd;
651                 init_waitqueue_entry(&wait, current);
652
653                 if (!test_cmd_list(ftgt_dev)) {
654                         add_wait_queue_exclusive(&ftgt_dev->fdev_waitQ, &wait);
655                         for (;;) {
656                                 set_current_state(TASK_INTERRUPTIBLE);
657                                 if (test_cmd_list(ftgt_dev))
658                                         break;
659                                 spin_unlock_bh(&ftgt_dev->fdev_lock);
660                                 schedule();
661                                 spin_lock_bh(&ftgt_dev->fdev_lock);
662                         }
663                         set_current_state(TASK_RUNNING);
664                         remove_wait_queue(&ftgt_dev->fdev_waitQ, &wait);
665                 }
666
667                 while (!list_empty(&ftgt_dev->fdev_cmd_list)) {
668                         cmd = list_entry(ftgt_dev->fdev_cmd_list.next, 
669                                 typeof(*cmd), fileio_cmd_list_entry);
670                         cmd->fileio_in_list = 0;
671                         list_del(&cmd->fileio_cmd_list_entry);
672                         spin_unlock_bh(&ftgt_dev->fdev_lock);
673                         fileio_do_job(cmd);
674                         spin_lock_bh(&ftgt_dev->fdev_lock);
675                         if (unlikely(ftgt_dev->shutdown))
676                                 break;
677                 }
678
679                 if (unlikely(ftgt_dev->shutdown))
680                         break;
681         }
682         spin_unlock_bh(&ftgt_dev->fdev_lock);
683
684         if (atomic_dec_and_test(&ftgt_dev->threads_count)) {
685                 smp_mb__after_atomic_dec();
686                 TRACE_DBG("%s", "Releasing shutdown_mutex");
687                 up(&ftgt_dev->shutdown_mutex);
688         }
689
690         TRACE_EXIT();
691         return 0;
692 }
693
694 static int fileio_attach_tgt(struct scst_tgt_dev *tgt_dev)
695 {
696         struct scst_fileio_dev *virt_dev =
697             (struct scst_fileio_dev *)tgt_dev->acg_dev->dev->dh_priv;
698         struct scst_fileio_tgt_dev *ftgt_dev;
699         int res = 0;
700
701         TRACE_ENTRY();
702
703         ftgt_dev = kzalloc(sizeof(*ftgt_dev), GFP_KERNEL);
704         if (ftgt_dev == NULL) {
705                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of per-session "
706                         "virtual device failed");
707                 res = -ENOMEM;
708                 goto out;
709         }
710
711         spin_lock_init(&ftgt_dev->fdev_lock);
712         INIT_LIST_HEAD(&ftgt_dev->fdev_cmd_list);
713         init_waitqueue_head(&ftgt_dev->fdev_waitQ);
714         atomic_set(&ftgt_dev->threads_count, 0);
715         init_MUTEX_LOCKED(&ftgt_dev->shutdown_mutex);
716         ftgt_dev->virt_dev = virt_dev;
717
718         if (!virt_dev->cdrom_empty) {
719                 ftgt_dev->fd = fileio_open(virt_dev);
720                 if (IS_ERR(ftgt_dev->fd)) {
721                         res = PTR_ERR(ftgt_dev->fd);
722                         PRINT_ERROR_PR("filp_open(%s) returned an error %d",
723                                        virt_dev->file_name, res);
724                         goto out_free;
725                 }
726         } else
727                 ftgt_dev->fd = NULL;
728
729         /* 
730          * Only ONE thread must be run here, otherwise the commands could
731          * be executed out of order !!
732          */
733         res = kernel_thread(fileio_cmd_thread, ftgt_dev, FILEIO_THREAD_FLAGS);
734         if (res < 0) {
735                 PRINT_ERROR_PR("kernel_thread() failed: %d", res);
736                 goto out_free_close;
737         }
738         res = 0;
739         atomic_inc(&ftgt_dev->threads_count);
740
741         tgt_dev->dh_priv = ftgt_dev;
742
743         down(&virt_dev->ftgt_list_mutex);
744         list_add_tail(&ftgt_dev->ftgt_list_entry, 
745                 &virt_dev->ftgt_list);
746         up(&virt_dev->ftgt_list_mutex);
747
748 out:
749         TRACE_EXIT_RES(res);
750         return res;
751
752 out_free_close:
753         if (ftgt_dev->fd)
754                 filp_close(ftgt_dev->fd, NULL);
755
756 out_free:
757         kfree(ftgt_dev);
758         goto out;
759 }
760
761 static void fileio_detach_tgt(struct scst_tgt_dev *tgt_dev)
762 {
763         struct scst_fileio_tgt_dev *ftgt_dev = 
764                 (struct scst_fileio_tgt_dev *)tgt_dev->dh_priv;
765         struct scst_fileio_dev *virt_dev =
766             (struct scst_fileio_dev *)tgt_dev->acg_dev->dev->dh_priv;
767
768         TRACE_ENTRY();
769
770         down(&virt_dev->ftgt_list_mutex);
771         list_del(&ftgt_dev->ftgt_list_entry);
772         up(&virt_dev->ftgt_list_mutex);
773
774         ftgt_dev->shutdown = 1;
775         wake_up_all(&ftgt_dev->fdev_waitQ);
776         down(&ftgt_dev->shutdown_mutex);
777
778         if (ftgt_dev->fd)
779                 filp_close(ftgt_dev->fd, NULL);
780
781         if (ftgt_dev->iv != NULL)
782                 kfree(ftgt_dev->iv);
783
784         kfree(ftgt_dev);
785
786         tgt_dev->dh_priv = NULL;
787
788         TRACE_EXIT();
789 }
790
791 /********************************************************************
792  *  Function:  disk_fileio_parse
793  *
794  *  Argument:  
795  *
796  *  Returns :  The state of the command
797  *
798  *  Description:  This does the parsing of the command
799  *
800  *  Note:  Not all states are allowed on return
801  ********************************************************************/
802 static int disk_fileio_parse(struct scst_cmd *cmd,
803         const struct scst_info_cdb *info_cdb)
804 {
805         int res = SCST_CMD_STATE_DEFAULT;
806         int fixed;
807         struct scst_fileio_dev *virt_dev =
808             (struct scst_fileio_dev *)cmd->dev->dh_priv;
809
810         TRACE_ENTRY();
811         
812         /*
813          * SCST sets good defaults for cmd->data_direction and cmd->bufflen
814          * based on info_cdb, therefore change them only if necessary
815          */
816
817         TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
818               info_cdb->op_name,
819               info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
820
821         fixed = info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED;
822         switch (cmd->cdb[0]) {
823         case READ_CAPACITY:
824                 cmd->bufflen = READ_CAP_LEN;
825                 cmd->data_direction = SCST_DATA_READ;
826                 break;
827         case SERVICE_ACTION_IN:
828                 if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
829                         cmd->bufflen = READ_CAP16_LEN;
830                         cmd->data_direction = SCST_DATA_READ;
831                 }
832                 break;
833         case VERIFY_6:
834         case VERIFY:
835         case VERIFY_12:
836         case VERIFY_16:
837                 if ((cmd->cdb[1] & BYTCHK) == 0) {
838                         cmd->data_len = 
839                             info_cdb->transfer_len << virt_dev->block_shift;
840                         cmd->bufflen = 0;
841                         cmd->data_direction = SCST_DATA_NONE;
842                         fixed = 0;
843                 } else
844                         cmd->data_len = 0;
845                 break;
846         default:
847                 /* It's all good */
848                 break;
849         }
850
851         if (fixed) {
852                 /* 
853                  * No need for locks here, since *_detach() can not be
854                  * called, when there are existing commands.
855                  */
856                 cmd->bufflen = info_cdb->transfer_len << virt_dev->block_shift;
857         }
858
859         TRACE_DBG("res %d, bufflen %zd, data_len %zd, direct %d",
860               res, cmd->bufflen, cmd->data_len, cmd->data_direction);
861
862         TRACE_EXIT();
863         return res;
864 }
865
866 static inline void fileio_queue_cmd(struct scst_cmd *cmd)
867 {
868         struct scst_fileio_tgt_dev *ftgt_dev =
869                 (struct scst_fileio_tgt_dev *)cmd->tgt_dev->dh_priv;
870         spin_lock_bh(&ftgt_dev->fdev_lock);
871         TRACE_DBG("Pushing cmd %p to IO thread", cmd);
872         list_add_tail(&cmd->fileio_cmd_list_entry, 
873                 &ftgt_dev->fdev_cmd_list);
874         cmd->fileio_in_list = 1;
875         spin_unlock_bh(&ftgt_dev->fdev_lock);
876         wake_up(&ftgt_dev->fdev_waitQ);
877 }
878
879
880 /********************************************************************
881  *  Function:  disk_fileio_exec
882  *
883  *  Argument:  
884  *
885  *  Returns : always SCST_EXEC_COMPLETED, real status is in error condition
886  *  in command
887  *
888  *  Description:  
889  ********************************************************************/
890 static int disk_fileio_exec(struct scst_cmd *cmd)
891 {
892         int delayed = 0;
893         int opcode = cmd->cdb[0];
894
895         TRACE_ENTRY();
896
897         cmd->status = 0;
898         cmd->masked_status = 0;
899         cmd->msg_status = 0;
900         cmd->host_status = DID_OK;
901         cmd->driver_status = 0;
902
903         /* 
904          * !!
905          * Only commands that unsensible to the execution order could be 
906          * performed here, in place. Other ones must be passed to the
907          * thread.
908          * !!
909          */
910         switch (opcode) {
911         case INQUIRY:
912                 fileio_exec_inquiry(cmd);
913                 break;
914         case READ_CAPACITY:
915                 fileio_exec_read_capacity(cmd);
916                 break;
917         case SERVICE_ACTION_IN:
918                 if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16)
919                         fileio_exec_read_capacity16(cmd);
920                 else
921                         goto def;
922                 break;
923         case WRITE_VERIFY:
924         case WRITE_VERIFY_12:
925         case WRITE_VERIFY_16:
926             /* fall through */
927         case WRITE_6:
928         case WRITE_10:
929         case WRITE_12:
930         case WRITE_16:
931             /* could move READ ONLY check up to here (currenlty in do_job()) */
932             /* fall through */
933         case MODE_SENSE:
934         case MODE_SENSE_10:
935         case MODE_SELECT:
936         case MODE_SELECT_10:
937         case READ_6:
938         case READ_10:
939         case READ_12:
940         case READ_16:
941         case SYNCHRONIZE_CACHE:
942         case VERIFY_6:
943         case VERIFY:
944         case VERIFY_12:
945         case VERIFY_16:
946         case START_STOP:
947         case RESERVE:
948         case RESERVE_10:
949         case RELEASE:
950         case RELEASE_10:
951                 fileio_queue_cmd(cmd);
952                 delayed = 1;
953                 break;
954         case TEST_UNIT_READY:
955                 break;
956         case REPORT_LUNS:
957 def:
958         default:
959                 TRACE_DBG("Invalid opcode 0x%02x", opcode);
960                 scst_set_cmd_error(cmd,
961                     SCST_LOAD_SENSE(scst_sense_invalid_opcode));
962         }
963
964         if (!delayed) {
965                 cmd->completed = 1;
966                 cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT);
967         }
968
969         TRACE_EXIT();
970         return SCST_EXEC_COMPLETED;
971 }
972
973 /********************************************************************
974  *  Function:  cdrom_fileio_parse
975  *
976  *  Argument:  
977  *
978  *  Returns :  The state of the command
979  *
980  *  Description:  This does the parsing of the command
981  *
982  *  Note:  Not all states are allowed on return
983  ********************************************************************/
984 static int cdrom_fileio_parse(struct scst_cmd *cmd,
985         const struct scst_info_cdb *info_cdb)
986 {
987         int res = SCST_CMD_STATE_DEFAULT;
988         int fixed;
989         struct scst_fileio_dev *virt_dev =
990             (struct scst_fileio_dev *)cmd->dev->dh_priv;
991
992         TRACE_ENTRY();
993         
994         /*
995          * SCST sets good defaults for cmd->data_direction and cmd->bufflen
996          * based on info_cdb, therefore change them only if necessary
997          */
998
999         TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
1000               info_cdb->op_name,
1001               info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
1002
1003         fixed = info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED;
1004         switch (cmd->cdb[0]) {
1005         case READ_CAPACITY:
1006                 cmd->bufflen = READ_CAP_LEN;
1007                 cmd->data_direction = SCST_DATA_READ;
1008                 break;
1009         case VERIFY_6:
1010         case VERIFY:
1011         case VERIFY_12:
1012         case VERIFY_16:
1013                 if ((cmd->cdb[1] & BYTCHK) == 0) {
1014                         cmd->data_len = 
1015                             info_cdb->transfer_len << virt_dev->block_shift;
1016                         cmd->bufflen = 0;
1017                         cmd->data_direction = SCST_DATA_NONE;
1018                         fixed = 0;
1019                 } else
1020                         cmd->data_len = 0;
1021                 break;
1022         default:
1023                 /* It's all good */
1024                 break;
1025         }
1026
1027         if (fixed) {
1028                 /* 
1029                  * No need for locks here, since *_detach() can not be
1030                  * called, when there are existing commands.
1031                  */
1032                 cmd->bufflen = info_cdb->transfer_len << virt_dev->block_shift;
1033         }
1034
1035         TRACE_DBG("res %d, bufflen %zd, data_len %zd, direct %d",
1036               res, cmd->bufflen, cmd->data_len, cmd->data_direction);
1037
1038         TRACE_EXIT_HRES(res);
1039         return res;
1040 }
1041
1042 /********************************************************************
1043  *  Function:  cdrom_fileio_exec
1044  *
1045  *  Argument:  
1046  *
1047  *  Returns :  
1048  *
1049  *  Description:  
1050  ********************************************************************/
1051 static int cdrom_fileio_exec(struct scst_cmd *cmd)
1052 {
1053         int delayed = 0;
1054         int opcode = cmd->cdb[0];
1055         struct scst_fileio_dev *virt_dev =
1056             (struct scst_fileio_dev *)cmd->dev->dh_priv;
1057
1058         TRACE_ENTRY();
1059
1060         cmd->status = 0;
1061         cmd->masked_status = 0;
1062         cmd->msg_status = 0;
1063         cmd->host_status = DID_OK;
1064         cmd->driver_status = 0;
1065
1066         if (virt_dev->cdrom_empty && (opcode != INQUIRY)) {
1067                 TRACE_DBG("%s", "CDROM empty");
1068                 scst_set_cmd_error(cmd,
1069                         SCST_LOAD_SENSE(scst_sense_not_ready));
1070                 goto out;
1071         }
1072
1073         /* 
1074          * No protection is necessary, because media_changed set only
1075          * in suspended state and exec() is serialized
1076          */
1077         if (virt_dev->media_changed && (cmd->cdb[0] != INQUIRY) && 
1078             (cmd->cdb[0] != REQUEST_SENSE) && (cmd->cdb[0] != REPORT_LUNS)) {
1079                 virt_dev->media_changed = 0;
1080                 TRACE_DBG("%s", "Reporting media changed");
1081                 scst_set_cmd_error(cmd,
1082                         SCST_LOAD_SENSE(scst_sense_medium_changed_UA));
1083                 goto out;
1084         }
1085
1086         /* 
1087          * !!
1088          * Only commands that unsensible to the execution order could be 
1089          * performed here, in place. Other ones must be passed to the
1090          * thread.
1091          * !!
1092          */
1093
1094         switch (opcode) {
1095         case INQUIRY:
1096                 fileio_exec_inquiry(cmd);
1097                 break;
1098         case READ_CAPACITY:
1099                 fileio_exec_read_capacity(cmd);
1100                 break;
1101         case WRITE_VERIFY:
1102         case WRITE_VERIFY_12:
1103         case WRITE_VERIFY_16:
1104             /* fall through */
1105         case MODE_SENSE:
1106         case MODE_SENSE_10:
1107         case MODE_SELECT:
1108         case MODE_SELECT_10:
1109         case READ_6:
1110         case READ_10:
1111         case READ_12:
1112         case READ_16:
1113         case WRITE_6:
1114         case WRITE_10:
1115         case WRITE_12:
1116         case WRITE_16:
1117         case VERIFY_6:
1118         case VERIFY:
1119         case VERIFY_12:
1120         case VERIFY_16:
1121         case START_STOP:
1122         case RESERVE:
1123         case RESERVE_10:
1124         case RELEASE:
1125         case RELEASE_10:
1126         case ALLOW_MEDIUM_REMOVAL:
1127         case READ_TOC:
1128                 fileio_queue_cmd(cmd);
1129                 delayed = 1;
1130                 break;
1131         case TEST_UNIT_READY:
1132                 break;
1133         case REPORT_LUNS:
1134         default:
1135                 TRACE_DBG("Invalid opcode 0x%02x", opcode);
1136                 scst_set_cmd_error(cmd,
1137                         SCST_LOAD_SENSE(scst_sense_invalid_opcode));
1138         }
1139
1140 out:
1141         if (!delayed) {
1142                 cmd->completed = 1;
1143                 cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT);
1144         }
1145
1146         TRACE_EXIT();
1147         return SCST_EXEC_COMPLETED;
1148 }
1149
1150 static void fileio_exec_inquiry(struct scst_cmd *cmd)
1151 {
1152         int32_t length, len, i;
1153         uint8_t *address;
1154         uint8_t *buf;
1155         struct scst_fileio_dev *virt_dev =
1156             (struct scst_fileio_dev *)cmd->dev->dh_priv;
1157
1158         /* ToDo: Performance Boost:
1159          * 1. remove kzalloc, buf
1160          * 2. do all checks before touching *address
1161          * 3. zero *address
1162          * 4. write directly to *address
1163          */
1164
1165         TRACE_ENTRY();
1166
1167         buf = kzalloc(INQ_BUF_SZ, 
1168                 scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
1169         if (buf == NULL) {
1170                 scst_set_busy(cmd);
1171                 goto out;
1172         }
1173
1174         length = scst_get_buf_first(cmd, &address);
1175         TRACE_DBG("length %d", length);
1176         if (unlikely(length <= 0)) {
1177                 PRINT_ERROR_PR("scst_get_buf_first() failed: %d", length);
1178                 scst_set_cmd_error(cmd,
1179                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1180                 goto out_free;
1181         }
1182
1183         /* 
1184          * ToDo: write through/back flags as well as read only one.
1185          * Also task queue size should be set on some value.
1186          */
1187
1188         if (cmd->cdb[1] & CMDDT) {
1189                 TRACE_DBG("%s", "INQUIRY: CMDDT is unsupported");
1190                 scst_set_cmd_error(cmd,
1191                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1192                 goto out_put;
1193         }
1194
1195         memset(buf, 0, sizeof(buf));
1196         buf[0] = cmd->dev->handler->type;      /* type dev */
1197         if (buf[0] == TYPE_ROM)
1198                 buf[1] = 0x80;      /* removable */
1199         /* Vital Product */
1200         if (cmd->cdb[1] & EVPD) {
1201                 int dev_id_num;
1202                 char dev_id_str[6];
1203                 
1204                 for (dev_id_num = 0, i = 0; i < strlen(virt_dev->name); i++) {
1205                         dev_id_num += virt_dev->name[i];
1206                 }
1207                 len = scnprintf(dev_id_str, 6, "%d", dev_id_num);
1208                 TRACE_DBG("num %d, str <%s>, len %d",
1209                            dev_id_num,dev_id_str, len);
1210                 if (0 == cmd->cdb[2]) { /* supported vital product data pages */
1211                         buf[3] = 3;
1212                         buf[4] = 0x0; /* this page */
1213                         buf[5] = 0x80; /* unit serial number */
1214                         buf[6] = 0x83; /* device identification */
1215                 } else if (0x80 == cmd->cdb[2]) { /* unit serial number */
1216                         buf[1] = 0x80;
1217                         buf[3] = len;
1218                         memcpy(&buf[4], dev_id_str, len);
1219                 } else if (0x83 == cmd->cdb[2]) { /* device identification */
1220                         int num = 4;
1221
1222                         buf[1] = 0x83;
1223                         /* Two identification descriptors: */
1224                         /* T10 vendor identifier field format (faked) */
1225                         buf[num + 0] = 0x2;     /* ASCII */
1226                         buf[num + 1] = 0x1;
1227                         buf[num + 2] = 0x0;
1228                         memcpy(&buf[num + 4], SCST_FIO_VENDOR, 8);
1229                         memset(&buf[num + 12], ' ', 16);
1230                         i = strlen(virt_dev->name);
1231                         i = i < 16 ? i : 16;
1232                         memcpy(&buf[num + 12], virt_dev->name, len);
1233                         memcpy(&buf[num + 28], dev_id_str, len);
1234                         buf[num + 3] = 8 + 16 + len;
1235                         num += buf[num + 3] + 4;
1236                         /* NAA IEEE registered identifier (faked) */
1237                         buf[num] = 0x1; /* binary */
1238                         buf[num + 1] = 0x3;
1239                         buf[num + 2] = 0x0;
1240                         buf[num + 3] = 0x8;
1241                         buf[num + 4] = 0x51;    /* ieee company id=0x123456 (faked) */
1242                         buf[num + 5] = 0x23;
1243                         buf[num + 6] = 0x45;
1244                         buf[num + 7] = 0x60;
1245                         buf[num + 8] = (dev_id_num >> 24);
1246                         buf[num + 9] = (dev_id_num >> 16) & 0xff;
1247                         buf[num + 10] = (dev_id_num >> 8) & 0xff;
1248                         buf[num + 11] = dev_id_num & 0xff;
1249
1250                         buf[3] = num + 12 - 4;
1251                 } else {
1252                         TRACE_DBG("INQUIRY: Unsupported EVPD page %x",
1253                                 cmd->cdb[2]);
1254                         scst_set_cmd_error(cmd,
1255                             SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1256                         goto out_put;
1257                 }
1258         } else {
1259                 if (cmd->cdb[2] != 0) {
1260                         TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
1261                         scst_set_cmd_error(cmd,
1262                             SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1263                         goto out_put;
1264                 }
1265
1266                 buf[2] = 4;             /* Device complies to this standard - SPC-2  */
1267                 buf[3] = 2;             /* data in format specified in this standard */
1268                 buf[4] = 31;            /* n - 4 = 35 - 4 = 31 for full 36 byte data */
1269                 buf[6] = 0; buf[7] = 2; /* BQue = 0, CMDQUE = 1 commands queuing supported */
1270
1271                 /* 8 byte ASCII Vendor Identification of the target - left aligned */
1272                 memcpy(&buf[8], SCST_FIO_VENDOR, 8);
1273
1274                 /* 16 byte ASCII Product Identification of the target - left aligned */
1275                 memset(&buf[16], ' ', 16);
1276                 len = strlen(virt_dev->name);
1277                 len = len < 16 ? len : 16;
1278                 memcpy(&buf[16], virt_dev->name, len);
1279
1280                 /* 4 byte ASCII Product Revision Level of the target - left aligned */
1281                 memcpy(&buf[32], SCST_FIO_REV, 4);
1282         }
1283
1284         memcpy(address, buf, length < INQ_BUF_SZ ? length : INQ_BUF_SZ);
1285         
1286 out_put:
1287         scst_put_buf(cmd, address);
1288
1289 out_free:
1290         kfree(buf);
1291
1292 out:
1293         TRACE_EXIT();
1294         return;
1295 }
1296
1297 /* 
1298  * <<Following mode pages info copied from ST318451LW with some corrections>>
1299  *
1300  * ToDo: revise them
1301  */
1302
1303 static int fileio_err_recov_pg(unsigned char *p, int pcontrol,
1304                                struct scst_fileio_dev *virt_dev)
1305 {       /* Read-Write Error Recovery page for mode_sense */
1306         const unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1307                                               5, 0, 0xff, 0xff};
1308
1309         memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1310         if (1 == pcontrol)
1311                 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1312         return sizeof(err_recov_pg);
1313 }
1314
1315 static int fileio_disconnect_pg(unsigned char *p, int pcontrol,
1316                                 struct scst_fileio_dev *virt_dev)
1317 {       /* Disconnect-Reconnect page for mode_sense */
1318         const unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1319                                                0, 0, 0, 0, 0, 0, 0, 0};
1320
1321         memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1322         if (1 == pcontrol)
1323                 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1324         return sizeof(disconnect_pg);
1325 }
1326
1327 static int fileio_format_pg(unsigned char *p, int pcontrol,
1328                             struct scst_fileio_dev *virt_dev)
1329 {       /* Format device page for mode_sense */
1330         const unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1331                                            0, 0, 0, 0, 0, 0, 0, 0,
1332                                            0, 0, 0, 0, 0x40, 0, 0, 0};
1333
1334         memcpy(p, format_pg, sizeof(format_pg));
1335         p[10] = (DEF_SECTORS_PER >> 8) & 0xff;
1336         p[11] = DEF_SECTORS_PER & 0xff;
1337         p[12] = (virt_dev->block_size >> 8) & 0xff;
1338         p[13] = virt_dev->block_size & 0xff;
1339         if (1 == pcontrol)
1340                 memset(p + 2, 0, sizeof(format_pg) - 2);
1341         return sizeof(format_pg);
1342 }
1343
1344 static int fileio_caching_pg(unsigned char *p, int pcontrol,
1345                              struct scst_fileio_dev *virt_dev)
1346 {       /* Caching page for mode_sense */
1347         const unsigned char caching_pg[] = {0x8, 18, 0x10, 0, 0xff, 0xff, 0, 0,
1348                 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1349
1350         memcpy(p, caching_pg, sizeof(caching_pg));
1351         p[2] |= !(virt_dev->wt_flag) ? WCE : 0;
1352         if (1 == pcontrol)
1353                 memset(p + 2, 0, sizeof(caching_pg) - 2);
1354         return sizeof(caching_pg);
1355 }
1356
1357 static int fileio_ctrl_m_pg(unsigned char *p, int pcontrol,
1358                             struct scst_fileio_dev *virt_dev)
1359 {       /* Control mode page for mode_sense */
1360         const unsigned char ctrl_m_pg[] = {0xa, 0xa, 0x22, 0, 0, 0x40, 0, 0,
1361                                            0, 0, 0x2, 0x4b};
1362
1363         memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1364         if (!virt_dev->wt_flag)
1365                 p[3] |= 0x10; /* Enable unrestricted reordering */
1366         if (1 == pcontrol)
1367                 memset(p + 2, 0, sizeof(ctrl_m_pg) - 2);
1368         return sizeof(ctrl_m_pg);
1369 }
1370
1371 static int fileio_iec_m_pg(unsigned char *p, int pcontrol,
1372                            struct scst_fileio_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 fileio_exec_mode_sense(struct scst_cmd *cmd)
1383 {
1384         int32_t length;
1385         uint8_t *address;
1386         uint8_t *buf;
1387         struct scst_fileio_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, 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_fileio_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_PR("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         memset(buf, 0, sizeof(buf));
1426         
1427         if (0x3 == pcontrol) {
1428                 TRACE_DBG("%s", "MODE SENSE: Saving values not supported");
1429                 scst_set_cmd_error(cmd,
1430                     SCST_LOAD_SENSE(scst_sense_saving_params_unsup));
1431                 goto out_put;
1432         }
1433
1434         if (msense_6) {
1435                 buf[1] = type;
1436                 buf[2] = dev_spec;
1437                 offset = 4;
1438         } else {
1439                 buf[2] = type;
1440                 buf[3] = dev_spec;
1441                 offset = 8;
1442         }
1443
1444         if (0 != subpcode) { /* TODO: Control Extension page */
1445                 TRACE_DBG("%s", "MODE SENSE: Only subpage 0 is supported");
1446                 scst_set_cmd_error(cmd,
1447                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1448                 goto out_put;
1449         }
1450
1451         if (!dbd) {
1452                 /* Create block descriptor */
1453                 buf[offset - 1] = 0x08;         /* block descriptor length */
1454                 if (nblocks >> 32) {
1455                         buf[offset + 0] = 0xFF;
1456                         buf[offset + 1] = 0xFF;
1457                         buf[offset + 2] = 0xFF;
1458                         buf[offset + 3] = 0xFF;
1459                 } else {
1460                         buf[offset + 0] = (nblocks >> (BYTE * 3)) & 0xFF;/* num blks */
1461                         buf[offset + 1] = (nblocks >> (BYTE * 2)) & 0xFF;
1462                         buf[offset + 2] = (nblocks >> (BYTE * 1)) & 0xFF;
1463                         buf[offset + 3] = (nblocks >> (BYTE * 0)) & 0xFF;
1464                 }
1465                 buf[offset + 4] = 0;                    /* density code */
1466                 buf[offset + 5] = (blocksize >> (BYTE * 2)) & 0xFF;/* blklen */
1467                 buf[offset + 6] = (blocksize >> (BYTE * 1)) & 0xFF;
1468                 buf[offset + 7] = (blocksize >> (BYTE * 0)) & 0xFF;
1469
1470                 offset += 8;                    /* increment offset */
1471         }
1472
1473         bp = buf + offset;
1474
1475         switch (pcode) {
1476         case 0x1:       /* Read-Write error recovery page, direct access */
1477                 len = fileio_err_recov_pg(bp, pcontrol, virt_dev);
1478                 offset += len;
1479                 break;
1480         case 0x2:       /* Disconnect-Reconnect page, all devices */
1481                 len = fileio_disconnect_pg(bp, pcontrol, virt_dev);
1482                 offset += len;
1483                 break;
1484         case 0x3:       /* Format device page, direct access */
1485                 len = fileio_format_pg(bp, pcontrol, virt_dev);
1486                 offset += len;
1487                 break;
1488         case 0x8:       /* Caching page, direct access */
1489                 len = fileio_caching_pg(bp, pcontrol, virt_dev);
1490                 offset += len;
1491                 break;
1492         case 0xa:       /* Control Mode page, all devices */
1493                 len = fileio_ctrl_m_pg(bp, pcontrol, virt_dev);
1494                 offset += len;
1495                 break;
1496         case 0x1c:      /* Informational Exceptions Mode page, all devices */
1497                 len = fileio_iec_m_pg(bp, pcontrol, virt_dev);
1498                 offset += len;
1499                 break;
1500         case 0x3f:      /* Read all Mode pages */
1501                 len = fileio_err_recov_pg(bp, pcontrol, virt_dev);
1502                 len += fileio_disconnect_pg(bp + len, pcontrol, virt_dev);
1503                 len += fileio_format_pg(bp + len, pcontrol, virt_dev);
1504                 len += fileio_caching_pg(bp + len, pcontrol, virt_dev);
1505                 len += fileio_ctrl_m_pg(bp + len, pcontrol, virt_dev);
1506                 len += fileio_iec_m_pg(bp + len, pcontrol, virt_dev);
1507                 offset += len;
1508                 break;
1509         default:
1510                 TRACE_DBG("MODE SENSE: Unsupported page %x", pcode);
1511                 scst_set_cmd_error(cmd,
1512                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1513                 goto out_put;
1514         }
1515         if (msense_6)
1516                 buf[0] = offset - 1;
1517         else {
1518                 buf[0] = ((offset - 2) >> 8) & 0xff;
1519                 buf[1] = (offset - 2) & 0xff;
1520         }
1521
1522         memcpy(address, buf, min(length, offset));
1523         
1524 out_put:
1525         scst_put_buf(cmd, address);
1526
1527 out_free:
1528         kfree(buf);
1529
1530 out:
1531         TRACE_EXIT();
1532         return;
1533 }
1534
1535 static int fileio_set_wt(struct scst_fileio_dev *virt_dev, int wt)
1536 {
1537         int res = 0;
1538         struct scst_fileio_tgt_dev *ftgt_dev;
1539         struct file *fd;
1540
1541         TRACE_ENTRY();
1542
1543         if (virt_dev->wt_flag == wt)
1544                 goto out;
1545
1546         virt_dev->wt_flag = wt;
1547
1548         scst_suspend_activity();
1549
1550         down(&virt_dev->ftgt_list_mutex);
1551         list_for_each_entry(ftgt_dev, &virt_dev->ftgt_list, 
1552                 ftgt_list_entry) 
1553         {
1554                 fd = fileio_open(virt_dev);
1555                 if (IS_ERR(fd)) {
1556                         res = PTR_ERR(fd);
1557                         PRINT_ERROR_PR("filp_open(%s) returned an error %d, "
1558                                 "unable to change the cache mode",
1559                                 virt_dev->file_name, res);
1560                         up(&virt_dev->ftgt_list_mutex);
1561                         res = 0; /* ?? ToDo */
1562                         goto out_resume;
1563                 }
1564                 if (ftgt_dev->fd)
1565                         filp_close(ftgt_dev->fd, NULL);
1566                 ftgt_dev->fd = fd;
1567         }
1568         up(&virt_dev->ftgt_list_mutex);
1569
1570 out_resume:
1571         scst_resume_activity();
1572
1573 out:
1574         TRACE_EXIT_RES(res);
1575         return res;
1576 }
1577
1578 static void fileio_exec_mode_select(struct scst_cmd *cmd)
1579 {
1580         int32_t length;
1581         uint8_t *address;
1582         struct scst_fileio_dev *virt_dev;
1583         int mselect_6, offset;
1584
1585         TRACE_ENTRY();
1586
1587         virt_dev = (struct scst_fileio_dev *)cmd->dev->dh_priv;
1588         mselect_6 = (MODE_SELECT == cmd->cdb[0]);
1589
1590         length = scst_get_buf_first(cmd, &address);
1591         if (unlikely(length <= 0)) {
1592                 PRINT_ERROR_PR("scst_get_buf_first() failed: %d", length);
1593                 scst_set_cmd_error(cmd,
1594                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1595                 goto out;
1596         }
1597
1598         if (!(cmd->cdb[1] & PF) || (cmd->cdb[1] & SP)) {
1599                 PRINT_ERROR_PR("MODE SELECT: PF and/or SP are wrongly set "
1600                         "(cdb[1]=%x)", cmd->cdb[1]);
1601                 scst_set_cmd_error(cmd,
1602                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1603                 goto out_put;
1604         }
1605
1606         if (mselect_6) {
1607                 offset = 4;
1608         } else {
1609                 offset = 8;
1610         }
1611
1612         if (address[offset - 1] == 8) {
1613                 offset += 8;
1614         } else if (address[offset - 1] != 0) {
1615                 PRINT_ERROR_PR("%s", "MODE SELECT: Wrong parameters list "
1616                         "lenght");
1617                 scst_set_cmd_error(cmd,
1618                     SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
1619                 goto out_put;
1620         }
1621
1622         while (length > offset + 2) {
1623                 if (address[offset] & PS) {
1624                         PRINT_ERROR_PR("%s", "MODE SELECT: Illegal PS bit");
1625                         scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1626                                 scst_sense_invalid_field_in_parm_list));
1627                         goto out_put;
1628                 }
1629                 if ((address[offset] & 0x3f) == 0x8) {  /* Caching page */
1630                         if (address[offset + 1] != 18) {
1631                                 PRINT_ERROR_PR("%s", "MODE SELECT: Invalid "
1632                                         "caching page request");
1633                                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
1634                                         scst_sense_invalid_field_in_parm_list));
1635                                 goto out_put;
1636                         }
1637                         if (fileio_set_wt(virt_dev,
1638                               (address[offset + 2] & WCE) ? 0 : 1) != 0) {
1639                                 scst_set_cmd_error(cmd,
1640                                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1641                                 goto out_put;
1642                         }
1643                         break;
1644                 }
1645                 offset += address[offset + 1];
1646         }
1647
1648 out_put:
1649         scst_put_buf(cmd, address);
1650
1651 out:
1652         TRACE_EXIT();
1653         return;
1654 }
1655
1656 static void fileio_exec_read_capacity(struct scst_cmd *cmd)
1657 {
1658         int32_t length;
1659         uint8_t *address;
1660         struct scst_fileio_dev *virt_dev;
1661         uint32_t blocksize;
1662         uint64_t nblocks;
1663         uint8_t buffer[READ_CAP_LEN];
1664
1665         TRACE_ENTRY();
1666
1667         virt_dev = (struct scst_fileio_dev *)cmd->dev->dh_priv;
1668         blocksize = virt_dev->block_size;
1669         nblocks = virt_dev->nblocks;
1670
1671         /* last block on the virt_dev is (nblocks-1) */
1672         memset(buffer, 0, sizeof(buffer));
1673         if (nblocks >> 32) {
1674                 buffer[0] = 0xFF;
1675                 buffer[1] = 0xFF;
1676                 buffer[2] = 0xFF;
1677                 buffer[3] = 0xFF;
1678         } else {
1679                 buffer[0] = ((nblocks - 1) >> (BYTE * 3)) & 0xFF;
1680                 buffer[1] = ((nblocks - 1) >> (BYTE * 2)) & 0xFF;
1681                 buffer[2] = ((nblocks - 1) >> (BYTE * 1)) & 0xFF;
1682                 buffer[3] = ((nblocks - 1) >> (BYTE * 0)) & 0xFF;
1683         }
1684         buffer[4] = (blocksize >> (BYTE * 3)) & 0xFF;
1685         buffer[5] = (blocksize >> (BYTE * 2)) & 0xFF;
1686         buffer[6] = (blocksize >> (BYTE * 1)) & 0xFF;
1687         buffer[7] = (blocksize >> (BYTE * 0)) & 0xFF;
1688         
1689         length = scst_get_buf_first(cmd, &address);
1690         if (unlikely(length <= 0)) {
1691                 PRINT_ERROR_PR("scst_get_buf_first() failed: %d", length);
1692                 scst_set_cmd_error(cmd,
1693                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1694                 goto out;
1695         }
1696
1697         memcpy(address, buffer, length < READ_CAP_LEN ? length : READ_CAP_LEN);
1698         
1699         scst_put_buf(cmd, address);
1700
1701 out:
1702         TRACE_EXIT();
1703         return;
1704 }
1705
1706 static void fileio_exec_read_capacity16(struct scst_cmd *cmd)
1707 {
1708         int32_t length;
1709         uint8_t *address;
1710         struct scst_fileio_dev *virt_dev;
1711         uint32_t blocksize;
1712         uint64_t nblocks;
1713         uint8_t buffer[READ_CAP16_LEN];
1714         uint64_t *data64;
1715
1716         TRACE_ENTRY();
1717
1718         virt_dev = (struct scst_fileio_dev *)cmd->dev->dh_priv;
1719         blocksize = virt_dev->block_size;
1720         nblocks = virt_dev->nblocks;
1721
1722         memset(buffer, 0, sizeof(buffer));
1723         data64 = (uint64_t*)buffer;
1724         data64[0] = cpu_to_be64(nblocks - 1);
1725         buffer[8] = (blocksize >> (BYTE * 3)) & 0xFF;
1726         buffer[9] = (blocksize >> (BYTE * 2)) & 0xFF;
1727         buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF;
1728         buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF;
1729
1730         length = scst_get_buf_first(cmd, &address);
1731         if (unlikely(length <= 0)) {
1732                 PRINT_ERROR_PR("scst_get_buf_first() failed: %d", length);
1733                 scst_set_cmd_error(cmd,
1734                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1735                 goto out;
1736         }
1737
1738         memcpy(address, buffer, length < READ_CAP16_LEN ? 
1739                                         length : READ_CAP16_LEN);
1740         
1741         scst_put_buf(cmd, address);
1742
1743 out:
1744         TRACE_EXIT();
1745         return;
1746 }
1747
1748 static void fileio_exec_read_toc(struct scst_cmd *cmd)
1749 {
1750         int32_t length, off = 0;
1751         uint8_t *address;
1752         struct scst_fileio_dev *virt_dev;
1753         uint32_t nblocks;
1754         uint8_t buffer[4+8+8] = { 0x00, 0x0a, 0x01, 0x01, 0x00, 0x14, 
1755                                   0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
1756
1757         TRACE_ENTRY();
1758
1759         if (cmd->dev->handler->type != TYPE_ROM) {
1760                 PRINT_ERROR_PR("%s", "READ TOC for non-CDROM device");
1761                 scst_set_cmd_error(cmd,
1762                         SCST_LOAD_SENSE(scst_sense_invalid_opcode));
1763                 goto out;
1764         }
1765
1766         if (cmd->cdb[2] & 0x0e/*Format*/) {
1767                 PRINT_ERROR_PR("%s", "READ TOC: invalid requested data format");
1768                 scst_set_cmd_error(cmd,
1769                         SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1770                 goto out;
1771         }
1772
1773         if ((cmd->cdb[6] != 0 && (cmd->cdb[2] & 0x01)) ||
1774             (cmd->cdb[6] > 1 && cmd->cdb[6] != 0xAA)) {
1775                 PRINT_ERROR_PR("READ TOC: invalid requested track number %x",
1776                         cmd->cdb[6]);
1777                 scst_set_cmd_error(cmd,
1778                         SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
1779                 goto out;
1780         }
1781
1782         length = scst_get_buf_first(cmd, &address);
1783         if (unlikely(length <= 0)) {
1784                 PRINT_ERROR_PR("scst_get_buf_first() failed: %d", length);
1785                 scst_set_cmd_error(cmd,
1786                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1787                 goto out;
1788         }
1789
1790         virt_dev = (struct scst_fileio_dev *)cmd->dev->dh_priv;
1791         /* FIXME when you have > 8TB ROM device. */
1792         nblocks = (uint32_t)virt_dev->nblocks;
1793
1794         /* Header */
1795         memset(buffer, 0, sizeof(buffer));
1796         buffer[2] = 0x01;    /* First Track/Session */
1797         buffer[3] = 0x01;    /* Last Track/Session */
1798         off = 4;
1799         if (cmd->cdb[6] <= 1)
1800         {
1801                 /* Fistr TOC Track Descriptor */
1802                 buffer[off+1] = 0x14; /* ADDR    0x10 - Q Sub-channel encodes current position data
1803                                          CONTROL 0x04 - Data track, recoreded uninterrupted */
1804                 buffer[off+2] = 0x01; /* Track Number */
1805                 off += 8;
1806         }
1807         if (!(cmd->cdb[2] & 0x01))
1808         {
1809                 /* Lead-out area TOC Track Descriptor */
1810                 buffer[off+1] = 0x14;
1811                 buffer[off+2] = 0xAA;     /* Track Number */
1812                 buffer[off+4] = (nblocks >> (BYTE * 3)) & 0xFF; /* Track Start Address */
1813                 buffer[off+5] = (nblocks >> (BYTE * 2)) & 0xFF;
1814                 buffer[off+6] = (nblocks >> (BYTE * 1)) & 0xFF;
1815                 buffer[off+7] = (nblocks >> (BYTE * 0)) & 0xFF;
1816                 off += 8;
1817         }
1818
1819         buffer[1] = off - 2;    /* Data  Length */
1820
1821         memcpy(address, buffer, (length < off) ? length : off);
1822         
1823         scst_put_buf(cmd, address);
1824
1825 out:
1826         TRACE_EXIT();
1827         return;
1828 }
1829
1830 static void fileio_exec_prevent_allow_medium_removal(struct scst_cmd *cmd)
1831 {
1832         struct scst_fileio_dev *virt_dev =
1833                 (struct scst_fileio_dev *)cmd->dev->dh_priv;
1834
1835         TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
1836
1837         /* 
1838          * No protection here, because in cdrom_fileio_change() the
1839          * activity is suspended and exec() is serialized
1840          */
1841         if (cmd->dev->handler->type == TYPE_ROM)
1842                 virt_dev->prevent_allow_medium_removal = 
1843                         cmd->cdb[4] & 0x01 ? 1 : 0;
1844         else {
1845                 PRINT_ERROR_PR("%s", "Prevent allow medium removal for "
1846                         "non-CDROM device");
1847                 scst_set_cmd_error(cmd,
1848                         SCST_LOAD_SENSE(scst_sense_invalid_opcode));
1849         }
1850
1851         return;
1852 }
1853
1854 static int fileio_fsync(struct scst_fileio_tgt_dev *ftgt_dev,
1855         loff_t loff, loff_t len, struct scst_cmd *cmd)
1856 {
1857         int res = 0;
1858         struct file *file = ftgt_dev->fd;
1859         struct inode *inode = file->f_dentry->d_inode;
1860         struct address_space *mapping = file->f_mapping;
1861
1862         TRACE_ENTRY();
1863
1864         if (ftgt_dev->virt_dev->nv_cache)
1865                 goto out;
1866
1867         res = sync_page_range(inode, mapping, loff, len);
1868         if (unlikely(res != 0)) {
1869                 PRINT_ERROR_PR("sync_page_range() failed (%d)", res);
1870                 if (cmd != NULL) {
1871                         scst_set_cmd_error(cmd,
1872                                 SCST_LOAD_SENSE(scst_sense_write_error));
1873                 }
1874         }
1875
1876         /* ToDo: flush the device cache, if needed */
1877
1878 out:
1879         TRACE_EXIT_RES(res);
1880         return res;
1881 }
1882
1883 static struct iovec *fileio_alloc_iv(struct scst_cmd *cmd,
1884         struct scst_fileio_tgt_dev *ftgt_dev)
1885 {
1886         int iv_count;
1887         
1888         iv_count = scst_get_buf_count(cmd);
1889         if (iv_count > ftgt_dev->iv_count) {
1890                 if (ftgt_dev->iv != NULL)
1891                         kfree(ftgt_dev->iv);
1892                 ftgt_dev->iv = kmalloc(sizeof(*ftgt_dev->iv) * iv_count, GFP_KERNEL);
1893                 if (ftgt_dev->iv == NULL) {
1894                         PRINT_ERROR_PR("Unable to allocate iv (%d)", iv_count);
1895                         scst_set_busy(cmd);
1896                         goto out;
1897                 }
1898                 ftgt_dev->iv_count = iv_count;
1899         }
1900
1901 out:
1902         return ftgt_dev->iv;
1903 }
1904
1905 static void fileio_exec_read(struct scst_cmd *cmd, loff_t loff)
1906 {
1907         mm_segment_t old_fs;
1908         loff_t err;
1909         ssize_t length, full_len;
1910         uint8_t *address;
1911         struct scst_fileio_dev *virt_dev =
1912             (struct scst_fileio_dev *)cmd->dev->dh_priv;
1913         struct scst_fileio_tgt_dev *ftgt_dev = 
1914                 (struct scst_fileio_tgt_dev *)cmd->tgt_dev->dh_priv;
1915         struct file *fd = ftgt_dev->fd;
1916         struct iovec *iv;
1917         int iv_count, i;
1918
1919         TRACE_ENTRY();
1920         
1921         iv = fileio_alloc_iv(cmd, ftgt_dev);
1922         if (iv == NULL)
1923                 goto out;
1924         
1925         iv_count = 0;
1926         full_len = 0;
1927         i = -1;
1928         length = scst_get_buf_first(cmd, &address);
1929         while (length > 0) {
1930                 full_len += length;
1931                 i++;
1932                 iv_count++;
1933                 iv[i].iov_base = address;
1934                 iv[i].iov_len = length;
1935                 length = scst_get_buf_next(cmd, &address);
1936         }
1937         if (unlikely(length < 0)) {
1938                 PRINT_ERROR_PR("scst_get_buf_() failed: %zd", length);
1939                 scst_set_cmd_error(cmd,
1940                     SCST_LOAD_SENSE(scst_sense_hardw_error));
1941                 goto out_put;
1942         }
1943         
1944         old_fs = get_fs();
1945         set_fs(get_ds());
1946         
1947         /* SEEK */      
1948         if (fd->f_op->llseek) {
1949                 err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
1950         } else {
1951                 err = default_llseek(fd, loff, 0/*SEEK_SET*/);
1952         }
1953         if (err != loff) {
1954                 PRINT_ERROR_PR("lseek trouble %Ld != %Ld", (uint64_t)err, 
1955                         (uint64_t)loff);
1956                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
1957                 goto out_set_fs;
1958         }
1959         
1960         /* READ */
1961         TRACE_DBG("reading(iv_count %d, full_len %zd)", iv_count, full_len);
1962         if (virt_dev->nullio)
1963                 err = full_len;
1964         else
1965                 err = fd->f_op->readv(fd, iv, iv_count, &fd->f_pos);
1966         if ((err < 0) || (err < full_len)) {
1967                 PRINT_ERROR_PR("readv() returned %Ld from %zd", (uint64_t)err, 
1968                         full_len);
1969                 if (err == -EAGAIN)
1970                         scst_set_busy(cmd);
1971                 else {
1972                         scst_set_cmd_error(cmd,
1973                             SCST_LOAD_SENSE(scst_sense_read_error));
1974                 }
1975                 goto out_set_fs;
1976         }
1977
1978 out_set_fs:
1979         set_fs(old_fs);
1980         
1981 out_put:        
1982         for(; i >= 0; i--)
1983                 scst_put_buf(cmd, iv[i].iov_base);
1984         
1985 out:
1986         TRACE_EXIT();
1987         return;
1988 }
1989
1990 static void fileio_exec_write(struct scst_cmd *cmd, loff_t loff)
1991 {
1992         mm_segment_t old_fs;
1993         loff_t err;
1994         ssize_t length, full_len;
1995         uint8_t *address;
1996         struct scst_fileio_dev *virt_dev =
1997             (struct scst_fileio_dev *)cmd->dev->dh_priv;
1998         struct scst_fileio_tgt_dev *ftgt_dev = 
1999                 (struct scst_fileio_tgt_dev *)cmd->tgt_dev->dh_priv;
2000         struct file *fd = ftgt_dev->fd;
2001         struct iovec *iv, *eiv;
2002         int iv_count, eiv_count;
2003
2004         TRACE_ENTRY();
2005
2006         iv = fileio_alloc_iv(cmd, ftgt_dev);
2007         if (iv == NULL)
2008                 goto out;
2009         
2010         iv_count = 0;
2011         full_len = 0;
2012         length = scst_get_buf_first(cmd, &address);
2013         while (length > 0) {
2014                 full_len += length;
2015                 iv[iv_count].iov_base = address;
2016                 iv[iv_count].iov_len = length;
2017                 iv_count++;
2018                 length = scst_get_buf_next(cmd, &address);
2019         }
2020         if (unlikely(length < 0)) {
2021                 PRINT_ERROR_PR("scst_get_buf_() failed: %zd", length);
2022                 scst_set_cmd_error(cmd,
2023                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2024                 goto out_put;
2025         }
2026         
2027         old_fs = get_fs();
2028         set_fs(get_ds());
2029         
2030         /* SEEK */
2031         if (fd->f_op->llseek) {
2032                 err = fd->f_op->llseek(fd, loff, 0 /*SEEK_SET */ );
2033         } else {
2034                 err = default_llseek(fd, loff, 0 /*SEEK_SET */ );
2035         }
2036         if (err != loff) {
2037                 PRINT_ERROR_PR("lseek trouble %Ld != %Ld", (uint64_t)err, 
2038                         (uint64_t)loff);
2039                 scst_set_cmd_error(cmd,
2040                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2041                 goto out_set_fs;
2042         }
2043         
2044         /* WRITE */
2045         eiv = iv;
2046         eiv_count = iv_count;
2047 restart:
2048         TRACE_DBG("writing(eiv_count %d, full_len %zd)", eiv_count, full_len);
2049
2050         if (virt_dev->nullio)
2051                 err = full_len;
2052         else
2053                 err = fd->f_op->writev(fd, eiv, eiv_count, &fd->f_pos);
2054         if (err < 0) {
2055                 PRINT_ERROR_PR("write() returned %Ld from %zd", 
2056                         (uint64_t)err, full_len);
2057                 if (err == -EAGAIN)
2058                         scst_set_busy(cmd);
2059                 else {
2060                         scst_set_cmd_error(cmd,
2061                             SCST_LOAD_SENSE(scst_sense_write_error));
2062                 }
2063                 goto out_set_fs;
2064         } else if (err < full_len) {
2065                 /* 
2066                  * Probably that's wrong, but sometimes write() returns
2067                  * value less, than requested. Let's restart.
2068                  */
2069                 int i, e = eiv_count;
2070                 TRACE_MGMT_DBG("write() returned %d from %zd "
2071                         "(iv_count=%d)", (int)err, full_len,
2072                         eiv_count);
2073                 if (err == 0) {
2074                         PRINT_INFO_PR("Suspicious: write() returned 0 from "
2075                                 "%zd (iv_count=%d)", full_len, eiv_count);
2076                 }
2077                 full_len -= err;
2078                 for(i = 0; i < e; i++) {
2079                         if (eiv->iov_len < err) {
2080                                 err -= eiv->iov_len;
2081                                 eiv++;
2082                                 eiv_count--;
2083                         } else {
2084                                 eiv->iov_base = 
2085                                         (uint8_t*)eiv->iov_base + err;
2086                                 eiv->iov_len -= err;
2087                                 break;
2088                         }
2089                 }
2090                 goto restart;
2091         }
2092
2093 out_set_fs:
2094         set_fs(old_fs);
2095
2096 out_put:        
2097         while (iv_count > 0) {
2098                 scst_put_buf(cmd, iv[iv_count-1].iov_base);
2099                 iv_count--;
2100         }
2101
2102 out:
2103         TRACE_EXIT();
2104         return;
2105 }
2106
2107 static void fileio_exec_verify(struct scst_cmd *cmd, loff_t loff)
2108 {
2109         mm_segment_t old_fs;
2110         loff_t err;
2111         ssize_t length, len_mem = 0;
2112         uint8_t *address_sav, *address;
2113         int compare;
2114         struct scst_fileio_tgt_dev *ftgt_dev = 
2115                 (struct scst_fileio_tgt_dev *)cmd->tgt_dev->dh_priv;
2116         struct file *fd = ftgt_dev->fd;
2117         uint8_t *mem_verify = NULL;
2118
2119         TRACE_ENTRY();
2120
2121         if (fileio_fsync(ftgt_dev, loff, cmd->bufflen, cmd) != 0)
2122                 goto out;
2123
2124         /* 
2125          * Until the cache is cleared prior the verifying, there is not
2126          * much point in this code. ToDo.
2127          *
2128          * Nevertherless, this code is valuable if the data have not read
2129          * from the file/disk yet.
2130          */
2131
2132         /* SEEK */
2133         old_fs = get_fs();
2134         set_fs(get_ds());
2135
2136         if (fd->f_op->llseek) {
2137                 err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
2138         } else {
2139                 err = default_llseek(fd, loff, 0/*SEEK_SET*/);
2140         }
2141         if (err != loff) {
2142                 PRINT_ERROR_PR("lseek trouble %Ld != %Ld", (uint64_t)err, 
2143                         (uint64_t)loff);
2144                 scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
2145                 goto out_set_fs;
2146         }
2147
2148         mem_verify = vmalloc(LEN_MEM);
2149         if (mem_verify == NULL) {
2150                 PRINT_ERROR_PR("Unable to allocate memory %d for verify",
2151                                LEN_MEM);
2152                 scst_set_cmd_error(cmd,
2153                                    SCST_LOAD_SENSE(scst_sense_hardw_error));
2154                 goto out_set_fs;
2155         }
2156
2157         length = scst_get_buf_first(cmd, &address);
2158         address_sav = address;
2159         if (!length && cmd->data_len) {
2160                 length = cmd->data_len;
2161                 compare = 0;
2162         } else
2163                 compare = 1;
2164
2165         while (length > 0) {
2166                 len_mem = length > LEN_MEM ? LEN_MEM : length;
2167                 TRACE_DBG("Verify: length %zd - len_mem %zd", length, len_mem);
2168
2169                 err = fd->f_op->read(fd, (char*)mem_verify, len_mem, &fd->f_pos);
2170                 if ((err < 0) || (err < len_mem)) {
2171                         PRINT_ERROR_PR("verify() returned %Ld from %zd",
2172                                 (uint64_t)err, len_mem);
2173                         if (err == -EAGAIN)
2174                                 scst_set_busy(cmd);
2175                         else {
2176                                 scst_set_cmd_error(cmd,
2177                                     SCST_LOAD_SENSE(scst_sense_read_error));
2178                         }
2179                         scst_put_buf(cmd, address_sav);
2180                         goto out_set_fs;
2181                 }
2182                 if (compare && memcmp(address, mem_verify, len_mem) != 0)
2183                 {
2184                         TRACE_DBG("Verify: error memcmp length %zd", length);
2185                         scst_set_cmd_error(cmd,
2186                             SCST_LOAD_SENSE(scst_sense_miscompare_error));
2187                         scst_put_buf(cmd, address_sav);
2188                         goto out_set_fs;
2189                 }
2190                 length -= len_mem;
2191                 address += len_mem;
2192                 if (compare && length <= 0)
2193                 {
2194                         scst_put_buf(cmd, address_sav);
2195                         length = scst_get_buf_next(cmd, &address);
2196                         address_sav = address;
2197                 }
2198         }
2199
2200         if (length < 0) {
2201                 PRINT_ERROR_PR("scst_get_buf_() failed: %zd", length);
2202                 scst_set_cmd_error(cmd,
2203                     SCST_LOAD_SENSE(scst_sense_hardw_error));
2204         }
2205
2206 out_set_fs:
2207         set_fs(old_fs);
2208         if (mem_verify)
2209                 vfree(mem_verify);
2210
2211 out:
2212         TRACE_EXIT();
2213         return;
2214 }
2215
2216 /* Called with BH off. Might be called under lock and IRQ off */
2217 static int fileio_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
2218         struct scst_tgt_dev *tgt_dev)
2219 {
2220         int res = SCST_DEV_TM_COMPLETED_SUCCESS;
2221
2222         TRACE_ENTRY();
2223
2224         if (mcmd->fn == SCST_ABORT_TASK) {
2225                 struct scst_cmd *cmd_to_abort = mcmd->cmd_to_abort;
2226                 struct scst_fileio_tgt_dev *ftgt_dev = 
2227                   (struct scst_fileio_tgt_dev *)cmd_to_abort->tgt_dev->dh_priv;
2228
2229                 /*
2230                  * It is safe relating to scst_list_lock despite of lockdep's
2231                  * warning. Just don't know how to tell it to lockdep.
2232                  */
2233                 /* BH already off */
2234                 spin_lock(&ftgt_dev->fdev_lock);
2235                 if (cmd_to_abort->fileio_in_list) {
2236                         TRACE(TRACE_MGMT, "Aborting cmd %p and moving it to "
2237                                 "the queue head", cmd_to_abort);
2238                         list_del(&cmd_to_abort->fileio_cmd_list_entry);
2239                         list_add(&cmd_to_abort->fileio_cmd_list_entry,
2240                                 &ftgt_dev->fdev_cmd_list);
2241                         wake_up(&ftgt_dev->fdev_waitQ);
2242                 }
2243                 spin_unlock(&ftgt_dev->fdev_lock);
2244         }
2245
2246         TRACE_EXIT_RES(res);
2247         return res;
2248 }
2249
2250 static inline struct scst_fileio_dev *fileio_alloc_dev(void)
2251 {
2252         struct scst_fileio_dev *dev;
2253         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2254         if (dev == NULL) {
2255                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of virtual "
2256                         "device failed");
2257                 goto out;
2258         }
2259         INIT_LIST_HEAD(&dev->ftgt_list);
2260         init_MUTEX(&dev->ftgt_list_mutex);
2261 out:
2262         return dev;
2263 }
2264
2265 struct fileio_proc_update_struct {
2266         int len, plen, pplen;
2267         off_t begin, pbegin, ppbegin;
2268         off_t pos;
2269 };
2270
2271 static int fileio_proc_update_size(int size, off_t offset, int length,
2272         struct fileio_proc_update_struct *p, int is_start)
2273 {
2274         int res = 0;
2275         if (size > 0) {
2276                 p->len += size;
2277                 p->pos = p->begin + p->len;
2278                 if (p->pos <= offset) {
2279                         p->len = 0;
2280                         p->begin = p->pos;
2281                 } else if (p->pos >= offset + length) {
2282                         res = 1;
2283                         goto out;
2284                 } else
2285                         res = 0;
2286         } else {
2287                 p->begin = p->ppbegin;
2288                 p->len = p->pplen;
2289                 res = 1;
2290                 goto out;
2291         }
2292         if (is_start) {
2293                 p->ppbegin = p->pbegin;
2294                 p->pplen = p->plen;
2295                 p->pbegin = p->begin;
2296                 p->plen = p->len;
2297         }
2298 out:
2299         return res;
2300 }
2301
2302 /* 
2303  * Called when a file in the /proc/DISK_FILEIO_NAME/DISK_FILEIO_NAME is read
2304  * or written 
2305  */
2306 static int disk_fileio_proc(char *buffer, char **start, off_t offset,
2307         int length, int *eof, struct scst_dev_type *dev_type, int inout)
2308 {
2309         int res = 0, action;
2310         char *p, *name, *file_name;
2311         struct scst_fileio_dev *virt_dev, *vv;
2312         int size;
2313         struct fileio_proc_update_struct pu;
2314
2315         TRACE_ENTRY();
2316
2317         memset(&pu, 0, sizeof(pu));
2318         
2319         /* VERY UGLY code. You can rewrite it if you want */
2320         
2321         if (down_interruptible(&scst_fileio_mutex) != 0) {
2322                 res = -EINTR;
2323                 goto out;
2324         }
2325         
2326         if (inout == 0) { /* read */
2327                 size = scnprintf(buffer, length, "%-17s %-11s %-11s %-15s %s\n",
2328                                "Name", "Size(MB)", "Block size", "Options", "File name");
2329                 if (fileio_proc_update_size(size, offset, length, &pu, 1))
2330                         goto stop_output;
2331
2332                 list_for_each_entry(virt_dev, &disk_fileio_dev_list, 
2333                         fileio_dev_list_entry)
2334                 {
2335                         int c;
2336                         size = scnprintf(buffer + pu.len, length - pu.len, 
2337                                 "%-17s %-11d %-12d", virt_dev->name,
2338                                 (uint32_t)(virt_dev->file_size >> 20),
2339                                 virt_dev->block_size);
2340                         if (fileio_proc_update_size(size, offset, length, &pu,
2341                                         1)) {
2342                                 goto stop_output;
2343                         }
2344                         c = 0;
2345                         if (virt_dev->wt_flag) {
2346                                 size = scnprintf(buffer + pu.len, length - pu.len, "WT");
2347                                 c += size;
2348                                 if (fileio_proc_update_size(size, offset,
2349                                                 length, &pu, 0)) {
2350                                         goto stop_output;
2351                                 }
2352                         }
2353                         if (virt_dev->nv_cache) {
2354                                 size = scnprintf(buffer + pu.len, length - pu.len,
2355                                         c ? ",NV" : "NV");
2356                                 c += size;
2357                                 if (fileio_proc_update_size(size, offset,
2358                                                 length, &pu, 0)) {
2359                                         goto stop_output;
2360                                 }
2361                         }
2362                         if (virt_dev->rd_only_flag) {
2363                                 size = scnprintf(buffer + pu.len, length - pu.len, 
2364                                         c ? ",RO" : "RO");
2365                                 c += size;
2366                                 if (fileio_proc_update_size(size, offset,
2367                                                 length, &pu, 0)) {
2368                                         goto stop_output;
2369                                 }
2370                         }
2371                         if (virt_dev->o_direct_flag) {
2372                                 size = scnprintf(buffer + pu.len, length - pu.len, 
2373                                         c ? ",DR" : "DR");
2374                                 c += size;
2375                                 if (fileio_proc_update_size(size, offset,
2376                                                 length, &pu, 0)) {
2377                                         goto stop_output;
2378                                 }
2379                         }
2380                         if (virt_dev->nullio) {
2381                                 size = scnprintf(buffer + pu.len, length - pu.len, 
2382                                         c ? ",NIO" : "NIO");
2383                                 c += size;
2384                                 if (fileio_proc_update_size(size, offset,
2385                                                 length, &pu, 0)) {
2386                                         goto stop_output;
2387                                 }
2388                         }
2389                         while (c < 16) {
2390                                 size = scnprintf(buffer + pu.len, length - pu.len, " ");
2391                                 if (fileio_proc_update_size(size, offset,
2392                                                 length, &pu, 0)) {
2393                                         goto stop_output;
2394                                 }
2395                                 c++;
2396                         }
2397                         size = scnprintf(buffer + pu.len, length - pu.len, "%s\n",
2398                                         virt_dev->file_name);
2399                         if (fileio_proc_update_size(size, offset, length, &pu,
2400                                         0)) {
2401                                 goto stop_output;
2402                         }
2403                 }
2404                 *eof = 1;
2405                 goto stop_output;
2406         } else {  /* write */
2407                 uint32_t block_size = DEF_DISK_BLOCKSIZE;
2408                 int block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
2409                 p = buffer;
2410                 if (p[strlen(p) - 1] == '\n') {
2411                         p[strlen(p) - 1] = '\0';
2412                 }
2413                 if (!strncmp("close ", p, 6)) {
2414                         p += 6;
2415                         action = 0;
2416                 } else if (!strncmp("open ", p, 5)) {
2417                         p += 5;
2418                         action = 2;
2419                 } else {
2420                         PRINT_ERROR_PR("Unknown action \"%s\"", p);
2421                         res = -EINVAL;
2422                         goto out_up;
2423                 }
2424
2425                 while (isspace(*p) && *p != '\0')
2426                         p++;
2427                 name = p;
2428                 while (!isspace(*p) && *p != '\0')
2429                         p++;
2430                 *p++ = '\0';
2431                 if (*name == '\0') {
2432                         PRINT_ERROR_PR("%s", "Name required");
2433                         res = -EINVAL;
2434                         goto out_up;
2435                 } else if (strlen(name) >= sizeof(virt_dev->name)) {
2436                         PRINT_ERROR_PR("Name is too long (max %zd "
2437                                 "characters)", sizeof(virt_dev->name)-1);
2438                         res = -EINVAL;
2439                         goto out_up;
2440                 }
2441
2442                 if (action) {                      /* open */
2443                         virt_dev = NULL;
2444                         list_for_each_entry(vv, &disk_fileio_dev_list,
2445                                             fileio_dev_list_entry)
2446                         {
2447                                 if (strcmp(vv->name, name) == 0) {
2448                                         virt_dev = vv;
2449                                         break;
2450                                 }
2451                         }
2452                         if (virt_dev) {
2453                                 PRINT_ERROR_PR("Virtual device with name "
2454                                        "%s already exist", name);
2455                                 res = -EINVAL;
2456                                 goto out_up;
2457                         }
2458
2459                         while (isspace(*p) && *p != '\0')
2460                                 p++;
2461                         file_name = p;
2462                         while (!isspace(*p) && *p != '\0')
2463                                 p++;
2464                         *p++ = '\0';
2465                         if (*file_name == '\0') {
2466                                 PRINT_ERROR_PR("%s", "File name required");
2467                                 res = -EINVAL;
2468                                 goto out_up;
2469                         } else if (*file_name != '/') {
2470                                 PRINT_ERROR_PR("File path \"%s\" is not "
2471                                         "absolute", file_name);
2472                                 res = -EINVAL;
2473                                 goto out_up;
2474                         }
2475
2476                         virt_dev = fileio_alloc_dev();
2477                         if (virt_dev == NULL) {
2478                                 TRACE(TRACE_OUT_OF_MEM, "%s",
2479                                       "Allocation of virt_dev failed");
2480                                 res = -ENOMEM;
2481                                 goto out_up;
2482                         }
2483
2484                         while (isspace(*p) && *p != '\0')
2485                                 p++;
2486
2487                         if (isdigit(*p)) {
2488                                 char *pp;
2489                                 uint32_t t;
2490                                 block_size = simple_strtoul(p, &pp, 0);
2491                                 p = pp;
2492                                 if ((*p != '\0') && !isspace(*p)) {
2493                                         PRINT_ERROR_PR("Parse error: \"%s\"", p);
2494                                         res = -EINVAL;
2495                                         goto out_free_vdev;
2496                                 }
2497                                 while (isspace(*p) && *p != '\0')
2498                                         p++;
2499
2500                                 t = block_size;
2501                                 block_shift = 0;
2502                                 while(1) {
2503                                         if ((t & 1) != 0)
2504                                                 break;
2505                                         t >>= 1;
2506                                         block_shift++;
2507                                 }
2508                                 if (block_shift < 9) {
2509                                         PRINT_ERROR_PR("Wrong block size %d",
2510                                                 block_size);
2511                                         res = -EINVAL;
2512                                         goto out_free_vdev;
2513                                 }
2514                         }
2515                         virt_dev->block_size = block_size;
2516                         virt_dev->block_shift = block_shift;
2517                         
2518                         while (*p != '\0') {
2519                                 if (!strncmp("WRITE_THROUGH", p, 13)) {
2520                                         p += 13;
2521                                         virt_dev->wt_flag = 1;
2522                                         TRACE_DBG("%s", "WRITE_THROUGH");
2523                                 } else if (!strncmp("NV_CACHE", p, 8)) {
2524                                         p += 8;
2525                                         virt_dev->nv_cache = 1;
2526                                         TRACE_DBG("%s", "NON-VOLATILE CACHE");
2527                                 } else if (!strncmp("READ_ONLY", p, 9)) {
2528                                         p += 9;
2529                                         virt_dev->rd_only_flag = 1;
2530                                         TRACE_DBG("%s", "READ_ONLY");
2531                                 } else if (!strncmp("O_DIRECT", p, 8)) {
2532                                         p += 8;
2533                         #if 0
2534                                         
2535                                         virt_dev->o_direct_flag = 1;
2536                                         TRACE_DBG("%s", "O_DIRECT");
2537                         #else
2538                                         PRINT_INFO_PR("%s flag doesn't currently"
2539                                             " work, ignoring it", "O_DIRECT");
2540                         #endif
2541                                 } else if (!strncmp("NULLIO", p, 6)) {
2542                                         p += 6;
2543                                         virt_dev->nullio = 1;
2544                                         TRACE_DBG("%s", "NULLIO");
2545                                 } else {
2546                                         PRINT_ERROR_PR("Unknown flag \"%s\"", p);
2547                                         res = -EINVAL;
2548                                         goto out_free_vdev;
2549                                 }
2550                                 while (isspace(*p) && *p != '\0')
2551                                         p++;
2552                         }
2553                         
2554                         strcpy(virt_dev->name, name);
2555
2556                         pu.len = strlen(file_name) + 1;
2557                         virt_dev->file_name = kmalloc(pu.len, GFP_KERNEL);
2558                         if (virt_dev->file_name == NULL) {
2559                                 TRACE(TRACE_OUT_OF_MEM, "%s",
2560                                       "Allocation of file_name failed");
2561                                 res = -ENOMEM;
2562                                 goto out_free_vdev;
2563                         }
2564                         strncpy(virt_dev->file_name, file_name, pu.len);
2565
2566                         list_add_tail(&virt_dev->fileio_dev_list_entry,
2567                                       &disk_fileio_dev_list);
2568
2569                         virt_dev->virt_id =
2570                             scst_register_virtual_device(&disk_devtype_fileio,
2571                                                          virt_dev->name);
2572                         if (virt_dev->virt_id < 0) {
2573                                 res = virt_dev->virt_id;
2574                                 goto out_free_vpath;
2575                         }
2576                         TRACE_DBG("Added virt_dev (name %s, file name %s, "
2577                                 "id %d, block size %d) to "
2578                                 "disk_fileio_dev_list", virt_dev->name,
2579                                 virt_dev->file_name, virt_dev->virt_id,
2580                                 virt_dev->block_size);
2581                 } else {                           /* close */
2582                         virt_dev = NULL;
2583                         list_for_each_entry(vv, &disk_fileio_dev_list,
2584                                             fileio_dev_list_entry)
2585                         {
2586                                 if (strcmp(vv->name, name) == 0) {
2587                                         virt_dev = vv;
2588                                         break;
2589                                 }
2590                         }
2591                         if (virt_dev == NULL) {
2592                                 PRINT_ERROR_PR("Device %s not found", name);
2593                                 res = -EINVAL;
2594                                 goto out_up;
2595                         }
2596                         scst_unregister_virtual_device(virt_dev->virt_id);
2597                         PRINT_INFO_PR("Virtual device %s unregistered", 
2598                                 virt_dev->name);
2599                         TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
2600
2601                         list_del(&virt_dev->fileio_dev_list_entry);
2602
2603                         kfree(virt_dev->file_name);
2604                         kfree(virt_dev);
2605                 }
2606                 res = length;
2607         }
2608
2609 out_up:
2610         up(&scst_fileio_mutex);
2611
2612 out:
2613         TRACE_EXIT_RES(res);
2614         return res;
2615
2616 stop_output:
2617         *start = buffer + (offset - pu.begin);
2618         pu.len -= (offset - pu.begin);
2619         if (pu.len > length)
2620                 pu.len = length;
2621         res = max(0, pu.len);
2622         goto out_up;
2623
2624 out_free_vpath:
2625         list_del(&virt_dev->fileio_dev_list_entry);
2626         kfree(virt_dev->file_name);
2627
2628 out_free_vdev:
2629         kfree(virt_dev);
2630         goto out_up;
2631 }
2632
2633 /* scst_fileio_mutex supposed to be held */
2634 static int cdrom_fileio_open(char *p, char *name)
2635 {
2636         struct scst_fileio_dev *virt_dev, *vv;
2637         char *file_name;
2638         int len;
2639         int res = 0;
2640         int cdrom_empty;
2641
2642         virt_dev = NULL;
2643         list_for_each_entry(vv, &cdrom_fileio_dev_list,
2644                             fileio_dev_list_entry)
2645         {
2646                 if (strcmp(vv->name, name) == 0) {
2647                         virt_dev = vv;
2648                         break;
2649                 }
2650         }
2651         if (virt_dev) {
2652                 PRINT_ERROR_PR("Virtual device with name "
2653                        "%s already exist", name);
2654                 res = -EINVAL;
2655                 goto out;
2656         }
2657
2658         while (isspace(*p) && *p != '\0')
2659                 p++;
2660         file_name = p;
2661         while (!isspace(*p) && *p != '\0')
2662                 p++;
2663         *p++ = '\0';
2664         if (*file_name == '\0') {
2665                 cdrom_empty = 1;
2666                 TRACE_DBG("%s", "No media");
2667         } else if (*file_name != '/') {
2668                 PRINT_ERROR_PR("File path \"%s\" is not "
2669                         "absolute", file_name);
2670                 res = -EINVAL;
2671                 goto out;
2672         } else
2673                 cdrom_empty = 0;
2674
2675         virt_dev = fileio_alloc_dev();
2676         if (virt_dev == NULL) {
2677                 TRACE(TRACE_OUT_OF_MEM, "%s",
2678                       "Allocation of virt_dev failed");
2679                 res = -ENOMEM;
2680                 goto out;
2681         }
2682         virt_dev->cdrom_empty = cdrom_empty;
2683
2684         strcpy(virt_dev->name, name);
2685
2686         if (!virt_dev->cdrom_empty) {
2687                 len = strlen(file_name) + 1;
2688                 virt_dev->file_name = kmalloc(len, GFP_KERNEL);
2689                 if (virt_dev->file_name == NULL) {
2690                         TRACE(TRACE_OUT_OF_MEM, "%s",
2691                               "Allocation of file_name failed");
2692                         res = -ENOMEM;
2693                         goto out_free_vdev;
2694                 }
2695                 strncpy(virt_dev->file_name, file_name, len);
2696         }
2697
2698         list_add_tail(&virt_dev->fileio_dev_list_entry,
2699                       &cdrom_fileio_dev_list);
2700
2701         virt_dev->virt_id =
2702             scst_register_virtual_device(&cdrom_devtype_fileio,
2703                                          virt_dev->name);
2704         if (virt_dev->virt_id < 0) {
2705                 res = virt_dev->virt_id;
2706                 goto out_free_vpath;
2707         }
2708         TRACE_DBG("Added virt_dev (name %s file_name %s id %d) "
2709                   "to cdrom_fileio_dev_list", virt_dev->name,
2710                   virt_dev->file_name, virt_dev->virt_id);
2711
2712 out:
2713         return res;
2714
2715 out_free_vpath:
2716         list_del(&virt_dev->fileio_dev_list_entry);
2717         kfree(virt_dev->file_name);
2718
2719 out_free_vdev:
2720         kfree(virt_dev);
2721         goto out;
2722 }
2723
2724 /* scst_fileio_mutex supposed to be held */
2725 static int cdrom_fileio_close(char *name)
2726 {
2727         struct scst_fileio_dev *virt_dev, *vv;
2728         int res = 0;
2729
2730         virt_dev = NULL;
2731         list_for_each_entry(vv, &cdrom_fileio_dev_list,
2732                             fileio_dev_list_entry)
2733         {
2734                 if (strcmp(vv->name, name) == 0) {
2735                         virt_dev = vv;
2736                         break;
2737                 }
2738         }
2739         if (virt_dev == NULL) {
2740                 PRINT_ERROR_PR("Virtual device with name "
2741                        "%s not found", name);
2742                 res = -EINVAL;
2743                 goto out;
2744         }
2745         scst_unregister_virtual_device(virt_dev->virt_id);
2746         PRINT_INFO_PR("Virtual device %s unregistered", 
2747                 virt_dev->name);
2748         TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
2749
2750         list_del(&virt_dev->fileio_dev_list_entry);
2751
2752         if (virt_dev->file_name)
2753                 kfree(virt_dev->file_name);
2754         kfree(virt_dev);
2755
2756 out:
2757         return res;
2758 }
2759
2760 /* scst_fileio_mutex supposed to be held */
2761 static int cdrom_fileio_change(char *p, char *name)
2762 {
2763         struct file *fd;
2764         struct scst_fileio_tgt_dev *ftgt_dev;
2765         loff_t err;
2766         mm_segment_t old_fs;
2767         struct scst_fileio_dev *virt_dev, *vv;
2768         char *file_name, *fn, *old_fn;
2769         int len;
2770         int res = 0;
2771
2772         virt_dev = NULL;
2773         list_for_each_entry(vv, &cdrom_fileio_dev_list,
2774                             fileio_dev_list_entry)
2775         {
2776                 if (strcmp(vv->name, name) == 0) {
2777                         virt_dev = vv;
2778                         break;
2779                 }
2780         }
2781         if (virt_dev == NULL) {
2782                 PRINT_ERROR_PR("Virtual device with name "
2783                        "%s not found", name);
2784                 res = -EINVAL;
2785                 goto out;
2786         }
2787
2788         while (isspace(*p) && *p != '\0')
2789                 p++;
2790         file_name = p;
2791         while (!isspace(*p) && *p != '\0')
2792                 p++;
2793         *p++ = '\0';
2794         if (*file_name == '\0') {
2795                 virt_dev->cdrom_empty = 1;
2796                 TRACE_DBG("%s", "No media");
2797         } else if (*file_name != '/') {
2798                 PRINT_ERROR_PR("File path \"%s\" is not "
2799                         "absolute", file_name);
2800                 res = -EINVAL;
2801                 goto out;
2802         } else
2803                 virt_dev->cdrom_empty = 0;
2804
2805         old_fn = virt_dev->file_name;
2806
2807         if (!virt_dev->cdrom_empty) {
2808                 len = strlen(file_name) + 1;
2809                 fn = kmalloc(len, GFP_KERNEL);
2810                 if (fn == NULL) {
2811                         TRACE(TRACE_OUT_OF_MEM, "%s",
2812                                 "Allocation of file_name failed");
2813                         res = -ENOMEM;
2814                         goto out;
2815                 }
2816
2817                 strncpy(fn, file_name, len);
2818                 virt_dev->file_name = fn;
2819
2820                 fd = fileio_open(virt_dev);
2821                 if (IS_ERR(fd)) {
2822                         res = PTR_ERR(fd);
2823                         PRINT_ERROR_PR("filp_open(%s) returned an error %d",
2824                                        virt_dev->file_name, res);
2825                         goto out_free;
2826                 }
2827                 if ((fd->f_op == NULL) || (fd->f_op->readv == NULL)) {
2828                         PRINT_ERROR_PR("%s", "Wrong f_op or FS doesn't "
2829                                 "have required capabilities");
2830                         res = -EINVAL;
2831                         filp_close(fd, NULL);
2832                         goto out_free;
2833                 }
2834
2835                 /* seek to end */
2836                 old_fs = get_fs();
2837                 set_fs(get_ds());
2838                 if (fd->f_op->llseek) {
2839                         err = fd->f_op->llseek(fd, 0, 2/*SEEK_END*/);
2840                 } else {
2841                         err = default_llseek(fd, 0, 2/*SEEK_END*/);
2842                 }
2843                 set_fs(old_fs);
2844                 filp_close(fd, NULL);
2845                 if (err < 0) {
2846                         res = err;
2847                         PRINT_ERROR_PR("llseek %s returned an error %d",
2848                                        virt_dev->file_name, res);
2849                         goto out_free;
2850                 }
2851         } else {
2852                 len = 0;
2853                 err = 0;
2854                 fn = NULL;
2855                 virt_dev->file_name = fn;
2856         }
2857
2858         scst_suspend_activity();
2859
2860         if (virt_dev->prevent_allow_medium_removal) {
2861                 PRINT_ERROR_PR("Prevent medium removal for "
2862                         "virtual device with name %s", name);
2863                 res = -EINVAL;
2864                 goto out_free_resume;
2865         }
2866
2867         virt_dev->file_size = err;
2868         virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
2869         if (!virt_dev->cdrom_empty)
2870                 virt_dev->media_changed = 1;
2871
2872         down(&virt_dev->ftgt_list_mutex);
2873         list_for_each_entry(ftgt_dev, &virt_dev->ftgt_list, 
2874                 ftgt_list_entry) 
2875         {
2876                 if (!virt_dev->cdrom_empty) {
2877                         fd = fileio_open(virt_dev);
2878                         if (IS_ERR(fd)) {
2879                                 res = PTR_ERR(fd);
2880                                 PRINT_ERROR_PR("filp_open(%s) returned an error %d, "
2881                                         "closing the device", virt_dev->file_name, res);
2882                                 up(&virt_dev->ftgt_list_mutex);
2883                                 goto out_err_resume;
2884                         }
2885                 } else
2886                         fd = NULL;
2887                 if (ftgt_dev->fd)
2888                         filp_close(ftgt_dev->fd, NULL);
2889                 ftgt_dev->fd = fd;
2890         }
2891         up(&virt_dev->ftgt_list_mutex);
2892
2893         if (!virt_dev->cdrom_empty) {
2894                 PRINT_INFO_PR("Changed SCSI target virtual cdrom %s "
2895                         "(file=\"%s\", fs=%LdMB, bs=%d, nblocks=%Ld, cyln=%Ld%s)",
2896                         virt_dev->name, virt_dev->file_name,
2897                         virt_dev->file_size >> 20, virt_dev->block_size,
2898                         virt_dev->nblocks, virt_dev->nblocks/64/32,
2899                         virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
2900                                                         "than 1" : "");
2901         } else {
2902                 PRINT_INFO_PR("Removed media from SCSI target virtual cdrom %s",
2903                         virt_dev->name);
2904         }
2905
2906         if (old_fn)
2907                 kfree(old_fn);
2908
2909 out_resume:
2910         scst_resume_activity();
2911
2912 out:
2913         return res;
2914
2915 out_free:
2916         virt_dev->file_name = old_fn;
2917         kfree(fn);
2918         goto out;
2919
2920 out_free_resume:
2921         virt_dev->file_name = old_fn;
2922         kfree(fn);
2923         goto out_resume;
2924
2925 out_err_resume:
2926         virt_dev->file_name = old_fn;
2927         kfree(fn);
2928         scst_resume_activity();
2929         cdrom_fileio_close(name);
2930         goto out;
2931 }
2932
2933 /* 
2934  * Called when a file in the /proc/CDROM_FILEIO_NAME/CDROM_FILEIO_NAME is read
2935  * or written 
2936  */
2937 static int cdrom_fileio_proc(char *buffer, char **start, off_t offset,
2938         int length, int *eof, struct scst_dev_type *dev_type, int inout)
2939 {
2940         int res = 0, action;
2941         char *p, *name;
2942         struct scst_fileio_dev *virt_dev;
2943         int size;
2944         struct fileio_proc_update_struct pu;
2945
2946         TRACE_ENTRY();
2947
2948         memset(&pu, 0, sizeof(pu));
2949
2950         if (down_interruptible(&scst_fileio_mutex) != 0) {
2951                 res = -EINTR;
2952                 goto out;
2953         }
2954         
2955         if (inout == 0) { /* read */
2956                 size = scnprintf(buffer, length, "%-17s %-9s %s\n",
2957                                "Name", "Size(MB)", "File name");
2958                 if (fileio_proc_update_size(size, offset, length, &pu, 1))
2959                         goto stop_output;
2960
2961                 list_for_each_entry(virt_dev, &cdrom_fileio_dev_list, 
2962                         fileio_dev_list_entry)
2963                 {
2964                         size = scnprintf(buffer + pu.len, length - pu.len, 
2965                                 "%-17s %-9d %s\n", virt_dev->name,
2966                                 (uint32_t)(virt_dev->file_size >> 20),
2967                                 virt_dev->file_name);
2968                         if (fileio_proc_update_size(size, offset, length, &pu,
2969                                         1)) {
2970                                 goto stop_output;
2971                         }
2972                 }
2973                 *eof = 1;
2974                 goto stop_output;
2975         } else {  /* write */
2976                 p = buffer;
2977                 if (p[strlen(p) - 1] == '\n') {
2978                         p[strlen(p) - 1] = '\0';
2979                 }
2980                 if (!strncmp("close ", p, 6)) {
2981                         p += 6;
2982                         action = 0;
2983                 } else if (!strncmp("change ", p, 5)) {
2984                         p += 7;
2985                         action = 1;
2986                 } else if (!strncmp("open ", p, 5)) {
2987                         p += 5;
2988                         action = 2;
2989                 } else {
2990                         PRINT_ERROR_PR("Unknown action \"%s\"", p);
2991                         res = -EINVAL;
2992                         goto out_up;
2993                 }
2994
2995                 while (isspace(*p) && *p != '\0')
2996                         p++;
2997                 name = p;
2998                 while (!isspace(*p) && *p != '\0')
2999                         p++;
3000                 *p++ = '\0';
3001                 if (*name == '\0') {
3002                         PRINT_ERROR_PR("%s", "Name required");
3003                         res = -EINVAL;
3004                         goto out_up;
3005                 } else if (strlen(name) >= sizeof(virt_dev->name)) {
3006                         PRINT_ERROR_PR("Name is too long (max %zd "
3007                                 "characters)", sizeof(virt_dev->name)-1);
3008                         res = -EINVAL;
3009                         goto out_up;
3010                 }
3011
3012                 if (action == 2) {                      /* open */
3013                         res = cdrom_fileio_open(p, name);
3014                         if (res != 0)
3015                                 goto out_up;
3016                 } else if (action == 1) {          /* change */
3017                         res = cdrom_fileio_change(p, name);
3018                         if (res != 0)
3019                                 goto out_up;
3020                 } else {                           /* close */
3021                         res = cdrom_fileio_close(name);
3022                         if (res != 0)
3023                                 goto out_up;
3024                 }
3025                 res = length;
3026         }
3027
3028 out_up:
3029         up(&scst_fileio_mutex);
3030
3031 out:
3032         TRACE_EXIT_RES(res);
3033         return res;
3034
3035 stop_output:
3036         *start = buffer + (offset - pu.begin);
3037         pu.len -= (offset - pu.begin);
3038         if (pu.len > length)
3039                 pu.len = length;
3040         res = pu.len;
3041         goto out_up;
3042 }
3043
3044 static int fileio_proc_help_build(struct scst_dev_type *dev_type)
3045 {
3046         int res = 0;
3047         struct proc_dir_entry *p, *root;
3048
3049         TRACE_ENTRY();
3050
3051         root = scst_proc_get_dev_type_root(dev_type);
3052         if (root) {
3053                 p = create_proc_read_entry(FILEIO_PROC_HELP,
3054                         S_IFREG | S_IRUGO, root,
3055                         fileio_proc_help_read,
3056                         (dev_type->type == TYPE_DISK) ? 
3057                                 disk_fileio_proc_help_string :
3058                                 cdrom_fileio_proc_help_string);
3059                 if (p == NULL) {
3060                         PRINT_ERROR_PR("Not enough memory to register dev "
3061                              "handler %s entry %s in /proc",
3062                               dev_type->name, FILEIO_PROC_HELP);
3063                         res = -ENOMEM;
3064                         goto out;
3065                 }
3066         }
3067
3068 out:
3069         TRACE_EXIT_RES(res);
3070         return res;
3071 }
3072
3073 static void fileio_proc_help_destroy(struct scst_dev_type *dev_type)
3074 {
3075         struct proc_dir_entry *root;
3076
3077         TRACE_ENTRY();
3078
3079         root = scst_proc_get_dev_type_root(dev_type);
3080         if (root)
3081                 remove_proc_entry(FILEIO_PROC_HELP, root);
3082
3083         TRACE_EXIT();
3084 }
3085
3086 static int fileio_proc_help_read(char *buffer, char **start, off_t offset,
3087                                       int length, int *eof, void *data)
3088 {
3089         int res = 0;
3090         char *s = (char*)data;
3091         
3092         TRACE_ENTRY();
3093         
3094         if (offset < strlen(s))
3095                 res = scnprintf(buffer, length, "%s", &s[offset]);
3096         
3097         TRACE_EXIT_RES(res);
3098         return res;
3099 }
3100
3101 static int __init init_scst_fileio(struct scst_dev_type *devtype)
3102 {
3103         int res = 0;
3104
3105         TRACE_ENTRY();
3106
3107         devtype->module = THIS_MODULE;
3108
3109         res = scst_register_virtual_dev_driver(devtype);
3110         if (res < 0)
3111                 goto out;
3112
3113         res = scst_dev_handler_build_std_proc(devtype);
3114         if (res < 0)
3115                 goto out_unreg;
3116
3117         res = fileio_proc_help_build(devtype);
3118         if (res < 0) {
3119                 goto out_destroy_proc;
3120         }
3121
3122 out:
3123         TRACE_EXIT_RES(res);
3124         return res;
3125
3126 out_destroy_proc:
3127         scst_dev_handler_destroy_std_proc(devtype);
3128
3129 out_unreg:
3130         scst_unregister_virtual_dev_driver(devtype);
3131         goto out;
3132 }
3133
3134 static void __exit exit_scst_fileio(struct scst_dev_type *devtype,
3135         struct list_head *fileio_dev_list)
3136 {
3137         TRACE_ENTRY();
3138
3139         down(&scst_fileio_mutex);
3140         while (1) {
3141                 struct scst_fileio_dev *virt_dev;
3142
3143                 if (list_empty(fileio_dev_list))
3144                         break;
3145                 
3146                 virt_dev = list_entry(fileio_dev_list->next, typeof(*virt_dev),
3147                                 fileio_dev_list_entry);
3148
3149                 scst_unregister_virtual_device(virt_dev->virt_id);
3150
3151                 list_del(&virt_dev->fileio_dev_list_entry);
3152
3153                 PRINT_INFO_PR("Virtual device %s unregistered", virt_dev->name);
3154                 TRACE_DBG("virt_id %d", virt_dev->virt_id);
3155                 kfree(virt_dev->file_name);
3156                 kfree(virt_dev);
3157         }
3158         up(&scst_fileio_mutex);
3159
3160         fileio_proc_help_destroy(devtype);
3161         scst_dev_handler_destroy_std_proc(devtype);
3162
3163         scst_unregister_virtual_dev_driver(devtype);
3164
3165         TRACE_EXIT();
3166         return;
3167 }
3168
3169 static int __init init_scst_fileio_driver(void)
3170 {
3171         int res;
3172         res = init_scst_fileio(&disk_devtype_fileio);
3173         if (res != 0)
3174                 goto out;
3175
3176         res = init_scst_fileio(&cdrom_devtype_fileio);
3177         if (res != 0)
3178                 goto out_err;
3179
3180 out:
3181         return res;
3182
3183 out_err:
3184         exit_scst_fileio(&disk_devtype_fileio, &disk_fileio_dev_list);
3185         goto out;
3186 }
3187
3188 static void __exit exit_scst_fileio_driver(void)
3189 {
3190         exit_scst_fileio(&disk_devtype_fileio, &disk_fileio_dev_list);
3191         exit_scst_fileio(&cdrom_devtype_fileio, &cdrom_fileio_dev_list);
3192
3193         /* 
3194          * Wait for one sec. to allow the thread(s) actually exit,
3195          * otherwise we can get Oops. Any better way?
3196          */
3197         {
3198                 unsigned long t = jiffies;
3199                 TRACE_DBG("%s", "Waiting 1 sec...");
3200                 while ((jiffies - t) < HZ)
3201                         schedule();
3202         }
3203 }
3204
3205 module_init(init_scst_fileio_driver);
3206 module_exit(exit_scst_fileio_driver);
3207
3208 MODULE_LICENSE("GPL");