mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-26 16:51:48 +00:00
2401 lines
75 KiB
Diff
2401 lines
75 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 242e6dfbff19..2ea579016292 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 72
|
|
+SUBLEVEL = 73
|
|
EXTRAVERSION =
|
|
NAME = Saber-toothed Squirrel
|
|
|
|
diff --git a/block/blk-core.c b/block/blk-core.c
|
|
index a02cfb7e4123..279f05dcbc87 100644
|
|
--- a/block/blk-core.c
|
|
+++ b/block/blk-core.c
|
|
@@ -499,7 +499,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
|
|
goto fail_id;
|
|
|
|
if (blk_throtl_init(q))
|
|
- goto fail_id;
|
|
+ goto fail_bdi;
|
|
|
|
setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
|
|
laptop_mode_timer_fn, (unsigned long) q);
|
|
@@ -524,6 +524,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
|
|
|
|
return q;
|
|
|
|
+fail_bdi:
|
|
+ bdi_destroy(&q->backing_dev_info);
|
|
fail_id:
|
|
ida_simple_remove(&blk_queue_ida, q->id);
|
|
fail_q:
|
|
diff --git a/block/elevator.c b/block/elevator.c
|
|
index f016855a46b0..dcef5d1bf999 100644
|
|
--- a/block/elevator.c
|
|
+++ b/block/elevator.c
|
|
@@ -961,7 +961,7 @@ fail_register:
|
|
/*
|
|
* Switch this queue to the given IO scheduler.
|
|
*/
|
|
-int elevator_change(struct request_queue *q, const char *name)
|
|
+static int __elevator_change(struct request_queue *q, const char *name)
|
|
{
|
|
char elevator_name[ELV_NAME_MAX];
|
|
struct elevator_type *e;
|
|
@@ -983,6 +983,18 @@ int elevator_change(struct request_queue *q, const char *name)
|
|
|
|
return elevator_switch(q, e);
|
|
}
|
|
+
|
|
+int elevator_change(struct request_queue *q, const char *name)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ /* Protect q->elevator from elevator_init() */
|
|
+ mutex_lock(&q->sysfs_lock);
|
|
+ ret = __elevator_change(q, name);
|
|
+ mutex_unlock(&q->sysfs_lock);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
EXPORT_SYMBOL(elevator_change);
|
|
|
|
ssize_t elv_iosched_store(struct request_queue *q, const char *name,
|
|
@@ -993,7 +1005,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name,
|
|
if (!q->elevator)
|
|
return count;
|
|
|
|
- ret = elevator_change(q, name);
|
|
+ ret = __elevator_change(q, name);
|
|
if (!ret)
|
|
return count;
|
|
|
|
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
|
|
index 0262210cad38..850246206b12 100644
|
|
--- a/crypto/algif_hash.c
|
|
+++ b/crypto/algif_hash.c
|
|
@@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
|
|
struct hash_ctx *ctx = ask->private;
|
|
int err;
|
|
|
|
+ if (flags & MSG_SENDPAGE_NOTLAST)
|
|
+ flags |= MSG_MORE;
|
|
+
|
|
lock_sock(sk);
|
|
sg_init_table(ctx->sgl.sg, 1);
|
|
sg_set_page(ctx->sgl.sg, page, size, offset);
|
|
@@ -161,8 +164,6 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
|
|
else if (len < ds)
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
lock_sock(sk);
|
|
if (ctx->more) {
|
|
ctx->more = 0;
|
|
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
|
|
index a1c4f0a55583..a19c027b29bd 100644
|
|
--- a/crypto/algif_skcipher.c
|
|
+++ b/crypto/algif_skcipher.c
|
|
@@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page,
|
|
struct skcipher_sg_list *sgl;
|
|
int err = -EINVAL;
|
|
|
|
+ if (flags & MSG_SENDPAGE_NOTLAST)
|
|
+ flags |= MSG_MORE;
|
|
+
|
|
lock_sock(sk);
|
|
if (!ctx->more && ctx->used)
|
|
goto unlock;
|
|
@@ -432,7 +435,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
|
|
long copied = 0;
|
|
|
|
lock_sock(sk);
|
|
- msg->msg_namelen = 0;
|
|
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
|
|
iovlen--, iov++) {
|
|
unsigned long seglen = iov->iov_len;
|
|
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
|
|
index 1c052127548c..b0e75ce3c8fc 100644
|
|
--- a/drivers/atm/idt77252.c
|
|
+++ b/drivers/atm/idt77252.c
|
|
@@ -3513,7 +3513,7 @@ init_card(struct atm_dev *dev)
|
|
tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */
|
|
if (tmp) {
|
|
memcpy(card->atmdev->esi, tmp->dev_addr, 6);
|
|
-
|
|
+ dev_put(tmp);
|
|
printk("%s: ESI %pM\n", card->name, card->atmdev->esi);
|
|
}
|
|
/*
|
|
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
|
|
index 2894461e0bdb..ff18e41f5b22 100644
|
|
--- a/drivers/connector/cn_proc.c
|
|
+++ b/drivers/connector/cn_proc.c
|
|
@@ -31,11 +31,23 @@
|
|
#include <linux/ptrace.h>
|
|
#include <linux/atomic.h>
|
|
|
|
-#include <asm/unaligned.h>
|
|
-
|
|
#include <linux/cn_proc.h>
|
|
|
|
-#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event))
|
|
+/*
|
|
+ * Size of a cn_msg followed by a proc_event structure. Since the
|
|
+ * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we
|
|
+ * add one 4-byte word to the size here, and then start the actual
|
|
+ * cn_msg structure 4 bytes into the stack buffer. The result is that
|
|
+ * the immediately following proc_event structure is aligned to 8 bytes.
|
|
+ */
|
|
+#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4)
|
|
+
|
|
+/* See comment above; we test our assumption about sizeof struct cn_msg here. */
|
|
+static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer)
|
|
+{
|
|
+ BUILD_BUG_ON(sizeof(struct cn_msg) != 20);
|
|
+ return (struct cn_msg *)(buffer + 4);
|
|
+}
|
|
|
|
static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
|
|
static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
|
|
@@ -55,19 +67,19 @@ void proc_fork_connector(struct task_struct *task)
|
|
{
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
struct timespec ts;
|
|
struct task_struct *parent;
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg*)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event*)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
ev->what = PROC_EVENT_FORK;
|
|
rcu_read_lock();
|
|
parent = rcu_dereference(task->real_parent);
|
|
@@ -90,17 +102,17 @@ void proc_exec_connector(struct task_struct *task)
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
struct timespec ts;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg*)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event*)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
ev->what = PROC_EVENT_EXEC;
|
|
ev->event_data.exec.process_pid = task->pid;
|
|
ev->event_data.exec.process_tgid = task->tgid;
|
|
@@ -116,14 +128,14 @@ void proc_id_connector(struct task_struct *task, int which_id)
|
|
{
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
struct timespec ts;
|
|
const struct cred *cred;
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg*)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event*)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
ev->what = which_id;
|
|
@@ -144,7 +156,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
|
|
rcu_read_unlock();
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
@@ -158,17 +170,17 @@ void proc_sid_connector(struct task_struct *task)
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
struct timespec ts;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg *)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event *)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
ev->what = PROC_EVENT_SID;
|
|
ev->event_data.sid.process_pid = task->pid;
|
|
ev->event_data.sid.process_tgid = task->tgid;
|
|
@@ -185,17 +197,17 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
struct timespec ts;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg *)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event *)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
ev->what = PROC_EVENT_PTRACE;
|
|
ev->event_data.ptrace.process_pid = task->pid;
|
|
ev->event_data.ptrace.process_tgid = task->tgid;
|
|
@@ -220,17 +232,17 @@ void proc_comm_connector(struct task_struct *task)
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
struct timespec ts;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg *)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event *)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
ev->what = PROC_EVENT_COMM;
|
|
ev->event_data.comm.process_pid = task->pid;
|
|
ev->event_data.comm.process_tgid = task->tgid;
|
|
@@ -247,18 +259,18 @@ void proc_exit_connector(struct task_struct *task)
|
|
{
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
struct timespec ts;
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg*)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event*)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
ev->what = PROC_EVENT_EXIT;
|
|
ev->event_data.exit.process_pid = task->pid;
|
|
ev->event_data.exit.process_tgid = task->tgid;
|
|
@@ -284,18 +296,18 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
|
|
{
|
|
struct cn_msg *msg;
|
|
struct proc_event *ev;
|
|
- __u8 buffer[CN_PROC_MSG_SIZE];
|
|
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
|
struct timespec ts;
|
|
|
|
if (atomic_read(&proc_event_num_listeners) < 1)
|
|
return;
|
|
|
|
- msg = (struct cn_msg*)buffer;
|
|
+ msg = buffer_to_cn_msg(buffer);
|
|
ev = (struct proc_event*)msg->data;
|
|
memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
msg->seq = rcvd_seq;
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
+ ev->timestamp_ns = timespec_to_ns(&ts);
|
|
ev->cpu = -1;
|
|
ev->what = PROC_EVENT_NONE;
|
|
ev->event_data.ack.err = err;
|
|
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
|
|
index 45c3433f7986..95f90479f285 100644
|
|
--- a/drivers/hid/hid-picolcd.c
|
|
+++ b/drivers/hid/hid-picolcd.c
|
|
@@ -1424,7 +1424,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
|
|
buf += 10;
|
|
cnt -= 10;
|
|
}
|
|
- if (!report)
|
|
+ if (!report || report->maxfield != 1)
|
|
return -EINVAL;
|
|
|
|
while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
|
|
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
|
|
index a60a54d8593a..abc6ac855598 100644
|
|
--- a/drivers/iommu/intel-iommu.c
|
|
+++ b/drivers/iommu/intel-iommu.c
|
|
@@ -778,7 +778,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
|
|
int offset;
|
|
|
|
BUG_ON(!domain->pgd);
|
|
- BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width);
|
|
+
|
|
+ if (addr_width < BITS_PER_LONG && pfn >> addr_width)
|
|
+ /* Address beyond IOMMU's addressing capabilities. */
|
|
+ return NULL;
|
|
+
|
|
parent = domain->pgd;
|
|
|
|
while (level > 0) {
|
|
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
|
|
index baf2686aa8eb..02125e6a9109 100644
|
|
--- a/drivers/isdn/isdnloop/isdnloop.c
|
|
+++ b/drivers/isdn/isdnloop/isdnloop.c
|
|
@@ -1083,8 +1083,10 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp)
|
|
spin_unlock_irqrestore(&card->isdnloop_lock, flags);
|
|
return -ENOMEM;
|
|
}
|
|
- for (i = 0; i < 3; i++)
|
|
- strcpy(card->s0num[i], sdef.num[i]);
|
|
+ for (i = 0; i < 3; i++) {
|
|
+ strlcpy(card->s0num[i], sdef.num[i],
|
|
+ sizeof(card->s0num[0]));
|
|
+ }
|
|
break;
|
|
case ISDN_PTYPE_1TR6:
|
|
if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",
|
|
@@ -1097,7 +1099,7 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp)
|
|
spin_unlock_irqrestore(&card->isdnloop_lock, flags);
|
|
return -ENOMEM;
|
|
}
|
|
- strcpy(card->s0num[0], sdef.num[0]);
|
|
+ strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0]));
|
|
card->s0num[1][0] = '\0';
|
|
card->s0num[2][0] = '\0';
|
|
break;
|
|
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
|
|
index abe2d699b6f3..ade1bcfb0e6d 100644
|
|
--- a/drivers/isdn/mISDN/socket.c
|
|
+++ b/drivers/isdn/mISDN/socket.c
|
|
@@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
{
|
|
struct sk_buff *skb;
|
|
struct sock *sk = sock->sk;
|
|
- struct sockaddr_mISDN *maddr;
|
|
|
|
int copied, err;
|
|
|
|
@@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (!skb)
|
|
return err;
|
|
|
|
- if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
|
|
- msg->msg_namelen = sizeof(struct sockaddr_mISDN);
|
|
- maddr = (struct sockaddr_mISDN *)msg->msg_name;
|
|
+ if (msg->msg_name) {
|
|
+ struct sockaddr_mISDN *maddr = msg->msg_name;
|
|
+
|
|
maddr->family = AF_ISDN;
|
|
maddr->dev = _pms(sk)->dev->id;
|
|
if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
|
|
@@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
maddr->sapi = _pms(sk)->ch.addr & 0xFF;
|
|
maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF;
|
|
}
|
|
- } else {
|
|
- if (msg->msg_namelen)
|
|
- printk(KERN_WARNING "%s: too small namelen %d\n",
|
|
- __func__, msg->msg_namelen);
|
|
- msg->msg_namelen = 0;
|
|
+ msg->msg_namelen = sizeof(*maddr);
|
|
}
|
|
|
|
copied = skb->len + MISDN_HEADER_LEN;
|
|
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
|
|
index 3f06df59fd82..535c3e276fc7 100644
|
|
--- a/drivers/md/dm-crypt.c
|
|
+++ b/drivers/md/dm-crypt.c
|
|
@@ -1262,20 +1262,6 @@ static int crypt_decode_key(u8 *key, char *hex, unsigned int size)
|
|
return 0;
|
|
}
|
|
|
|
-/*
|
|
- * Encode key into its hex representation
|
|
- */
|
|
-static void crypt_encode_key(char *hex, u8 *key, unsigned int size)
|
|
-{
|
|
- unsigned int i;
|
|
-
|
|
- for (i = 0; i < size; i++) {
|
|
- sprintf(hex, "%02x", *key);
|
|
- hex += 2;
|
|
- key++;
|
|
- }
|
|
-}
|
|
-
|
|
static void crypt_free_tfms(struct crypt_config *cc)
|
|
{
|
|
unsigned i;
|
|
@@ -1741,11 +1727,11 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
|
|
return DM_MAPIO_SUBMITTED;
|
|
}
|
|
|
|
-static int crypt_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned int maxlen)
|
|
+static void crypt_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned int maxlen)
|
|
{
|
|
struct crypt_config *cc = ti->private;
|
|
- unsigned int sz = 0;
|
|
+ unsigned i, sz = 0;
|
|
|
|
switch (type) {
|
|
case STATUSTYPE_INFO:
|
|
@@ -1755,17 +1741,11 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
|
|
case STATUSTYPE_TABLE:
|
|
DMEMIT("%s ", cc->cipher_string);
|
|
|
|
- if (cc->key_size > 0) {
|
|
- if ((maxlen - sz) < ((cc->key_size << 1) + 1))
|
|
- return -ENOMEM;
|
|
-
|
|
- crypt_encode_key(result + sz, cc->key, cc->key_size);
|
|
- sz += cc->key_size << 1;
|
|
- } else {
|
|
- if (sz >= maxlen)
|
|
- return -ENOMEM;
|
|
- result[sz++] = '-';
|
|
- }
|
|
+ if (cc->key_size > 0)
|
|
+ for (i = 0; i < cc->key_size; i++)
|
|
+ DMEMIT("%02x", cc->key[i]);
|
|
+ else
|
|
+ DMEMIT("-");
|
|
|
|
DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
|
|
cc->dev->name, (unsigned long long)cc->start);
|
|
@@ -1775,7 +1755,6 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
|
|
|
|
break;
|
|
}
|
|
- return 0;
|
|
}
|
|
|
|
static void crypt_postsuspend(struct dm_target *ti)
|
|
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
|
|
index 2dc22dddb2ae..ee99912596cb 100644
|
|
--- a/drivers/md/dm-delay.c
|
|
+++ b/drivers/md/dm-delay.c
|
|
@@ -294,8 +294,8 @@ static int delay_map(struct dm_target *ti, struct bio *bio,
|
|
return delay_bio(dc, dc->read_delay, bio);
|
|
}
|
|
|
|
-static int delay_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned maxlen)
|
|
+static void delay_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned maxlen)
|
|
{
|
|
struct delay_c *dc = ti->private;
|
|
int sz = 0;
|
|
@@ -315,8 +315,6 @@ static int delay_status(struct dm_target *ti, status_type_t type,
|
|
dc->write_delay);
|
|
break;
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static int delay_iterate_devices(struct dm_target *ti,
|
|
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
|
|
index ac49c01f1a44..f29d665fe83a 100644
|
|
--- a/drivers/md/dm-flakey.c
|
|
+++ b/drivers/md/dm-flakey.c
|
|
@@ -332,8 +332,8 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
|
|
return error;
|
|
}
|
|
|
|
-static int flakey_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned int maxlen)
|
|
+static void flakey_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned int maxlen)
|
|
{
|
|
unsigned sz = 0;
|
|
struct flakey_c *fc = ti->private;
|
|
@@ -363,7 +363,6 @@ static int flakey_status(struct dm_target *ti, status_type_t type,
|
|
|
|
break;
|
|
}
|
|
- return 0;
|
|
}
|
|
|
|
static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
|
|
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
|
|
index f011d4b3c139..d365365bdb99 100644
|
|
--- a/drivers/md/dm-ioctl.c
|
|
+++ b/drivers/md/dm-ioctl.c
|
|
@@ -1066,6 +1066,7 @@ static void retrieve_status(struct dm_table *table,
|
|
num_targets = dm_table_get_num_targets(table);
|
|
for (i = 0; i < num_targets; i++) {
|
|
struct dm_target *ti = dm_table_get_target(table, i);
|
|
+ size_t l;
|
|
|
|
remaining = len - (outptr - outbuf);
|
|
if (remaining <= sizeof(struct dm_target_spec)) {
|
|
@@ -1089,15 +1090,18 @@ static void retrieve_status(struct dm_table *table,
|
|
}
|
|
|
|
/* Get the status/table string from the target driver */
|
|
- if (ti->type->status) {
|
|
- if (ti->type->status(ti, type, outptr, remaining)) {
|
|
- param->flags |= DM_BUFFER_FULL_FLAG;
|
|
- break;
|
|
- }
|
|
- } else
|
|
+ if (ti->type->status)
|
|
+ ti->type->status(ti, type, outptr, remaining);
|
|
+ else
|
|
outptr[0] = '\0';
|
|
|
|
- outptr += strlen(outptr) + 1;
|
|
+ l = strlen(outptr) + 1;
|
|
+ if (l == remaining) {
|
|
+ param->flags |= DM_BUFFER_FULL_FLAG;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ outptr += l;
|
|
used = param->data_start + (outptr - outbuf);
|
|
|
|
outptr = align_ptr(outptr);
|
|
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
|
|
index 3639eeab6042..5a5e9c8b29a7 100644
|
|
--- a/drivers/md/dm-linear.c
|
|
+++ b/drivers/md/dm-linear.c
|
|
@@ -95,8 +95,8 @@ static int linear_map(struct dm_target *ti, struct bio *bio,
|
|
return DM_MAPIO_REMAPPED;
|
|
}
|
|
|
|
-static int linear_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned int maxlen)
|
|
+static void linear_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned int maxlen)
|
|
{
|
|
struct linear_c *lc = (struct linear_c *) ti->private;
|
|
|
|
@@ -110,7 +110,6 @@ static int linear_status(struct dm_target *ti, status_type_t type,
|
|
(unsigned long long)lc->start);
|
|
break;
|
|
}
|
|
- return 0;
|
|
}
|
|
|
|
static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
|
|
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
|
|
index 754f38f8a692..b74cb796c17c 100644
|
|
--- a/drivers/md/dm-mpath.c
|
|
+++ b/drivers/md/dm-mpath.c
|
|
@@ -1343,8 +1343,8 @@ static void multipath_resume(struct dm_target *ti)
|
|
* [priority selector-name num_ps_args [ps_args]*
|
|
* num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
|
|
*/
|
|
-static int multipath_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned int maxlen)
|
|
+static void multipath_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned int maxlen)
|
|
{
|
|
int sz = 0;
|
|
unsigned long flags;
|
|
@@ -1447,8 +1447,6 @@ static int multipath_status(struct dm_target *ti, status_type_t type,
|
|
}
|
|
|
|
spin_unlock_irqrestore(&m->lock, flags);
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
|
|
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
|
|
index 68965e663248..ead5ca99a749 100644
|
|
--- a/drivers/md/dm-raid.c
|
|
+++ b/drivers/md/dm-raid.c
|
|
@@ -1067,8 +1067,8 @@ static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_c
|
|
return DM_MAPIO_SUBMITTED;
|
|
}
|
|
|
|
-static int raid_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned maxlen)
|
|
+static void raid_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned maxlen)
|
|
{
|
|
struct raid_set *rs = ti->private;
|
|
unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
|
|
@@ -1203,8 +1203,6 @@ static int raid_status(struct dm_target *ti, status_type_t type,
|
|
DMEMIT(" -");
|
|
}
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
|
|
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
|
|
index b58b7a33914a..a3cf259275af 100644
|
|
--- a/drivers/md/dm-raid1.c
|
|
+++ b/drivers/md/dm-raid1.c
|
|
@@ -1362,8 +1362,8 @@ static char device_status_char(struct mirror *m)
|
|
}
|
|
|
|
|
|
-static int mirror_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned int maxlen)
|
|
+static void mirror_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned int maxlen)
|
|
{
|
|
unsigned int m, sz = 0;
|
|
struct mirror_set *ms = (struct mirror_set *) ti->private;
|
|
@@ -1398,8 +1398,6 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
|
|
if (ms->features & DM_RAID1_HANDLE_ERRORS)
|
|
DMEMIT(" 1 handle_errors");
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static int mirror_iterate_devices(struct dm_target *ti,
|
|
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
|
|
index 448050c87be0..db77ac693323 100644
|
|
--- a/drivers/md/dm-snap.c
|
|
+++ b/drivers/md/dm-snap.c
|
|
@@ -1845,8 +1845,8 @@ static void snapshot_merge_resume(struct dm_target *ti)
|
|
start_merge(s);
|
|
}
|
|
|
|
-static int snapshot_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned int maxlen)
|
|
+static void snapshot_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned int maxlen)
|
|
{
|
|
unsigned sz = 0;
|
|
struct dm_snapshot *snap = ti->private;
|
|
@@ -1892,8 +1892,6 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
|
|
maxlen - sz);
|
|
break;
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static int snapshot_iterate_devices(struct dm_target *ti,
|
|
@@ -2148,8 +2146,8 @@ static void origin_resume(struct dm_target *ti)
|
|
ti->split_io = get_origin_minimum_chunksize(dev->bdev);
|
|
}
|
|
|
|
-static int origin_status(struct dm_target *ti, status_type_t type, char *result,
|
|
- unsigned int maxlen)
|
|
+static void origin_status(struct dm_target *ti, status_type_t type, char *result,
|
|
+ unsigned int maxlen)
|
|
{
|
|
struct dm_dev *dev = ti->private;
|
|
|
|
@@ -2162,8 +2160,6 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result,
|
|
snprintf(result, maxlen, "%s", dev->name);
|
|
break;
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
|
|
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
|
|
index 35c94ff24ad5..58ffcda3dab3 100644
|
|
--- a/drivers/md/dm-stripe.c
|
|
+++ b/drivers/md/dm-stripe.c
|
|
@@ -302,8 +302,8 @@ static int stripe_map(struct dm_target *ti, struct bio *bio,
|
|
*
|
|
*/
|
|
|
|
-static int stripe_status(struct dm_target *ti,
|
|
- status_type_t type, char *result, unsigned int maxlen)
|
|
+static void stripe_status(struct dm_target *ti,
|
|
+ status_type_t type, char *result, unsigned int maxlen)
|
|
{
|
|
struct stripe_c *sc = (struct stripe_c *) ti->private;
|
|
char buffer[sc->stripes + 1];
|
|
@@ -330,7 +330,6 @@ static int stripe_status(struct dm_target *ti,
|
|
(unsigned long long)sc->stripe[i].physical_start);
|
|
break;
|
|
}
|
|
- return 0;
|
|
}
|
|
|
|
static int stripe_end_io(struct dm_target *ti, struct bio *bio,
|
|
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
|
|
index 7c3ab8fcdbd3..c540dfff1f81 100644
|
|
--- a/drivers/md/dm-thin.c
|
|
+++ b/drivers/md/dm-thin.c
|
|
@@ -2325,8 +2325,8 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
|
|
* <transaction id> <used metadata sectors>/<total metadata sectors>
|
|
* <used data sectors>/<total data sectors> <held metadata root>
|
|
*/
|
|
-static int pool_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned maxlen)
|
|
+static void pool_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned maxlen)
|
|
{
|
|
int r, count;
|
|
unsigned sz = 0;
|
|
@@ -2343,32 +2343,41 @@ static int pool_status(struct dm_target *ti, status_type_t type,
|
|
|
|
switch (type) {
|
|
case STATUSTYPE_INFO:
|
|
- r = dm_pool_get_metadata_transaction_id(pool->pmd,
|
|
- &transaction_id);
|
|
- if (r)
|
|
- return r;
|
|
+ r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id);
|
|
+ if (r) {
|
|
+ DMERR("dm_pool_get_metadata_transaction_id returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
- r = dm_pool_get_free_metadata_block_count(pool->pmd,
|
|
- &nr_free_blocks_metadata);
|
|
- if (r)
|
|
- return r;
|
|
+ r = dm_pool_get_free_metadata_block_count(pool->pmd, &nr_free_blocks_metadata);
|
|
+ if (r) {
|
|
+ DMERR("dm_pool_get_free_metadata_block_count returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
r = dm_pool_get_metadata_dev_size(pool->pmd, &nr_blocks_metadata);
|
|
- if (r)
|
|
- return r;
|
|
+ if (r) {
|
|
+ DMERR("dm_pool_get_metadata_dev_size returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
- r = dm_pool_get_free_block_count(pool->pmd,
|
|
- &nr_free_blocks_data);
|
|
- if (r)
|
|
- return r;
|
|
+ r = dm_pool_get_free_block_count(pool->pmd, &nr_free_blocks_data);
|
|
+ if (r) {
|
|
+ DMERR("dm_pool_get_free_block_count returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
r = dm_pool_get_data_dev_size(pool->pmd, &nr_blocks_data);
|
|
- if (r)
|
|
- return r;
|
|
+ if (r) {
|
|
+ DMERR("dm_pool_get_data_dev_size returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
r = dm_pool_get_held_metadata_root(pool->pmd, &held_root);
|
|
- if (r)
|
|
- return r;
|
|
+ if (r) {
|
|
+ DMERR("dm_pool_get_metadata_snap returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
DMEMIT("%llu %llu/%llu %llu/%llu ",
|
|
(unsigned long long)transaction_id,
|
|
@@ -2406,8 +2415,10 @@ static int pool_status(struct dm_target *ti, status_type_t type,
|
|
|
|
break;
|
|
}
|
|
+ return;
|
|
|
|
- return 0;
|
|
+err:
|
|
+ DMEMIT("Error");
|
|
}
|
|
|
|
static int pool_iterate_devices(struct dm_target *ti,
|
|
@@ -2659,8 +2670,8 @@ static void thin_postsuspend(struct dm_target *ti)
|
|
/*
|
|
* <nr mapped sectors> <highest mapped sector>
|
|
*/
|
|
-static int thin_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned maxlen)
|
|
+static void thin_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned maxlen)
|
|
{
|
|
int r;
|
|
ssize_t sz = 0;
|
|
@@ -2674,12 +2685,16 @@ static int thin_status(struct dm_target *ti, status_type_t type,
|
|
switch (type) {
|
|
case STATUSTYPE_INFO:
|
|
r = dm_thin_get_mapped_count(tc->td, &mapped);
|
|
- if (r)
|
|
- return r;
|
|
+ if (r) {
|
|
+ DMERR("dm_thin_get_mapped_count returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
r = dm_thin_get_highest_mapped_block(tc->td, &highest);
|
|
- if (r < 0)
|
|
- return r;
|
|
+ if (r < 0) {
|
|
+ DMERR("dm_thin_get_highest_mapped_block returned %d", r);
|
|
+ goto err;
|
|
+ }
|
|
|
|
DMEMIT("%llu ", mapped * tc->pool->sectors_per_block);
|
|
if (r)
|
|
@@ -2699,7 +2714,10 @@ static int thin_status(struct dm_target *ti, status_type_t type,
|
|
}
|
|
}
|
|
|
|
- return 0;
|
|
+ return;
|
|
+
|
|
+err:
|
|
+ DMEMIT("Error");
|
|
}
|
|
|
|
static int thin_iterate_devices(struct dm_target *ti,
|
|
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
|
|
index 9ab2a6a582b6..ac099847a4b3 100644
|
|
--- a/drivers/md/dm-verity.c
|
|
+++ b/drivers/md/dm-verity.c
|
|
@@ -514,8 +514,8 @@ static int verity_map(struct dm_target *ti, struct bio *bio,
|
|
/*
|
|
* Status: V (valid) or C (corruption found)
|
|
*/
|
|
-static int verity_status(struct dm_target *ti, status_type_t type,
|
|
- char *result, unsigned maxlen)
|
|
+static void verity_status(struct dm_target *ti, status_type_t type,
|
|
+ char *result, unsigned maxlen)
|
|
{
|
|
struct dm_verity *v = ti->private;
|
|
unsigned sz = 0;
|
|
@@ -546,8 +546,6 @@ static int verity_status(struct dm_target *ti, status_type_t type,
|
|
DMEMIT("%02x", v->salt[x]);
|
|
break;
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static int verity_ioctl(struct dm_target *ti, unsigned cmd,
|
|
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
|
|
index 833ff16f5fe1..c32a9093159a 100644
|
|
--- a/drivers/mmc/card/block.c
|
|
+++ b/drivers/mmc/card/block.c
|
|
@@ -701,7 +701,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
|
|
* Otherwise we don't understand what happened, so abort.
|
|
*/
|
|
static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
|
|
- struct mmc_blk_request *brq, int *ecc_err)
|
|
+ struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
|
|
{
|
|
bool prev_cmd_status_valid = true;
|
|
u32 status, stop_status = 0;
|
|
@@ -739,6 +739,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
|
|
(brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
|
|
*ecc_err = 1;
|
|
|
|
+ /* Flag General errors */
|
|
+ if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
|
|
+ if ((status & R1_ERROR) ||
|
|
+ (brq->stop.resp[0] & R1_ERROR)) {
|
|
+ pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
|
|
+ req->rq_disk->disk_name, __func__,
|
|
+ brq->stop.resp[0], status);
|
|
+ *gen_err = 1;
|
|
+ }
|
|
+
|
|
/*
|
|
* Check the current card state. If it is in some data transfer
|
|
* mode, tell it to stop (and hopefully transition back to TRAN.)
|
|
@@ -758,6 +768,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
|
|
return ERR_ABORT;
|
|
if (stop_status & R1_CARD_ECC_FAILED)
|
|
*ecc_err = 1;
|
|
+ if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
|
|
+ if (stop_status & R1_ERROR) {
|
|
+ pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
|
|
+ req->rq_disk->disk_name, __func__,
|
|
+ stop_status);
|
|
+ *gen_err = 1;
|
|
+ }
|
|
}
|
|
|
|
/* Check for set block count errors */
|
|
@@ -1007,7 +1024,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|
mmc_active);
|
|
struct mmc_blk_request *brq = &mq_mrq->brq;
|
|
struct request *req = mq_mrq->req;
|
|
- int ecc_err = 0;
|
|
+ int ecc_err = 0, gen_err = 0;
|
|
|
|
/*
|
|
* sbc.error indicates a problem with the set block count
|
|
@@ -1021,7 +1038,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|
*/
|
|
if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
|
|
brq->data.error) {
|
|
- switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
|
|
+ switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
|
|
case ERR_RETRY:
|
|
return MMC_BLK_RETRY;
|
|
case ERR_ABORT:
|
|
@@ -1051,6 +1068,15 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|
*/
|
|
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
|
|
u32 status;
|
|
+
|
|
+ /* Check stop command response */
|
|
+ if (brq->stop.resp[0] & R1_ERROR) {
|
|
+ pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
|
|
+ req->rq_disk->disk_name, __func__,
|
|
+ brq->stop.resp[0]);
|
|
+ gen_err = 1;
|
|
+ }
|
|
+
|
|
do {
|
|
int err = get_card_status(card, &status, 5);
|
|
if (err) {
|
|
@@ -1058,6 +1084,14 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|
req->rq_disk->disk_name, err);
|
|
return MMC_BLK_CMD_ERR;
|
|
}
|
|
+
|
|
+ if (status & R1_ERROR) {
|
|
+ pr_err("%s: %s: general error sending status command, card status %#x\n",
|
|
+ req->rq_disk->disk_name, __func__,
|
|
+ status);
|
|
+ gen_err = 1;
|
|
+ }
|
|
+
|
|
/*
|
|
* Some cards mishandle the status bits,
|
|
* so make sure to check both the busy
|
|
@@ -1067,6 +1101,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|
(R1_CURRENT_STATE(status) == R1_STATE_PRG));
|
|
}
|
|
|
|
+ /* if general error occurs, retry the write operation. */
|
|
+ if (gen_err) {
|
|
+ pr_warning("%s: retrying write for general error\n",
|
|
+ req->rq_disk->disk_name);
|
|
+ return MMC_BLK_RETRY;
|
|
+ }
|
|
+
|
|
if (brq->data.error) {
|
|
pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
|
|
req->rq_disk->disk_name, brq->data.error,
|
|
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
|
|
index c40c0a871818..f42a00ac38d7 100644
|
|
--- a/drivers/net/bonding/bond_sysfs.c
|
|
+++ b/drivers/net/bonding/bond_sysfs.c
|
|
@@ -533,8 +533,9 @@ static ssize_t bonding_store_arp_interval(struct device *d,
|
|
goto out;
|
|
}
|
|
if (bond->params.mode == BOND_MODE_ALB ||
|
|
- bond->params.mode == BOND_MODE_TLB) {
|
|
- pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n",
|
|
+ bond->params.mode == BOND_MODE_TLB ||
|
|
+ bond->params.mode == BOND_MODE_8023AD) {
|
|
+ pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n",
|
|
bond->dev->name, bond->dev->name);
|
|
ret = -EINVAL;
|
|
goto out;
|
|
@@ -692,6 +693,8 @@ static ssize_t bonding_store_downdelay(struct device *d,
|
|
int new_value, ret = count;
|
|
struct bonding *bond = to_bond(d);
|
|
|
|
+ if (!rtnl_trylock())
|
|
+ return restart_syscall();
|
|
if (!(bond->params.miimon)) {
|
|
pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
|
|
bond->dev->name);
|
|
@@ -725,6 +728,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
|
|
}
|
|
|
|
out:
|
|
+ rtnl_unlock();
|
|
return ret;
|
|
}
|
|
static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
|
|
@@ -747,6 +751,8 @@ static ssize_t bonding_store_updelay(struct device *d,
|
|
int new_value, ret = count;
|
|
struct bonding *bond = to_bond(d);
|
|
|
|
+ if (!rtnl_trylock())
|
|
+ return restart_syscall();
|
|
if (!(bond->params.miimon)) {
|
|
pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
|
|
bond->dev->name);
|
|
@@ -780,6 +786,7 @@ static ssize_t bonding_store_updelay(struct device *d,
|
|
}
|
|
|
|
out:
|
|
+ rtnl_unlock();
|
|
return ret;
|
|
}
|
|
static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
|
|
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
|
|
index 2e0d8762bb52..bac88c22d990 100644
|
|
--- a/drivers/net/ppp/pppoe.c
|
|
+++ b/drivers/net/ppp/pppoe.c
|
|
@@ -985,8 +985,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (error < 0)
|
|
goto end;
|
|
|
|
- m->msg_namelen = 0;
|
|
-
|
|
if (skb) {
|
|
total_len = min_t(size_t, total_len, skb->len);
|
|
error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
|
|
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
|
|
index acb9370fdb14..7aa8668f0a0c 100644
|
|
--- a/drivers/video/kyro/fbdev.c
|
|
+++ b/drivers/video/kyro/fbdev.c
|
|
@@ -625,15 +625,15 @@ static int kyrofb_ioctl(struct fb_info *info,
|
|
}
|
|
break;
|
|
case KYRO_IOCTL_UVSTRIDE:
|
|
- if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
|
|
+ if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
|
|
return -EFAULT;
|
|
break;
|
|
case KYRO_IOCTL_STRIDE:
|
|
- if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
|
|
+ if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
|
|
return -EFAULT;
|
|
break;
|
|
case KYRO_IOCTL_OVERLAY_OFFSET:
|
|
- if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
|
|
+ if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
|
|
return -EFAULT;
|
|
break;
|
|
}
|
|
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
|
|
index 53459b055cfc..25d839ed0ae1 100644
|
|
--- a/fs/nfsd/nfssvc.c
|
|
+++ b/fs/nfsd/nfssvc.c
|
|
@@ -11,7 +11,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/fs_struct.h>
|
|
#include <linux/swap.h>
|
|
-#include <linux/nsproxy.h>
|
|
|
|
#include <linux/sunrpc/stats.h>
|
|
#include <linux/sunrpc/svcsock.h>
|
|
@@ -330,7 +329,7 @@ static int nfsd_get_default_max_blksize(void)
|
|
int nfsd_create_serv(void)
|
|
{
|
|
int error;
|
|
- struct net *net = current->nsproxy->net_ns;
|
|
+ struct net *net = &init_net;
|
|
|
|
WARN_ON(!mutex_is_locked(&nfsd_mutex));
|
|
if (nfsd_serv) {
|
|
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
|
|
index 98f34b886f95..fa09b579f67c 100644
|
|
--- a/include/linux/device-mapper.h
|
|
+++ b/include/linux/device-mapper.h
|
|
@@ -72,8 +72,8 @@ typedef void (*dm_postsuspend_fn) (struct dm_target *ti);
|
|
typedef int (*dm_preresume_fn) (struct dm_target *ti);
|
|
typedef void (*dm_resume_fn) (struct dm_target *ti);
|
|
|
|
-typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
|
|
- char *result, unsigned int maxlen);
|
|
+typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
|
|
+ char *result, unsigned int maxlen);
|
|
|
|
typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
|
|
|
|
diff --git a/include/linux/net.h b/include/linux/net.h
|
|
index 95fea1432dd3..45232814fc03 100644
|
|
--- a/include/linux/net.h
|
|
+++ b/include/linux/net.h
|
|
@@ -198,6 +198,14 @@ struct proto_ops {
|
|
#endif
|
|
int (*sendmsg) (struct kiocb *iocb, struct socket *sock,
|
|
struct msghdr *m, size_t total_len);
|
|
+ /* Notes for implementing recvmsg:
|
|
+ * ===============================
|
|
+ * msg->msg_namelen should get updated by the recvmsg handlers
|
|
+ * iff msg_name != NULL. It is by default 0 to prevent
|
|
+ * returning uninitialized memory to user space. The recvfrom
|
|
+ * handlers can assume that msg.msg_name is either NULL or has
|
|
+ * a minimum size of sizeof(struct sockaddr_storage).
|
|
+ */
|
|
int (*recvmsg) (struct kiocb *iocb, struct socket *sock,
|
|
struct msghdr *m, size_t total_len,
|
|
int flags);
|
|
diff --git a/include/linux/random.h b/include/linux/random.h
|
|
index 7e58ad27b7ff..54b1fd3efdfa 100644
|
|
--- a/include/linux/random.h
|
|
+++ b/include/linux/random.h
|
|
@@ -87,9 +87,9 @@ static inline void prandom32_seed(struct rnd_state *state, u64 seed)
|
|
{
|
|
u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
|
|
|
|
- state->s1 = __seed(i, 1);
|
|
- state->s2 = __seed(i, 7);
|
|
- state->s3 = __seed(i, 15);
|
|
+ state->s1 = __seed(i, 2);
|
|
+ state->s2 = __seed(i, 8);
|
|
+ state->s3 = __seed(i, 16);
|
|
}
|
|
|
|
#ifdef CONFIG_ARCH_RANDOM
|
|
diff --git a/include/net/ip.h b/include/net/ip.h
|
|
index 0750bf7d424f..6d6b12f4753c 100644
|
|
--- a/include/net/ip.h
|
|
+++ b/include/net/ip.h
|
|
@@ -466,7 +466,7 @@ extern int compat_ip_getsockopt(struct sock *sk, int level,
|
|
int optname, char __user *optval, int __user *optlen);
|
|
extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
|
|
|
|
-extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
|
|
+extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
|
|
extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
|
|
__be16 port, u32 info, u8 *payload);
|
|
extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
|
|
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
|
|
index 12a1bd2e9879..fa7af9183dc9 100644
|
|
--- a/include/net/ipv6.h
|
|
+++ b/include/net/ipv6.h
|
|
@@ -606,8 +606,10 @@ extern int compat_ipv6_getsockopt(struct sock *sk,
|
|
extern int ip6_datagram_connect(struct sock *sk,
|
|
struct sockaddr *addr, int addr_len);
|
|
|
|
-extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
|
|
-extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
|
|
+extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
|
|
+ int *addr_len);
|
|
+extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
|
|
+ int *addr_len);
|
|
extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
|
|
u32 info, u8 *payload);
|
|
extern void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
|
|
diff --git a/lib/random32.c b/lib/random32.c
|
|
index 938bde5876ac..aa95712c1431 100644
|
|
--- a/lib/random32.c
|
|
+++ b/lib/random32.c
|
|
@@ -92,7 +92,7 @@ void srandom32(u32 entropy)
|
|
*/
|
|
for_each_possible_cpu (i) {
|
|
struct rnd_state *state = &per_cpu(net_rand_state, i);
|
|
- state->s1 = __seed(state->s1 ^ entropy, 1);
|
|
+ state->s1 = __seed(state->s1 ^ entropy, 2);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(srandom32);
|
|
@@ -109,9 +109,9 @@ static int __init random32_init(void)
|
|
struct rnd_state *state = &per_cpu(net_rand_state,i);
|
|
|
|
#define LCG(x) ((x) * 69069) /* super-duper LCG */
|
|
- state->s1 = __seed(LCG(i + jiffies), 1);
|
|
- state->s2 = __seed(LCG(state->s1), 7);
|
|
- state->s3 = __seed(LCG(state->s2), 15);
|
|
+ state->s1 = __seed(LCG(i + jiffies), 2);
|
|
+ state->s2 = __seed(LCG(state->s1), 8);
|
|
+ state->s3 = __seed(LCG(state->s2), 16);
|
|
|
|
/* "warm it up" */
|
|
prandom32(state);
|
|
@@ -138,9 +138,9 @@ static int __init random32_reseed(void)
|
|
u32 seeds[3];
|
|
|
|
get_random_bytes(&seeds, sizeof(seeds));
|
|
- state->s1 = __seed(seeds[0], 1);
|
|
- state->s2 = __seed(seeds[1], 7);
|
|
- state->s3 = __seed(seeds[2], 15);
|
|
+ state->s1 = __seed(seeds[0], 2);
|
|
+ state->s2 = __seed(seeds[1], 8);
|
|
+ state->s3 = __seed(seeds[2], 16);
|
|
|
|
/* mix it in */
|
|
prandom32(state);
|
|
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
|
|
index bfa9ab93eda5..334d4cd7612f 100644
|
|
--- a/net/appletalk/ddp.c
|
|
+++ b/net/appletalk/ddp.c
|
|
@@ -1740,7 +1740,6 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
|
|
size_t size, int flags)
|
|
{
|
|
struct sock *sk = sock->sk;
|
|
- struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
|
|
struct ddpehdr *ddp;
|
|
int copied = 0;
|
|
int offset = 0;
|
|
@@ -1769,14 +1768,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
|
|
}
|
|
err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
|
|
|
|
- if (!err) {
|
|
- if (sat) {
|
|
- sat->sat_family = AF_APPLETALK;
|
|
- sat->sat_port = ddp->deh_sport;
|
|
- sat->sat_addr.s_node = ddp->deh_snode;
|
|
- sat->sat_addr.s_net = ddp->deh_snet;
|
|
- }
|
|
- msg->msg_namelen = sizeof(*sat);
|
|
+ if (!err && msg->msg_name) {
|
|
+ struct sockaddr_at *sat = msg->msg_name;
|
|
+ sat->sat_family = AF_APPLETALK;
|
|
+ sat->sat_port = ddp->deh_sport;
|
|
+ sat->sat_addr.s_node = ddp->deh_snode;
|
|
+ sat->sat_addr.s_net = ddp->deh_snet;
|
|
+ msg->msg_namelen = sizeof(*sat);
|
|
}
|
|
|
|
skb_free_datagram(sk, skb); /* Free the datagram. */
|
|
diff --git a/net/atm/common.c b/net/atm/common.c
|
|
index f0a9b7eb3732..0c0ad930a632 100644
|
|
--- a/net/atm/common.c
|
|
+++ b/net/atm/common.c
|
|
@@ -520,8 +520,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
|
struct sk_buff *skb;
|
|
int copied, error = -EINVAL;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
if (sock->state != SS_CONNECTED)
|
|
return -ENOTCONN;
|
|
|
|
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
|
|
index 68b39927ecda..ca1820cf22f2 100644
|
|
--- a/net/ax25/af_ax25.c
|
|
+++ b/net/ax25/af_ax25.c
|
|
@@ -1640,11 +1640,11 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
|
|
|
|
- if (msg->msg_namelen != 0) {
|
|
- struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
|
|
+ if (msg->msg_name) {
|
|
ax25_digi digi;
|
|
ax25_address src;
|
|
const unsigned char *mac = skb_mac_header(skb);
|
|
+ struct sockaddr_ax25 *sax = msg->msg_name;
|
|
|
|
memset(sax, 0, sizeof(struct full_sockaddr_ax25));
|
|
ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
|
|
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
|
|
index c2943484eab4..af3775f3d640 100644
|
|
--- a/net/bluetooth/af_bluetooth.c
|
|
+++ b/net/bluetooth/af_bluetooth.c
|
|
@@ -240,8 +240,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags & (MSG_OOB))
|
|
return -EOPNOTSUPP;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
skb = skb_recv_datagram(sk, flags, noblock, &err);
|
|
if (!skb) {
|
|
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
|
@@ -306,8 +304,6 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags & MSG_OOB)
|
|
return -EOPNOTSUPP;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
BT_DBG("sk %p size %zu", sk, size);
|
|
|
|
lock_sock(sk);
|
|
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
|
|
index bedc768c8cdf..8c2cb05e50ea 100644
|
|
--- a/net/bluetooth/hci_sock.c
|
|
+++ b/net/bluetooth/hci_sock.c
|
|
@@ -767,8 +767,6 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (!skb)
|
|
return err;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
copied = skb->len;
|
|
if (len < copied) {
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
|
|
index c79db7f7533b..8d1edd7207df 100644
|
|
--- a/net/bluetooth/rfcomm/sock.c
|
|
+++ b/net/bluetooth/rfcomm/sock.c
|
|
@@ -628,7 +628,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
|
|
rfcomm_dlc_accept(d);
|
|
- msg->msg_namelen = 0;
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
|
|
index e1144e1617be..ff44f5f16780 100644
|
|
--- a/net/bridge/br_if.c
|
|
+++ b/net/bridge/br_if.c
|
|
@@ -170,6 +170,8 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
|
|
del_nbp(p);
|
|
}
|
|
|
|
+ br_fdb_delete_by_port(br, NULL, 1);
|
|
+
|
|
del_timer_sync(&br->gc_timer);
|
|
|
|
br_sysfs_delbr(br->dev);
|
|
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
|
|
index 24a68861881c..9e8351598f8a 100644
|
|
--- a/net/caif/caif_socket.c
|
|
+++ b/net/caif/caif_socket.c
|
|
@@ -287,8 +287,6 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (m->msg_flags&MSG_OOB)
|
|
goto read_error;
|
|
|
|
- m->msg_namelen = 0;
|
|
-
|
|
skb = skb_recv_datagram(sk, flags, 0 , &ret);
|
|
if (!skb)
|
|
goto read_error;
|
|
@@ -362,8 +360,6 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags&MSG_OOB)
|
|
goto out;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
/*
|
|
* Lock the socket to prevent queue disordering
|
|
* while sleeps in memcpy_tomsg
|
|
diff --git a/net/compat.c b/net/compat.c
|
|
index ee84d82d7287..17f997e14f63 100644
|
|
--- a/net/compat.c
|
|
+++ b/net/compat.c
|
|
@@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
|
|
__get_user(kmsg->msg_flags, &umsg->msg_flags))
|
|
return -EFAULT;
|
|
if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
|
|
- return -EINVAL;
|
|
+ kmsg->msg_namelen = sizeof(struct sockaddr_storage);
|
|
kmsg->msg_name = compat_ptr(tmp1);
|
|
kmsg->msg_iov = compat_ptr(tmp2);
|
|
kmsg->msg_control = compat_ptr(tmp3);
|
|
@@ -93,7 +93,8 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
- kern_msg->msg_name = kern_address;
|
|
+ if (kern_msg->msg_name)
|
|
+ kern_msg->msg_name = kern_address;
|
|
} else
|
|
kern_msg->msg_name = NULL;
|
|
|
|
diff --git a/net/core/dev.c b/net/core/dev.c
|
|
index 7db83d64e4f7..cebdc15ce327 100644
|
|
--- a/net/core/dev.c
|
|
+++ b/net/core/dev.c
|
|
@@ -4443,7 +4443,7 @@ static void dev_change_rx_flags(struct net_device *dev, int flags)
|
|
{
|
|
const struct net_device_ops *ops = dev->netdev_ops;
|
|
|
|
- if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags)
|
|
+ if (ops->ndo_change_rx_flags)
|
|
ops->ndo_change_rx_flags(dev, flags);
|
|
}
|
|
|
|
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
|
|
index c02e63c908da..c0c21b1ce1ec 100644
|
|
--- a/net/core/fib_rules.c
|
|
+++ b/net/core/fib_rules.c
|
|
@@ -443,7 +443,8 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
|
|
if (frh->action && (frh->action != rule->action))
|
|
continue;
|
|
|
|
- if (frh->table && (frh_get_table(frh, tb) != rule->table))
|
|
+ if (frh_get_table(frh, tb) &&
|
|
+ (frh_get_table(frh, tb) != rule->table))
|
|
continue;
|
|
|
|
if (tb[FRA_PRIORITY] &&
|
|
diff --git a/net/core/iovec.c b/net/core/iovec.c
|
|
index 7e7aeb01de45..7fd34a56aeb3 100644
|
|
--- a/net/core/iovec.c
|
|
+++ b/net/core/iovec.c
|
|
@@ -48,7 +48,8 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
- m->msg_name = address;
|
|
+ if (m->msg_name)
|
|
+ m->msg_name = address;
|
|
} else {
|
|
m->msg_name = NULL;
|
|
}
|
|
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
|
|
index 114d8a9e8570..546b1334fad4 100644
|
|
--- a/net/core/pktgen.c
|
|
+++ b/net/core/pktgen.c
|
|
@@ -2521,6 +2521,8 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
|
|
if (x) {
|
|
int ret;
|
|
__u8 *eth;
|
|
+ struct iphdr *iph;
|
|
+
|
|
nhead = x->props.header_len - skb_headroom(skb);
|
|
if (nhead > 0) {
|
|
ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
|
|
@@ -2542,6 +2544,11 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
|
|
eth = (__u8 *) skb_push(skb, ETH_HLEN);
|
|
memcpy(eth, pkt_dev->hh, 12);
|
|
*(u16 *) ð[12] = protocol;
|
|
+
|
|
+ /* Update IPv4 header len as well as checksum value */
|
|
+ iph = ip_hdr(skb);
|
|
+ iph->tot_len = htons(skb->len - ETH_HLEN);
|
|
+ ip_send_check(iph);
|
|
}
|
|
}
|
|
return 1;
|
|
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
|
|
index 840821b90bcd..ddbdceb9594b 100644
|
|
--- a/net/ieee802154/6lowpan.c
|
|
+++ b/net/ieee802154/6lowpan.c
|
|
@@ -803,7 +803,7 @@ lowpan_process_data(struct sk_buff *skb)
|
|
* Traffic class carried in-line
|
|
* ECN + DSCP (1 byte), Flow Label is elided
|
|
*/
|
|
- case 1: /* 10b */
|
|
+ case 2: /* 10b */
|
|
if (!skb->len)
|
|
goto drop;
|
|
tmp = lowpan_fetch_skb_u8(skb);
|
|
@@ -816,7 +816,7 @@ lowpan_process_data(struct sk_buff *skb)
|
|
* Flow Label carried in-line
|
|
* ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
|
|
*/
|
|
- case 2: /* 01b */
|
|
+ case 1: /* 01b */
|
|
if (!skb->len)
|
|
goto drop;
|
|
tmp = lowpan_fetch_skb_u8(skb);
|
|
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
|
|
index 424fafbc8cb0..ec0751051db7 100644
|
|
--- a/net/ipv4/datagram.c
|
|
+++ b/net/ipv4/datagram.c
|
|
@@ -57,7 +57,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|
if (IS_ERR(rt)) {
|
|
err = PTR_ERR(rt);
|
|
if (err == -ENETUNREACH)
|
|
- IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
|
|
+ IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
|
|
goto out;
|
|
}
|
|
|
|
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
|
|
index 374828487003..0bd174faff8f 100644
|
|
--- a/net/ipv4/ip_sockglue.c
|
|
+++ b/net/ipv4/ip_sockglue.c
|
|
@@ -367,7 +367,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
|
|
/*
|
|
* Handle MSG_ERRQUEUE
|
|
*/
|
|
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
|
|
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
|
{
|
|
struct sock_exterr_skb *serr;
|
|
struct sk_buff *skb, *skb2;
|
|
@@ -404,6 +404,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
|
|
serr->addr_offset);
|
|
sin->sin_port = serr->port;
|
|
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
|
|
+ *addr_len = sizeof(*sin);
|
|
}
|
|
|
|
memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
|
|
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
|
|
index c234bda5b801..e80db1e6b0b2 100644
|
|
--- a/net/ipv4/ping.c
|
|
+++ b/net/ipv4/ping.c
|
|
@@ -774,7 +774,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|
err = PTR_ERR(rt);
|
|
rt = NULL;
|
|
if (err == -ENETUNREACH)
|
|
- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
|
|
+ IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
|
|
goto out;
|
|
}
|
|
|
|
@@ -852,10 +852,10 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|
|
|
if (flags & MSG_ERRQUEUE) {
|
|
if (family == AF_INET) {
|
|
- return ip_recv_error(sk, msg, len);
|
|
+ return ip_recv_error(sk, msg, len, addr_len);
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
} else if (family == AF_INET6) {
|
|
- return pingv6_ops.ipv6_recv_error(sk, msg, len);
|
|
+ return pingv6_ops.ipv6_recv_error(sk, msg, len);
|
|
#endif
|
|
}
|
|
}
|
|
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
|
|
index c6b9ca651ab3..48c6ebcb7fe0 100644
|
|
--- a/net/ipv4/raw.c
|
|
+++ b/net/ipv4/raw.c
|
|
@@ -688,11 +688,8 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|
if (flags & MSG_OOB)
|
|
goto out;
|
|
|
|
- if (addr_len)
|
|
- *addr_len = sizeof(*sin);
|
|
-
|
|
if (flags & MSG_ERRQUEUE) {
|
|
- err = ip_recv_error(sk, msg, len);
|
|
+ err = ip_recv_error(sk, msg, len, addr_len);
|
|
goto out;
|
|
}
|
|
|
|
@@ -718,6 +715,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|
sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
|
|
sin->sin_port = 0;
|
|
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
|
|
+ *addr_len = sizeof(*sin);
|
|
}
|
|
if (inet->cmsg_flags)
|
|
ip_cmsg_recv(msg, skb);
|
|
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
|
|
index ae03b7b75af6..727678dc7968 100644
|
|
--- a/net/ipv4/tcp_ipv4.c
|
|
+++ b/net/ipv4/tcp_ipv4.c
|
|
@@ -176,7 +176,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|
if (IS_ERR(rt)) {
|
|
err = PTR_ERR(rt);
|
|
if (err == -ENETUNREACH)
|
|
- IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
|
|
+ IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
|
|
return err;
|
|
}
|
|
|
|
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
|
|
index 0b6136d578f6..7949b5d1663f 100644
|
|
--- a/net/ipv4/udp.c
|
|
+++ b/net/ipv4/udp.c
|
|
@@ -940,7 +940,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|
err = PTR_ERR(rt);
|
|
rt = NULL;
|
|
if (err == -ENETUNREACH)
|
|
- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
|
|
+ IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
|
|
goto out;
|
|
}
|
|
|
|
@@ -1039,6 +1039,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
|
|
struct udp_sock *up = udp_sk(sk);
|
|
int ret;
|
|
|
|
+ if (flags & MSG_SENDPAGE_NOTLAST)
|
|
+ flags |= MSG_MORE;
|
|
+
|
|
if (!up->pending) {
|
|
struct msghdr msg = { .msg_flags = flags|MSG_MORE };
|
|
|
|
@@ -1174,14 +1177,8 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|
int is_udplite = IS_UDPLITE(sk);
|
|
bool slow;
|
|
|
|
- /*
|
|
- * Check any passed addresses
|
|
- */
|
|
- if (addr_len)
|
|
- *addr_len = sizeof(*sin);
|
|
-
|
|
if (flags & MSG_ERRQUEUE)
|
|
- return ip_recv_error(sk, msg, len);
|
|
+ return ip_recv_error(sk, msg, len, addr_len);
|
|
|
|
try_again:
|
|
skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
|
|
@@ -1234,6 +1231,7 @@ try_again:
|
|
sin->sin_port = udp_hdr(skb)->source;
|
|
sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
|
|
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
|
|
+ *addr_len = sizeof(*sin);
|
|
}
|
|
if (inet->cmsg_flags)
|
|
ip_cmsg_recv(msg, skb);
|
|
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
|
|
index 76832c8dc89d..94e5258f3560 100644
|
|
--- a/net/ipv6/datagram.c
|
|
+++ b/net/ipv6/datagram.c
|
|
@@ -315,7 +315,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
|
|
/*
|
|
* Handle MSG_ERRQUEUE
|
|
*/
|
|
-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
|
|
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
|
{
|
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
|
struct sock_exterr_skb *serr;
|
|
@@ -366,6 +366,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
|
|
ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset),
|
|
&sin->sin6_addr);
|
|
}
|
|
+ *addr_len = sizeof(*sin);
|
|
}
|
|
|
|
memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
|
|
@@ -374,6 +375,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
|
|
if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
|
|
sin->sin6_family = AF_INET6;
|
|
sin->sin6_flowinfo = 0;
|
|
+ sin->sin6_port = 0;
|
|
sin->sin6_scope_id = 0;
|
|
if (skb->protocol == htons(ETH_P_IPV6)) {
|
|
sin->sin6_addr = ipv6_hdr(skb)->saddr;
|
|
@@ -418,7 +420,8 @@ out:
|
|
/*
|
|
* Handle IPV6_RECVPATHMTU
|
|
*/
|
|
-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
|
|
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
|
|
+ int *addr_len)
|
|
{
|
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
|
struct sk_buff *skb;
|
|
@@ -452,6 +455,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
|
|
sin->sin6_port = 0;
|
|
sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id;
|
|
sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr;
|
|
+ *addr_len = sizeof(*sin);
|
|
}
|
|
|
|
put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info);
|
|
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
|
|
index 7dabea3a7125..91cd5f1657b7 100644
|
|
--- a/net/ipv6/ip6_output.c
|
|
+++ b/net/ipv6/ip6_output.c
|
|
@@ -144,8 +144,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
|
|
return res;
|
|
}
|
|
rcu_read_unlock();
|
|
- IP6_INC_STATS_BH(dev_net(dst->dev),
|
|
- ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
|
|
+ IP6_INC_STATS(dev_net(dst->dev),
|
|
+ ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
|
|
kfree_skb(skb);
|
|
return -EINVAL;
|
|
}
|
|
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
|
|
index 3ee28700de4c..d6820d019b2b 100644
|
|
--- a/net/ipv6/raw.c
|
|
+++ b/net/ipv6/raw.c
|
|
@@ -457,14 +457,11 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
|
|
if (flags & MSG_OOB)
|
|
return -EOPNOTSUPP;
|
|
|
|
- if (addr_len)
|
|
- *addr_len=sizeof(*sin6);
|
|
-
|
|
if (flags & MSG_ERRQUEUE)
|
|
- return ipv6_recv_error(sk, msg, len);
|
|
+ return ipv6_recv_error(sk, msg, len, addr_len);
|
|
|
|
if (np->rxpmtu && np->rxopt.bits.rxpmtu)
|
|
- return ipv6_recv_rxpmtu(sk, msg, len);
|
|
+ return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
|
|
|
|
skb = skb_recv_datagram(sk, flags, noblock, &err);
|
|
if (!skb)
|
|
@@ -499,6 +496,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
|
|
sin6->sin6_scope_id = 0;
|
|
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
|
|
sin6->sin6_scope_id = IP6CB(skb)->iif;
|
|
+ *addr_len = sizeof(*sin6);
|
|
}
|
|
|
|
sock_recv_ts_and_drops(msg, sk, skb);
|
|
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
|
|
index f79bfdbc247f..98fd7384c446 100644
|
|
--- a/net/ipv6/udp.c
|
|
+++ b/net/ipv6/udp.c
|
|
@@ -348,14 +348,11 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
|
|
int is_udp4;
|
|
bool slow;
|
|
|
|
- if (addr_len)
|
|
- *addr_len=sizeof(struct sockaddr_in6);
|
|
-
|
|
if (flags & MSG_ERRQUEUE)
|
|
- return ipv6_recv_error(sk, msg, len);
|
|
+ return ipv6_recv_error(sk, msg, len, addr_len);
|
|
|
|
if (np->rxpmtu && np->rxopt.bits.rxpmtu)
|
|
- return ipv6_recv_rxpmtu(sk, msg, len);
|
|
+ return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
|
|
|
|
try_again:
|
|
skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
|
|
@@ -423,7 +420,7 @@ try_again:
|
|
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
|
|
sin6->sin6_scope_id = IP6CB(skb)->iif;
|
|
}
|
|
-
|
|
+ *addr_len = sizeof(*sin6);
|
|
}
|
|
if (is_udp4) {
|
|
if (inet->cmsg_flags)
|
|
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
|
|
index 9680226640ef..8c06a5065772 100644
|
|
--- a/net/ipx/af_ipx.c
|
|
+++ b/net/ipx/af_ipx.c
|
|
@@ -1835,8 +1835,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (skb->tstamp.tv64)
|
|
sk->sk_stamp = skb->tstamp;
|
|
|
|
- msg->msg_namelen = sizeof(*sipx);
|
|
-
|
|
if (sipx) {
|
|
sipx->sipx_family = AF_IPX;
|
|
sipx->sipx_port = ipx->ipx_source.sock;
|
|
@@ -1844,6 +1842,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net;
|
|
sipx->sipx_type = ipx->ipx_type;
|
|
sipx->sipx_zero = 0;
|
|
+ msg->msg_namelen = sizeof(*sipx);
|
|
}
|
|
rc = copied;
|
|
|
|
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
|
|
index bd25678b1d50..12218f705315 100644
|
|
--- a/net/irda/af_irda.c
|
|
+++ b/net/irda/af_irda.c
|
|
@@ -1386,8 +1386,6 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
|
|
|
|
IRDA_DEBUG(4, "%s()\n", __func__);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
|
|
flags & MSG_DONTWAIT, &err);
|
|
if (!skb)
|
|
@@ -1452,8 +1450,6 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
|
|
target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
|
|
timeo = sock_rcvtimeo(sk, noblock);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
do {
|
|
int chunk;
|
|
struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue);
|
|
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
|
|
index 625bc50391cc..cd6f7a991d80 100644
|
|
--- a/net/iucv/af_iucv.c
|
|
+++ b/net/iucv/af_iucv.c
|
|
@@ -1331,8 +1331,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
struct sk_buff *skb, *rskb, *cskb;
|
|
int err = 0;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
if ((sk->sk_state == IUCV_DISCONN) &&
|
|
skb_queue_empty(&iucv->backlog_skb_q) &&
|
|
skb_queue_empty(&sk->sk_receive_queue) &&
|
|
diff --git a/net/key/af_key.c b/net/key/af_key.c
|
|
index 2f3ce93d3fc1..d5cd43920ccb 100644
|
|
--- a/net/key/af_key.c
|
|
+++ b/net/key/af_key.c
|
|
@@ -3595,7 +3595,6 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
|
|
if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
|
|
goto out;
|
|
|
|
- msg->msg_namelen = 0;
|
|
skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
|
|
if (skb == NULL)
|
|
goto out;
|
|
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
|
|
index b1d4370c8962..ea247600f7d9 100644
|
|
--- a/net/l2tp/l2tp_ip.c
|
|
+++ b/net/l2tp/l2tp_ip.c
|
|
@@ -569,9 +569,6 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
|
|
if (flags & MSG_OOB)
|
|
goto out;
|
|
|
|
- if (addr_len)
|
|
- *addr_len = sizeof(*sin);
|
|
-
|
|
skb = skb_recv_datagram(sk, flags, noblock, &err);
|
|
if (!skb)
|
|
goto out;
|
|
@@ -594,6 +591,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
|
|
sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
|
|
sin->sin_port = 0;
|
|
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
|
|
+ *addr_len = sizeof(*sin);
|
|
}
|
|
if (inet->cmsg_flags)
|
|
ip_cmsg_recv(msg, skb);
|
|
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
|
|
index 904bc098790d..22112754ba06 100644
|
|
--- a/net/l2tp/l2tp_ppp.c
|
|
+++ b/net/l2tp/l2tp_ppp.c
|
|
@@ -200,8 +200,6 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (sk->sk_state & PPPOX_BOUND)
|
|
goto end;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
err = 0;
|
|
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
|
|
flags & MSG_DONTWAIT, &err);
|
|
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
|
|
index e4d2fbb59a7e..df08d7779e1d 100644
|
|
--- a/net/llc/af_llc.c
|
|
+++ b/net/llc/af_llc.c
|
|
@@ -721,8 +721,6 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
int target; /* Read at least this many bytes */
|
|
long timeo;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
lock_sock(sk);
|
|
copied = -ENOTCONN;
|
|
if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
|
|
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
|
|
index 9017e3ef8fee..ff960b792ee4 100644
|
|
--- a/net/netlink/af_netlink.c
|
|
+++ b/net/netlink/af_netlink.c
|
|
@@ -1443,8 +1443,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
|
|
}
|
|
#endif
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
copied = data_skb->len;
|
|
if (len < copied) {
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
|
|
index 7ed9b1d0c102..dcf6791ec76d 100644
|
|
--- a/net/netrom/af_netrom.c
|
|
+++ b/net/netrom/af_netrom.c
|
|
@@ -1181,10 +1181,9 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
sax->sax25_family = AF_NETROM;
|
|
skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
|
|
AX25_ADDR_LEN);
|
|
+ msg->msg_namelen = sizeof(*sax);
|
|
}
|
|
|
|
- msg->msg_namelen = sizeof(*sax);
|
|
-
|
|
skb_free_datagram(sk, skb);
|
|
|
|
release_sock(sk);
|
|
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
|
|
index e879dce52818..44835ceb5562 100644
|
|
--- a/net/nfc/rawsock.c
|
|
+++ b/net/nfc/rawsock.c
|
|
@@ -235,8 +235,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (!skb)
|
|
return rc;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
copied = skb->len;
|
|
if (len < copied) {
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
|
|
index 8ed5d9302e88..dbe1715c629f 100644
|
|
--- a/net/packet/af_packet.c
|
|
+++ b/net/packet/af_packet.c
|
|
@@ -294,6 +294,7 @@ struct packet_sock {
|
|
unsigned int tp_reserve;
|
|
unsigned int tp_loss:1;
|
|
unsigned int tp_tstamp;
|
|
+ struct net_device __rcu *cached_dev;
|
|
struct packet_type prot_hook ____cacheline_aligned_in_smp;
|
|
};
|
|
|
|
@@ -349,11 +350,15 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po);
|
|
static void register_prot_hook(struct sock *sk)
|
|
{
|
|
struct packet_sock *po = pkt_sk(sk);
|
|
+
|
|
if (!po->running) {
|
|
- if (po->fanout)
|
|
+ if (po->fanout) {
|
|
__fanout_link(sk, po);
|
|
- else
|
|
+ } else {
|
|
dev_add_pack(&po->prot_hook);
|
|
+ rcu_assign_pointer(po->cached_dev, po->prot_hook.dev);
|
|
+ }
|
|
+
|
|
sock_hold(sk);
|
|
po->running = 1;
|
|
}
|
|
@@ -371,10 +376,13 @@ static void __unregister_prot_hook(struct sock *sk, bool sync)
|
|
struct packet_sock *po = pkt_sk(sk);
|
|
|
|
po->running = 0;
|
|
- if (po->fanout)
|
|
+ if (po->fanout) {
|
|
__fanout_unlink(sk, po);
|
|
- else
|
|
+ } else {
|
|
__dev_remove_pack(&po->prot_hook);
|
|
+ RCU_INIT_POINTER(po->cached_dev, NULL);
|
|
+ }
|
|
+
|
|
__sock_put(sk);
|
|
|
|
if (sync) {
|
|
@@ -496,9 +504,9 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po,
|
|
|
|
pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
|
|
|
|
- spin_lock(&rb_queue->lock);
|
|
+ spin_lock_bh(&rb_queue->lock);
|
|
pkc->delete_blk_timer = 1;
|
|
- spin_unlock(&rb_queue->lock);
|
|
+ spin_unlock_bh(&rb_queue->lock);
|
|
|
|
prb_del_retire_blk_timer(pkc);
|
|
}
|
|
@@ -2044,12 +2052,24 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
|
|
return tp_len;
|
|
}
|
|
|
|
+static struct net_device *packet_cached_dev_get(struct packet_sock *po)
|
|
+{
|
|
+ struct net_device *dev;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ dev = rcu_dereference(po->cached_dev);
|
|
+ if (dev)
|
|
+ dev_hold(dev);
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ return dev;
|
|
+}
|
|
+
|
|
static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
|
|
{
|
|
struct sk_buff *skb;
|
|
struct net_device *dev;
|
|
__be16 proto;
|
|
- bool need_rls_dev = false;
|
|
int err, reserve = 0;
|
|
void *ph;
|
|
struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
|
|
@@ -2063,7 +2083,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
|
|
|
|
err = -EBUSY;
|
|
if (saddr == NULL) {
|
|
- dev = po->prot_hook.dev;
|
|
+ dev = packet_cached_dev_get(po);
|
|
proto = po->num;
|
|
addr = NULL;
|
|
} else {
|
|
@@ -2077,19 +2097,17 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
|
|
proto = saddr->sll_protocol;
|
|
addr = saddr->sll_addr;
|
|
dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
|
|
- need_rls_dev = true;
|
|
}
|
|
|
|
err = -ENXIO;
|
|
if (unlikely(dev == NULL))
|
|
goto out;
|
|
-
|
|
- reserve = dev->hard_header_len;
|
|
-
|
|
err = -ENETDOWN;
|
|
if (unlikely(!(dev->flags & IFF_UP)))
|
|
goto out_put;
|
|
|
|
+ reserve = dev->hard_header_len;
|
|
+
|
|
size_max = po->tx_ring.frame_size
|
|
- (po->tp_hdrlen - sizeof(struct sockaddr_ll));
|
|
|
|
@@ -2166,8 +2184,7 @@ out_status:
|
|
__packet_set_status(po, ph, status);
|
|
kfree_skb(skb);
|
|
out_put:
|
|
- if (need_rls_dev)
|
|
- dev_put(dev);
|
|
+ dev_put(dev);
|
|
out:
|
|
mutex_unlock(&po->pg_vec_lock);
|
|
return err;
|
|
@@ -2205,7 +2222,6 @@ static int packet_snd(struct socket *sock,
|
|
struct sk_buff *skb;
|
|
struct net_device *dev;
|
|
__be16 proto;
|
|
- bool need_rls_dev = false;
|
|
unsigned char *addr;
|
|
int err, reserve = 0;
|
|
struct virtio_net_hdr vnet_hdr = { 0 };
|
|
@@ -2221,7 +2237,7 @@ static int packet_snd(struct socket *sock,
|
|
*/
|
|
|
|
if (saddr == NULL) {
|
|
- dev = po->prot_hook.dev;
|
|
+ dev = packet_cached_dev_get(po);
|
|
proto = po->num;
|
|
addr = NULL;
|
|
} else {
|
|
@@ -2233,19 +2249,17 @@ static int packet_snd(struct socket *sock,
|
|
proto = saddr->sll_protocol;
|
|
addr = saddr->sll_addr;
|
|
dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
|
|
- need_rls_dev = true;
|
|
}
|
|
|
|
err = -ENXIO;
|
|
- if (dev == NULL)
|
|
+ if (unlikely(dev == NULL))
|
|
goto out_unlock;
|
|
- if (sock->type == SOCK_RAW)
|
|
- reserve = dev->hard_header_len;
|
|
-
|
|
err = -ENETDOWN;
|
|
- if (!(dev->flags & IFF_UP))
|
|
+ if (unlikely(!(dev->flags & IFF_UP)))
|
|
goto out_unlock;
|
|
|
|
+ if (sock->type == SOCK_RAW)
|
|
+ reserve = dev->hard_header_len;
|
|
if (po->has_vnet_hdr) {
|
|
vnet_hdr_len = sizeof(vnet_hdr);
|
|
|
|
@@ -2378,15 +2392,14 @@ static int packet_snd(struct socket *sock,
|
|
if (err > 0 && (err = net_xmit_errno(err)) != 0)
|
|
goto out_unlock;
|
|
|
|
- if (need_rls_dev)
|
|
- dev_put(dev);
|
|
+ dev_put(dev);
|
|
|
|
return len;
|
|
|
|
out_free:
|
|
kfree_skb(skb);
|
|
out_unlock:
|
|
- if (dev && need_rls_dev)
|
|
+ if (dev)
|
|
dev_put(dev);
|
|
out:
|
|
return err;
|
|
@@ -2603,6 +2616,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
|
|
po = pkt_sk(sk);
|
|
sk->sk_family = PF_PACKET;
|
|
po->num = proto;
|
|
+ RCU_INIT_POINTER(po->cached_dev, NULL);
|
|
|
|
sk->sk_destruct = packet_sock_destruct;
|
|
sk_refcnt_debug_inc(sk);
|
|
@@ -2691,7 +2705,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
struct sock *sk = sock->sk;
|
|
struct sk_buff *skb;
|
|
int copied, err;
|
|
- struct sockaddr_ll *sll;
|
|
int vnet_hdr_len = 0;
|
|
|
|
err = -EINVAL;
|
|
@@ -2774,22 +2787,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
goto out_free;
|
|
}
|
|
|
|
- /*
|
|
- * If the address length field is there to be filled in, we fill
|
|
- * it in now.
|
|
+ /* You lose any data beyond the buffer you gave. If it worries
|
|
+ * a user program they can ask the device for its MTU
|
|
+ * anyway.
|
|
*/
|
|
-
|
|
- sll = &PACKET_SKB_CB(skb)->sa.ll;
|
|
- if (sock->type == SOCK_PACKET)
|
|
- msg->msg_namelen = sizeof(struct sockaddr_pkt);
|
|
- else
|
|
- msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr);
|
|
-
|
|
- /*
|
|
- * You lose any data beyond the buffer you gave. If it worries a
|
|
- * user program they can ask the device for its MTU anyway.
|
|
- */
|
|
-
|
|
copied = skb->len;
|
|
if (copied > len) {
|
|
copied = len;
|
|
@@ -2802,9 +2803,20 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
sock_recv_ts_and_drops(msg, sk, skb);
|
|
|
|
- if (msg->msg_name)
|
|
+ if (msg->msg_name) {
|
|
+ /* If the address length field is there to be filled
|
|
+ * in, we fill it in now.
|
|
+ */
|
|
+ if (sock->type == SOCK_PACKET) {
|
|
+ msg->msg_namelen = sizeof(struct sockaddr_pkt);
|
|
+ } else {
|
|
+ struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
|
|
+ msg->msg_namelen = sll->sll_halen +
|
|
+ offsetof(struct sockaddr_ll, sll_addr);
|
|
+ }
|
|
memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
|
|
msg->msg_namelen);
|
|
+ }
|
|
|
|
if (pkt_sk(sk)->auxdata) {
|
|
struct tpacket_auxdata aux;
|
|
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
|
|
index bf35b4e1a14c..b25f2d321e05 100644
|
|
--- a/net/phonet/datagram.c
|
|
+++ b/net/phonet/datagram.c
|
|
@@ -139,9 +139,6 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk,
|
|
MSG_CMSG_COMPAT))
|
|
goto out_nofree;
|
|
|
|
- if (addr_len)
|
|
- *addr_len = sizeof(sa);
|
|
-
|
|
skb = skb_recv_datagram(sk, flags, noblock, &rval);
|
|
if (skb == NULL)
|
|
goto out_nofree;
|
|
@@ -162,8 +159,10 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk,
|
|
|
|
rval = (flags & MSG_TRUNC) ? skb->len : copylen;
|
|
|
|
- if (msg->msg_name != NULL)
|
|
- memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn));
|
|
+ if (msg->msg_name != NULL) {
|
|
+ memcpy(msg->msg_name, &sa, sizeof(sa));
|
|
+ *addr_len = sizeof(sa);
|
|
+ }
|
|
|
|
out:
|
|
skb_free_datagram(sk, skb);
|
|
diff --git a/net/rds/recv.c b/net/rds/recv.c
|
|
index 9f0f17cf6bf9..de339b24ca14 100644
|
|
--- a/net/rds/recv.c
|
|
+++ b/net/rds/recv.c
|
|
@@ -410,8 +410,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
|
|
|
rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
if (msg_flags & MSG_OOB)
|
|
goto out;
|
|
|
|
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
|
|
index 7f645d115795..ce5f5b934ea1 100644
|
|
--- a/net/rose/af_rose.c
|
|
+++ b/net/rose/af_rose.c
|
|
@@ -1220,7 +1220,6 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
{
|
|
struct sock *sk = sock->sk;
|
|
struct rose_sock *rose = rose_sk(sk);
|
|
- struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name;
|
|
size_t copied;
|
|
unsigned char *asmptr;
|
|
struct sk_buff *skb;
|
|
@@ -1256,8 +1255,11 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
|
|
|
|
- if (srose != NULL) {
|
|
- memset(srose, 0, msg->msg_namelen);
|
|
+ if (msg->msg_name) {
|
|
+ struct sockaddr_rose *srose;
|
|
+
|
|
+ memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
|
|
+ srose = msg->msg_name;
|
|
srose->srose_family = AF_ROSE;
|
|
srose->srose_addr = rose->dest_addr;
|
|
srose->srose_call = rose->dest_call;
|
|
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c
|
|
index 4b48687c3890..898492a8d61b 100644
|
|
--- a/net/rxrpc/ar-recvmsg.c
|
|
+++ b/net/rxrpc/ar-recvmsg.c
|
|
@@ -143,10 +143,13 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
/* copy the peer address and timestamp */
|
|
if (!continue_call) {
|
|
- if (msg->msg_name && msg->msg_namelen > 0)
|
|
+ if (msg->msg_name) {
|
|
+ size_t len =
|
|
+ sizeof(call->conn->trans->peer->srx);
|
|
memcpy(msg->msg_name,
|
|
- &call->conn->trans->peer->srx,
|
|
- sizeof(call->conn->trans->peer->srx));
|
|
+ &call->conn->trans->peer->srx, len);
|
|
+ msg->msg_namelen = len;
|
|
+ }
|
|
sock_recv_ts_and_drops(msg, &rx->sk, skb);
|
|
}
|
|
|
|
diff --git a/net/socket.c b/net/socket.c
|
|
index acc769562707..4006452e8475 100644
|
|
--- a/net/socket.c
|
|
+++ b/net/socket.c
|
|
@@ -215,12 +215,13 @@ static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
|
|
int err;
|
|
int len;
|
|
|
|
+ BUG_ON(klen > sizeof(struct sockaddr_storage));
|
|
err = get_user(len, ulen);
|
|
if (err)
|
|
return err;
|
|
if (len > klen)
|
|
len = klen;
|
|
- if (len < 0 || len > sizeof(struct sockaddr_storage))
|
|
+ if (len < 0)
|
|
return -EINVAL;
|
|
if (len) {
|
|
if (audit_sockaddr(klen, kaddr))
|
|
@@ -1775,8 +1776,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
|
|
msg.msg_iov = &iov;
|
|
iov.iov_len = size;
|
|
iov.iov_base = ubuf;
|
|
- msg.msg_name = (struct sockaddr *)&address;
|
|
- msg.msg_namelen = sizeof(address);
|
|
+ /* Save some cycles and don't copy the address if not needed */
|
|
+ msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
|
|
+ /* We assume all kernel code knows the size of sockaddr_storage */
|
|
+ msg.msg_namelen = 0;
|
|
if (sock->file->f_flags & O_NONBLOCK)
|
|
flags |= MSG_DONTWAIT;
|
|
err = sock_recvmsg(sock, &msg, size, flags);
|
|
@@ -1905,7 +1908,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
|
|
if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
|
|
return -EFAULT;
|
|
if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
|
|
- return -EINVAL;
|
|
+ kmsg->msg_namelen = sizeof(struct sockaddr_storage);
|
|
return 0;
|
|
}
|
|
|
|
@@ -2161,16 +2164,14 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
|
|
goto out;
|
|
}
|
|
|
|
- /*
|
|
- * Save the user-mode address (verify_iovec will change the
|
|
- * kernel msghdr to use the kernel address space)
|
|
+ /* Save the user-mode address (verify_iovec will change the
|
|
+ * kernel msghdr to use the kernel address space)
|
|
*/
|
|
-
|
|
uaddr = (__force void __user *)msg_sys->msg_name;
|
|
uaddr_len = COMPAT_NAMELEN(msg);
|
|
- if (MSG_CMSG_COMPAT & flags) {
|
|
+ if (MSG_CMSG_COMPAT & flags)
|
|
err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
|
|
- } else
|
|
+ else
|
|
err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
|
|
if (err < 0)
|
|
goto out_freeiov;
|
|
@@ -2179,6 +2180,9 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
|
|
cmsg_ptr = (unsigned long)msg_sys->msg_control;
|
|
msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
|
|
|
|
+ /* We assume all kernel code knows the size of sockaddr_storage */
|
|
+ msg_sys->msg_namelen = 0;
|
|
+
|
|
if (sock->file->f_flags & O_NONBLOCK)
|
|
flags |= MSG_DONTWAIT;
|
|
err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
|
|
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
|
|
index 1441ab70b98c..64b847008ee3 100644
|
|
--- a/net/tipc/socket.c
|
|
+++ b/net/tipc/socket.c
|
|
@@ -949,9 +949,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
|
|
goto exit;
|
|
}
|
|
|
|
- /* will be updated in set_orig_addr() if needed */
|
|
- m->msg_namelen = 0;
|
|
-
|
|
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
|
|
restart:
|
|
|
|
@@ -1078,9 +1075,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
|
|
goto exit;
|
|
}
|
|
|
|
- /* will be updated in set_orig_addr() if needed */
|
|
- m->msg_namelen = 0;
|
|
-
|
|
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
|
|
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
|
|
restart:
|
|
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
|
|
index ed005b425a7c..0540dd9b0387 100644
|
|
--- a/net/unix/af_unix.c
|
|
+++ b/net/unix/af_unix.c
|
|
@@ -1755,7 +1755,6 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
|
|
{
|
|
struct unix_sock *u = unix_sk(sk);
|
|
|
|
- msg->msg_namelen = 0;
|
|
if (u->addr) {
|
|
msg->msg_namelen = u->addr->len;
|
|
memcpy(msg->msg_name, u->addr->name, u->addr->len);
|
|
@@ -1779,8 +1778,6 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags&MSG_OOB)
|
|
goto out;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
err = mutex_lock_interruptible(&u->readlock);
|
|
if (err) {
|
|
err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
|
|
@@ -1922,8 +1919,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
|
|
timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
/* Lock the socket to prevent queue disordering
|
|
* while sleeps in memcpy_tomsg
|
|
*/
|
|
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
|
|
index b943e3e71bd2..92aed9e45c73 100644
|
|
--- a/net/x25/af_x25.c
|
|
+++ b/net/x25/af_x25.c
|
|
@@ -1343,10 +1343,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (sx25) {
|
|
sx25->sx25_family = AF_X25;
|
|
sx25->sx25_addr = x25->dest_addr;
|
|
+ msg->msg_namelen = sizeof(*sx25);
|
|
}
|
|
|
|
- msg->msg_namelen = sizeof(struct sockaddr_x25);
|
|
-
|
|
x25_check_rbuf(sk);
|
|
rc = copied;
|
|
out_free_dgram:
|