f5388e1abfa63c6f3262c5a54e2668ae8a258a28
[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(TRACE_MINOR, "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 /* 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                 unsigned long flags;
2225                 struct scst_cmd *cmd_to_abort = mcmd->cmd_to_abort;
2226                 struct scst_fileio_tgt_dev *ftgt_dev = 
2227                   (struct scst_fileio_tgt_dev *)cmd_to_abort->tgt_dev->dh_priv;
2228                 /* 
2229                  * Actually, _bh lock is enough here. But, since we
2230                  * could be called with IRQ off, the in-kernel debug check
2231                  * gives false alarm on using _bh lock. So, let's suppress it.
2232                  */
2233                 spin_lock_irqsave(&ftgt_dev->fdev_lock, flags);
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_irqrestore(&ftgt_dev->fdev_lock, flags);
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 static int fileio_proc_update_size(int size, int *len,
2265         off_t *begin, off_t *pos, off_t *offset)
2266 {
2267         int res;
2268         if (size > 0) {
2269                 *len += size;
2270                 *pos = *begin + *len;
2271                 if (*pos < *offset) {
2272                         *len = 0;
2273                         *begin = *pos;
2274                 }
2275                 res = 0;
2276         } else
2277                 res = 1;
2278         return res;
2279 }
2280
2281 /* 
2282  * Called when a file in the /proc/DISK_FILEIO_NAME/DISK_FILEIO_NAME is read
2283  * or written 
2284  */
2285 static int disk_fileio_proc(char *buffer, char **start, off_t offset,
2286         int length, int *eof, struct scst_dev_type *dev_type, int inout)
2287 {
2288         int res = 0, action;
2289         char *p, *name, *file_name;
2290         struct scst_fileio_dev *virt_dev, *vv;
2291         int size, len = 0;
2292         off_t begin = 0, pos = 0;
2293
2294         TRACE_ENTRY();
2295         
2296         /* VERY UGLY code. You can rewrite it if you want */
2297         
2298         if (down_interruptible(&scst_fileio_mutex) != 0) {
2299                 res = -EINTR;
2300                 goto out;
2301         }
2302         
2303         if (inout == 0) { /* read */
2304                 size = scnprintf(buffer, length, "%-17s %-12s %-15s %s\n",
2305                                "Name", "Size(MB)", "Options", "File name");
2306                 if (fileio_proc_update_size(size, &len, &begin, &pos, &offset)) {
2307                         res = len;
2308                         goto out_up;
2309                 }
2310
2311                 list_for_each_entry(virt_dev, &disk_fileio_dev_list, 
2312                         fileio_dev_list_entry)
2313                 {
2314                         int c;
2315                         size = scnprintf(buffer + len, length - len, 
2316                                 "%-17s %-13d", virt_dev->name,
2317                                 (uint32_t)(virt_dev->file_size >> 20));
2318                         if (fileio_proc_update_size(size, &len, &begin, &pos, 
2319                                                 &offset)) {
2320                                 res = len;
2321                                 goto out_up;
2322                         }
2323                         c = 0;
2324                         if (virt_dev->wt_flag) {
2325                                 size = scnprintf(buffer + len, length - len, "WT");
2326                                 c += size;
2327                                 if (fileio_proc_update_size(size, &len, &begin, 
2328                                                         &pos, &offset)) {
2329                                         res = len;
2330                                         goto out_up;
2331                                 }
2332                         }
2333                         if (virt_dev->nv_cache) {
2334                                 size = scnprintf(buffer + len, length - len,
2335                                         c ? ",NV" : "NV");
2336                                 c += size;
2337                                 if (fileio_proc_update_size(size, &len, &begin, 
2338                                                         &pos, &offset)) {
2339                                         res = len;
2340                                         goto out_up;
2341                                 }
2342                         }
2343                         if (virt_dev->rd_only_flag) {
2344                                 size = scnprintf(buffer + len, length - len, 
2345                                         c ? ",RO" : "RO");
2346                                 c += size;
2347                                 if (fileio_proc_update_size(size, &len, &begin, 
2348                                                         &pos, &offset)) {
2349                                         res = len;
2350                                         goto out_up;
2351                                 }
2352                         }
2353                         if (virt_dev->o_direct_flag) {
2354                                 size = scnprintf(buffer + len, length - len, 
2355                                         c ? ",DR" : "DR");
2356                                 c += size;
2357                                 if (fileio_proc_update_size(size, &len, &begin, 
2358                                                         &pos, &offset)) {
2359                                         res = len;
2360                                         goto out_up;
2361                                 }
2362                         }
2363                         if (virt_dev->nullio) {
2364                                 size = scnprintf(buffer + len, length - len, 
2365                                         c ? ",NIO" : "NIO");
2366                                 c += size;
2367                                 if (fileio_proc_update_size(size, &len, &begin, 
2368                                                         &pos, &offset)) {
2369                                         res = len;
2370                                         goto out_up;
2371                                 }
2372                         }
2373                         while (c < 16) {
2374                                 size = scnprintf(buffer + len, length - len, " ");
2375                                 if (fileio_proc_update_size(size, &len, &begin, &pos, 
2376                                                 &offset)) {
2377                                         res = len;
2378                                         goto out_up;
2379                                 }
2380                                 c++;
2381                         }
2382                         size = scnprintf(buffer + len, length - len, "%s\n",
2383                                         virt_dev->file_name);
2384                         if (fileio_proc_update_size(size, &len, &begin, 
2385                                                 &pos, &offset)) {
2386                                 res = len;
2387                                 goto out_up;
2388                         }
2389                 }
2390                 *start = buffer + (offset - begin);
2391                 len -= (offset - begin);
2392                 if (len > length)
2393                         len = length;
2394                 res = len;
2395                 *eof = 1;
2396         } 
2397         else {  /* write */
2398                 uint32_t block_size = DEF_DISK_BLOCKSIZE;
2399                 int block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
2400                 p = buffer;
2401                 if (p[strlen(p) - 1] == '\n') {
2402                         p[strlen(p) - 1] = '\0';
2403                 }
2404                 if (!strncmp("close ", p, 6)) {
2405                         p += 6;
2406                         action = 0;
2407                 } else if (!strncmp("open ", p, 5)) {
2408                         p += 5;
2409                         action = 2;
2410                 } else {
2411                         PRINT_ERROR_PR("Unknown action \"%s\"", p);
2412                         res = -EINVAL;
2413                         goto out_up;
2414                 }
2415
2416                 while (isspace(*p) && *p != '\0')
2417                         p++;
2418                 name = p;
2419                 while (!isspace(*p) && *p != '\0')
2420                         p++;
2421                 *p++ = '\0';
2422                 if (*name == '\0') {
2423                         PRINT_ERROR_PR("%s", "Name required");
2424                         res = -EINVAL;
2425                         goto out_up;
2426                 } else if (strlen(name) >= sizeof(virt_dev->name)) {
2427                         PRINT_ERROR_PR("Name is too long (max %zd "
2428                                 "characters)", sizeof(virt_dev->name)-1);
2429                         res = -EINVAL;
2430                         goto out_up;
2431                 }
2432
2433                 if (action) {                      /* open */
2434                         virt_dev = NULL;
2435                         list_for_each_entry(vv, &disk_fileio_dev_list,
2436                                             fileio_dev_list_entry)
2437                         {
2438                                 if (strcmp(vv->name, name) == 0) {
2439                                         virt_dev = vv;
2440                                         break;
2441                                 }
2442                         }
2443                         if (virt_dev) {
2444                                 PRINT_ERROR_PR("Virtual device with name "
2445                                        "%s already exist", name);
2446                                 res = -EINVAL;
2447                                 goto out_up;
2448                         }
2449
2450                         while (isspace(*p) && *p != '\0')
2451                                 p++;
2452                         file_name = p;
2453                         while (!isspace(*p) && *p != '\0')
2454                                 p++;
2455                         *p++ = '\0';
2456                         if (*file_name == '\0') {
2457                                 PRINT_ERROR_PR("%s", "File name required");
2458                                 res = -EINVAL;
2459                                 goto out_up;
2460                         } else if (*file_name != '/') {
2461                                 PRINT_ERROR_PR("File path \"%s\" is not "
2462                                         "absolute", file_name);
2463                                 res = -EINVAL;
2464                                 goto out_up;
2465                         }
2466
2467                         virt_dev = fileio_alloc_dev();
2468                         if (virt_dev == NULL) {
2469                                 TRACE(TRACE_OUT_OF_MEM, "%s",
2470                                       "Allocation of virt_dev failed");
2471                                 res = -ENOMEM;
2472                                 goto out_up;
2473                         }
2474
2475                         while (isspace(*p) && *p != '\0')
2476                                 p++;
2477
2478                         if (isdigit(*p)) {
2479                                 char *pp;
2480                                 uint32_t t;
2481                                 block_size = simple_strtoul(p, &pp, 0);
2482                                 p = pp;
2483                                 if ((*p != '\0') && !isspace(*p)) {
2484                                         PRINT_ERROR_PR("Parse error: \"%s\"", p);
2485                                         res = -EINVAL;
2486                                         goto out_free_vdev;
2487                                 }
2488                                 while (isspace(*p) && *p != '\0')
2489                                         p++;
2490
2491                                 t = block_size;
2492                                 block_shift = 0;
2493                                 while(1) {
2494                                         if ((t & 1) != 0)
2495                                                 break;
2496                                         t >>= 1;
2497                                         block_shift++;
2498                                 }
2499                                 if (block_shift < 9) {
2500                                         PRINT_ERROR_PR("Wrong block size %d",
2501                                                 block_size);
2502                                         res = -EINVAL;
2503                                         goto out_free_vdev;
2504                                 }
2505                         }
2506                         virt_dev->block_size = block_size;
2507                         virt_dev->block_shift = block_shift;
2508                         
2509                         while (*p != '\0') {
2510                                 if (!strncmp("WRITE_THROUGH", p, 13)) {
2511                                         p += 13;
2512                                         virt_dev->wt_flag = 1;
2513                                         TRACE_DBG("%s", "WRITE_THROUGH");
2514                                 } else if (!strncmp("NV_CACHE", p, 8)) {
2515                                         p += 8;
2516                                         virt_dev->nv_cache = 1;
2517                                         TRACE_DBG("%s", "NON-VOLATILE CACHE");
2518                                 } else if (!strncmp("READ_ONLY", p, 9)) {
2519                                         p += 9;
2520                                         virt_dev->rd_only_flag = 1;
2521                                         TRACE_DBG("%s", "READ_ONLY");
2522                                 } else if (!strncmp("O_DIRECT", p, 8)) {
2523                                         p += 8;
2524                                         virt_dev->o_direct_flag = 1;
2525                                         TRACE_DBG("%s", "O_DIRECT");
2526                                 } else if (!strncmp("NULLIO", p, 6)) {
2527                                         p += 6;
2528                                         virt_dev->nullio = 1;
2529                                         TRACE_DBG("%s", "NULLIO");
2530                                 } else {
2531                                         PRINT_ERROR_PR("Unknown flag \"%s\"", p);
2532                                         res = -EINVAL;
2533                                         goto out_free_vdev;
2534                                 }
2535                                 while (isspace(*p) && *p != '\0')
2536                                         p++;
2537                         }
2538                         
2539                         strcpy(virt_dev->name, name);
2540
2541                         len = strlen(file_name) + 1;
2542                         virt_dev->file_name = kmalloc(len, GFP_KERNEL);
2543                         if (virt_dev->file_name == NULL) {
2544                                 TRACE(TRACE_OUT_OF_MEM, "%s",
2545                                       "Allocation of file_name failed");
2546                                 res = -ENOMEM;
2547                                 goto out_free_vdev;
2548                         }
2549                         strncpy(virt_dev->file_name, file_name, len);
2550
2551                         list_add_tail(&virt_dev->fileio_dev_list_entry,
2552                                       &disk_fileio_dev_list);
2553
2554                         virt_dev->virt_id =
2555                             scst_register_virtual_device(&disk_devtype_fileio,
2556                                                          virt_dev->name);
2557                         if (virt_dev->virt_id < 0) {
2558                                 res = virt_dev->virt_id;
2559                                 goto out_free_vpath;
2560                         }
2561                         TRACE_DBG("Added virt_dev (name %s, file name %s, "
2562                                 "id %d, block size %d) to "
2563                                 "disk_fileio_dev_list", virt_dev->name,
2564                                 virt_dev->file_name, virt_dev->virt_id,
2565                                 virt_dev->block_size);
2566                 } else {                           /* close */
2567                         virt_dev = NULL;
2568                         list_for_each_entry(vv, &disk_fileio_dev_list,
2569                                             fileio_dev_list_entry)
2570                         {
2571                                 if (strcmp(vv->name, name) == 0) {
2572                                         virt_dev = vv;
2573                                         break;
2574                                 }
2575                         }
2576                         if (virt_dev == NULL) {
2577                                 PRINT_ERROR_PR("Device %s not found", name);
2578                                 res = -EINVAL;
2579                                 goto out_up;
2580                         }
2581                         scst_unregister_virtual_device(virt_dev->virt_id);
2582                         PRINT_INFO_PR("Virtual device %s unregistered", 
2583                                 virt_dev->name);
2584                         TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
2585
2586                         list_del(&virt_dev->fileio_dev_list_entry);
2587
2588                         kfree(virt_dev->file_name);
2589                         kfree(virt_dev);
2590                 }
2591                 res = length;
2592         }
2593
2594 out_up:
2595         up(&scst_fileio_mutex);
2596
2597 out:
2598         TRACE_EXIT_RES(res);
2599         return res;
2600
2601 out_free_vpath:
2602         list_del(&virt_dev->fileio_dev_list_entry);
2603         kfree(virt_dev->file_name);
2604
2605 out_free_vdev:
2606         kfree(virt_dev);
2607         goto out_up;
2608 }
2609
2610 /* scst_fileio_mutex supposed to be held */
2611 static int cdrom_fileio_open(char *p, char *name)
2612 {
2613         struct scst_fileio_dev *virt_dev, *vv;
2614         char *file_name;
2615         int len;
2616         int res = 0;
2617         int cdrom_empty;
2618
2619         virt_dev = NULL;
2620         list_for_each_entry(vv, &cdrom_fileio_dev_list,
2621                             fileio_dev_list_entry)
2622         {
2623                 if (strcmp(vv->name, name) == 0) {
2624                         virt_dev = vv;
2625                         break;
2626                 }
2627         }
2628         if (virt_dev) {
2629                 PRINT_ERROR_PR("Virtual device with name "
2630                        "%s already exist", name);
2631                 res = -EINVAL;
2632                 goto out;
2633         }
2634
2635         while (isspace(*p) && *p != '\0')
2636                 p++;
2637         file_name = p;
2638         while (!isspace(*p) && *p != '\0')
2639                 p++;
2640         *p++ = '\0';
2641         if (*file_name == '\0') {
2642                 cdrom_empty = 1;
2643                 TRACE_DBG("%s", "No media");
2644         } else if (*file_name != '/') {
2645                 PRINT_ERROR_PR("File path \"%s\" is not "
2646                         "absolute", file_name);
2647                 res = -EINVAL;
2648                 goto out;
2649         } else
2650                 cdrom_empty = 0;
2651
2652         virt_dev = fileio_alloc_dev();
2653         if (virt_dev == NULL) {
2654                 TRACE(TRACE_OUT_OF_MEM, "%s",
2655                       "Allocation of virt_dev failed");
2656                 res = -ENOMEM;
2657                 goto out;
2658         }
2659         virt_dev->cdrom_empty = cdrom_empty;
2660
2661         strcpy(virt_dev->name, name);
2662
2663         if (!virt_dev->cdrom_empty) {
2664                 len = strlen(file_name) + 1;
2665                 virt_dev->file_name = kmalloc(len, GFP_KERNEL);
2666                 if (virt_dev->file_name == NULL) {
2667                         TRACE(TRACE_OUT_OF_MEM, "%s",
2668                               "Allocation of file_name failed");
2669                         res = -ENOMEM;
2670                         goto out_free_vdev;
2671                 }
2672                 strncpy(virt_dev->file_name, file_name, len);
2673         }
2674
2675         list_add_tail(&virt_dev->fileio_dev_list_entry,
2676                       &cdrom_fileio_dev_list);
2677
2678         virt_dev->virt_id =
2679             scst_register_virtual_device(&cdrom_devtype_fileio,
2680                                          virt_dev->name);
2681         if (virt_dev->virt_id < 0) {
2682                 res = virt_dev->virt_id;
2683                 goto out_free_vpath;
2684         }
2685         TRACE_DBG("Added virt_dev (name %s file_name %s id %d) "
2686                   "to cdrom_fileio_dev_list", virt_dev->name,
2687                   virt_dev->file_name, virt_dev->virt_id);
2688
2689 out:
2690         return res;
2691
2692 out_free_vpath:
2693         list_del(&virt_dev->fileio_dev_list_entry);
2694         kfree(virt_dev->file_name);
2695
2696 out_free_vdev:
2697         kfree(virt_dev);
2698         goto out;
2699 }
2700
2701 /* scst_fileio_mutex supposed to be held */
2702 static int cdrom_fileio_close(char *name)
2703 {
2704         struct scst_fileio_dev *virt_dev, *vv;
2705         int res = 0;
2706
2707         virt_dev = NULL;
2708         list_for_each_entry(vv, &cdrom_fileio_dev_list,
2709                             fileio_dev_list_entry)
2710         {
2711                 if (strcmp(vv->name, name) == 0) {
2712                         virt_dev = vv;
2713                         break;
2714                 }
2715         }
2716         if (virt_dev == NULL) {
2717                 PRINT_ERROR_PR("Virtual device with name "
2718                        "%s not found", name);
2719                 res = -EINVAL;
2720                 goto out;
2721         }
2722         scst_unregister_virtual_device(virt_dev->virt_id);
2723         PRINT_INFO_PR("Virtual device %s unregistered", 
2724                 virt_dev->name);
2725         TRACE_DBG("virt_id %d unregister", virt_dev->virt_id);
2726
2727         list_del(&virt_dev->fileio_dev_list_entry);
2728
2729         if (virt_dev->file_name)
2730                 kfree(virt_dev->file_name);
2731         kfree(virt_dev);
2732
2733 out:
2734         return res;
2735 }
2736
2737 /* scst_fileio_mutex supposed to be held */
2738 static int cdrom_fileio_change(char *p, char *name)
2739 {
2740         struct file *fd;
2741         struct scst_fileio_tgt_dev *ftgt_dev;
2742         loff_t err;
2743         mm_segment_t old_fs;
2744         struct scst_fileio_dev *virt_dev, *vv;
2745         char *file_name, *fn, *old_fn;
2746         int len;
2747         int res = 0;
2748
2749         virt_dev = NULL;
2750         list_for_each_entry(vv, &cdrom_fileio_dev_list,
2751                             fileio_dev_list_entry)
2752         {
2753                 if (strcmp(vv->name, name) == 0) {
2754                         virt_dev = vv;
2755                         break;
2756                 }
2757         }
2758         if (virt_dev == NULL) {
2759                 PRINT_ERROR_PR("Virtual device with name "
2760                        "%s not found", name);
2761                 res = -EINVAL;
2762                 goto out;
2763         }
2764
2765         while (isspace(*p) && *p != '\0')
2766                 p++;
2767         file_name = p;
2768         while (!isspace(*p) && *p != '\0')
2769                 p++;
2770         *p++ = '\0';
2771         if (*file_name == '\0') {
2772                 virt_dev->cdrom_empty = 1;
2773                 TRACE_DBG("%s", "No media");
2774         } else if (*file_name != '/') {
2775                 PRINT_ERROR_PR("File path \"%s\" is not "
2776                         "absolute", file_name);
2777                 res = -EINVAL;
2778                 goto out;
2779         } else
2780                 virt_dev->cdrom_empty = 0;
2781
2782         old_fn = virt_dev->file_name;
2783
2784         if (!virt_dev->cdrom_empty) {
2785                 len = strlen(file_name) + 1;
2786                 fn = kmalloc(len, GFP_KERNEL);
2787                 if (fn == NULL) {
2788                         TRACE(TRACE_OUT_OF_MEM, "%s",
2789                                 "Allocation of file_name failed");
2790                         res = -ENOMEM;
2791                         goto out;
2792                 }
2793
2794                 strncpy(fn, file_name, len);
2795                 virt_dev->file_name = fn;
2796
2797                 fd = fileio_open(virt_dev);
2798                 if (IS_ERR(fd)) {
2799                         res = PTR_ERR(fd);
2800                         PRINT_ERROR_PR("filp_open(%s) returned an error %d",
2801                                        virt_dev->file_name, res);
2802                         goto out_free;
2803                 }
2804                 if ((fd->f_op == NULL) || (fd->f_op->readv == NULL)) {
2805                         PRINT_ERROR_PR("%s", "Wrong f_op or FS doesn't "
2806                                 "have required capabilities");
2807                         res = -EINVAL;
2808                         filp_close(fd, NULL);
2809                         goto out_free;
2810                 }
2811
2812                 /* seek to end */
2813                 old_fs = get_fs();
2814                 set_fs(get_ds());
2815                 if (fd->f_op->llseek) {
2816                         err = fd->f_op->llseek(fd, 0, 2/*SEEK_END*/);
2817                 } else {
2818                         err = default_llseek(fd, 0, 2/*SEEK_END*/);
2819                 }
2820                 set_fs(old_fs);
2821                 filp_close(fd, NULL);
2822                 if (err < 0) {
2823                         res = err;
2824                         PRINT_ERROR_PR("llseek %s returned an error %d",
2825                                        virt_dev->file_name, res);
2826                         goto out_free;
2827                 }
2828         } else {
2829                 len = 0;
2830                 err = 0;
2831                 fn = NULL;
2832                 virt_dev->file_name = fn;
2833         }
2834
2835         scst_suspend_activity();
2836
2837         if (virt_dev->prevent_allow_medium_removal) {
2838                 PRINT_ERROR_PR("Prevent medium removal for "
2839                         "virtual device with name %s", name);
2840                 res = -EINVAL;
2841                 goto out_free_resume;
2842         }
2843
2844         virt_dev->file_size = err;
2845         virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
2846         if (!virt_dev->cdrom_empty)
2847                 virt_dev->media_changed = 1;
2848
2849         down(&virt_dev->ftgt_list_mutex);
2850         list_for_each_entry(ftgt_dev, &virt_dev->ftgt_list, 
2851                 ftgt_list_entry) 
2852         {
2853                 if (!virt_dev->cdrom_empty) {
2854                         fd = fileio_open(virt_dev);
2855                         if (IS_ERR(fd)) {
2856                                 res = PTR_ERR(fd);
2857                                 PRINT_ERROR_PR("filp_open(%s) returned an error %d, "
2858                                         "closing the device", virt_dev->file_name, res);
2859                                 up(&virt_dev->ftgt_list_mutex);
2860                                 goto out_err_resume;
2861                         }
2862                 } else
2863                         fd = NULL;
2864                 if (ftgt_dev->fd)
2865                         filp_close(ftgt_dev->fd, NULL);
2866                 ftgt_dev->fd = fd;
2867         }
2868         up(&virt_dev->ftgt_list_mutex);
2869
2870         if (!virt_dev->cdrom_empty) {
2871                 PRINT_INFO_PR("Changed SCSI target virtual cdrom %s "
2872                         "(file=\"%s\", fs=%LdMB, bs=%d, nblocks=%Ld, cyln=%Ld%s)",
2873                         virt_dev->name, virt_dev->file_name,
2874                         virt_dev->file_size >> 20, virt_dev->block_size,
2875                         virt_dev->nblocks, virt_dev->nblocks/64/32,
2876                         virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
2877                                                         "than 1" : "");
2878         } else {
2879                 PRINT_INFO_PR("Removed media from SCSI target virtual cdrom %s",
2880                         virt_dev->name);
2881         }
2882
2883         if (old_fn)
2884                 kfree(old_fn);
2885
2886 out_resume:
2887         scst_resume_activity();
2888
2889 out:
2890         return res;
2891
2892 out_free:
2893         virt_dev->file_name = old_fn;
2894         kfree(fn);
2895         goto out;
2896
2897 out_free_resume:
2898         virt_dev->file_name = old_fn;
2899         kfree(fn);
2900         goto out_resume;
2901
2902 out_err_resume:
2903         virt_dev->file_name = old_fn;
2904         kfree(fn);
2905         scst_resume_activity();
2906         cdrom_fileio_close(name);
2907         goto out;
2908 }
2909
2910 /* 
2911  * Called when a file in the /proc/CDROM_FILEIO_NAME/CDROM_FILEIO_NAME is read
2912  * or written 
2913  */
2914 static int cdrom_fileio_proc(char *buffer, char **start, off_t offset,
2915         int length, int *eof, struct scst_dev_type *dev_type, int inout)
2916 {
2917         int res = 0, action;
2918         char *p, *name;
2919         struct scst_fileio_dev *virt_dev;
2920         int size, len = 0;
2921         off_t begin = 0, pos = 0;
2922
2923         TRACE_ENTRY();
2924
2925         if (down_interruptible(&scst_fileio_mutex) != 0) {
2926                 res = -EINTR;
2927                 goto out;
2928         }
2929         
2930         if (inout == 0) { /* read */
2931                 size = scnprintf(buffer, length, "%-17s %-9s %s\n",
2932                                "Name", "Size(MB)", "File name");
2933                 if (fileio_proc_update_size(size, &len, &begin, &pos, 
2934                                         &offset)) {
2935                         res = len;
2936                         goto out_up;
2937                 }
2938
2939                 list_for_each_entry(virt_dev, &cdrom_fileio_dev_list, 
2940                         fileio_dev_list_entry)
2941                 {
2942                         size = scnprintf(buffer + len, length - len, 
2943                                 "%-17s %-9d %s\n", virt_dev->name,
2944                                 (uint32_t)(virt_dev->file_size >> 20),
2945                                 virt_dev->file_name);
2946                         if (fileio_proc_update_size(size, &len, &begin, 
2947                                                 &pos, &offset)) {
2948                                 res = len;
2949                                 goto out_up;
2950                         }
2951                 }
2952                 *start = buffer + (offset - begin);
2953                 len -= (offset - begin);
2954                 if (len > length)
2955                         len = length;
2956                 res = len;
2957         } 
2958         else {  /* write */
2959                 p = buffer;
2960                 if (p[strlen(p) - 1] == '\n') {
2961                         p[strlen(p) - 1] = '\0';
2962                 }
2963                 if (!strncmp("close ", p, 6)) {
2964                         p += 6;
2965                         action = 0;
2966                 } else if (!strncmp("change ", p, 5)) {
2967                         p += 7;
2968                         action = 1;
2969                 } else if (!strncmp("open ", p, 5)) {
2970                         p += 5;
2971                         action = 2;
2972                 } else {
2973                         PRINT_ERROR_PR("Unknown action \"%s\"", p);
2974                         res = -EINVAL;
2975                         goto out_up;
2976                 }
2977
2978                 while (isspace(*p) && *p != '\0')
2979                         p++;
2980                 name = p;
2981                 while (!isspace(*p) && *p != '\0')
2982                         p++;
2983                 *p++ = '\0';
2984                 if (*name == '\0') {
2985                         PRINT_ERROR_PR("%s", "Name required");
2986                         res = -EINVAL;
2987                         goto out_up;
2988                 } else if (strlen(name) >= sizeof(virt_dev->name)) {
2989                         PRINT_ERROR_PR("Name is too long (max %zd "
2990                                 "characters)", sizeof(virt_dev->name)-1);
2991                         res = -EINVAL;
2992                         goto out_up;
2993                 }
2994
2995                 if (action == 2) {                      /* open */
2996                         res = cdrom_fileio_open(p, name);
2997                         if (res != 0)
2998                                 goto out_up;
2999                 } else if (action == 1) {          /* change */
3000                         res = cdrom_fileio_change(p, name);
3001                         if (res != 0)
3002                                 goto out_up;
3003                 } else {                           /* close */
3004                         res = cdrom_fileio_close(name);
3005                         if (res != 0)
3006                                 goto out_up;
3007                 }
3008                 res = length;
3009         }
3010
3011 out_up:
3012         up(&scst_fileio_mutex);
3013
3014 out:
3015         TRACE_EXIT_RES(res);
3016         return res;
3017
3018 }
3019
3020 static int fileio_proc_help_build(struct scst_dev_type *dev_type)
3021 {
3022         int res = 0;
3023         struct proc_dir_entry *p, *root;
3024
3025         TRACE_ENTRY();
3026
3027         root = scst_proc_get_dev_type_root(dev_type);
3028         if (root) {
3029                 p = create_proc_read_entry(FILEIO_PROC_HELP,
3030                         S_IFREG | S_IRUGO, root,
3031                         fileio_proc_help_read,
3032                         (dev_type->type == TYPE_DISK) ? 
3033                                 disk_fileio_proc_help_string :
3034                                 cdrom_fileio_proc_help_string);
3035                 if (p == NULL) {
3036                         PRINT_ERROR_PR("Not enough memory to register dev "
3037                              "handler %s entry %s in /proc",
3038                               dev_type->name, FILEIO_PROC_HELP);
3039                         res = -ENOMEM;
3040                         goto out;
3041                 }
3042         }
3043
3044 out:
3045         TRACE_EXIT_RES(res);
3046         return res;
3047 }
3048
3049 static void fileio_proc_help_destroy(struct scst_dev_type *dev_type)
3050 {
3051         struct proc_dir_entry *root;
3052
3053         TRACE_ENTRY();
3054
3055         root = scst_proc_get_dev_type_root(dev_type);
3056         if (root)
3057                 remove_proc_entry(FILEIO_PROC_HELP, root);
3058
3059         TRACE_EXIT();
3060 }
3061
3062 static int fileio_proc_help_read(char *buffer, char **start, off_t offset,
3063                                       int length, int *eof, void *data)
3064 {
3065         int res = 0;
3066         char *s = (char*)data;
3067         
3068         TRACE_ENTRY();
3069         
3070         if (offset < strlen(s))
3071                 res = scnprintf(buffer, length, "%s", &s[offset]);
3072         
3073         TRACE_EXIT_RES(res);
3074         return res;
3075 }
3076
3077 static int __init init_scst_fileio(struct scst_dev_type *devtype)
3078 {
3079         int res = 0;
3080
3081         TRACE_ENTRY();
3082
3083         devtype->module = THIS_MODULE;
3084
3085         res = scst_register_virtual_dev_driver(devtype);
3086         if (res < 0)
3087                 goto out;
3088
3089         res = scst_dev_handler_build_std_proc(devtype);
3090         if (res < 0)
3091                 goto out_unreg;
3092
3093         res = fileio_proc_help_build(devtype);
3094         if (res < 0) {
3095                 goto out_destroy_proc;
3096         }
3097
3098 out:
3099         TRACE_EXIT_RES(res);
3100         return res;
3101
3102 out_destroy_proc:
3103         scst_dev_handler_destroy_std_proc(devtype);
3104
3105 out_unreg:
3106         scst_unregister_virtual_dev_driver(devtype);
3107         goto out;
3108 }
3109
3110 static void __exit exit_scst_fileio(struct scst_dev_type *devtype,
3111         struct list_head *fileio_dev_list)
3112 {
3113         TRACE_ENTRY();
3114
3115         down(&scst_fileio_mutex);
3116         while (1) {
3117                 struct scst_fileio_dev *virt_dev;
3118
3119                 if (list_empty(fileio_dev_list))
3120                         break;
3121                 
3122                 virt_dev = list_entry(fileio_dev_list->next, typeof(*virt_dev),
3123                                 fileio_dev_list_entry);
3124
3125                 scst_unregister_virtual_device(virt_dev->virt_id);
3126
3127                 list_del(&virt_dev->fileio_dev_list_entry);
3128
3129                 PRINT_INFO_PR("Virtual device %s unregistered", virt_dev->name);
3130                 TRACE_DBG("virt_id %d", virt_dev->virt_id);
3131                 kfree(virt_dev->file_name);
3132                 kfree(virt_dev);
3133         }
3134         up(&scst_fileio_mutex);
3135
3136         fileio_proc_help_destroy(devtype);
3137         scst_dev_handler_destroy_std_proc(devtype);
3138
3139         scst_unregister_virtual_dev_driver(devtype);
3140
3141         TRACE_EXIT();
3142         return;
3143 }
3144
3145 static int __init init_scst_fileio_driver(void)
3146 {
3147         int res;
3148         res = init_scst_fileio(&disk_devtype_fileio);
3149         if (res != 0)
3150                 goto out;
3151
3152         res = init_scst_fileio(&cdrom_devtype_fileio);
3153         if (res != 0)
3154                 goto out_err;
3155
3156 out:
3157         return res;
3158
3159 out_err:
3160         exit_scst_fileio(&disk_devtype_fileio, &disk_fileio_dev_list);
3161         goto out;
3162 }
3163
3164 static void __exit exit_scst_fileio_driver(void)
3165 {
3166         exit_scst_fileio(&disk_devtype_fileio, &disk_fileio_dev_list);
3167         exit_scst_fileio(&cdrom_devtype_fileio, &cdrom_fileio_dev_list);
3168
3169         /* 
3170          * Wait for one sec. to allow the thread(s) actually exit,
3171          * otherwise we can get Oops. Any better way?
3172          */
3173         {
3174                 unsigned long t = jiffies;
3175                 TRACE_DBG("%s", "Waiting 1 sec...");
3176                 while ((jiffies - t) < HZ)
3177                         schedule();
3178         }
3179 }
3180
3181 module_init(init_scst_fileio_driver);
3182 module_exit(exit_scst_fileio_driver);
3183
3184 MODULE_LICENSE("GPL");