Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *    character device frontend for tape device driver
0004  *
0005  *  S390 and zSeries version
0006  *    Copyright IBM Corp. 2001, 2006
0007  *    Author(s): Carsten Otte <cotte@de.ibm.com>
0008  *       Michael Holzheu <holzheu@de.ibm.com>
0009  *       Tuan Ngo-Anh <ngoanh@de.ibm.com>
0010  *       Martin Schwidefsky <schwidefsky@de.ibm.com>
0011  */
0012 
0013 #define KMSG_COMPONENT "tape"
0014 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0015 
0016 #include <linux/module.h>
0017 #include <linux/types.h>
0018 #include <linux/proc_fs.h>
0019 #include <linux/mtio.h>
0020 #include <linux/compat.h>
0021 
0022 #include <linux/uaccess.h>
0023 
0024 #define TAPE_DBF_AREA   tape_core_dbf
0025 
0026 #include "tape.h"
0027 #include "tape_std.h"
0028 #include "tape_class.h"
0029 
0030 #define TAPECHAR_MAJOR      0   /* get dynamic major */
0031 
0032 /*
0033  * file operation structure for tape character frontend
0034  */
0035 static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *);
0036 static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *);
0037 static int tapechar_open(struct inode *,struct file *);
0038 static int tapechar_release(struct inode *,struct file *);
0039 static long tapechar_ioctl(struct file *, unsigned int, unsigned long);
0040 #ifdef CONFIG_COMPAT
0041 static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long);
0042 #endif
0043 
0044 static const struct file_operations tape_fops =
0045 {
0046     .owner = THIS_MODULE,
0047     .read = tapechar_read,
0048     .write = tapechar_write,
0049     .unlocked_ioctl = tapechar_ioctl,
0050 #ifdef CONFIG_COMPAT
0051     .compat_ioctl = tapechar_compat_ioctl,
0052 #endif
0053     .open = tapechar_open,
0054     .release = tapechar_release,
0055     .llseek = no_llseek,
0056 };
0057 
0058 static int tapechar_major = TAPECHAR_MAJOR;
0059 
0060 /*
0061  * This function is called for every new tapedevice
0062  */
0063 int
0064 tapechar_setup_device(struct tape_device * device)
0065 {
0066     char    device_name[20];
0067 
0068     sprintf(device_name, "ntibm%i", device->first_minor / 2);
0069     device->nt = register_tape_dev(
0070         &device->cdev->dev,
0071         MKDEV(tapechar_major, device->first_minor),
0072         &tape_fops,
0073         device_name,
0074         "non-rewinding"
0075     );
0076     device_name[0] = 'r';
0077     device->rt = register_tape_dev(
0078         &device->cdev->dev,
0079         MKDEV(tapechar_major, device->first_minor + 1),
0080         &tape_fops,
0081         device_name,
0082         "rewinding"
0083     );
0084 
0085     return 0;
0086 }
0087 
0088 void
0089 tapechar_cleanup_device(struct tape_device *device)
0090 {
0091     unregister_tape_dev(&device->cdev->dev, device->rt);
0092     device->rt = NULL;
0093     unregister_tape_dev(&device->cdev->dev, device->nt);
0094     device->nt = NULL;
0095 }
0096 
0097 static int
0098 tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
0099 {
0100     struct idal_buffer *new;
0101 
0102     if (device->char_data.idal_buf != NULL &&
0103         device->char_data.idal_buf->size == block_size)
0104         return 0;
0105 
0106     if (block_size > MAX_BLOCKSIZE) {
0107         DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n",
0108             block_size, MAX_BLOCKSIZE);
0109         return -EINVAL;
0110     }
0111 
0112     /* The current idal buffer is not correct. Allocate a new one. */
0113     new = idal_buffer_alloc(block_size, 0);
0114     if (IS_ERR(new))
0115         return -ENOMEM;
0116 
0117     if (device->char_data.idal_buf != NULL)
0118         idal_buffer_free(device->char_data.idal_buf);
0119 
0120     device->char_data.idal_buf = new;
0121 
0122     return 0;
0123 }
0124 
0125 /*
0126  * Tape device read function
0127  */
0128 static ssize_t
0129 tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
0130 {
0131     struct tape_device *device;
0132     struct tape_request *request;
0133     size_t block_size;
0134     int rc;
0135 
0136     DBF_EVENT(6, "TCHAR:read\n");
0137     device = (struct tape_device *) filp->private_data;
0138 
0139     /*
0140      * If the tape isn't terminated yet, do it now. And since we then
0141      * are at the end of the tape there wouldn't be anything to read
0142      * anyways. So we return immediately.
0143      */
0144     if(device->required_tapemarks) {
0145         return tape_std_terminate_write(device);
0146     }
0147 
0148     /* Find out block size to use */
0149     if (device->char_data.block_size != 0) {
0150         if (count < device->char_data.block_size) {
0151             DBF_EVENT(3, "TCHAR:read smaller than block "
0152                   "size was requested\n");
0153             return -EINVAL;
0154         }
0155         block_size = device->char_data.block_size;
0156     } else {
0157         block_size = count;
0158     }
0159 
0160     rc = tapechar_check_idalbuffer(device, block_size);
0161     if (rc)
0162         return rc;
0163 
0164     DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
0165     /* Let the discipline build the ccw chain. */
0166     request = device->discipline->read_block(device, block_size);
0167     if (IS_ERR(request))
0168         return PTR_ERR(request);
0169     /* Execute it. */
0170     rc = tape_do_io(device, request);
0171     if (rc == 0) {
0172         rc = block_size - request->rescnt;
0173         DBF_EVENT(6, "TCHAR:rbytes:  %x\n", rc);
0174         /* Copy data from idal buffer to user space. */
0175         if (idal_buffer_to_user(device->char_data.idal_buf,
0176                     data, rc) != 0)
0177             rc = -EFAULT;
0178     }
0179     tape_free_request(request);
0180     return rc;
0181 }
0182 
0183 /*
0184  * Tape device write function
0185  */
0186 static ssize_t
0187 tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos)
0188 {
0189     struct tape_device *device;
0190     struct tape_request *request;
0191     size_t block_size;
0192     size_t written;
0193     int nblocks;
0194     int i, rc;
0195 
0196     DBF_EVENT(6, "TCHAR:write\n");
0197     device = (struct tape_device *) filp->private_data;
0198     /* Find out block size and number of blocks */
0199     if (device->char_data.block_size != 0) {
0200         if (count < device->char_data.block_size) {
0201             DBF_EVENT(3, "TCHAR:write smaller than block "
0202                   "size was requested\n");
0203             return -EINVAL;
0204         }
0205         block_size = device->char_data.block_size;
0206         nblocks = count / block_size;
0207     } else {
0208         block_size = count;
0209         nblocks = 1;
0210     }
0211 
0212     rc = tapechar_check_idalbuffer(device, block_size);
0213     if (rc)
0214         return rc;
0215 
0216     DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
0217     DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
0218     /* Let the discipline build the ccw chain. */
0219     request = device->discipline->write_block(device, block_size);
0220     if (IS_ERR(request))
0221         return PTR_ERR(request);
0222     rc = 0;
0223     written = 0;
0224     for (i = 0; i < nblocks; i++) {
0225         /* Copy data from user space to idal buffer. */
0226         if (idal_buffer_from_user(device->char_data.idal_buf,
0227                       data, block_size)) {
0228             rc = -EFAULT;
0229             break;
0230         }
0231         rc = tape_do_io(device, request);
0232         if (rc)
0233             break;
0234         DBF_EVENT(6, "TCHAR:wbytes: %lx\n",
0235               block_size - request->rescnt);
0236         written += block_size - request->rescnt;
0237         if (request->rescnt != 0)
0238             break;
0239         data += block_size;
0240     }
0241     tape_free_request(request);
0242     if (rc == -ENOSPC) {
0243         /*
0244          * Ok, the device has no more space. It has NOT written
0245          * the block.
0246          */
0247         if (device->discipline->process_eov)
0248             device->discipline->process_eov(device);
0249         if (written > 0)
0250             rc = 0;
0251 
0252     }
0253 
0254     /*
0255      * After doing a write we always need two tapemarks to correctly
0256      * terminate the tape (one to terminate the file, the second to
0257      * flag the end of recorded data.
0258      * Since process_eov positions the tape in front of the written
0259      * tapemark it doesn't hurt to write two marks again.
0260      */
0261     if (!rc)
0262         device->required_tapemarks = 2;
0263 
0264     return rc ? rc : written;
0265 }
0266 
0267 /*
0268  * Character frontend tape device open function.
0269  */
0270 static int
0271 tapechar_open (struct inode *inode, struct file *filp)
0272 {
0273     struct tape_device *device;
0274     int minor, rc;
0275 
0276     DBF_EVENT(6, "TCHAR:open: %i:%i\n",
0277         imajor(file_inode(filp)),
0278         iminor(file_inode(filp)));
0279 
0280     if (imajor(file_inode(filp)) != tapechar_major)
0281         return -ENODEV;
0282 
0283     minor = iminor(file_inode(filp));
0284     device = tape_find_device(minor / TAPE_MINORS_PER_DEV);
0285     if (IS_ERR(device)) {
0286         DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n");
0287         return PTR_ERR(device);
0288     }
0289 
0290     rc = tape_open(device);
0291     if (rc == 0) {
0292         filp->private_data = device;
0293         stream_open(inode, filp);
0294     } else
0295         tape_put_device(device);
0296 
0297     return rc;
0298 }
0299 
0300 /*
0301  * Character frontend tape device release function.
0302  */
0303 
0304 static int
0305 tapechar_release(struct inode *inode, struct file *filp)
0306 {
0307     struct tape_device *device;
0308 
0309     DBF_EVENT(6, "TCHAR:release: %x\n", iminor(inode));
0310     device = (struct tape_device *) filp->private_data;
0311 
0312     /*
0313      * If this is the rewinding tape minor then rewind. In that case we
0314      * write all required tapemarks. Otherwise only one to terminate the
0315      * file.
0316      */
0317     if ((iminor(inode) & 1) != 0) {
0318         if (device->required_tapemarks)
0319             tape_std_terminate_write(device);
0320         tape_mtop(device, MTREW, 1);
0321     } else {
0322         if (device->required_tapemarks > 1) {
0323             if (tape_mtop(device, MTWEOF, 1) == 0)
0324                 device->required_tapemarks--;
0325         }
0326     }
0327 
0328     if (device->char_data.idal_buf != NULL) {
0329         idal_buffer_free(device->char_data.idal_buf);
0330         device->char_data.idal_buf = NULL;
0331     }
0332     tape_release(device);
0333     filp->private_data = NULL;
0334     tape_put_device(device);
0335 
0336     return 0;
0337 }
0338 
0339 /*
0340  * Tape device io controls.
0341  */
0342 static int
0343 __tapechar_ioctl(struct tape_device *device,
0344          unsigned int no, void __user *data)
0345 {
0346     int rc;
0347 
0348     if (no == MTIOCTOP) {
0349         struct mtop op;
0350 
0351         if (copy_from_user(&op, data, sizeof(op)) != 0)
0352             return -EFAULT;
0353         if (op.mt_count < 0)
0354             return -EINVAL;
0355 
0356         /*
0357          * Operations that change tape position should write final
0358          * tapemarks.
0359          */
0360         switch (op.mt_op) {
0361             case MTFSF:
0362             case MTBSF:
0363             case MTFSR:
0364             case MTBSR:
0365             case MTREW:
0366             case MTOFFL:
0367             case MTEOM:
0368             case MTRETEN:
0369             case MTBSFM:
0370             case MTFSFM:
0371             case MTSEEK:
0372                 if (device->required_tapemarks)
0373                     tape_std_terminate_write(device);
0374         }
0375         rc = tape_mtop(device, op.mt_op, op.mt_count);
0376 
0377         if (op.mt_op == MTWEOF && rc == 0) {
0378             if (op.mt_count > device->required_tapemarks)
0379                 device->required_tapemarks = 0;
0380             else
0381                 device->required_tapemarks -= op.mt_count;
0382         }
0383         return rc;
0384     }
0385     if (no == MTIOCPOS) {
0386         /* MTIOCPOS: query the tape position. */
0387         struct mtpos pos;
0388 
0389         rc = tape_mtop(device, MTTELL, 1);
0390         if (rc < 0)
0391             return rc;
0392         pos.mt_blkno = rc;
0393         return put_user_mtpos(data, &pos);
0394     }
0395     if (no == MTIOCGET) {
0396         /* MTIOCGET: query the tape drive status. */
0397         struct mtget get;
0398 
0399         memset(&get, 0, sizeof(get));
0400         get.mt_type = MT_ISUNKNOWN;
0401         get.mt_resid = 0 /* device->devstat.rescnt */;
0402         get.mt_dsreg =
0403             ((device->char_data.block_size << MT_ST_BLKSIZE_SHIFT)
0404              & MT_ST_BLKSIZE_MASK);
0405         /* FIXME: mt_gstat, mt_erreg, mt_fileno */
0406         get.mt_gstat = 0;
0407         get.mt_erreg = 0;
0408         get.mt_fileno = 0;
0409         get.mt_gstat  = device->tape_generic_status;
0410 
0411         if (device->medium_state == MS_LOADED) {
0412             rc = tape_mtop(device, MTTELL, 1);
0413 
0414             if (rc < 0)
0415                 return rc;
0416 
0417             if (rc == 0)
0418                 get.mt_gstat |= GMT_BOT(~0);
0419 
0420             get.mt_blkno = rc;
0421         }
0422 
0423         return put_user_mtget(data, &get);
0424     }
0425     /* Try the discipline ioctl function. */
0426     if (device->discipline->ioctl_fn == NULL)
0427         return -EINVAL;
0428     return device->discipline->ioctl_fn(device, no, (unsigned long)data);
0429 }
0430 
0431 static long
0432 tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data)
0433 {
0434     struct tape_device *device;
0435     long rc;
0436 
0437     DBF_EVENT(6, "TCHAR:ioct\n");
0438 
0439     device = (struct tape_device *) filp->private_data;
0440     mutex_lock(&device->mutex);
0441     rc = __tapechar_ioctl(device, no, (void __user *)data);
0442     mutex_unlock(&device->mutex);
0443     return rc;
0444 }
0445 
0446 #ifdef CONFIG_COMPAT
0447 static long
0448 tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
0449 {
0450     struct tape_device *device = filp->private_data;
0451     long rc;
0452 
0453     if (no == MTIOCPOS32)
0454         no = MTIOCPOS;
0455     else if (no == MTIOCGET32)
0456         no = MTIOCGET;
0457 
0458     mutex_lock(&device->mutex);
0459     rc = __tapechar_ioctl(device, no, compat_ptr(data));
0460     mutex_unlock(&device->mutex);
0461     return rc;
0462 }
0463 #endif /* CONFIG_COMPAT */
0464 
0465 /*
0466  * Initialize character device frontend.
0467  */
0468 int
0469 tapechar_init (void)
0470 {
0471     dev_t   dev;
0472 
0473     if (alloc_chrdev_region(&dev, 0, 256, "tape") != 0)
0474         return -1;
0475 
0476     tapechar_major = MAJOR(dev);
0477 
0478     return 0;
0479 }
0480 
0481 /*
0482  * cleanup
0483  */
0484 void
0485 tapechar_exit(void)
0486 {
0487     unregister_chrdev_region(MKDEV(tapechar_major, 0), 256);
0488 }