mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-01 02:21:16 +00:00
4a36e44c45
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJVoAOcAAoJEDjbvchgkmk+UhcP/1EOwnsJDcZ/sZkkclNgRmrJ yLBCW65caLAI2E3SmIdKvHQwIx7lHzX5gmWRBrvx+fIl4KhaNKEQ0NCOf1ATaVuQ MkYMdkicXWpLiFNdKokezryevGS8T1RME+2QlPFv3++Rby1Gy90YD5tu7YlIrEn7 sPRJQHEPCzVAQ7Lqhd66yHICM6/QvdefXj4pjh7vV8IMb2YwnY4vqYt7RxnJCUfP tqljxrT274kzpA2awzALNh+o3B3/Y4W9ROmlDWviw3JBc9gEqFXYwbDf8KDwA5c0 sp9GPGed/dV5DFuqRcAHksJenFnE3E4gZjo/R5hluHQU27peBuRfXev2hZyBfZqG 796eUOky8fb0OiyxHfT2vhfGeD7CHI/asvIAORjDBVUqzJy9nkkby3XJ0U4tW+pz VkcilD2oHw1uRIFH3JoBWTJ9W6CYSNFG1qxw+brgfKT5otJG/dBiI8kBABx+aTq7 V+A2cvf11oVwDEb93dnVypMGsfCywqzJUwEIRli9fTFjK7Fg9CBSGX38nwVGUaRv M2/NeloTyWqUQE41Nd11gCu+hKQRtUU77nxpZcSeKn1XsbpO9/7dHTwcELRuKnTD 9XDksqPznXmC9KXGj7XMcRkLyWyB//JHjay0FCS6b4S6v7R5nrEIRjcpdB+H1WLd zMOXRH4ZlcOAS/Yt2QMd =8AB3 -----END PGP SIGNATURE----- Merge upstream tag 'v3.10.84' into LA.BR.1.3.3 This merge brings us up-to-date as of upstream tag v3.10.84 * tag 'v3.10.84' (317 commits): Linux 3.10.84 fs: Fix S_NOSEC handling KVM: x86: make vapics_in_nmi_mode atomic MIPS: Fix KVM guest fixmap address x86/PCI: Use host bridge _CRS info on Foxconn K8M890-8237A powerpc/perf: Fix book3s kernel to userspace backtraces arm: KVM: force execution of HCPTR access on VM exit Revert "crypto: talitos - convert to use be16_add_cpu()" crypto: talitos - avoid memleak in talitos_alg_alloc() sctp: Fix race between OOTB responce and route removal packet: avoid out of bounds read in round robin fanout packet: read num_members once in packet_rcv_fanout() bridge: fix br_stp_set_bridge_priority race conditions bridge: fix multicast router rlist endless loop sparc: Use GFP_ATOMIC in ldc_alloc_exp_dring() as it can be called in softirq context Linux 3.10.83 bus: mvebu: pass the coherency availability information at init time KVM: nSVM: Check for NRIPS support before updating control field ARM: clk-imx6q: refine sata's parent d_walk() might skip too much ipv6: update ip6_rt_last_gc every time GC is run ipv6: prevent fib6_run_gc() contention xfrm: Increase the garbage collector threshold Btrfs: make xattr replace operations atomic x86/microcode/intel: Guard against stack overflow in the loader fs: take i_mutex during prepare_binprm for set[ug]id executables hpsa: add missing pci_set_master in kdump path hpsa: refine the pci enable/disable handling sb_edac: Fix erroneous bytes->gigabytes conversion ACPICA: Utilities: Cleanup to remove useless ACPI_PRINTF/FORMAT_xxx helpers. ACPICA: Utilities: Cleanup to convert physical address printing formats. __ptrace_may_access() should not deny sub-threads include/linux/sched.h: don't use task->pid/tgid in same_thread_group/has_group_leader_pid netfilter: Zero the tuple in nfnl_cthelper_parse_tuple() netfilter: nfnetlink_cthelper: Remove 'const' and '&' to avoid warnings config: Enable NEED_DMA_MAP_STATE by default when SWIOTLB is selected get rid of s_files and files_lock fput: turn "list_head delayed_fput_list" into llist_head Linux 3.10.82 lpfc: Add iotag memory barrier pipe: iovec: Fix memory corruption when retrying atomic copy as non-atomic drm/mgag200: Reject non-character-cell-aligned mode widths tracing: Have filter check for balanced ops crypto: caam - fix RNG buffer cache alignment Linux 3.10.81 btrfs: cleanup orphans while looking up default subvolume btrfs: incorrect handling for fiemap_fill_next_extent return cfg80211: wext: clear sinfo struct before calling driver mm/memory_hotplug.c: set zone->wait_table to null after freeing it drm/i915: Fix DDC probe for passive adapters pata_octeon_cf: fix broken build ozwpan: unchecked signed subtraction leads to DoS ozwpan: divide-by-zero leading to panic ozwpan: Use proper check to prevent heap overflow MIPS: Fix enabling of DEBUG_STACKOVERFLOW ring-buffer-benchmark: Fix the wrong sched_priority of producer USB: serial: ftdi_sio: Add support for a Motion Tracker Development Board USB: cp210x: add ID for HubZ dual ZigBee and Z-Wave dongle block: fix ext_dev_lock lockdep report Input: elantech - fix detection of touchpads where the revision matches a known rate ALSA: usb-audio: add MAYA44 USB+ mixer control names ALSA: usb-audio: Add mic volume fix quirk for Logitech Quickcam Fusion ALSA: hda/realtek - Add a fixup for another Acer Aspire 9420 iio: adis16400: Compute the scan mask from channel indices iio: adis16400: Use != channel indices for the two voltage channels iio: adis16400: Report pressure channel scale xen: netback: read hotplug script once at start of day. udp: fix behavior of wrong checksums net_sched: invoke ->attach() after setting dev->qdisc unix/caif: sk_socket can disappear when state is unlocked net: dp83640: fix broken calibration routine. bridge: fix parsing of MLDv2 reports ipv4: Avoid crashing in ip_error net: phy: Allow EEE for all RGMII variants Linux 3.10.80 fs/binfmt_elf.c:load_elf_binary(): return -EINVAL on zero-length mappings vfs: read file_handle only once in handle_to_path ACPI / init: Fix the ordering of acpi_reserve_resources() Input: elantech - fix semi-mt protocol for v3 HW rtlwifi: rtl8192cu: Fix kernel deadlock md/raid5: don't record new size if resize_stripes fails. svcrpc: fix potential GSSX_ACCEPT_SEC_CONTEXT decoding failures ARM: fix missing syscall trace exit ARM: dts: imx27: only map 4 Kbyte for fec registers crypto: s390/ghash - Fix incorrect ghash icv buffer handling. rt2x00: add new rt2800usb device DWA 130 libata: Ignore spurious PHY event on LPM policy change libata: Add helper to determine when PHY events should be ignored ext4: check for zero length extent explicitly ext4: convert write_begin methods to stable_page_writes semantics mmc: atmel-mci: fix bad variable type for clkdiv powerpc: Align TOC to 256 bytes usb: gadget: configfs: Fix interfaces array NULL-termination usb-storage: Add NO_WP_DETECT quirk for Lacie 059f:0651 devices USB: cp210x: add ID for KCF Technologies PRN device USB: pl2303: Remove support for Samsung I330 USB: visor: Match I330 phone more precisely xhci: gracefully handle xhci_irq dead device xhci: Solve full event ring by increasing TRBS_PER_SEGMENT to 256 xhci: fix isoc endpoint dequeue from advancing too far on transaction error target/pscsi: Don't leak scsi_host if hba is VIRTUAL_HOST ASoC: wm8994: correct BCLK DIV 348 to 384 ASoC: wm8960: fix "RINPUT3" audio route error ASoC: mc13783: Fix wrong mask value used in mc13xxx_reg_rmw() calls ALSA: hda - Add headphone quirk for Lifebook E752 ALSA: hda - Add Conexant codecs CX20721, CX20722, CX20723 and CX20724 d_walk() might skip too much lib: Fix strnlen_user() to not touch memory after specified maximum hwmon: (ntc_thermistor) Ensure iio channel is of type IIO_VOLTAGE libceph: request a new osdmap if lingering request maps to no osd lguest: fix out-by-one error in address checking. fs, omfs: add NULL terminator in the end up the token list KVM: MMU: fix CR4.SMEP=1, CR0.WP=0 with shadow pages net: socket: Fix the wrong returns for recvmsg and sendmsg kernel: use the gnu89 standard explicitly staging, rtl8192e, LLVMLinux: Remove unused inline prototype staging: rtl8712, rtl8712: avoid lots of build warnings staging, rtl8192e, LLVMLinux: Change extern inline to static inline drm/i915: Fix declaration of intel_gmbus_{is_forced_bit/is_port_falid} staging: wlags49_h2: fix extern inline functions Linux 3.10.79 ACPICA: Utilities: Cleanup to enforce ACPI_PHYSADDR_TO_PTR()/ACPI_PTR_TO_PHYSADDR(). ACPICA: Tables: Change acpi_find_root_pointer() to use acpi_physical_address. revert "softirq: Add support for triggering softirq work on softirqs" sound/oss: fix deadlock in sequencer_ioctl(SNDCTL_SEQ_OUTOFBAND) mmc: card: Don't access RPMB partitions for normal read/write pinctrl: Don't just pretend to protect pinctrl_maps, do it for real drm/i915: Add missing MacBook Pro models with dual channel LVDS ARM: mvebu: armada-xp-openblocks-ax3-4: Disable internal RTC ARM: dts: imx23-olinuxino: Fix dr_mode of usb0 ARM: dts: imx28: Fix AUART4 TX-DMA interrupt name ARM: dts: imx25: Add #pwm-cells to pwm4 gpio: sysfs: fix memory leaks and device hotplug gpio: unregister gpiochip device before removing it xen/console: Update console event channel on resume mm/memory-failure: call shake_page() when error hits thp tail page nilfs2: fix sanity check of btree level in nilfs_btree_root_broken() ocfs2: dlm: fix race between purge and get lock resource Linux 3.10.78 ARC: signal handling robustify UBI: fix soft lockup in ubi_check_volume() Drivers: hv: vmbus: Don't wait after requesting offers ARM: dts: dove: Fix uart[23] reg property staging: panel: fix lcd type usb: gadget: printer: enqueue printer's response for setup request usb: host: oxu210hp: use new USB_RESUME_TIMEOUT 3w-sas: fix command completion race 3w-9xxx: fix command completion race 3w-xxxx: fix command completion race ext4: fix data corruption caused by unwritten and delayed extents rbd: end I/O the entire obj_request on error serial: of-serial: Remove device_type = "serial" registration ALSA: hda - Fix mute-LED fixed mode ALSA: emu10k1: Emu10k2 32 bit DMA mode ALSA: emu10k1: Fix card shortname string buffer overflow ALSA: emux: Fix mutex deadlock in OSS emulation ALSA: emux: Fix mutex deadlock at unloading ipv4: Missing sk_nulls_node_init() in ping_unhash(). Linux 3.10.77 s390: Fix build error nosave: consolidate __nosave_{begin,end} in <asm/sections.h> memstick: mspro_block: add missing curly braces C6x: time: Ensure consistency in __init wl18xx: show rx_frames_per_rates as an array as it really is lib: memzero_explicit: use barrier instead of OPTIMIZER_HIDE_VAR e1000: add dummy allocator to fix race condition between mtu change and netpoll ksoftirqd: Enable IRQs and call cond_resched() before poking RCU RCU pathwalk breakage when running into a symlink overmounting something drm/i915: cope with large i2c transfers drm/radeon: fix doublescan modes (v2) i2c: core: Export bus recovery functions IB/mlx4: Fix WQE LSO segment calculation IB/core: don't disallow registering region starting at 0x0 IB/core: disallow registering 0-sized memory region stk1160: Make sure current buffer is released mvsas: fix panic on expander attached SATA devices Drivers: hv: vmbus: Fix a bug in the error path in vmbus_open() xtensa: provide __NR_sync_file_range2 instead of __NR_sync_file_range xtensa: xtfpga: fix hardware lockup caused by LCD driver ACPICA: Utilities: split IO address types from data type models. drivers: parport: Kconfig: exclude arm64 for PARPORT_PC scsi: storvsc: Fix a bug in copy_from_bounce_buffer() UBI: fix check for "too many bytes" UBI: initialize LEB number variable UBI: fix out of bounds write UBI: account for bitflips in both the VID header and data tools/power turbostat: Use $(CURDIR) instead of $(PWD) and add support for O= option in Makefile powerpc/perf: Cap 64bit userspace backtraces to PERF_MAX_STACK_DEPTH ext4: make fsync to sync parent dir in no-journal for real this time arm64: kernel: compiling issue, need delete read_current_timer() video: vgacon: Don't build on arm64 console: Disable VGA text console support on cris drivers: parport: Kconfig: exclude h8300 for PARPORT_PC parport: disable PC-style parallel port support on cris rtlwifi: rtl8192cu: Add new device ID rtlwifi: rtl8192cu: Add new USB ID ptrace: fix race between ptrace_resume() and wait_task_stopped() fs/binfmt_elf.c: fix bug in loading of PIE binaries Input: elantech - fix absolute mode setting on some ASUS laptops ALSA: emu10k1: don't deadlock in proc-functions usb: core: hub: use new USB_RESUME_TIMEOUT usb: host: sl811: use new USB_RESUME_TIMEOUT usb: host: xhci: use new USB_RESUME_TIMEOUT usb: host: isp116x: use new USB_RESUME_TIMEOUT usb: host: r8a66597: use new USB_RESUME_TIMEOUT usb: define a generic USB_RESUME_TIMEOUT macro usb: phy: Find the right match in devm_usb_phy_match ARM: S3C64XX: Use fixed IRQ bases to avoid conflicts on Cragganmore ARM: 8320/1: fix integer overflow in ELF_ET_DYN_BASE power_supply: lp8788-charger: Fix leaked power supply on probe fail ring-buffer: Replace this_cpu_*() with __this_cpu_*() spi: spidev: fix possible arithmetic overflow for multi-transfer message cdc-wdm: fix endianness bug in debug statements MIPS: Hibernate: flush TLB entries earlier KVM: use slowpath for cross page cached accesses s390/hibernate: fix save and restore of kernel text section KVM: s390: Zero out current VMDB of STSI before including level3 data. usb: gadget: composite: enable BESL support Btrfs: fix inode eviction infinite loop after cloning into it Btrfs: fix log tree corruption when fs mounted with -o discard tcp: avoid looping in tcp_send_fin() tcp: fix possible deadlock in tcp_send_fin() ip_forward: Drop frames with attached skb->sk Linux 3.10.76 dcache: Fix locking bugs in backported "deal with deadlock in d_walk()" arc: mm: Fix build failure sb_edac: avoid INTERNAL ERROR message in EDAC with unspecified channel x86: mm: move mmap_sem unlock from mm_fault_error() to caller vm: make stack guard page errors return VM_FAULT_SIGSEGV rather than SIGBUS vm: add VM_FAULT_SIGSEGV handling support deal with deadlock in d_walk() move d_rcu from overlapping d_child to overlapping d_alias kconfig: Fix warning "‘jump’ may be used uninitialized" KVM: x86: SYSENTER emulation is broken netfilter: conntrack: disable generic tracking for known protocols Bluetooth: Ignore isochronous endpoints for Intel USB bootloader Bluetooth: Add support for Intel bootloader devices Bluetooth: btusb: Add IMC Networks (Broadcom based) Bluetooth: Add firmware update for Atheros 0cf3:311f Bluetooth: Enable Atheros 0cf3:311e for firmware upload mm: Fix NULL pointer dereference in madvise(MADV_WILLNEED) support splice: Apply generic position and size checks to each write jfs: fix readdir regression serial: 8250_dw: Fix deadlock in LCR workaround benet: Call dev_kfree_skby_any instead of kfree_skb. ixgb: Call dev_kfree_skby_any instead of dev_kfree_skb. tg3: Call dev_kfree_skby_any instead of dev_kfree_skb. bnx2: Call dev_kfree_skby_any instead of dev_kfree_skb. r8169: Call dev_kfree_skby_any instead of dev_kfree_skb. 8139too: Call dev_kfree_skby_any instead of dev_kfree_skb. 8139cp: Call dev_kfree_skby_any instead of kfree_skb. tcp: tcp_make_synack() should clear skb->tstamp tcp: fix FRTO undo on cumulative ACK of SACKed range ipv6: Don't reduce hop limit for an interface tcp: prevent fetching dst twice in early demux code remove extra definitions of U32_MAX conditionally define U32_MAX Linux 3.10.75 pagemap: do not leak physical addresses to non-privileged userspace console: Fix console name size mismatch IB/mlx4: Saturate RoCE port PMA counters in case of overflow kernel.h: define u8, s8, u32, etc. limits net: llc: use correct size for sysctl timeout entries net: rds: use correct size for max unacked packets and bytes ipc: fix compat msgrcv with negative msgtyp core, nfqueue, openvswitch: fix compilation warning media: s5p-mfc: fix mmap support for 64bit arch iscsi target: fix oops when adding reject pdu ocfs2: _really_ sync the right range be2iscsi: Fix kernel panic when device initialization fails cifs: fix use-after-free bug in find_writable_file usb: xhci: apply XHCI_AVOID_BEI quirk to all Intel xHCI controllers cpuidle: ACPI: do not overwrite name and description of C0 dmaengine: omap-dma: Fix memory leak when terminating running transfer iio: imu: Use iio_trigger_get for indio_dev->trig assignment iio: inv_mpu6050: Clear timestamps fifo while resetting hardware fifo Defer processing of REQ_PREEMPT requests for blocked devices USB: ftdi_sio: Use jtag quirk for SNAP Connect E10 USB: ftdi_sio: Added custom PID for Synapse Wireless product radeon: Do not directly dereference pointers to BIOS area. writeback: fix possible underflow in write bandwidth calculation writeback: add missing INITIAL_JIFFIES init in global_update_bandwidth() mm/memory hotplug: postpone the reset of obsolete pgdat nbd: fix possible memory leak iwlwifi: dvm: run INIT firmware again upon .start() IB/uverbs: Prevent integer overflow in ib_umem_get address arithmetic IB/core: Avoid leakage from kernel to user space tcp: Fix crash in TCP Fast Open selinux: fix sel_write_enforce broken return value ALSA: hda - Fix headphone pin config for Lifebook T731 ALSA: usb - Creative USB X-Fi Pro SB1095 volume knob support ALSA: hda - Add one more node in the EAPD supporting candidate list Linux 3.10.74 net: ethernet: pcnet32: Setup the SRAM and NOUFLO on Am79C97{3, 5} powerpc/mpc85xx: Add ranges to etsec2 nodes hfsplus: fix B-tree corruption after insertion at position 0 dm: hold suspend_lock while suspending device during device deletion vt6655: RFbSetPower fix missing rate RATE_12M perf: Fix irq_work 'tail' recursion Revert "iwlwifi: mvm: fix failure path when power_update fails in add_interface" mac80211: drop unencrypted frames in mesh fwding mac80211: disable u-APSD queues by default nl80211: ignore HT/VHT capabilities without QoS/WMM tcm_qla2xxx: Fix incorrect use of __transport_register_session tcm_fc: missing curly braces in ft_invl_hw_context() ASoC: wm8955: Fix wrong value references for boolean kctl ASoC: adav80x: Fix wrong value references for boolean kctl ASoC: ak4641: Fix wrong value references for boolean kctl ASoC: wm8904: Fix wrong value references for boolean kctl ASoC: wm8903: Fix wrong value references for boolean kctl ASoC: wm2000: Fix wrong value references for boolean kctl ASoC: wm8731: Fix wrong value references for boolean kctl ASoC: tas5086: Fix wrong value references for boolean kctl ASoC: wm8960: Fix wrong value references for boolean kctl ASoC: cs4271: Fix wrong value references for boolean kctl ASoC: sgtl5000: remove useless register write clearing CHRGPUMP_POWERUP Change-Id: Ib7976ee2c7224e39074157e28db4158db40b00db Signed-off-by: Kaushal Kumar <kaushalk@codeaurora.org>
512 lines
13 KiB
C
512 lines
13 KiB
C
/*
|
|
* Copyright (C) Neil Brown 2002
|
|
* Copyright (C) Christoph Hellwig 2007
|
|
*
|
|
* This file contains the code mapping from inodes to NFS file handles,
|
|
* and for mapping back from file handles to dentries.
|
|
*
|
|
* For details on why we do all the strange and hairy things in here
|
|
* take a look at Documentation/filesystems/nfs/Exporting.
|
|
*/
|
|
#include <linux/exportfs.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/file.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/namei.h>
|
|
#include <linux/sched.h>
|
|
|
|
#define dprintk(fmt, args...) do{}while(0)
|
|
|
|
|
|
static int get_name(const struct path *path, char *name, struct dentry *child);
|
|
|
|
|
|
static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir,
|
|
char *name, struct dentry *child)
|
|
{
|
|
const struct export_operations *nop = dir->d_sb->s_export_op;
|
|
struct path path = {.mnt = mnt, .dentry = dir};
|
|
|
|
if (nop->get_name)
|
|
return nop->get_name(dir, name, child);
|
|
else
|
|
return get_name(&path, name, child);
|
|
}
|
|
|
|
/*
|
|
* Check if the dentry or any of it's aliases is acceptable.
|
|
*/
|
|
static struct dentry *
|
|
find_acceptable_alias(struct dentry *result,
|
|
int (*acceptable)(void *context, struct dentry *dentry),
|
|
void *context)
|
|
{
|
|
struct dentry *dentry, *toput = NULL;
|
|
struct inode *inode;
|
|
|
|
if (acceptable(context, result))
|
|
return result;
|
|
|
|
inode = result->d_inode;
|
|
spin_lock(&inode->i_lock);
|
|
hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
|
|
dget(dentry);
|
|
spin_unlock(&inode->i_lock);
|
|
if (toput)
|
|
dput(toput);
|
|
if (dentry != result && acceptable(context, dentry)) {
|
|
dput(result);
|
|
return dentry;
|
|
}
|
|
spin_lock(&inode->i_lock);
|
|
toput = dentry;
|
|
}
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
if (toput)
|
|
dput(toput);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Find root of a disconnected subtree and return a reference to it.
|
|
*/
|
|
static struct dentry *
|
|
find_disconnected_root(struct dentry *dentry)
|
|
{
|
|
dget(dentry);
|
|
while (!IS_ROOT(dentry)) {
|
|
struct dentry *parent = dget_parent(dentry);
|
|
|
|
if (!(parent->d_flags & DCACHE_DISCONNECTED)) {
|
|
dput(parent);
|
|
break;
|
|
}
|
|
|
|
dput(dentry);
|
|
dentry = parent;
|
|
}
|
|
return dentry;
|
|
}
|
|
|
|
/*
|
|
* Make sure target_dir is fully connected to the dentry tree.
|
|
*
|
|
* It may already be, as the flag isn't always updated when connection happens.
|
|
*/
|
|
static int
|
|
reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
|
|
{
|
|
int noprogress = 0;
|
|
int err = -ESTALE;
|
|
|
|
/*
|
|
* It is possible that a confused file system might not let us complete
|
|
* the path to the root. For example, if get_parent returns a directory
|
|
* in which we cannot find a name for the child. While this implies a
|
|
* very sick filesystem we don't want it to cause knfsd to spin. Hence
|
|
* the noprogress counter. If we go through the loop 10 times (2 is
|
|
* probably enough) without getting anywhere, we just give up
|
|
*/
|
|
while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
|
|
struct dentry *pd = find_disconnected_root(target_dir);
|
|
|
|
if (!IS_ROOT(pd)) {
|
|
/* must have found a connected parent - great */
|
|
spin_lock(&pd->d_lock);
|
|
pd->d_flags &= ~DCACHE_DISCONNECTED;
|
|
spin_unlock(&pd->d_lock);
|
|
noprogress = 0;
|
|
} else if (pd == mnt->mnt_sb->s_root) {
|
|
printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
|
|
spin_lock(&pd->d_lock);
|
|
pd->d_flags &= ~DCACHE_DISCONNECTED;
|
|
spin_unlock(&pd->d_lock);
|
|
noprogress = 0;
|
|
} else {
|
|
/*
|
|
* We have hit the top of a disconnected path, try to
|
|
* find parent and connect.
|
|
*
|
|
* Racing with some other process renaming a directory
|
|
* isn't much of a problem here. If someone renames
|
|
* the directory, it will end up properly connected,
|
|
* which is what we want
|
|
*
|
|
* Getting the parent can't be supported generically,
|
|
* the locking is too icky.
|
|
*
|
|
* Instead we just return EACCES. If server reboots
|
|
* or inodes get flushed, you lose
|
|
*/
|
|
struct dentry *ppd = ERR_PTR(-EACCES);
|
|
struct dentry *npd;
|
|
|
|
mutex_lock(&pd->d_inode->i_mutex);
|
|
if (mnt->mnt_sb->s_export_op->get_parent)
|
|
ppd = mnt->mnt_sb->s_export_op->get_parent(pd);
|
|
mutex_unlock(&pd->d_inode->i_mutex);
|
|
|
|
if (IS_ERR(ppd)) {
|
|
err = PTR_ERR(ppd);
|
|
dprintk("%s: get_parent of %ld failed, err %d\n",
|
|
__func__, pd->d_inode->i_ino, err);
|
|
dput(pd);
|
|
break;
|
|
}
|
|
|
|
dprintk("%s: find name of %lu in %lu\n", __func__,
|
|
pd->d_inode->i_ino, ppd->d_inode->i_ino);
|
|
err = exportfs_get_name(mnt, ppd, nbuf, pd);
|
|
if (err) {
|
|
dput(ppd);
|
|
dput(pd);
|
|
if (err == -ENOENT)
|
|
/* some race between get_parent and
|
|
* get_name? just try again
|
|
*/
|
|
continue;
|
|
break;
|
|
}
|
|
dprintk("%s: found name: %s\n", __func__, nbuf);
|
|
mutex_lock(&ppd->d_inode->i_mutex);
|
|
npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
|
|
mutex_unlock(&ppd->d_inode->i_mutex);
|
|
if (IS_ERR(npd)) {
|
|
err = PTR_ERR(npd);
|
|
dprintk("%s: lookup failed: %d\n",
|
|
__func__, err);
|
|
dput(ppd);
|
|
dput(pd);
|
|
break;
|
|
}
|
|
/* we didn't really want npd, we really wanted
|
|
* a side-effect of the lookup.
|
|
* hopefully, npd == pd, though it isn't really
|
|
* a problem if it isn't
|
|
*/
|
|
if (npd == pd)
|
|
noprogress = 0;
|
|
else
|
|
printk("%s: npd != pd\n", __func__);
|
|
dput(npd);
|
|
dput(ppd);
|
|
if (IS_ROOT(pd)) {
|
|
/* something went wrong, we have to give up */
|
|
dput(pd);
|
|
break;
|
|
}
|
|
}
|
|
dput(pd);
|
|
}
|
|
|
|
if (target_dir->d_flags & DCACHE_DISCONNECTED) {
|
|
/* something went wrong - oh-well */
|
|
if (!err)
|
|
err = -ESTALE;
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct getdents_callback {
|
|
struct dir_context ctx;
|
|
char *name; /* name that was found. It already points to a
|
|
buffer NAME_MAX+1 is size */
|
|
unsigned long ino; /* the inum we are looking for */
|
|
int found; /* inode matched? */
|
|
int sequence; /* sequence counter */
|
|
};
|
|
|
|
/*
|
|
* A rather strange filldir function to capture
|
|
* the name matching the specified inode number.
|
|
*/
|
|
static int filldir_one(void * __buf, const char * name, int len,
|
|
loff_t pos, u64 ino, unsigned int d_type)
|
|
{
|
|
struct getdents_callback *buf = __buf;
|
|
int result = 0;
|
|
|
|
buf->sequence++;
|
|
if (buf->ino == ino) {
|
|
memcpy(buf->name, name, len);
|
|
buf->name[len] = '\0';
|
|
buf->found = 1;
|
|
result = -1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* get_name - default export_operations->get_name function
|
|
* @dentry: the directory in which to find a name
|
|
* @name: a pointer to a %NAME_MAX+1 char buffer to store the name
|
|
* @child: the dentry for the child directory.
|
|
*
|
|
* calls readdir on the parent until it finds an entry with
|
|
* the same inode number as the child, and returns that.
|
|
*/
|
|
static int get_name(const struct path *path, char *name, struct dentry *child)
|
|
{
|
|
const struct cred *cred = current_cred();
|
|
struct inode *dir = path->dentry->d_inode;
|
|
int error;
|
|
struct file *file;
|
|
struct getdents_callback buffer = {
|
|
.ctx.actor = filldir_one,
|
|
.name = name,
|
|
.ino = child->d_inode->i_ino
|
|
};
|
|
|
|
error = -ENOTDIR;
|
|
if (!dir || !S_ISDIR(dir->i_mode))
|
|
goto out;
|
|
error = -EINVAL;
|
|
if (!dir->i_fop)
|
|
goto out;
|
|
/*
|
|
* Open the directory ...
|
|
*/
|
|
file = dentry_open(path, O_RDONLY, cred);
|
|
error = PTR_ERR(file);
|
|
if (IS_ERR(file))
|
|
goto out;
|
|
|
|
error = -EINVAL;
|
|
if (!file->f_op->readdir && !file->f_op->iterate)
|
|
goto out_close;
|
|
|
|
buffer.sequence = 0;
|
|
while (1) {
|
|
int old_seq = buffer.sequence;
|
|
|
|
error = iterate_dir(file, &buffer.ctx);
|
|
if (buffer.found) {
|
|
error = 0;
|
|
break;
|
|
}
|
|
|
|
if (error < 0)
|
|
break;
|
|
|
|
error = -ENOENT;
|
|
if (old_seq == buffer.sequence)
|
|
break;
|
|
}
|
|
|
|
out_close:
|
|
fput(file);
|
|
out:
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* export_encode_fh - default export_operations->encode_fh function
|
|
* @inode: the object to encode
|
|
* @fh: where to store the file handle fragment
|
|
* @max_len: maximum length to store there
|
|
* @parent: parent directory inode, if wanted
|
|
*
|
|
* This default encode_fh function assumes that the 32 inode number
|
|
* is suitable for locating an inode, and that the generation number
|
|
* can be used to check that it is still valid. It places them in the
|
|
* filehandle fragment where export_decode_fh expects to find them.
|
|
*/
|
|
static int export_encode_fh(struct inode *inode, struct fid *fid,
|
|
int *max_len, struct inode *parent)
|
|
{
|
|
int len = *max_len;
|
|
int type = FILEID_INO32_GEN;
|
|
|
|
if (parent && (len < 4)) {
|
|
*max_len = 4;
|
|
return FILEID_INVALID;
|
|
} else if (len < 2) {
|
|
*max_len = 2;
|
|
return FILEID_INVALID;
|
|
}
|
|
|
|
len = 2;
|
|
fid->i32.ino = inode->i_ino;
|
|
fid->i32.gen = inode->i_generation;
|
|
if (parent) {
|
|
fid->i32.parent_ino = parent->i_ino;
|
|
fid->i32.parent_gen = parent->i_generation;
|
|
len = 4;
|
|
type = FILEID_INO32_GEN_PARENT;
|
|
}
|
|
*max_len = len;
|
|
return type;
|
|
}
|
|
|
|
int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
|
|
int *max_len, struct inode *parent)
|
|
{
|
|
const struct export_operations *nop = inode->i_sb->s_export_op;
|
|
|
|
if (nop && nop->encode_fh)
|
|
return nop->encode_fh(inode, fid->raw, max_len, parent);
|
|
|
|
return export_encode_fh(inode, fid, max_len, parent);
|
|
}
|
|
EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);
|
|
|
|
int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
|
|
int connectable)
|
|
{
|
|
int error;
|
|
struct dentry *p = NULL;
|
|
struct inode *inode = dentry->d_inode, *parent = NULL;
|
|
|
|
if (connectable && !S_ISDIR(inode->i_mode)) {
|
|
p = dget_parent(dentry);
|
|
/*
|
|
* note that while p might've ceased to be our parent already,
|
|
* it's still pinned by and still positive.
|
|
*/
|
|
parent = p->d_inode;
|
|
}
|
|
|
|
error = exportfs_encode_inode_fh(inode, fid, max_len, parent);
|
|
dput(p);
|
|
|
|
return error;
|
|
}
|
|
EXPORT_SYMBOL_GPL(exportfs_encode_fh);
|
|
|
|
struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
|
|
int fh_len, int fileid_type,
|
|
int (*acceptable)(void *, struct dentry *), void *context)
|
|
{
|
|
const struct export_operations *nop = mnt->mnt_sb->s_export_op;
|
|
struct dentry *result, *alias;
|
|
char nbuf[NAME_MAX+1];
|
|
int err;
|
|
|
|
/*
|
|
* Try to get any dentry for the given file handle from the filesystem.
|
|
*/
|
|
if (!nop || !nop->fh_to_dentry)
|
|
return ERR_PTR(-ESTALE);
|
|
result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
|
|
if (!result)
|
|
result = ERR_PTR(-ESTALE);
|
|
if (IS_ERR(result))
|
|
return result;
|
|
|
|
if (S_ISDIR(result->d_inode->i_mode)) {
|
|
/*
|
|
* This request is for a directory.
|
|
*
|
|
* On the positive side there is only one dentry for each
|
|
* directory inode. On the negative side this implies that we
|
|
* to ensure our dentry is connected all the way up to the
|
|
* filesystem root.
|
|
*/
|
|
if (result->d_flags & DCACHE_DISCONNECTED) {
|
|
err = reconnect_path(mnt, result, nbuf);
|
|
if (err)
|
|
goto err_result;
|
|
}
|
|
|
|
if (!acceptable(context, result)) {
|
|
err = -EACCES;
|
|
goto err_result;
|
|
}
|
|
|
|
return result;
|
|
} else {
|
|
/*
|
|
* It's not a directory. Life is a little more complicated.
|
|
*/
|
|
struct dentry *target_dir, *nresult;
|
|
|
|
/*
|
|
* See if either the dentry we just got from the filesystem
|
|
* or any alias for it is acceptable. This is always true
|
|
* if this filesystem is exported without the subtreecheck
|
|
* option. If the filesystem is exported with the subtree
|
|
* check option there's a fair chance we need to look at
|
|
* the parent directory in the file handle and make sure
|
|
* it's connected to the filesystem root.
|
|
*/
|
|
alias = find_acceptable_alias(result, acceptable, context);
|
|
if (alias)
|
|
return alias;
|
|
|
|
/*
|
|
* Try to extract a dentry for the parent directory from the
|
|
* file handle. If this fails we'll have to give up.
|
|
*/
|
|
err = -ESTALE;
|
|
if (!nop->fh_to_parent)
|
|
goto err_result;
|
|
|
|
target_dir = nop->fh_to_parent(mnt->mnt_sb, fid,
|
|
fh_len, fileid_type);
|
|
if (!target_dir)
|
|
goto err_result;
|
|
err = PTR_ERR(target_dir);
|
|
if (IS_ERR(target_dir))
|
|
goto err_result;
|
|
|
|
/*
|
|
* And as usual we need to make sure the parent directory is
|
|
* connected to the filesystem root. The VFS really doesn't
|
|
* like disconnected directories..
|
|
*/
|
|
err = reconnect_path(mnt, target_dir, nbuf);
|
|
if (err) {
|
|
dput(target_dir);
|
|
goto err_result;
|
|
}
|
|
|
|
/*
|
|
* Now that we've got both a well-connected parent and a
|
|
* dentry for the inode we're after, make sure that our
|
|
* inode is actually connected to the parent.
|
|
*/
|
|
err = exportfs_get_name(mnt, target_dir, nbuf, result);
|
|
if (!err) {
|
|
mutex_lock(&target_dir->d_inode->i_mutex);
|
|
nresult = lookup_one_len(nbuf, target_dir,
|
|
strlen(nbuf));
|
|
mutex_unlock(&target_dir->d_inode->i_mutex);
|
|
if (!IS_ERR(nresult)) {
|
|
if (nresult->d_inode) {
|
|
dput(result);
|
|
result = nresult;
|
|
} else
|
|
dput(nresult);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* At this point we are done with the parent, but it's pinned
|
|
* by the child dentry anyway.
|
|
*/
|
|
dput(target_dir);
|
|
|
|
/*
|
|
* And finally make sure the dentry is actually acceptable
|
|
* to NFSD.
|
|
*/
|
|
alias = find_acceptable_alias(result, acceptable, context);
|
|
if (!alias) {
|
|
err = -EACCES;
|
|
goto err_result;
|
|
}
|
|
|
|
return alias;
|
|
}
|
|
|
|
err_result:
|
|
dput(result);
|
|
return ERR_PTR(err);
|
|
}
|
|
EXPORT_SYMBOL_GPL(exportfs_decode_fh);
|
|
|
|
MODULE_LICENSE("GPL");
|