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