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