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