Changes in 4.9.187 MIPS: ath79: fix ar933x uart parity mode MIPS: fix build on non-linux hosts arm64/efi: Mark __efistub_stext_offset as an absolute symbol explicitly dmaengine: imx-sdma: fix use-after-free on probe error path ath10k: Do not send probe response template for mesh ath9k: Check for errors when reading SREV register ath6kl: add some bounds checking ath: DFS JP domain W56 fixed pulse type 3 RADAR detection batman-adv: fix for leaked TVLV handler. media: dvb: usb: fix use after free in dvb_usb_device_exit crypto: talitos - fix skcipher failure due to wrong output IV media: marvell-ccic: fix DMA s/g desc number calculation media: vpss: fix a potential NULL pointer dereference media: media_device_enum_links32: clean a reserved field net: stmmac: dwmac1000: Clear unused address entries net: stmmac: dwmac4/5: Clear unused address entries signal/pid_namespace: Fix reboot_pid_ns to use send_sig not force_sig af_key: fix leaks in key_pol_get_resp and dump_sp. xfrm: Fix xfrm sel prefix length validation media: mc-device.c: don't memset __user pointer contents media: staging: media: davinci_vpfe: - Fix for memory leak if decoder initialization fails. net: phy: Check against net_device being NULL crypto: talitos - properly handle split ICV. crypto: talitos - Align SEC1 accesses to 32 bits boundaries. tua6100: Avoid build warnings. locking/lockdep: Fix merging of hlocks with non-zero references media: wl128x: Fix some error handling in fm_v4l2_init_video_device() cpupower : frequency-set -r option misses the last cpu in related cpu list net: fec: Do not use netdev messages too early net: axienet: Fix race condition causing TX hang s390/qdio: handle PENDING state for QEBSM devices perf cs-etm: Properly set the value of 'old' and 'head' in snapshot mode perf test 6: Fix missing kvm module load for s390 gpio: omap: fix lack of irqstatus_raw0 for OMAP4 gpio: omap: ensure irq is enabled before wakeup regmap: fix bulk writes on paged registers bpf: silence warning messages in core rcu: Force inlining of rcu_read_lock() blkcg, writeback: dead memcgs shouldn't contribute to writeback ownership arbitration xfrm: fix sa selector validation perf evsel: Make perf_evsel__name() accept a NULL argument vhost_net: disable zerocopy by default ipoib: correcly show a VF hardware address EDAC/sysfs: Fix memory leak when creating a csrow object ipsec: select crypto ciphers for xfrm_algo media: i2c: fix warning same module names ntp: Limit TAI-UTC offset timer_list: Guard procfs specific code acpi/arm64: ignore 5.1 FADTs that are reported as 5.0 media: coda: fix mpeg2 sequence number handling media: coda: increment sequence offset for the last returned frame mt7601u: do not schedule rx_tasklet when the device has been disconnected x86/build: Add 'set -e' to mkcapflags.sh to delete broken capflags.c mt7601u: fix possible memory leak when the device is disconnected ath10k: fix PCIE device wake up failed perf tools: Increase MAX_NR_CPUS and MAX_CACHES libata: don't request sense data on !ZAC ATA devices clocksource/drivers/exynos_mct: Increase priority over ARM arch timer rslib: Fix decoding of shortened codes rslib: Fix handling of of caller provided syndrome ixgbe: Check DDM existence in transceiver before access crypto: asymmetric_keys - select CRYPTO_HASH where needed EDAC: Fix global-out-of-bounds write when setting edac_mc_poll_msec bcache: check c->gc_thread by IS_ERR_OR_NULL in cache_set_flush() iwlwifi: mvm: Drop large non sta frames net: usb: asix: init MAC address buffers gpiolib: Fix references to gpiod_[gs]et_*value_cansleep() variants Bluetooth: hci_bcsp: Fix memory leak in rx_skb Bluetooth: 6lowpan: search for destination address in all peers Bluetooth: Check state in l2cap_disconnect_rsp Bluetooth: validate BLE connection interval updates gtp: fix Illegal context switch in RCU read-side critical section. gtp: fix use-after-free in gtp_newlink() xen: let alloc_xenballooned_pages() fail if not enough memory free scsi: NCR5380: Reduce goto statements in NCR5380_select() scsi: NCR5380: Always re-enable reselection interrupt scsi: mac_scsi: Increase PIO/PDMA transfer length threshold crypto: ghash - fix unaligned memory access in ghash_setkey() crypto: arm64/sha1-ce - correct digest for empty data in finup crypto: arm64/sha2-ce - correct digest for empty data in finup crypto: chacha20poly1305 - fix atomic sleep when using async algorithm crypto: crypto4xx - fix a potential double free in ppc4xx_trng_probe Input: gtco - bounds check collection indent level regulator: s2mps11: Fix buck7 and buck8 wrong voltages arm64: tegra: Update Jetson TX1 GPU regulator timings iwlwifi: pcie: don't service an interrupt that was masked tracing/snapshot: Resize spare buffer if size changed NFSv4: Handle the special Linux file open access mode lib/scatterlist: Fix mapping iterator when sg->offset is greater than PAGE_SIZE ALSA: seq: Break too long mutex context in the write loop ALSA: hda/realtek: apply ALC891 headset fixup to one Dell machine media: v4l2: Test type instead of cfg->type in v4l2_ctrl_new_custom() media: coda: Remove unbalanced and unneeded mutex unlock KVM: x86/vPMU: refine kvm_pmu err msg when event creation failed arm64: tegra: Fix AGIC register range fs/proc/proc_sysctl.c: fix the default values of i_uid/i_gid on /proc/sys inodes. drm/nouveau/i2c: Enable i2c pads & busses during preinit padata: use smp_mb in padata_reorder to avoid orphaned padata jobs 9p/virtio: Add cleanup path in p9_virtio_init PCI: Do not poll for PME if the device is in D3cold Btrfs: add missing inode version, ctime and mtime updates when punching hole libnvdimm/pfn: fix fsdax-mode namespace info-block zero-fields take floppy compat ioctls to sodding floppy.c floppy: fix div-by-zero in setup_format_params floppy: fix out-of-bounds read in next_valid_format floppy: fix invalid pointer dereference in drive_name floppy: fix out-of-bounds read in copy_buffer coda: pass the host file in vma->vm_file on mmap gpu: ipu-v3: ipu-ic: Fix saturation bit offset in TPMEM crypto: ccp - Validate the the error value used to index error messages PCI: hv: Delete the device earlier from hbus->children for hot-remove PCI: hv: Fix a use-after-free bug in hv_eject_device_work() crypto: caam - limit output IV to CBC to work around CTR mode DMA issue um: Allow building and running on older hosts um: Fix FP register size for XSTATE/XSAVE parisc: Ensure userspace privilege for ptraced processes in regset functions parisc: Fix kernel panic due invalid values in IAOQ0 or IAOQ1 powerpc/32s: fix suspend/resume when IBATs 4-7 are used powerpc/watchpoint: Restore NV GPRs while returning from exception eCryptfs: fix a couple type promotion bugs intel_th: msu: Fix single mode with disabled IOMMU Bluetooth: Add SMP workaround Microsoft Surface Precision Mouse bug usb: Handle USB3 remote wakeup for LPM enabled devices correctly dm bufio: fix deadlock with loop device compiler.h, kasan: Avoid duplicating __read_once_size_nocheck() compiler.h: Add read_word_at_a_time() function. lib/strscpy: Shut up KASAN false-positives in strscpy() ext4: allow directory holes bnx2x: Prevent load reordering in tx completion processing bnx2x: Prevent ptp_task to be rescheduled indefinitely caif-hsi: fix possible deadlock in cfhsi_exit_module() igmp: fix memory leak in igmpv3_del_delrec() ipv4: don't set IPv6 only flags to IPv4 addresses net: bcmgenet: use promisc for unsupported filters net: dsa: mv88e6xxx: wait after reset deactivation net: neigh: fix multiple neigh timer scheduling net: openvswitch: fix csum updates for MPLS actions nfc: fix potential illegal memory access rxrpc: Fix send on a connected, but unbound socket sky2: Disable MSI on ASUS P6T vrf: make sure skb->data contains ip header to make routing macsec: fix use-after-free of skb during RX macsec: fix checksumming after decryption netrom: fix a memory leak in nr_rx_frame() netrom: hold sock when setting skb->destructor bonding: validate ip header before check IPPROTO_IGMP tcp: Reset bytes_acked and bytes_received when disconnecting net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling net: bridge: mcast: fix stale ipv6 hdr pointer when handling v6 query net: bridge: stp: don't cache eth dest pointer before skb pull perf/x86/amd/uncore: Rename 'L2' to 'LLC' perf/x86/amd/uncore: Get correct number of cores sharing last level cache perf/events/amd/uncore: Fix amd_uncore_llc ID to use pre-defined cpu_llc_id NFSv4: Fix open create exclusive when the server reboots nfsd: increase DRC cache limit nfsd: give out fewer session slots as limit approaches nfsd: fix performance-limiting session calculation nfsd: Fix overflow causing non-working mounts on 1 TB machines drm/panel: simple: Fix panel_simple_dsi_probe usb: core: hub: Disable hub-initiated U1/U2 tty: max310x: Fix invalid baudrate divisors calculator pinctrl: rockchip: fix leaked of_node references tty: serial: cpm_uart - fix init when SMC is relocated drm/bridge: tc358767: read display_props in get_modes() drm/bridge: sii902x: pixel clock unit is 10kHz instead of 1kHz memstick: Fix error cleanup path of memstick_init tty/serial: digicolor: Fix digicolor-usart already registered warning tty: serial: msm_serial: avoid system lockup condition serial: 8250: Fix TX interrupt handling condition drm/virtio: Add memory barriers for capset cache. phy: renesas: rcar-gen2: Fix memory leak at error paths drm/rockchip: Properly adjust to a true clock in adjusted_mode tty: serial_core: Set port active bit in uart_port_activate usb: gadget: Zero ffs_io_data powerpc/pci/of: Fix OF flags parsing for 64bit BARs PCI: sysfs: Ignore lockdep for remove attribute kbuild: Add -Werror=unknown-warning-option to CLANG_FLAGS PCI: xilinx-nwl: Fix Multi MSI data programming iio: iio-utils: Fix possible incorrect mask calculation recordmcount: Fix spurious mcount entries on powerpc mfd: core: Set fwnode for created devices mfd: arizona: Fix undefined behavior mfd: hi655x-pmic: Fix missing return value check for devm_regmap_init_mmio_clk um: Silence lockdep complaint about mmap_sem powerpc/4xx/uic: clear pending interrupt after irq type/pol change RDMA/i40iw: Set queue pair state when being queried serial: sh-sci: Terminate TX DMA during buffer flushing serial: sh-sci: Fix TX DMA buffer flushing and workqueue races kallsyms: exclude kasan local symbols on s390 perf test mmap-thread-lookup: Initialize variable to suppress memory sanitizer warning RDMA/rxe: Fill in wc byte_len with IB_WC_RECV_RDMA_WITH_IMM powerpc/boot: add {get, put}_unaligned_be32 to xz_config.h f2fs: avoid out-of-range memory access mailbox: handle failed named mailbox channel request powerpc/eeh: Handle hugepages in ioremap space sh: prevent warnings when using iounmap mm/kmemleak.c: fix check for softirq context 9p: pass the correct prototype to read_cache_page mm/mmu_notifier: use hlist_add_head_rcu() locking/lockdep: Fix lock used or unused stats error locking/lockdep: Hide unused 'class' variable usb: wusbcore: fix unbalanced get/put cluster_id usb: pci-quirks: Correct AMD PLL quirk detection x86/sysfb_efi: Add quirks for some devices with swapped width and height x86/speculation/mds: Apply more accurate check on hypervisor platform hpet: Fix division by zero in hpet_time_div() ALSA: line6: Fix wrong altsetting for LINE6_PODHD500_1 ALSA: hda - Add a conexant codec entry to let mute led work powerpc/tm: Fix oops on sigreturn on systems without TM access: avoid the RCU grace period for the temporary subjective credentials ipv6: check sk sk_type and protocol early in ip_mroute_set/getsockopt tcp: reset sk_send_head in tcp_write_queue_purge arm64: dts: marvell: Fix A37xx UART0 register size i2c: qup: fixed releasing dma without flush operation completion arm64: compat: Provide definition for COMPAT_SIGMINSTKSZ ISDN: hfcsusb: checking idx of ep configuration media: au0828: fix null dereference in error path media: cpia2_usb: first wake up, then free in disconnect media: radio-raremono: change devm_k*alloc to k*alloc Bluetooth: hci_uart: check for missing tty operations sched/fair: Don't free p->numa_faults with concurrent readers drivers/pps/pps.c: clear offset flags in PPS_SETPARAMS ioctl ceph: hold i_ceph_lock when removing caps for freeing inode Linux 4.9.187 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
277 lines
6.9 KiB
C
277 lines
6.9 KiB
C
/*
|
|
* File operations for Coda.
|
|
* Original version: (C) 1996 Peter Braam
|
|
* Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
|
|
*
|
|
* Carnegie Mellon encourages users of this code to contribute improvements
|
|
* to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/time.h>
|
|
#include <linux/file.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/cred.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/string.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#include <linux/coda.h>
|
|
#include <linux/coda_psdev.h>
|
|
|
|
#include "coda_linux.h"
|
|
#include "coda_int.h"
|
|
|
|
static ssize_t
|
|
coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
|
{
|
|
struct file *coda_file = iocb->ki_filp;
|
|
struct coda_file_info *cfi = CODA_FTOC(coda_file);
|
|
|
|
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
|
|
|
|
return vfs_iter_read(cfi->cfi_container, to, &iocb->ki_pos);
|
|
}
|
|
|
|
static ssize_t
|
|
coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
|
|
{
|
|
struct file *coda_file = iocb->ki_filp;
|
|
struct inode *coda_inode = file_inode(coda_file);
|
|
struct coda_file_info *cfi = CODA_FTOC(coda_file);
|
|
struct file *host_file;
|
|
ssize_t ret;
|
|
|
|
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
|
|
|
|
host_file = cfi->cfi_container;
|
|
file_start_write(host_file);
|
|
inode_lock(coda_inode);
|
|
ret = vfs_iter_write(cfi->cfi_container, to, &iocb->ki_pos);
|
|
coda_inode->i_size = file_inode(host_file)->i_size;
|
|
coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
|
|
coda_inode->i_mtime = coda_inode->i_ctime = current_time(coda_inode);
|
|
inode_unlock(coda_inode);
|
|
file_end_write(host_file);
|
|
return ret;
|
|
}
|
|
|
|
struct coda_vm_ops {
|
|
atomic_t refcnt;
|
|
struct file *coda_file;
|
|
const struct vm_operations_struct *host_vm_ops;
|
|
struct vm_operations_struct vm_ops;
|
|
};
|
|
|
|
static void
|
|
coda_vm_open(struct vm_area_struct *vma)
|
|
{
|
|
struct coda_vm_ops *cvm_ops =
|
|
container_of(vma->vm_ops, struct coda_vm_ops, vm_ops);
|
|
|
|
atomic_inc(&cvm_ops->refcnt);
|
|
|
|
if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->open)
|
|
cvm_ops->host_vm_ops->open(vma);
|
|
}
|
|
|
|
static void
|
|
coda_vm_close(struct vm_area_struct *vma)
|
|
{
|
|
struct coda_vm_ops *cvm_ops =
|
|
container_of(vma->vm_ops, struct coda_vm_ops, vm_ops);
|
|
|
|
if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->close)
|
|
cvm_ops->host_vm_ops->close(vma);
|
|
|
|
if (atomic_dec_and_test(&cvm_ops->refcnt)) {
|
|
vma->vm_ops = cvm_ops->host_vm_ops;
|
|
fput(cvm_ops->coda_file);
|
|
kfree(cvm_ops);
|
|
}
|
|
}
|
|
|
|
static int
|
|
coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
|
|
{
|
|
struct coda_file_info *cfi;
|
|
struct coda_inode_info *cii;
|
|
struct file *host_file;
|
|
struct inode *coda_inode, *host_inode;
|
|
struct coda_vm_ops *cvm_ops;
|
|
int ret;
|
|
|
|
cfi = CODA_FTOC(coda_file);
|
|
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
|
|
host_file = cfi->cfi_container;
|
|
|
|
if (!host_file->f_op->mmap)
|
|
return -ENODEV;
|
|
|
|
if (WARN_ON(coda_file != vma->vm_file))
|
|
return -EIO;
|
|
|
|
cvm_ops = kmalloc(sizeof(struct coda_vm_ops), GFP_KERNEL);
|
|
if (!cvm_ops)
|
|
return -ENOMEM;
|
|
|
|
coda_inode = file_inode(coda_file);
|
|
host_inode = file_inode(host_file);
|
|
|
|
cii = ITOC(coda_inode);
|
|
spin_lock(&cii->c_lock);
|
|
coda_file->f_mapping = host_file->f_mapping;
|
|
if (coda_inode->i_mapping == &coda_inode->i_data)
|
|
coda_inode->i_mapping = host_inode->i_mapping;
|
|
|
|
/* only allow additional mmaps as long as userspace isn't changing
|
|
* the container file on us! */
|
|
else if (coda_inode->i_mapping != host_inode->i_mapping) {
|
|
spin_unlock(&cii->c_lock);
|
|
kfree(cvm_ops);
|
|
return -EBUSY;
|
|
}
|
|
|
|
/* keep track of how often the coda_inode/host_file has been mmapped */
|
|
cii->c_mapcount++;
|
|
cfi->cfi_mapcount++;
|
|
spin_unlock(&cii->c_lock);
|
|
|
|
vma->vm_file = get_file(host_file);
|
|
ret = host_file->f_op->mmap(host_file, vma);
|
|
|
|
if (ret) {
|
|
/* if call_mmap fails, our caller will put coda_file so we
|
|
* should drop the reference to the host_file that we got.
|
|
*/
|
|
fput(host_file);
|
|
kfree(cvm_ops);
|
|
} else {
|
|
/* here we add redirects for the open/close vm_operations */
|
|
cvm_ops->host_vm_ops = vma->vm_ops;
|
|
if (vma->vm_ops)
|
|
cvm_ops->vm_ops = *vma->vm_ops;
|
|
|
|
cvm_ops->vm_ops.open = coda_vm_open;
|
|
cvm_ops->vm_ops.close = coda_vm_close;
|
|
cvm_ops->coda_file = coda_file;
|
|
atomic_set(&cvm_ops->refcnt, 1);
|
|
|
|
vma->vm_ops = &cvm_ops->vm_ops;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int coda_open(struct inode *coda_inode, struct file *coda_file)
|
|
{
|
|
struct file *host_file = NULL;
|
|
int error;
|
|
unsigned short flags = coda_file->f_flags & (~O_EXCL);
|
|
unsigned short coda_flags = coda_flags_to_cflags(flags);
|
|
struct coda_file_info *cfi;
|
|
|
|
cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
|
|
if (!cfi)
|
|
return -ENOMEM;
|
|
|
|
error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
|
|
&host_file);
|
|
if (!host_file)
|
|
error = -EIO;
|
|
|
|
if (error) {
|
|
kfree(cfi);
|
|
return error;
|
|
}
|
|
|
|
host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC);
|
|
|
|
cfi->cfi_magic = CODA_MAGIC;
|
|
cfi->cfi_mapcount = 0;
|
|
cfi->cfi_container = host_file;
|
|
|
|
BUG_ON(coda_file->private_data != NULL);
|
|
coda_file->private_data = cfi;
|
|
return 0;
|
|
}
|
|
|
|
int coda_release(struct inode *coda_inode, struct file *coda_file)
|
|
{
|
|
unsigned short flags = (coda_file->f_flags) & (~O_EXCL);
|
|
unsigned short coda_flags = coda_flags_to_cflags(flags);
|
|
struct coda_file_info *cfi;
|
|
struct coda_inode_info *cii;
|
|
struct inode *host_inode;
|
|
int err;
|
|
|
|
cfi = CODA_FTOC(coda_file);
|
|
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
|
|
|
|
err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
|
|
coda_flags, coda_file->f_cred->fsuid);
|
|
|
|
host_inode = file_inode(cfi->cfi_container);
|
|
cii = ITOC(coda_inode);
|
|
|
|
/* did we mmap this file? */
|
|
spin_lock(&cii->c_lock);
|
|
if (coda_inode->i_mapping == &host_inode->i_data) {
|
|
cii->c_mapcount -= cfi->cfi_mapcount;
|
|
if (!cii->c_mapcount)
|
|
coda_inode->i_mapping = &coda_inode->i_data;
|
|
}
|
|
spin_unlock(&cii->c_lock);
|
|
|
|
fput(cfi->cfi_container);
|
|
kfree(coda_file->private_data);
|
|
coda_file->private_data = NULL;
|
|
|
|
/* VFS fput ignores the return value from file_operations->release, so
|
|
* there is no use returning an error here */
|
|
return 0;
|
|
}
|
|
|
|
int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync)
|
|
{
|
|
struct file *host_file;
|
|
struct inode *coda_inode = file_inode(coda_file);
|
|
struct coda_file_info *cfi;
|
|
int err;
|
|
|
|
if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
|
|
S_ISLNK(coda_inode->i_mode)))
|
|
return -EINVAL;
|
|
|
|
err = filemap_write_and_wait_range(coda_inode->i_mapping, start, end);
|
|
if (err)
|
|
return err;
|
|
inode_lock(coda_inode);
|
|
|
|
cfi = CODA_FTOC(coda_file);
|
|
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
|
|
host_file = cfi->cfi_container;
|
|
|
|
err = vfs_fsync(host_file, datasync);
|
|
if (!err && !datasync)
|
|
err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
|
|
inode_unlock(coda_inode);
|
|
|
|
return err;
|
|
}
|
|
|
|
const struct file_operations coda_file_operations = {
|
|
.llseek = generic_file_llseek,
|
|
.read_iter = coda_file_read_iter,
|
|
.write_iter = coda_file_write_iter,
|
|
.mmap = coda_file_mmap,
|
|
.open = coda_open,
|
|
.release = coda_release,
|
|
.fsync = coda_fsync,
|
|
.splice_read = generic_file_splice_read,
|
|
};
|
|
|