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