mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Merge android-4.14-q.136 (7870b28) into msm-4.14
* refs/heads/tmp-7870b28: Linux 4.14.136 ip_tunnel: allow not to count pkts on tstats by setting skb's dev to NULL ceph: hold i_ceph_lock when removing caps for freeing inode Fix allyesconfig output. drivers/pps/pps.c: clear offset flags in PPS_SETPARAMS ioctl sched/fair: Don't free p->numa_faults with concurrent readers Bluetooth: hci_uart: check for missing tty operations hv_sock: Add support for delayed close iommu/iova: Fix compilation error with !CONFIG_IOMMU_IOVA iommu/vt-d: Don't queue_iova() if there is no flush queue media: radio-raremono: change devm_k*alloc to k*alloc NFS: Cleanup if nfs_match_client is interrupted media: pvrusb2: use a different format for warnings media: cpia2_usb: first wake up, then free in disconnect ath10k: Change the warning message string media: au0828: fix null dereference in error path ISDN: hfcsusb: checking idx of ep configuration binder: fix possible UAF when freeing buffer arm64: compat: Provide definition for COMPAT_SIGMINSTKSZ i2c: qup: fixed releasing dma without flush operation completion arm64: dts: marvell: Fix A37xx UART0 register size NFSv4: Fix lookup revalidate of regular files NFS: Refactor nfs_lookup_revalidate() NFS: Fix dentry revalidation on NFSv4 lookup vsock: correct removal of socket from the list VSOCK: use TCP state constants for sk_state ANDROID: fix up 9p filesystem due to CFI non-upstream patches Change-Id: I2838e5b80d1ff80132d5cbbe113ecc0037df9d5d Signed-off-by: Blagovest Kolenichev <bkolenichev@codeaurora.org>
This commit is contained in:
commit
50f461f659
@ -8,6 +8,6 @@ Required properties:
|
||||
Example:
|
||||
serial@12000 {
|
||||
compatible = "marvell,armada-3700-uart";
|
||||
reg = <0x12000 0x400>;
|
||||
reg = <0x12000 0x200>;
|
||||
interrupts = <43>;
|
||||
};
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 14
|
||||
SUBLEVEL = 135
|
||||
SUBLEVEL = 136
|
||||
EXTRAVERSION =
|
||||
NAME = Petit Gorille
|
||||
|
||||
|
@ -134,7 +134,7 @@
|
||||
|
||||
uart0: serial@12000 {
|
||||
compatible = "marvell,armada-3700-uart";
|
||||
reg = <0x12000 0x400>;
|
||||
reg = <0x12000 0x200>;
|
||||
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -234,6 +234,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
#define compat_user_stack_pointer() (user_stack_pointer(task_pt_regs(current)))
|
||||
#define COMPAT_MINSIGSTKSZ 2048
|
||||
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
|
@ -8,27 +8,19 @@ config SH_ALPHA_BOARD
|
||||
bool
|
||||
|
||||
config SH_DEVICE_TREE
|
||||
bool "Board Described by Device Tree"
|
||||
bool
|
||||
select OF
|
||||
select OF_EARLY_FLATTREE
|
||||
select TIMER_OF
|
||||
select COMMON_CLK
|
||||
select GENERIC_CALIBRATE_DELAY
|
||||
help
|
||||
Select Board Described by Device Tree to build a kernel that
|
||||
does not hard-code any board-specific knowledge but instead uses
|
||||
a device tree blob provided by the boot-loader. You must enable
|
||||
drivers for any hardware you want to use separately. At this
|
||||
time, only boards based on the open-hardware J-Core processors
|
||||
have sufficient driver coverage to use this option; do not
|
||||
select it if you are using original SuperH hardware.
|
||||
|
||||
config SH_JCORE_SOC
|
||||
bool "J-Core SoC"
|
||||
depends on SH_DEVICE_TREE && (CPU_SH2 || CPU_J2)
|
||||
select SH_DEVICE_TREE
|
||||
select CLKSRC_JCORE_PIT
|
||||
select JCORE_AIC
|
||||
default y if CPU_J2
|
||||
depends on CPU_J2
|
||||
help
|
||||
Select this option to include drivers core components of the
|
||||
J-Core SoC, including interrupt controllers and timers.
|
||||
|
@ -2135,8 +2135,18 @@ static struct binder_thread *binder_get_txn_from_and_acq_inner(
|
||||
|
||||
static void binder_free_transaction(struct binder_transaction *t)
|
||||
{
|
||||
if (t->buffer)
|
||||
t->buffer->transaction = NULL;
|
||||
struct binder_proc *target_proc = t->to_proc;
|
||||
|
||||
if (target_proc) {
|
||||
binder_inner_proc_lock(target_proc);
|
||||
if (t->buffer)
|
||||
t->buffer->transaction = NULL;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
}
|
||||
/*
|
||||
* If the transaction has no target_proc, then
|
||||
* t->buffer->transaction has already been cleared.
|
||||
*/
|
||||
kfree(t);
|
||||
binder_stats_deleted(BINDER_STAT_TRANSACTION);
|
||||
}
|
||||
@ -3845,10 +3855,12 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||
buffer->debug_id,
|
||||
buffer->transaction ? "active" : "finished");
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
if (buffer->transaction) {
|
||||
buffer->transaction->buffer = NULL;
|
||||
buffer->transaction = NULL;
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
if (buffer->async_transaction && buffer->target_node) {
|
||||
struct binder_node *buf_node;
|
||||
struct binder_work *w;
|
||||
|
@ -101,6 +101,9 @@ static int ath_open(struct hci_uart *hu)
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
if (!hci_uart_has_flow_control(hu))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ath = kzalloc(sizeof(*ath), GFP_KERNEL);
|
||||
if (!ath)
|
||||
return -ENOMEM;
|
||||
|
@ -305,6 +305,9 @@ static int bcm_open(struct hci_uart *hu)
|
||||
|
||||
bt_dev_dbg(hu->hdev, "hu %p", hu);
|
||||
|
||||
if (!hci_uart_has_flow_control(hu))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
|
||||
if (!bcm)
|
||||
return -ENOMEM;
|
||||
|
@ -406,6 +406,9 @@ static int intel_open(struct hci_uart *hu)
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
if (!hci_uart_has_flow_control(hu))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
intel = kzalloc(sizeof(*intel), GFP_KERNEL);
|
||||
if (!intel)
|
||||
return -ENOMEM;
|
||||
|
@ -297,6 +297,19 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the underlying device or tty has flow control support */
|
||||
bool hci_uart_has_flow_control(struct hci_uart *hu)
|
||||
{
|
||||
/* serdev nodes check if the needed operations are present */
|
||||
if (hu->serdev)
|
||||
return true;
|
||||
|
||||
if (hu->tty->driver->ops->tiocmget && hu->tty->driver->ops->tiocmset)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Flow control or un-flow control the device */
|
||||
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
|
||||
{
|
||||
|
@ -66,6 +66,9 @@ static int mrvl_open(struct hci_uart *hu)
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
if (!hci_uart_has_flow_control(hu))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mrvl = kzalloc(sizeof(*mrvl), GFP_KERNEL);
|
||||
if (!mrvl)
|
||||
return -ENOMEM;
|
||||
|
@ -117,6 +117,7 @@ void hci_uart_unregister_device(struct hci_uart *hu);
|
||||
int hci_uart_tx_wakeup(struct hci_uart *hu);
|
||||
int hci_uart_init_ready(struct hci_uart *hu);
|
||||
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
|
||||
bool hci_uart_has_flow_control(struct hci_uart *hu);
|
||||
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
|
||||
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
|
||||
unsigned int oper_speed);
|
||||
|
@ -844,6 +844,8 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
|
||||
}
|
||||
|
||||
if (ret || qup->bus_err || qup->qup_err) {
|
||||
reinit_completion(&qup->xfer);
|
||||
|
||||
if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
|
||||
dev_err(qup->dev, "change to run state timed out");
|
||||
goto desc_err;
|
||||
|
@ -3702,7 +3702,7 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
|
||||
|
||||
freelist = domain_unmap(domain, start_pfn, last_pfn);
|
||||
|
||||
if (intel_iommu_strict) {
|
||||
if (intel_iommu_strict || !has_iova_flush_queue(&domain->iovad)) {
|
||||
iommu_flush_iotlb_psi(iommu, domain, start_pfn,
|
||||
nrpages, !freelist, 0);
|
||||
/* free iova */
|
||||
|
@ -58,9 +58,14 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(init_iova_domain);
|
||||
|
||||
bool has_iova_flush_queue(struct iova_domain *iovad)
|
||||
{
|
||||
return !!iovad->fq;
|
||||
}
|
||||
|
||||
static void free_iova_flush_queue(struct iova_domain *iovad)
|
||||
{
|
||||
if (!iovad->fq)
|
||||
if (!has_iova_flush_queue(iovad))
|
||||
return;
|
||||
|
||||
if (timer_pending(&iovad->fq_timer))
|
||||
@ -78,13 +83,14 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
|
||||
int init_iova_flush_queue(struct iova_domain *iovad,
|
||||
iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
|
||||
{
|
||||
struct iova_fq __percpu *queue;
|
||||
int cpu;
|
||||
|
||||
atomic64_set(&iovad->fq_flush_start_cnt, 0);
|
||||
atomic64_set(&iovad->fq_flush_finish_cnt, 0);
|
||||
|
||||
iovad->fq = alloc_percpu(struct iova_fq);
|
||||
if (!iovad->fq)
|
||||
queue = alloc_percpu(struct iova_fq);
|
||||
if (!queue)
|
||||
return -ENOMEM;
|
||||
|
||||
iovad->flush_cb = flush_cb;
|
||||
@ -93,13 +99,17 @@ int init_iova_flush_queue(struct iova_domain *iovad,
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct iova_fq *fq;
|
||||
|
||||
fq = per_cpu_ptr(iovad->fq, cpu);
|
||||
fq = per_cpu_ptr(queue, cpu);
|
||||
fq->head = 0;
|
||||
fq->tail = 0;
|
||||
|
||||
spin_lock_init(&fq->lock);
|
||||
}
|
||||
|
||||
smp_wmb();
|
||||
|
||||
iovad->fq = queue;
|
||||
|
||||
setup_timer(&iovad->fq_timer, fq_flush_timeout, (unsigned long)iovad);
|
||||
atomic_set(&iovad->fq_timer_on, 0);
|
||||
|
||||
|
@ -1963,6 +1963,9 @@ hfcsusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
|
||||
/* get endpoint base */
|
||||
idx = ((ep_addr & 0x7f) - 1) * 2;
|
||||
if (idx > 15)
|
||||
return -EIO;
|
||||
|
||||
if (ep_addr & 0x80)
|
||||
idx++;
|
||||
attr = ep->desc.bmAttributes;
|
||||
|
@ -283,6 +283,14 @@ static int vidioc_g_frequency(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void raremono_device_release(struct v4l2_device *v4l2_dev)
|
||||
{
|
||||
struct raremono_device *radio = to_raremono_dev(v4l2_dev);
|
||||
|
||||
kfree(radio->buffer);
|
||||
kfree(radio);
|
||||
}
|
||||
|
||||
/* File system interface */
|
||||
static const struct v4l2_file_operations usb_raremono_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
@ -307,12 +315,14 @@ static int usb_raremono_probe(struct usb_interface *intf,
|
||||
struct raremono_device *radio;
|
||||
int retval = 0;
|
||||
|
||||
radio = devm_kzalloc(&intf->dev, sizeof(struct raremono_device), GFP_KERNEL);
|
||||
if (radio)
|
||||
radio->buffer = devm_kmalloc(&intf->dev, BUFFER_LENGTH, GFP_KERNEL);
|
||||
|
||||
if (!radio || !radio->buffer)
|
||||
radio = kzalloc(sizeof(*radio), GFP_KERNEL);
|
||||
if (!radio)
|
||||
return -ENOMEM;
|
||||
radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
|
||||
if (!radio->buffer) {
|
||||
kfree(radio);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
radio->usbdev = interface_to_usbdev(intf);
|
||||
radio->intf = intf;
|
||||
@ -336,7 +346,8 @@ static int usb_raremono_probe(struct usb_interface *intf,
|
||||
if (retval != 3 ||
|
||||
(get_unaligned_be16(&radio->buffer[1]) & 0xfff) == 0x0242) {
|
||||
dev_info(&intf->dev, "this is not Thanko's Raremono.\n");
|
||||
return -ENODEV;
|
||||
retval = -ENODEV;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
dev_info(&intf->dev, "Thanko's Raremono connected: (%04X:%04X)\n",
|
||||
@ -345,7 +356,7 @@ static int usb_raremono_probe(struct usb_interface *intf,
|
||||
retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
|
||||
if (retval < 0) {
|
||||
dev_err(&intf->dev, "couldn't register v4l2_device\n");
|
||||
return retval;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
mutex_init(&radio->lock);
|
||||
@ -357,6 +368,7 @@ static int usb_raremono_probe(struct usb_interface *intf,
|
||||
radio->vdev.ioctl_ops = &usb_raremono_ioctl_ops;
|
||||
radio->vdev.lock = &radio->lock;
|
||||
radio->vdev.release = video_device_release_empty;
|
||||
radio->v4l2_dev.release = raremono_device_release;
|
||||
|
||||
usb_set_intfdata(intf, &radio->v4l2_dev);
|
||||
|
||||
@ -372,6 +384,10 @@ static int usb_raremono_probe(struct usb_interface *intf,
|
||||
}
|
||||
dev_err(&intf->dev, "could not register video device\n");
|
||||
v4l2_device_unregister(&radio->v4l2_dev);
|
||||
|
||||
free_mem:
|
||||
kfree(radio->buffer);
|
||||
kfree(radio);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -623,6 +623,12 @@ static int au0828_usb_probe(struct usb_interface *interface,
|
||||
/* Setup */
|
||||
au0828_card_setup(dev);
|
||||
|
||||
/*
|
||||
* Store the pointer to the au0828_dev so it can be accessed in
|
||||
* au0828_usb_disconnect
|
||||
*/
|
||||
usb_set_intfdata(interface, dev);
|
||||
|
||||
/* Analog TV */
|
||||
retval = au0828_analog_register(dev, interface);
|
||||
if (retval) {
|
||||
@ -641,12 +647,6 @@ static int au0828_usb_probe(struct usb_interface *interface,
|
||||
/* Remote controller */
|
||||
au0828_rc_register(dev);
|
||||
|
||||
/*
|
||||
* Store the pointer to the au0828_dev so it can be accessed in
|
||||
* au0828_usb_disconnect
|
||||
*/
|
||||
usb_set_intfdata(interface, dev);
|
||||
|
||||
pr_info("Registered device AU0828 [%s]\n",
|
||||
dev->board.name == NULL ? "Unset" : dev->board.name);
|
||||
|
||||
|
@ -901,7 +901,6 @@ static void cpia2_usb_disconnect(struct usb_interface *intf)
|
||||
cpia2_unregister_camera(cam);
|
||||
v4l2_device_disconnect(&cam->v4l2_dev);
|
||||
mutex_unlock(&cam->v4l2_lock);
|
||||
v4l2_device_put(&cam->v4l2_dev);
|
||||
|
||||
if(cam->buffers) {
|
||||
DBG("Wakeup waiting processes\n");
|
||||
@ -913,6 +912,8 @@ static void cpia2_usb_disconnect(struct usb_interface *intf)
|
||||
DBG("Releasing interface\n");
|
||||
usb_driver_release_interface(&cpia2_driver, intf);
|
||||
|
||||
v4l2_device_put(&cam->v4l2_dev);
|
||||
|
||||
LOG("CPiA2 camera disconnected.\n");
|
||||
}
|
||||
|
||||
|
@ -1680,7 +1680,7 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl)
|
||||
}
|
||||
if (!hdw->flag_decoder_missed) {
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"WARNING: No decoder present");
|
||||
"***WARNING*** No decoder present");
|
||||
hdw->flag_decoder_missed = !0;
|
||||
trace_stbit("flag_decoder_missed",
|
||||
hdw->flag_decoder_missed);
|
||||
@ -2365,7 +2365,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
|
||||
if (hdw_desc->flag_is_experimental) {
|
||||
pvr2_trace(PVR2_TRACE_INFO, "**********");
|
||||
pvr2_trace(PVR2_TRACE_INFO,
|
||||
"WARNING: Support for this device (%s) is experimental.",
|
||||
"***WARNING*** Support for this device (%s) is experimental.",
|
||||
hdw_desc->description);
|
||||
pvr2_trace(PVR2_TRACE_INFO,
|
||||
"Important functionality might not be entirely working.");
|
||||
|
@ -343,11 +343,11 @@ static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
|
||||
|
||||
if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"WARNING: Detected a wedged cx25840 chip; the device will not work.");
|
||||
"***WARNING*** Detected a wedged cx25840 chip; the device will not work.");
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"WARNING: Try power cycling the pvrusb2 device.");
|
||||
"***WARNING*** Try power cycling the pvrusb2 device.");
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"WARNING: Disabling further access to the device to prevent other foul-ups.");
|
||||
"***WARNING*** Disabling further access to the device to prevent other foul-ups.");
|
||||
// This blocks all further communication with the part.
|
||||
hdw->i2c_func[0x44] = NULL;
|
||||
pvr2_hdw_render_useless(hdw);
|
||||
|
@ -353,7 +353,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
|
||||
bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
|
||||
pvr2_trace(
|
||||
PVR2_TRACE_ERROR_LEGS,
|
||||
"WARNING: Failed to classify the following standard(s): %.*s",
|
||||
"***WARNING*** Failed to classify the following standard(s): %.*s",
|
||||
bcnt,buf);
|
||||
}
|
||||
|
||||
|
@ -1025,7 +1025,7 @@ static int ath10k_usb_probe(struct usb_interface *interface,
|
||||
}
|
||||
|
||||
/* TODO: remove this once USB support is fully implemented */
|
||||
ath10k_warn(ar, "WARNING: ath10k USB support is incomplete, don't expect anything to work!\n");
|
||||
ath10k_warn(ar, "Warning: ath10k USB support is incomplete, don't expect anything to work!\n");
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -166,6 +166,14 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
pps->params.mode |= PPS_CANWAIT;
|
||||
pps->params.api_version = PPS_API_VERS;
|
||||
|
||||
/*
|
||||
* Clear unused fields of pps_kparams to avoid leaking
|
||||
* uninitialized data of the PPS_SETPARAMS caller via
|
||||
* PPS_GETPARAMS
|
||||
*/
|
||||
pps->params.assert_off_tu.flags = 0;
|
||||
pps->params.clear_off_tu.flags = 0;
|
||||
|
||||
spin_unlock_irq(&pps->lock);
|
||||
|
||||
break;
|
||||
|
@ -50,9 +50,9 @@
|
||||
* @page: structure to page
|
||||
*
|
||||
*/
|
||||
static int v9fs_fid_readpage(void *data, struct page *page)
|
||||
static int v9fs_fid_readpage(struct file *data, struct page *page)
|
||||
{
|
||||
struct p9_fid *fid = data;
|
||||
struct p9_fid *fid = (struct p9_fid *)data;
|
||||
struct inode *inode = page->mapping->host;
|
||||
struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE};
|
||||
struct iov_iter to;
|
||||
@ -294,7 +294,7 @@ start:
|
||||
if (len == PAGE_SIZE)
|
||||
goto out;
|
||||
|
||||
retval = v9fs_fid_readpage(v9inode->writeback_fid, page);
|
||||
retval = v9fs_fid_readpage((struct file *)v9inode->writeback_fid, page);
|
||||
put_page(page);
|
||||
if (!retval)
|
||||
goto start;
|
||||
|
@ -1119,20 +1119,23 @@ static int send_cap_msg(struct cap_msg_args *arg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue cap releases when an inode is dropped from our cache. Since
|
||||
* inode is about to be destroyed, there is no need for i_ceph_lock.
|
||||
* Queue cap releases when an inode is dropped from our cache.
|
||||
*/
|
||||
void ceph_queue_caps_release(struct inode *inode)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
struct rb_node *p;
|
||||
|
||||
/* lock i_ceph_lock, because ceph_d_revalidate(..., LOOKUP_RCU)
|
||||
* may call __ceph_caps_issued_mask() on a freeing inode. */
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
p = rb_first(&ci->i_caps);
|
||||
while (p) {
|
||||
struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
|
||||
p = rb_next(p);
|
||||
__ceph_remove_cap(cap, true);
|
||||
}
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1808,7 +1808,7 @@ static int do_execveat_common(int fd, struct filename *filename,
|
||||
current->in_execve = 0;
|
||||
membarrier_execve(current);
|
||||
acct_update_integrals(current);
|
||||
task_numa_free(current);
|
||||
task_numa_free(current, false);
|
||||
free_bprm(bprm);
|
||||
kfree(pathbuf);
|
||||
putname(filename);
|
||||
|
@ -416,10 +416,10 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
|
||||
clp = nfs_match_client(cl_init);
|
||||
if (clp) {
|
||||
spin_unlock(&nn->nfs_client_lock);
|
||||
if (IS_ERR(clp))
|
||||
return clp;
|
||||
if (new)
|
||||
new->rpc_ops->free_client(new);
|
||||
if (IS_ERR(clp))
|
||||
return clp;
|
||||
return nfs_found_client(cl_init, clp);
|
||||
}
|
||||
if (new) {
|
||||
|
293
fs/nfs/dir.c
293
fs/nfs/dir.c
@ -1060,6 +1060,100 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
|
||||
return !nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU);
|
||||
}
|
||||
|
||||
static int
|
||||
nfs_lookup_revalidate_done(struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode, int error)
|
||||
{
|
||||
switch (error) {
|
||||
case 1:
|
||||
dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is valid\n",
|
||||
__func__, dentry);
|
||||
return 1;
|
||||
case 0:
|
||||
nfs_mark_for_revalidate(dir);
|
||||
if (inode && S_ISDIR(inode->i_mode)) {
|
||||
/* Purge readdir caches. */
|
||||
nfs_zap_caches(inode);
|
||||
/*
|
||||
* We can't d_drop the root of a disconnected tree:
|
||||
* its d_hash is on the s_anon list and d_drop() would hide
|
||||
* it from shrink_dcache_for_unmount(), leading to busy
|
||||
* inodes on unmount and further oopses.
|
||||
*/
|
||||
if (IS_ROOT(dentry))
|
||||
return 1;
|
||||
}
|
||||
dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is invalid\n",
|
||||
__func__, dentry);
|
||||
return 0;
|
||||
}
|
||||
dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) lookup returned error %d\n",
|
||||
__func__, dentry, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nfs_lookup_revalidate_negative(struct inode *dir, struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
int ret = 1;
|
||||
if (nfs_neg_need_reval(dir, dentry, flags)) {
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
ret = 0;
|
||||
}
|
||||
return nfs_lookup_revalidate_done(dir, dentry, NULL, ret);
|
||||
}
|
||||
|
||||
static int
|
||||
nfs_lookup_revalidate_delegated(struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode)
|
||||
{
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
return nfs_lookup_revalidate_done(dir, dentry, inode, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
nfs_lookup_revalidate_dentry(struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct nfs_fh *fhandle;
|
||||
struct nfs_fattr *fattr;
|
||||
struct nfs4_label *label;
|
||||
int ret;
|
||||
|
||||
ret = -ENOMEM;
|
||||
fhandle = nfs_alloc_fhandle();
|
||||
fattr = nfs_alloc_fattr();
|
||||
label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
|
||||
if (fhandle == NULL || fattr == NULL || IS_ERR(label))
|
||||
goto out;
|
||||
|
||||
ret = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
|
||||
if (ret < 0) {
|
||||
if (ret == -ESTALE || ret == -ENOENT)
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
if (nfs_compare_fh(NFS_FH(inode), fhandle))
|
||||
goto out;
|
||||
if (nfs_refresh_inode(inode, fattr) < 0)
|
||||
goto out;
|
||||
|
||||
nfs_setsecurity(inode, fattr, label);
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
|
||||
/* set a readdirplus hint that we had a cache miss */
|
||||
nfs_force_use_readdirplus(dir);
|
||||
ret = 1;
|
||||
out:
|
||||
nfs_free_fattr(fattr);
|
||||
nfs_free_fhandle(fhandle);
|
||||
nfs4_label_free(label);
|
||||
return nfs_lookup_revalidate_done(dir, dentry, inode, ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called every time the dcache has a lookup hit,
|
||||
* and we should check whether we can really trust that
|
||||
@ -1071,58 +1165,36 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
|
||||
* If the parent directory is seen to have changed, we throw out the
|
||||
* cached dentry and do a new lookup.
|
||||
*/
|
||||
static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
static int
|
||||
nfs_do_lookup_revalidate(struct inode *dir, struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct inode *dir;
|
||||
struct inode *inode;
|
||||
struct dentry *parent;
|
||||
struct nfs_fh *fhandle = NULL;
|
||||
struct nfs_fattr *fattr = NULL;
|
||||
struct nfs4_label *label = NULL;
|
||||
int error;
|
||||
|
||||
if (flags & LOOKUP_RCU) {
|
||||
parent = ACCESS_ONCE(dentry->d_parent);
|
||||
dir = d_inode_rcu(parent);
|
||||
if (!dir)
|
||||
return -ECHILD;
|
||||
} else {
|
||||
parent = dget_parent(dentry);
|
||||
dir = d_inode(parent);
|
||||
}
|
||||
nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
|
||||
inode = d_inode(dentry);
|
||||
|
||||
if (!inode) {
|
||||
if (nfs_neg_need_reval(dir, dentry, flags)) {
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
goto out_bad;
|
||||
}
|
||||
goto out_valid;
|
||||
}
|
||||
if (!inode)
|
||||
return nfs_lookup_revalidate_negative(dir, dentry, flags);
|
||||
|
||||
if (is_bad_inode(inode)) {
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
dfprintk(LOOKUPCACHE, "%s: %pd2 has dud inode\n",
|
||||
__func__, dentry);
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
if (NFS_PROTO(dir)->have_delegation(inode, FMODE_READ))
|
||||
goto out_set_verifier;
|
||||
return nfs_lookup_revalidate_delegated(dir, dentry, inode);
|
||||
|
||||
/* Force a full look up iff the parent directory has changed */
|
||||
if (!nfs_is_exclusive_create(dir, flags) &&
|
||||
nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) {
|
||||
error = nfs_lookup_verify_inode(inode, flags);
|
||||
if (error) {
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
if (error == -ESTALE)
|
||||
goto out_zap_parent;
|
||||
goto out_error;
|
||||
nfs_zap_caches(dir);
|
||||
goto out_bad;
|
||||
}
|
||||
nfs_advise_use_readdirplus(dir);
|
||||
goto out_valid;
|
||||
@ -1134,81 +1206,45 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
if (NFS_STALE(inode))
|
||||
goto out_bad;
|
||||
|
||||
error = -ENOMEM;
|
||||
fhandle = nfs_alloc_fhandle();
|
||||
fattr = nfs_alloc_fattr();
|
||||
if (fhandle == NULL || fattr == NULL)
|
||||
goto out_error;
|
||||
|
||||
label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT);
|
||||
if (IS_ERR(label))
|
||||
goto out_error;
|
||||
|
||||
trace_nfs_lookup_revalidate_enter(dir, dentry, flags);
|
||||
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
|
||||
error = nfs_lookup_revalidate_dentry(dir, dentry, inode);
|
||||
trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error);
|
||||
if (error == -ESTALE || error == -ENOENT)
|
||||
goto out_bad;
|
||||
if (error)
|
||||
goto out_error;
|
||||
if (nfs_compare_fh(NFS_FH(inode), fhandle))
|
||||
goto out_bad;
|
||||
if ((error = nfs_refresh_inode(inode, fattr)) != 0)
|
||||
goto out_bad;
|
||||
return error;
|
||||
out_valid:
|
||||
return nfs_lookup_revalidate_done(dir, dentry, inode, 1);
|
||||
out_bad:
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
return nfs_lookup_revalidate_done(dir, dentry, inode, 0);
|
||||
}
|
||||
|
||||
nfs_setsecurity(inode, fattr, label);
|
||||
static int
|
||||
__nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags,
|
||||
int (*reval)(struct inode *, struct dentry *, unsigned int))
|
||||
{
|
||||
struct dentry *parent;
|
||||
struct inode *dir;
|
||||
int ret;
|
||||
|
||||
nfs_free_fattr(fattr);
|
||||
nfs_free_fhandle(fhandle);
|
||||
nfs4_label_free(label);
|
||||
|
||||
/* set a readdirplus hint that we had a cache miss */
|
||||
nfs_force_use_readdirplus(dir);
|
||||
|
||||
out_set_verifier:
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
out_valid:
|
||||
if (flags & LOOKUP_RCU) {
|
||||
parent = ACCESS_ONCE(dentry->d_parent);
|
||||
dir = d_inode_rcu(parent);
|
||||
if (!dir)
|
||||
return -ECHILD;
|
||||
ret = reval(dir, dentry, flags);
|
||||
if (parent != ACCESS_ONCE(dentry->d_parent))
|
||||
return -ECHILD;
|
||||
} else
|
||||
} else {
|
||||
parent = dget_parent(dentry);
|
||||
ret = reval(d_inode(parent), dentry, flags);
|
||||
dput(parent);
|
||||
dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is valid\n",
|
||||
__func__, dentry);
|
||||
return 1;
|
||||
out_zap_parent:
|
||||
nfs_zap_caches(dir);
|
||||
out_bad:
|
||||
WARN_ON(flags & LOOKUP_RCU);
|
||||
nfs_free_fattr(fattr);
|
||||
nfs_free_fhandle(fhandle);
|
||||
nfs4_label_free(label);
|
||||
nfs_mark_for_revalidate(dir);
|
||||
if (inode && S_ISDIR(inode->i_mode)) {
|
||||
/* Purge readdir caches. */
|
||||
nfs_zap_caches(inode);
|
||||
/*
|
||||
* We can't d_drop the root of a disconnected tree:
|
||||
* its d_hash is on the s_anon list and d_drop() would hide
|
||||
* it from shrink_dcache_for_unmount(), leading to busy
|
||||
* inodes on unmount and further oopses.
|
||||
*/
|
||||
if (IS_ROOT(dentry))
|
||||
goto out_valid;
|
||||
}
|
||||
dput(parent);
|
||||
dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is invalid\n",
|
||||
__func__, dentry);
|
||||
return 0;
|
||||
out_error:
|
||||
WARN_ON(flags & LOOKUP_RCU);
|
||||
nfs_free_fattr(fattr);
|
||||
nfs_free_fhandle(fhandle);
|
||||
nfs4_label_free(label);
|
||||
dput(parent);
|
||||
dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) lookup returned error %d\n",
|
||||
__func__, dentry, error);
|
||||
return error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
{
|
||||
return __nfs_lookup_revalidate(dentry, flags, nfs_do_lookup_revalidate);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1561,62 +1597,55 @@ no_open:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_atomic_open);
|
||||
|
||||
static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
static int
|
||||
nfs4_do_lookup_revalidate(struct inode *dir, struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct inode *inode;
|
||||
int ret = 0;
|
||||
|
||||
if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY))
|
||||
goto no_open;
|
||||
goto full_reval;
|
||||
if (d_mountpoint(dentry))
|
||||
goto no_open;
|
||||
if (NFS_SB(dentry->d_sb)->caps & NFS_CAP_ATOMIC_OPEN_V1)
|
||||
goto no_open;
|
||||
goto full_reval;
|
||||
|
||||
inode = d_inode(dentry);
|
||||
|
||||
/* We can't create new files in nfs_open_revalidate(), so we
|
||||
* optimize away revalidation of negative dentries.
|
||||
*/
|
||||
if (inode == NULL) {
|
||||
struct dentry *parent;
|
||||
struct inode *dir;
|
||||
if (inode == NULL)
|
||||
goto full_reval;
|
||||
|
||||
if (flags & LOOKUP_RCU) {
|
||||
parent = ACCESS_ONCE(dentry->d_parent);
|
||||
dir = d_inode_rcu(parent);
|
||||
if (!dir)
|
||||
return -ECHILD;
|
||||
} else {
|
||||
parent = dget_parent(dentry);
|
||||
dir = d_inode(parent);
|
||||
}
|
||||
if (!nfs_neg_need_reval(dir, dentry, flags))
|
||||
ret = 1;
|
||||
else if (flags & LOOKUP_RCU)
|
||||
ret = -ECHILD;
|
||||
if (!(flags & LOOKUP_RCU))
|
||||
dput(parent);
|
||||
else if (parent != ACCESS_ONCE(dentry->d_parent))
|
||||
return -ECHILD;
|
||||
goto out;
|
||||
}
|
||||
if (NFS_PROTO(dir)->have_delegation(inode, FMODE_READ))
|
||||
return nfs_lookup_revalidate_delegated(dir, dentry, inode);
|
||||
|
||||
/* NFS only supports OPEN on regular files */
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
goto no_open;
|
||||
goto full_reval;
|
||||
|
||||
/* We cannot do exclusive creation on a positive dentry */
|
||||
if (flags & LOOKUP_EXCL)
|
||||
goto no_open;
|
||||
if (flags & (LOOKUP_EXCL | LOOKUP_REVAL))
|
||||
goto reval_dentry;
|
||||
|
||||
/* Check if the directory changed */
|
||||
if (!nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU))
|
||||
goto reval_dentry;
|
||||
|
||||
/* Let f_op->open() actually open (and revalidate) the file */
|
||||
ret = 1;
|
||||
return 1;
|
||||
reval_dentry:
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
return nfs_lookup_revalidate_dentry(dir, dentry, inode);;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
full_reval:
|
||||
return nfs_do_lookup_revalidate(dir, dentry, flags);
|
||||
}
|
||||
|
||||
no_open:
|
||||
return nfs_lookup_revalidate(dentry, flags);
|
||||
static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
{
|
||||
return __nfs_lookup_revalidate(dentry, flags,
|
||||
nfs4_do_lookup_revalidate);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NFSV4 */
|
||||
|
@ -1317,12 +1317,20 @@ static bool nfs4_mode_match_open_stateid(struct nfs4_state *state,
|
||||
return false;
|
||||
}
|
||||
|
||||
static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode)
|
||||
static int can_open_cached(struct nfs4_state *state, fmode_t mode,
|
||||
int open_mode, enum open_claim_type4 claim)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (open_mode & (O_EXCL|O_TRUNC))
|
||||
goto out;
|
||||
switch (claim) {
|
||||
case NFS4_OPEN_CLAIM_NULL:
|
||||
case NFS4_OPEN_CLAIM_FH:
|
||||
goto out;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (mode & (FMODE_READ|FMODE_WRITE)) {
|
||||
case FMODE_READ:
|
||||
ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0
|
||||
@ -1617,7 +1625,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
|
||||
|
||||
for (;;) {
|
||||
spin_lock(&state->owner->so_lock);
|
||||
if (can_open_cached(state, fmode, open_mode)) {
|
||||
if (can_open_cached(state, fmode, open_mode, claim)) {
|
||||
update_open_stateflags(state, fmode);
|
||||
spin_unlock(&state->owner->so_lock);
|
||||
goto out_return_state;
|
||||
@ -2141,7 +2149,8 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
|
||||
if (data->state != NULL) {
|
||||
struct nfs_delegation *delegation;
|
||||
|
||||
if (can_open_cached(data->state, data->o_arg.fmode, data->o_arg.open_flags))
|
||||
if (can_open_cached(data->state, data->o_arg.fmode,
|
||||
data->o_arg.open_flags, claim))
|
||||
goto out_no_action;
|
||||
rcu_read_lock();
|
||||
delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
|
||||
|
@ -154,6 +154,7 @@ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
|
||||
void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
|
||||
void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
|
||||
unsigned long start_pfn, unsigned long pfn_32bit);
|
||||
bool has_iova_flush_queue(struct iova_domain *iovad);
|
||||
int init_iova_flush_queue(struct iova_domain *iovad,
|
||||
iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
|
||||
struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
|
||||
@ -234,6 +235,11 @@ static inline void init_iova_domain(struct iova_domain *iovad,
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool has_iova_flush_queue(struct iova_domain *iovad)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int init_iova_flush_queue(struct iova_domain *iovad,
|
||||
iova_flush_cb flush_cb,
|
||||
iova_entry_dtor entry_dtor)
|
||||
|
@ -19,7 +19,7 @@
|
||||
extern void task_numa_fault(int last_node, int node, int pages, int flags);
|
||||
extern pid_t task_numa_group_id(struct task_struct *p);
|
||||
extern void set_numabalancing_state(bool enabled);
|
||||
extern void task_numa_free(struct task_struct *p);
|
||||
extern void task_numa_free(struct task_struct *p, bool final);
|
||||
extern bool should_numa_migrate_memory(struct task_struct *p, struct page *page,
|
||||
int src_nid, int dst_cpu);
|
||||
#else
|
||||
@ -34,7 +34,7 @@ static inline pid_t task_numa_group_id(struct task_struct *p)
|
||||
static inline void set_numabalancing_state(bool enabled)
|
||||
{
|
||||
}
|
||||
static inline void task_numa_free(struct task_struct *p)
|
||||
static inline void task_numa_free(struct task_struct *p, bool final)
|
||||
{
|
||||
}
|
||||
static inline bool should_numa_migrate_memory(struct task_struct *p,
|
||||
|
@ -22,9 +22,6 @@
|
||||
|
||||
#include "vsock_addr.h"
|
||||
|
||||
/* vsock-specific sock->sk_state constants */
|
||||
#define VSOCK_SS_LISTEN 255
|
||||
|
||||
#define LAST_RESERVED_PORT 1023
|
||||
|
||||
#define vsock_sk(__sk) ((struct vsock_sock *)__sk)
|
||||
|
@ -418,7 +418,7 @@ void __put_task_struct(struct task_struct *tsk)
|
||||
WARN_ON(tsk == current);
|
||||
|
||||
cgroup_free(tsk);
|
||||
task_numa_free(tsk);
|
||||
task_numa_free(tsk, true);
|
||||
security_task_free(tsk);
|
||||
exit_creds(tsk);
|
||||
delayacct_tsk_free(tsk);
|
||||
|
@ -2429,13 +2429,23 @@ no_join:
|
||||
return;
|
||||
}
|
||||
|
||||
void task_numa_free(struct task_struct *p)
|
||||
/*
|
||||
* Get rid of NUMA staticstics associated with a task (either current or dead).
|
||||
* If @final is set, the task is dead and has reached refcount zero, so we can
|
||||
* safely free all relevant data structures. Otherwise, there might be
|
||||
* concurrent reads from places like load balancing and procfs, and we should
|
||||
* reset the data back to default state without freeing ->numa_faults.
|
||||
*/
|
||||
void task_numa_free(struct task_struct *p, bool final)
|
||||
{
|
||||
struct numa_group *grp = p->numa_group;
|
||||
void *numa_faults = p->numa_faults;
|
||||
unsigned long *numa_faults = p->numa_faults;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (!numa_faults)
|
||||
return;
|
||||
|
||||
if (grp) {
|
||||
spin_lock_irqsave(&grp->lock, flags);
|
||||
for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
|
||||
@ -2448,8 +2458,14 @@ void task_numa_free(struct task_struct *p)
|
||||
put_numa_group(grp);
|
||||
}
|
||||
|
||||
p->numa_faults = NULL;
|
||||
kfree(numa_faults);
|
||||
if (final) {
|
||||
p->numa_faults = NULL;
|
||||
kfree(numa_faults);
|
||||
} else {
|
||||
p->total_numa_faults = 0;
|
||||
for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
|
||||
numa_faults[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -89,9 +89,12 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
|
||||
__ip_select_ident(net, iph, skb_shinfo(skb)->gso_segs ?: 1);
|
||||
|
||||
err = ip_local_out(net, sk, skb);
|
||||
if (unlikely(net_xmit_eval(err)))
|
||||
pkt_len = 0;
|
||||
iptunnel_xmit_stats(dev, pkt_len);
|
||||
|
||||
if (dev) {
|
||||
if (unlikely(net_xmit_eval(err)))
|
||||
pkt_len = 0;
|
||||
iptunnel_xmit_stats(dev, pkt_len);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iptunnel_xmit);
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
* not support simultaneous connects (two "client" sockets connecting).
|
||||
*
|
||||
* - "Server" sockets are referred to as listener sockets throughout this
|
||||
* implementation because they are in the VSOCK_SS_LISTEN state. When a
|
||||
* implementation because they are in the TCP_LISTEN state. When a
|
||||
* connection request is received (the second kind of socket mentioned above),
|
||||
* we create a new socket and refer to it as a pending socket. These pending
|
||||
* sockets are placed on the pending connection list of the listener socket.
|
||||
@ -82,6 +82,15 @@
|
||||
* argument, we must ensure the reference count is increased to ensure the
|
||||
* socket isn't freed before the function is run; the deferred function will
|
||||
* then drop the reference.
|
||||
*
|
||||
* - sk->sk_state uses the TCP state constants because they are widely used by
|
||||
* other address families and exposed to userspace tools like ss(8):
|
||||
*
|
||||
* TCP_CLOSE - unconnected
|
||||
* TCP_SYN_SENT - connecting
|
||||
* TCP_ESTABLISHED - connected
|
||||
* TCP_CLOSING - disconnecting
|
||||
* TCP_LISTEN - listening
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
@ -279,7 +288,8 @@ EXPORT_SYMBOL_GPL(vsock_insert_connected);
|
||||
void vsock_remove_bound(struct vsock_sock *vsk)
|
||||
{
|
||||
spin_lock_bh(&vsock_table_lock);
|
||||
__vsock_remove_bound(vsk);
|
||||
if (__vsock_in_bound_table(vsk))
|
||||
__vsock_remove_bound(vsk);
|
||||
spin_unlock_bh(&vsock_table_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vsock_remove_bound);
|
||||
@ -287,7 +297,8 @@ EXPORT_SYMBOL_GPL(vsock_remove_bound);
|
||||
void vsock_remove_connected(struct vsock_sock *vsk)
|
||||
{
|
||||
spin_lock_bh(&vsock_table_lock);
|
||||
__vsock_remove_connected(vsk);
|
||||
if (__vsock_in_connected_table(vsk))
|
||||
__vsock_remove_connected(vsk);
|
||||
spin_unlock_bh(&vsock_table_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vsock_remove_connected);
|
||||
@ -323,35 +334,10 @@ struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vsock_find_connected_socket);
|
||||
|
||||
static bool vsock_in_bound_table(struct vsock_sock *vsk)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
spin_lock_bh(&vsock_table_lock);
|
||||
ret = __vsock_in_bound_table(vsk);
|
||||
spin_unlock_bh(&vsock_table_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool vsock_in_connected_table(struct vsock_sock *vsk)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
spin_lock_bh(&vsock_table_lock);
|
||||
ret = __vsock_in_connected_table(vsk);
|
||||
spin_unlock_bh(&vsock_table_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vsock_remove_sock(struct vsock_sock *vsk)
|
||||
{
|
||||
if (vsock_in_bound_table(vsk))
|
||||
vsock_remove_bound(vsk);
|
||||
|
||||
if (vsock_in_connected_table(vsk))
|
||||
vsock_remove_connected(vsk);
|
||||
vsock_remove_bound(vsk);
|
||||
vsock_remove_connected(vsk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vsock_remove_sock);
|
||||
|
||||
@ -482,10 +468,9 @@ static void vsock_pending_work(struct work_struct *work)
|
||||
* incoming packets can't find this socket, and to reduce the reference
|
||||
* count.
|
||||
*/
|
||||
if (vsock_in_connected_table(vsk))
|
||||
vsock_remove_connected(vsk);
|
||||
vsock_remove_connected(vsk);
|
||||
|
||||
sk->sk_state = SS_FREE;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
|
||||
out:
|
||||
release_sock(sk);
|
||||
@ -626,7 +611,6 @@ struct sock *__vsock_create(struct net *net,
|
||||
|
||||
sk->sk_destruct = vsock_sk_destruct;
|
||||
sk->sk_backlog_rcv = vsock_queue_rcv_skb;
|
||||
sk->sk_state = 0;
|
||||
sock_reset_flag(sk, SOCK_DONE);
|
||||
|
||||
INIT_LIST_HEAD(&vsk->bound_table);
|
||||
@ -902,7 +886,7 @@ static unsigned int vsock_poll(struct file *file, struct socket *sock,
|
||||
/* Listening sockets that have connections in their accept
|
||||
* queue can be read.
|
||||
*/
|
||||
if (sk->sk_state == VSOCK_SS_LISTEN
|
||||
if (sk->sk_state == TCP_LISTEN
|
||||
&& !vsock_is_accept_queue_empty(sk))
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
|
||||
@ -931,7 +915,7 @@ static unsigned int vsock_poll(struct file *file, struct socket *sock,
|
||||
}
|
||||
|
||||
/* Connected sockets that can produce data can be written. */
|
||||
if (sk->sk_state == SS_CONNECTED) {
|
||||
if (sk->sk_state == TCP_ESTABLISHED) {
|
||||
if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
|
||||
bool space_avail_now = false;
|
||||
int ret = transport->notify_poll_out(
|
||||
@ -953,7 +937,7 @@ static unsigned int vsock_poll(struct file *file, struct socket *sock,
|
||||
* POLLOUT|POLLWRNORM when peer is closed and nothing to read,
|
||||
* but local send is not shutdown.
|
||||
*/
|
||||
if (sk->sk_state == SS_UNCONNECTED) {
|
||||
if (sk->sk_state == TCP_CLOSE) {
|
||||
if (!(sk->sk_shutdown & SEND_SHUTDOWN))
|
||||
mask |= POLLOUT | POLLWRNORM;
|
||||
|
||||
@ -1123,9 +1107,9 @@ static void vsock_connect_timeout(struct work_struct *work)
|
||||
sk = sk_vsock(vsk);
|
||||
|
||||
lock_sock(sk);
|
||||
if (sk->sk_state == SS_CONNECTING &&
|
||||
if (sk->sk_state == TCP_SYN_SENT &&
|
||||
(sk->sk_shutdown != SHUTDOWN_MASK)) {
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
sk->sk_err = ETIMEDOUT;
|
||||
sk->sk_error_report(sk);
|
||||
cancel = 1;
|
||||
@ -1171,7 +1155,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
|
||||
err = -EALREADY;
|
||||
break;
|
||||
default:
|
||||
if ((sk->sk_state == VSOCK_SS_LISTEN) ||
|
||||
if ((sk->sk_state == TCP_LISTEN) ||
|
||||
vsock_addr_cast(addr, addr_len, &remote_addr) != 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@ -1194,7 +1178,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
sk->sk_state = SS_CONNECTING;
|
||||
sk->sk_state = TCP_SYN_SENT;
|
||||
|
||||
err = transport->connect(vsk);
|
||||
if (err < 0)
|
||||
@ -1214,7 +1198,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
|
||||
timeout = vsk->connect_timeout;
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
||||
|
||||
while (sk->sk_state != SS_CONNECTED && sk->sk_err == 0) {
|
||||
while (sk->sk_state != TCP_ESTABLISHED && sk->sk_err == 0) {
|
||||
if (flags & O_NONBLOCK) {
|
||||
/* If we're not going to block, we schedule a timeout
|
||||
* function to generate a timeout on the connection
|
||||
@ -1235,13 +1219,13 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
|
||||
|
||||
if (signal_pending(current)) {
|
||||
err = sock_intr_errno(timeout);
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
sock->state = SS_UNCONNECTED;
|
||||
vsock_transport_cancel_pkt(vsk);
|
||||
goto out_wait;
|
||||
} else if (timeout == 0) {
|
||||
err = -ETIMEDOUT;
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
sock->state = SS_UNCONNECTED;
|
||||
vsock_transport_cancel_pkt(vsk);
|
||||
goto out_wait;
|
||||
@ -1252,7 +1236,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
|
||||
|
||||
if (sk->sk_err) {
|
||||
err = -sk->sk_err;
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
sock->state = SS_UNCONNECTED;
|
||||
} else {
|
||||
err = 0;
|
||||
@ -1285,7 +1269,7 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (listener->sk_state != VSOCK_SS_LISTEN) {
|
||||
if (listener->sk_state != TCP_LISTEN) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -1375,7 +1359,7 @@ static int vsock_listen(struct socket *sock, int backlog)
|
||||
}
|
||||
|
||||
sk->sk_max_ack_backlog = backlog;
|
||||
sk->sk_state = VSOCK_SS_LISTEN;
|
||||
sk->sk_state = TCP_LISTEN;
|
||||
|
||||
err = 0;
|
||||
|
||||
@ -1555,7 +1539,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||
|
||||
/* Callers should not provide a destination with stream sockets. */
|
||||
if (msg->msg_namelen) {
|
||||
err = sk->sk_state == SS_CONNECTED ? -EISCONN : -EOPNOTSUPP;
|
||||
err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1566,7 +1550,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sk->sk_state != SS_CONNECTED ||
|
||||
if (sk->sk_state != TCP_ESTABLISHED ||
|
||||
!vsock_addr_bound(&vsk->local_addr)) {
|
||||
err = -ENOTCONN;
|
||||
goto out;
|
||||
@ -1690,7 +1674,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
if (sk->sk_state != SS_CONNECTED) {
|
||||
if (sk->sk_state != TCP_ESTABLISHED) {
|
||||
/* Recvmsg is supposed to return 0 if a peer performs an
|
||||
* orderly shutdown. Differentiate between that case and when a
|
||||
* peer has not connected or a local shutdown occured with the
|
||||
|
@ -35,6 +35,9 @@
|
||||
/* The MTU is 16KB per the host side's design */
|
||||
#define HVS_MTU_SIZE (1024 * 16)
|
||||
|
||||
/* How long to wait for graceful shutdown of a connection */
|
||||
#define HVS_CLOSE_TIMEOUT (8 * HZ)
|
||||
|
||||
struct vmpipe_proto_header {
|
||||
u32 pkt_type;
|
||||
u32 data_size;
|
||||
@ -290,19 +293,32 @@ static void hvs_channel_cb(void *ctx)
|
||||
sk->sk_write_space(sk);
|
||||
}
|
||||
|
||||
static void hvs_do_close_lock_held(struct vsock_sock *vsk,
|
||||
bool cancel_timeout)
|
||||
{
|
||||
struct sock *sk = sk_vsock(vsk);
|
||||
|
||||
sock_set_flag(sk, SOCK_DONE);
|
||||
vsk->peer_shutdown = SHUTDOWN_MASK;
|
||||
if (vsock_stream_has_data(vsk) <= 0)
|
||||
sk->sk_state = TCP_CLOSING;
|
||||
sk->sk_state_change(sk);
|
||||
if (vsk->close_work_scheduled &&
|
||||
(!cancel_timeout || cancel_delayed_work(&vsk->close_work))) {
|
||||
vsk->close_work_scheduled = false;
|
||||
vsock_remove_sock(vsk);
|
||||
|
||||
/* Release the reference taken while scheduling the timeout */
|
||||
sock_put(sk);
|
||||
}
|
||||
}
|
||||
|
||||
static void hvs_close_connection(struct vmbus_channel *chan)
|
||||
{
|
||||
struct sock *sk = get_per_channel_state(chan);
|
||||
struct vsock_sock *vsk = vsock_sk(sk);
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sock_set_flag(sk, SOCK_DONE);
|
||||
vsk->peer_shutdown |= SEND_SHUTDOWN | RCV_SHUTDOWN;
|
||||
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
hvs_do_close_lock_held(vsock_sk(sk), true);
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
@ -336,8 +352,8 @@ static void hvs_open_connection(struct vmbus_channel *chan)
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
if ((conn_from_host && sk->sk_state != VSOCK_SS_LISTEN) ||
|
||||
(!conn_from_host && sk->sk_state != SS_CONNECTING))
|
||||
if ((conn_from_host && sk->sk_state != TCP_LISTEN) ||
|
||||
(!conn_from_host && sk->sk_state != TCP_SYN_SENT))
|
||||
goto out;
|
||||
|
||||
if (conn_from_host) {
|
||||
@ -349,7 +365,7 @@ static void hvs_open_connection(struct vmbus_channel *chan)
|
||||
if (!new)
|
||||
goto out;
|
||||
|
||||
new->sk_state = SS_CONNECTING;
|
||||
new->sk_state = TCP_SYN_SENT;
|
||||
vnew = vsock_sk(new);
|
||||
hvs_new = vnew->trans;
|
||||
hvs_new->chan = chan;
|
||||
@ -383,7 +399,7 @@ static void hvs_open_connection(struct vmbus_channel *chan)
|
||||
hvs_set_channel_pending_send_size(chan);
|
||||
|
||||
if (conn_from_host) {
|
||||
new->sk_state = SS_CONNECTED;
|
||||
new->sk_state = TCP_ESTABLISHED;
|
||||
sk->sk_ack_backlog++;
|
||||
|
||||
hvs_addr_init(&vnew->local_addr, if_type);
|
||||
@ -396,7 +412,7 @@ static void hvs_open_connection(struct vmbus_channel *chan)
|
||||
|
||||
vsock_enqueue_accept(sk, new);
|
||||
} else {
|
||||
sk->sk_state = SS_CONNECTED;
|
||||
sk->sk_state = TCP_ESTABLISHED;
|
||||
sk->sk_socket->state = SS_CONNECTED;
|
||||
|
||||
vsock_insert_connected(vsock_sk(sk));
|
||||
@ -446,50 +462,80 @@ static int hvs_connect(struct vsock_sock *vsk)
|
||||
return vmbus_send_tl_connect_request(&h->vm_srv_id, &h->host_srv_id);
|
||||
}
|
||||
|
||||
static void hvs_shutdown_lock_held(struct hvsock *hvs, int mode)
|
||||
{
|
||||
struct vmpipe_proto_header hdr;
|
||||
|
||||
if (hvs->fin_sent || !hvs->chan)
|
||||
return;
|
||||
|
||||
/* It can't fail: see hvs_channel_writable_bytes(). */
|
||||
(void)hvs_send_data(hvs->chan, (struct hvs_send_buf *)&hdr, 0);
|
||||
hvs->fin_sent = true;
|
||||
}
|
||||
|
||||
static int hvs_shutdown(struct vsock_sock *vsk, int mode)
|
||||
{
|
||||
struct sock *sk = sk_vsock(vsk);
|
||||
struct vmpipe_proto_header hdr;
|
||||
struct hvs_send_buf *send_buf;
|
||||
struct hvsock *hvs;
|
||||
|
||||
if (!(mode & SEND_SHUTDOWN))
|
||||
return 0;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
hvs = vsk->trans;
|
||||
if (hvs->fin_sent)
|
||||
goto out;
|
||||
|
||||
send_buf = (struct hvs_send_buf *)&hdr;
|
||||
|
||||
/* It can't fail: see hvs_channel_writable_bytes(). */
|
||||
(void)hvs_send_data(hvs->chan, send_buf, 0);
|
||||
|
||||
hvs->fin_sent = true;
|
||||
out:
|
||||
hvs_shutdown_lock_held(vsk->trans, mode);
|
||||
release_sock(sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hvs_close_timeout(struct work_struct *work)
|
||||
{
|
||||
struct vsock_sock *vsk =
|
||||
container_of(work, struct vsock_sock, close_work.work);
|
||||
struct sock *sk = sk_vsock(vsk);
|
||||
|
||||
sock_hold(sk);
|
||||
lock_sock(sk);
|
||||
if (!sock_flag(sk, SOCK_DONE))
|
||||
hvs_do_close_lock_held(vsk, false);
|
||||
|
||||
vsk->close_work_scheduled = false;
|
||||
release_sock(sk);
|
||||
sock_put(sk);
|
||||
}
|
||||
|
||||
/* Returns true, if it is safe to remove socket; false otherwise */
|
||||
static bool hvs_close_lock_held(struct vsock_sock *vsk)
|
||||
{
|
||||
struct sock *sk = sk_vsock(vsk);
|
||||
|
||||
if (!(sk->sk_state == TCP_ESTABLISHED ||
|
||||
sk->sk_state == TCP_CLOSING))
|
||||
return true;
|
||||
|
||||
if ((sk->sk_shutdown & SHUTDOWN_MASK) != SHUTDOWN_MASK)
|
||||
hvs_shutdown_lock_held(vsk->trans, SHUTDOWN_MASK);
|
||||
|
||||
if (sock_flag(sk, SOCK_DONE))
|
||||
return true;
|
||||
|
||||
/* This reference will be dropped by the delayed close routine */
|
||||
sock_hold(sk);
|
||||
INIT_DELAYED_WORK(&vsk->close_work, hvs_close_timeout);
|
||||
vsk->close_work_scheduled = true;
|
||||
schedule_delayed_work(&vsk->close_work, HVS_CLOSE_TIMEOUT);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void hvs_release(struct vsock_sock *vsk)
|
||||
{
|
||||
struct sock *sk = sk_vsock(vsk);
|
||||
struct hvsock *hvs = vsk->trans;
|
||||
struct vmbus_channel *chan;
|
||||
bool remove_sock;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
sk->sk_state = TCP_CLOSING;
|
||||
vsock_remove_sock(vsk);
|
||||
|
||||
remove_sock = hvs_close_lock_held(vsk);
|
||||
release_sock(sk);
|
||||
|
||||
chan = hvs->chan;
|
||||
if (chan)
|
||||
hvs_shutdown(vsk, RCV_SHUTDOWN | SEND_SHUTDOWN);
|
||||
|
||||
if (remove_sock)
|
||||
vsock_remove_sock(vsk);
|
||||
}
|
||||
|
||||
static void hvs_destruct(struct vsock_sock *vsk)
|
||||
|
@ -417,7 +417,7 @@ static void virtio_vsock_event_fill(struct virtio_vsock *vsock)
|
||||
static void virtio_vsock_reset_sock(struct sock *sk)
|
||||
{
|
||||
lock_sock(sk);
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
sk->sk_err = ECONNRESET;
|
||||
sk->sk_error_report(sk);
|
||||
release_sock(sk);
|
||||
|
@ -716,7 +716,7 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
|
||||
sock_set_flag(sk, SOCK_DONE);
|
||||
vsk->peer_shutdown = SHUTDOWN_MASK;
|
||||
if (vsock_stream_has_data(vsk) <= 0)
|
||||
sk->sk_state = SS_DISCONNECTING;
|
||||
sk->sk_state = TCP_CLOSING;
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
if (vsk->close_work_scheduled &&
|
||||
@ -756,8 +756,8 @@ static bool virtio_transport_close(struct vsock_sock *vsk)
|
||||
{
|
||||
struct sock *sk = &vsk->sk;
|
||||
|
||||
if (!(sk->sk_state == SS_CONNECTED ||
|
||||
sk->sk_state == SS_DISCONNECTING))
|
||||
if (!(sk->sk_state == TCP_ESTABLISHED ||
|
||||
sk->sk_state == TCP_CLOSING))
|
||||
return true;
|
||||
|
||||
/* Already received SHUTDOWN from peer, reply with RST */
|
||||
@ -816,7 +816,7 @@ virtio_transport_recv_connecting(struct sock *sk,
|
||||
|
||||
switch (le16_to_cpu(pkt->hdr.op)) {
|
||||
case VIRTIO_VSOCK_OP_RESPONSE:
|
||||
sk->sk_state = SS_CONNECTED;
|
||||
sk->sk_state = TCP_ESTABLISHED;
|
||||
sk->sk_socket->state = SS_CONNECTED;
|
||||
vsock_insert_connected(vsk);
|
||||
sk->sk_state_change(sk);
|
||||
@ -836,7 +836,7 @@ virtio_transport_recv_connecting(struct sock *sk,
|
||||
|
||||
destroy:
|
||||
virtio_transport_reset(vsk, pkt);
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
sk->sk_err = skerr;
|
||||
sk->sk_error_report(sk);
|
||||
return err;
|
||||
@ -872,7 +872,7 @@ virtio_transport_recv_connected(struct sock *sk,
|
||||
vsk->peer_shutdown |= SEND_SHUTDOWN;
|
||||
if (vsk->peer_shutdown == SHUTDOWN_MASK &&
|
||||
vsock_stream_has_data(vsk) <= 0)
|
||||
sk->sk_state = SS_DISCONNECTING;
|
||||
sk->sk_state = TCP_CLOSING;
|
||||
if (le32_to_cpu(pkt->hdr.flags))
|
||||
sk->sk_state_change(sk);
|
||||
break;
|
||||
@ -943,7 +943,7 @@ virtio_transport_recv_listen(struct sock *sk, struct virtio_vsock_pkt *pkt)
|
||||
|
||||
lock_sock_nested(child, SINGLE_DEPTH_NESTING);
|
||||
|
||||
child->sk_state = SS_CONNECTED;
|
||||
child->sk_state = TCP_ESTABLISHED;
|
||||
|
||||
vchild = vsock_sk(child);
|
||||
vsock_addr_init(&vchild->local_addr, le64_to_cpu(pkt->hdr.dst_cid),
|
||||
@ -1031,18 +1031,18 @@ void virtio_transport_recv_pkt(struct virtio_vsock_pkt *pkt)
|
||||
sk->sk_write_space(sk);
|
||||
|
||||
switch (sk->sk_state) {
|
||||
case VSOCK_SS_LISTEN:
|
||||
case TCP_LISTEN:
|
||||
virtio_transport_recv_listen(sk, pkt);
|
||||
virtio_transport_free_pkt(pkt);
|
||||
break;
|
||||
case SS_CONNECTING:
|
||||
case TCP_SYN_SENT:
|
||||
virtio_transport_recv_connecting(sk, pkt);
|
||||
virtio_transport_free_pkt(pkt);
|
||||
break;
|
||||
case SS_CONNECTED:
|
||||
case TCP_ESTABLISHED:
|
||||
virtio_transport_recv_connected(sk, pkt);
|
||||
break;
|
||||
case SS_DISCONNECTING:
|
||||
case TCP_CLOSING:
|
||||
virtio_transport_recv_disconnecting(sk, pkt);
|
||||
virtio_transport_free_pkt(pkt);
|
||||
break;
|
||||
|
@ -776,7 +776,7 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
|
||||
/* The local context ID may be out of date, update it. */
|
||||
vsk->local_addr.svm_cid = dst.svm_cid;
|
||||
|
||||
if (sk->sk_state == SS_CONNECTED)
|
||||
if (sk->sk_state == TCP_ESTABLISHED)
|
||||
vmci_trans(vsk)->notify_ops->handle_notify_pkt(
|
||||
sk, pkt, true, &dst, &src,
|
||||
&bh_process_pkt);
|
||||
@ -834,7 +834,9 @@ static void vmci_transport_handle_detach(struct sock *sk)
|
||||
* left in our consume queue.
|
||||
*/
|
||||
if (vsock_stream_has_data(vsk) <= 0) {
|
||||
if (sk->sk_state == SS_CONNECTING) {
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
|
||||
if (sk->sk_state == TCP_SYN_SENT) {
|
||||
/* The peer may detach from a queue pair while
|
||||
* we are still in the connecting state, i.e.,
|
||||
* if the peer VM is killed after attaching to
|
||||
@ -843,12 +845,10 @@ static void vmci_transport_handle_detach(struct sock *sk)
|
||||
* event like a reset.
|
||||
*/
|
||||
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_err = ECONNRESET;
|
||||
sk->sk_error_report(sk);
|
||||
return;
|
||||
}
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
}
|
||||
sk->sk_state_change(sk);
|
||||
}
|
||||
@ -916,17 +916,17 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work)
|
||||
vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
|
||||
|
||||
switch (sk->sk_state) {
|
||||
case VSOCK_SS_LISTEN:
|
||||
case TCP_LISTEN:
|
||||
vmci_transport_recv_listen(sk, pkt);
|
||||
break;
|
||||
case SS_CONNECTING:
|
||||
case TCP_SYN_SENT:
|
||||
/* Processing of pending connections for servers goes through
|
||||
* the listening socket, so see vmci_transport_recv_listen()
|
||||
* for that path.
|
||||
*/
|
||||
vmci_transport_recv_connecting_client(sk, pkt);
|
||||
break;
|
||||
case SS_CONNECTED:
|
||||
case TCP_ESTABLISHED:
|
||||
vmci_transport_recv_connected(sk, pkt);
|
||||
break;
|
||||
default:
|
||||
@ -975,7 +975,7 @@ static int vmci_transport_recv_listen(struct sock *sk,
|
||||
vsock_sk(pending)->local_addr.svm_cid = pkt->dg.dst.context;
|
||||
|
||||
switch (pending->sk_state) {
|
||||
case SS_CONNECTING:
|
||||
case TCP_SYN_SENT:
|
||||
err = vmci_transport_recv_connecting_server(sk,
|
||||
pending,
|
||||
pkt);
|
||||
@ -1105,7 +1105,7 @@ static int vmci_transport_recv_listen(struct sock *sk,
|
||||
vsock_add_pending(sk, pending);
|
||||
sk->sk_ack_backlog++;
|
||||
|
||||
pending->sk_state = SS_CONNECTING;
|
||||
pending->sk_state = TCP_SYN_SENT;
|
||||
vmci_trans(vpending)->produce_size =
|
||||
vmci_trans(vpending)->consume_size = qp_size;
|
||||
vmci_trans(vpending)->queue_pair_size = qp_size;
|
||||
@ -1229,11 +1229,11 @@ vmci_transport_recv_connecting_server(struct sock *listener,
|
||||
* the socket will be valid until it is removed from the queue.
|
||||
*
|
||||
* If we fail sending the attach below, we remove the socket from the
|
||||
* connected list and move the socket to SS_UNCONNECTED before
|
||||
* connected list and move the socket to TCP_CLOSE before
|
||||
* releasing the lock, so a pending slow path processing of an incoming
|
||||
* packet will not see the socket in the connected state in that case.
|
||||
*/
|
||||
pending->sk_state = SS_CONNECTED;
|
||||
pending->sk_state = TCP_ESTABLISHED;
|
||||
|
||||
vsock_insert_connected(vpending);
|
||||
|
||||
@ -1264,7 +1264,7 @@ vmci_transport_recv_connecting_server(struct sock *listener,
|
||||
|
||||
destroy:
|
||||
pending->sk_err = skerr;
|
||||
pending->sk_state = SS_UNCONNECTED;
|
||||
pending->sk_state = TCP_CLOSE;
|
||||
/* As long as we drop our reference, all necessary cleanup will handle
|
||||
* when the cleanup function drops its reference and our destruct
|
||||
* implementation is called. Note that since the listen handler will
|
||||
@ -1302,7 +1302,7 @@ vmci_transport_recv_connecting_client(struct sock *sk,
|
||||
* accounting (it can already be found since it's in the bound
|
||||
* table).
|
||||
*/
|
||||
sk->sk_state = SS_CONNECTED;
|
||||
sk->sk_state = TCP_ESTABLISHED;
|
||||
sk->sk_socket->state = SS_CONNECTED;
|
||||
vsock_insert_connected(vsk);
|
||||
sk->sk_state_change(sk);
|
||||
@ -1370,7 +1370,7 @@ vmci_transport_recv_connecting_client(struct sock *sk,
|
||||
destroy:
|
||||
vmci_transport_send_reset(sk, pkt);
|
||||
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
sk->sk_err = skerr;
|
||||
sk->sk_error_report(sk);
|
||||
return err;
|
||||
@ -1558,7 +1558,7 @@ static int vmci_transport_recv_connected(struct sock *sk,
|
||||
sock_set_flag(sk, SOCK_DONE);
|
||||
vsk->peer_shutdown = SHUTDOWN_MASK;
|
||||
if (vsock_stream_has_data(vsk) <= 0)
|
||||
sk->sk_state = SS_DISCONNECTING;
|
||||
sk->sk_state = TCP_CLOSING;
|
||||
|
||||
sk->sk_state_change(sk);
|
||||
break;
|
||||
@ -1826,7 +1826,7 @@ static int vmci_transport_connect(struct vsock_sock *vsk)
|
||||
err = vmci_transport_send_conn_request(
|
||||
sk, vmci_trans(vsk)->queue_pair_size);
|
||||
if (err < 0) {
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
@ -1836,7 +1836,7 @@ static int vmci_transport_connect(struct vsock_sock *vsk)
|
||||
sk, vmci_trans(vsk)->queue_pair_size,
|
||||
supported_proto_versions);
|
||||
if (err < 0) {
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ vmci_transport_notify_pkt_poll_in(struct sock *sk,
|
||||
* queue. Ask for notifications when there is something to
|
||||
* read.
|
||||
*/
|
||||
if (sk->sk_state == SS_CONNECTED) {
|
||||
if (sk->sk_state == TCP_ESTABLISHED) {
|
||||
if (!send_waiting_read(sk, 1))
|
||||
return -1;
|
||||
|
||||
|
@ -176,7 +176,7 @@ vmci_transport_notify_pkt_poll_in(struct sock *sk,
|
||||
* queue. Ask for notifications when there is something to
|
||||
* read.
|
||||
*/
|
||||
if (sk->sk_state == SS_CONNECTED)
|
||||
if (sk->sk_state == TCP_ESTABLISHED)
|
||||
vsock_block_update_write_window(sk);
|
||||
*data_ready_now = false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user