b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * File operations for Coda.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) * Original version: (C) 1996 Peter Braam
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * Carnegie Mellon encourages users of this code to contribute improvements
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/types.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/time.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) #include <linux/stat.h>
7596b27dbd8de (Randy Dunlap 2008-11-19 11:30:27 -0800 17) #include <linux/cred.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) #include <linux/errno.h>
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 19) #include <linux/spinlock.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) #include <linux/string.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 21) #include <linux/slab.h>
834b46c37a290 (Fabian Frederick 2014-08-08 14:20:33 -0700 22) #include <linux/uaccess.h>
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 23) #include <linux/uio.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25) #include <linux/coda.h>
8fc8b9df83138 (David Howells 2019-07-16 16:28:47 -0700 26) #include "coda_psdev.h"
31a203df9c109 (Al Viro 2011-01-12 16:36:09 -0500 27) #include "coda_linux.h"
c98d8cfbc600a (Adrian Bunk 2006-03-24 03:15:53 -0800 28) #include "coda_int.h"
c98d8cfbc600a (Adrian Bunk 2006-03-24 03:15:53 -0800 29)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 30) struct coda_vm_ops {
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 31) atomic_t refcnt;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 32) struct file *coda_file;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 33) const struct vm_operations_struct *host_vm_ops;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 34) struct vm_operations_struct vm_ops;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 35) };
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 36)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37) static ssize_t
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 38) coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) {
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 40) struct file *coda_file = iocb->ki_filp;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 41) struct inode *coda_inode = file_inode(coda_file);
5bb44810f47a0 (Fabian Frederick 2019-07-16 16:29:09 -0700 42) struct coda_file_info *cfi = coda_ftoc(coda_file);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 43) loff_t ki_pos = iocb->ki_pos;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 44) size_t count = iov_iter_count(to);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 45) ssize_t ret;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 46)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 47) ret = venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 48) &cfi->cfi_access_intent,
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 49) count, ki_pos, CODA_ACCESS_TYPE_READ);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 50) if (ret)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 51) goto finish_read;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 52)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 53) ret = vfs_iter_read(cfi->cfi_container, to, &iocb->ki_pos, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 55) finish_read:
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 56) venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 57) &cfi->cfi_access_intent,
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 58) count, ki_pos, CODA_ACCESS_TYPE_READ_FINISH);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 59) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) static ssize_t
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 63) coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) {
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 65) struct file *coda_file = iocb->ki_filp;
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 66) struct inode *coda_inode = file_inode(coda_file);
5bb44810f47a0 (Fabian Frederick 2019-07-16 16:29:09 -0700 67) struct coda_file_info *cfi = coda_ftoc(coda_file);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 68) struct file *host_file = cfi->cfi_container;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 69) loff_t ki_pos = iocb->ki_pos;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 70) size_t count = iov_iter_count(to);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 73) ret = venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 74) &cfi->cfi_access_intent,
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 75) count, ki_pos, CODA_ACCESS_TYPE_WRITE);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 76) if (ret)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 77) goto finish_write;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 78)
03d95eb2f2578 (Al Viro 2013-03-20 13:04:20 -0400 79) file_start_write(host_file);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 80) inode_lock(coda_inode);
abbb65899aecf (Christoph Hellwig 2017-05-27 11:16:52 +0300 81) ret = vfs_iter_write(cfi->cfi_container, to, &iocb->ki_pos, 0);
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 82) coda_inode->i_size = file_inode(host_file)->i_size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 83) coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 84) coda_inode->i_mtime = coda_inode->i_ctime = current_time(coda_inode);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 85) inode_unlock(coda_inode);
03d95eb2f2578 (Al Viro 2013-03-20 13:04:20 -0400 86) file_end_write(host_file);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 87)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 88) finish_write:
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 89) venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 90) &cfi->cfi_access_intent,
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 91) count, ki_pos, CODA_ACCESS_TYPE_WRITE_FINISH);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 92) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 93) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 94)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 95) static void
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 96) coda_vm_open(struct vm_area_struct *vma)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 97) {
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 98) struct coda_vm_ops *cvm_ops =
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 99) container_of(vma->vm_ops, struct coda_vm_ops, vm_ops);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 100)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 101) atomic_inc(&cvm_ops->refcnt);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 102)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 103) if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->open)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 104) cvm_ops->host_vm_ops->open(vma);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 105) }
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 106)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 107) static void
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 108) coda_vm_close(struct vm_area_struct *vma)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 109) {
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 110) struct coda_vm_ops *cvm_ops =
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 111) container_of(vma->vm_ops, struct coda_vm_ops, vm_ops);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 112)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 113) if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->close)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 114) cvm_ops->host_vm_ops->close(vma);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 115)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 116) if (atomic_dec_and_test(&cvm_ops->refcnt)) {
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 117) vma->vm_ops = cvm_ops->host_vm_ops;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 118) fput(cvm_ops->coda_file);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 119) kfree(cvm_ops);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 120) }
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 121) }
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 122)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 123) static int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 124) coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 125) {
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 126) struct inode *coda_inode = file_inode(coda_file);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 127) struct coda_file_info *cfi = coda_ftoc(coda_file);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 128) struct file *host_file = cfi->cfi_container;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 129) struct inode *host_inode = file_inode(host_file);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130) struct coda_inode_info *cii;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 131) struct coda_vm_ops *cvm_ops;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 132) loff_t ppos;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 133) size_t count;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 134) int ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 135)
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 136) if (!host_file->f_op->mmap)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 137) return -ENODEV;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 138)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 139) if (WARN_ON(coda_file != vma->vm_file))
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 140) return -EIO;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 141)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 142) count = vma->vm_end - vma->vm_start;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 143) ppos = vma->vm_pgoff * PAGE_SIZE;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 144)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 145) ret = venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 146) &cfi->cfi_access_intent,
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 147) count, ppos, CODA_ACCESS_TYPE_MMAP);
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 148) if (ret)
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 149) return ret;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 150)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 151) cvm_ops = kmalloc(sizeof(struct coda_vm_ops), GFP_KERNEL);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 152) if (!cvm_ops)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 153) return -ENOMEM;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 154)
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 155) cii = ITOC(coda_inode);
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 156) spin_lock(&cii->c_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157) coda_file->f_mapping = host_file->f_mapping;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 158) if (coda_inode->i_mapping == &coda_inode->i_data)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 159) coda_inode->i_mapping = host_inode->i_mapping;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 161) /* only allow additional mmaps as long as userspace isn't changing
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 162) * the container file on us! */
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 163) else if (coda_inode->i_mapping != host_inode->i_mapping) {
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 164) spin_unlock(&cii->c_lock);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 165) kfree(cvm_ops);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166) return -EBUSY;
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 167) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169) /* keep track of how often the coda_inode/host_file has been mmapped */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170) cii->c_mapcount++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 171) cfi->cfi_mapcount++;
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 172) spin_unlock(&cii->c_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 174) vma->vm_file = get_file(host_file);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 175) ret = call_mmap(vma->vm_file, vma);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 176)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 177) if (ret) {
9da29c7f77cd0 (Christian König 2021-04-23 14:28:51 -0700 178) /* if call_mmap fails, our caller will put host_file so we
9da29c7f77cd0 (Christian König 2021-04-23 14:28:51 -0700 179) * should drop the reference to the coda_file that we got.
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 180) */
9da29c7f77cd0 (Christian König 2021-04-23 14:28:51 -0700 181) fput(coda_file);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 182) kfree(cvm_ops);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 183) } else {
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 184) /* here we add redirects for the open/close vm_operations */
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 185) cvm_ops->host_vm_ops = vma->vm_ops;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 186) if (vma->vm_ops)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 187) cvm_ops->vm_ops = *vma->vm_ops;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 188)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 189) cvm_ops->vm_ops.open = coda_vm_open;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 190) cvm_ops->vm_ops.close = coda_vm_close;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 191) cvm_ops->coda_file = coda_file;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 192) atomic_set(&cvm_ops->refcnt, 1);
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 193)
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 194) vma->vm_ops = &cvm_ops->vm_ops;
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 195) }
7fa0a1da3dadf (Jan Harkes 2019-07-16 16:28:04 -0700 196) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 197) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 199) int coda_open(struct inode *coda_inode, struct file *coda_file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 200) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201) struct file *host_file = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) unsigned short flags = coda_file->f_flags & (~O_EXCL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204) unsigned short coda_flags = coda_flags_to_cflags(flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 205) struct coda_file_info *cfi;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 206)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207) cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
6ecbc4e1a3950 (Josh Triplett 2006-07-30 03:03:56 -0700 208) if (!cfi)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 210)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 211) error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
38c2e4370da49 (Jan Harkes 2007-07-19 01:48:41 -0700 212) &host_file);
38c2e4370da49 (Jan Harkes 2007-07-19 01:48:41 -0700 213) if (!host_file)
38c2e4370da49 (Jan Harkes 2007-07-19 01:48:41 -0700 214) error = -EIO;
38c2e4370da49 (Jan Harkes 2007-07-19 01:48:41 -0700 215)
38c2e4370da49 (Jan Harkes 2007-07-19 01:48:41 -0700 216) if (error) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) kfree(cfi);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 219) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) cfi->cfi_magic = CODA_MAGIC;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224) cfi->cfi_mapcount = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225) cfi->cfi_container = host_file;
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 226) /* assume access intents are supported unless we hear otherwise */
a9fba24c6ac9b (Pedro Cuadra 2019-07-16 16:29:13 -0700 227) cfi->cfi_access_intent = true;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 228)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229) BUG_ON(coda_file->private_data != NULL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 230) coda_file->private_data = cfi;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 231) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 232) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234) int coda_release(struct inode *coda_inode, struct file *coda_file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) unsigned short flags = (coda_file->f_flags) & (~O_EXCL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) unsigned short coda_flags = coda_flags_to_cflags(flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 238) struct coda_file_info *cfi;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 239) struct coda_inode_info *cii;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) struct inode *host_inode;
f7cc02b871561 (Yoshihisa Abe 2010-10-25 02:03:45 -0400 241) int err;
3cf01f28c303b (Jan Harkes 2007-07-19 01:48:51 -0700 242)
5bb44810f47a0 (Fabian Frederick 2019-07-16 16:29:09 -0700 243) cfi = coda_ftoc(coda_file);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244)
d3fec424b23c4 (Jan Harkes 2007-07-21 04:37:26 -0700 245) err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
d76b0d9b2d87c (David Howells 2008-11-14 10:39:25 +1100 246) coda_flags, coda_file->f_cred->fsuid);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 247)
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 248) host_inode = file_inode(cfi->cfi_container);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 249) cii = ITOC(coda_inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 250)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 251) /* did we mmap this file? */
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 252) spin_lock(&cii->c_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 253) if (coda_inode->i_mapping == &host_inode->i_data) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 254) cii->c_mapcount -= cfi->cfi_mapcount;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255) if (!cii->c_mapcount)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) coda_inode->i_mapping = &coda_inode->i_data;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 257) }
b5ce1d83a62fc (Yoshihisa Abe 2010-10-25 02:03:44 -0400 258) spin_unlock(&cii->c_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 259)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 260) fput(cfi->cfi_container);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 261) kfree(coda_file->private_data);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262) coda_file->private_data = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263)
d3fec424b23c4 (Jan Harkes 2007-07-21 04:37:26 -0700 264) /* VFS fput ignores the return value from file_operations->release, so
d3fec424b23c4 (Jan Harkes 2007-07-21 04:37:26 -0700 265) * there is no use returning an error here */
d3fec424b23c4 (Jan Harkes 2007-07-21 04:37:26 -0700 266) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 269) int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 271) struct file *host_file;
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 272) struct inode *coda_inode = file_inode(coda_file);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 273) struct coda_file_info *cfi;
f7cc02b871561 (Yoshihisa Abe 2010-10-25 02:03:45 -0400 274) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277) S_ISLNK(coda_inode->i_mode)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 278) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 279)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 280) err = filemap_write_and_wait_range(coda_inode->i_mapping, start, end);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 281) if (err)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 282) return err;
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 283) inode_lock(coda_inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 284)
5bb44810f47a0 (Fabian Frederick 2019-07-16 16:29:09 -0700 285) cfi = coda_ftoc(coda_file);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 286) host_file = cfi->cfi_container;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 287)
8018ab0574809 (Christoph Hellwig 2010-03-22 17:32:25 +0100 288) err = vfs_fsync(host_file, datasync);
f7cc02b871561 (Yoshihisa Abe 2010-10-25 02:03:45 -0400 289) if (!err && !datasync)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 290) err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 291) inode_unlock(coda_inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 295)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 296) const struct file_operations coda_file_operations = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 297) .llseek = generic_file_llseek,
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 298) .read_iter = coda_file_read_iter,
c12c49e70218e (Al Viro 2015-04-03 10:58:11 -0400 299) .write_iter = coda_file_write_iter,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 300) .mmap = coda_file_mmap,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 301) .open = coda_open,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 302) .release = coda_release,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 303) .fsync = coda_fsync,
82c156f853840 (Al Viro 2016-09-22 23:35:42 -0400 304) .splice_read = generic_file_splice_read,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305) };