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