You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
nfsd: merge stable fix into main nfsd branch
This commit is contained in:
+10
-2
@@ -445,6 +445,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
|
||||
* @func: callback function on filter match
|
||||
* @data: returned parameter for callback function
|
||||
* @ident: string for calling module identification
|
||||
* @sk: socket pointer (might be NULL)
|
||||
*
|
||||
* Description:
|
||||
* Invokes the callback function with the received sk_buff and the given
|
||||
@@ -468,7 +469,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
|
||||
*/
|
||||
int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
|
||||
void (*func)(struct sk_buff *, void *), void *data,
|
||||
char *ident)
|
||||
char *ident, struct sock *sk)
|
||||
{
|
||||
struct receiver *r;
|
||||
struct hlist_head *rl;
|
||||
@@ -496,6 +497,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
|
||||
r->func = func;
|
||||
r->data = data;
|
||||
r->ident = ident;
|
||||
r->sk = sk;
|
||||
|
||||
hlist_add_head_rcu(&r->list, rl);
|
||||
d->entries++;
|
||||
@@ -520,8 +522,11 @@ EXPORT_SYMBOL(can_rx_register);
|
||||
static void can_rx_delete_receiver(struct rcu_head *rp)
|
||||
{
|
||||
struct receiver *r = container_of(rp, struct receiver, rcu);
|
||||
struct sock *sk = r->sk;
|
||||
|
||||
kmem_cache_free(rcv_cache, r);
|
||||
if (sk)
|
||||
sock_put(sk);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -596,8 +601,11 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
|
||||
spin_unlock(&can_rcvlists_lock);
|
||||
|
||||
/* schedule the receiver item for deletion */
|
||||
if (r)
|
||||
if (r) {
|
||||
if (r->sk)
|
||||
sock_hold(r->sk);
|
||||
call_rcu(&r->rcu, can_rx_delete_receiver);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(can_rx_unregister);
|
||||
|
||||
|
||||
+2
-1
@@ -50,13 +50,14 @@
|
||||
|
||||
struct receiver {
|
||||
struct hlist_node list;
|
||||
struct rcu_head rcu;
|
||||
canid_t can_id;
|
||||
canid_t mask;
|
||||
unsigned long matches;
|
||||
void (*func)(struct sk_buff *, void *);
|
||||
void *data;
|
||||
char *ident;
|
||||
struct sock *sk;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
|
||||
|
||||
+18
-9
@@ -734,14 +734,23 @@ static struct bcm_op *bcm_find_op(struct list_head *ops,
|
||||
|
||||
static void bcm_remove_op(struct bcm_op *op)
|
||||
{
|
||||
hrtimer_cancel(&op->timer);
|
||||
hrtimer_cancel(&op->thrtimer);
|
||||
if (op->tsklet.func) {
|
||||
while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
|
||||
test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
|
||||
hrtimer_active(&op->timer)) {
|
||||
hrtimer_cancel(&op->timer);
|
||||
tasklet_kill(&op->tsklet);
|
||||
}
|
||||
}
|
||||
|
||||
if (op->tsklet.func)
|
||||
tasklet_kill(&op->tsklet);
|
||||
|
||||
if (op->thrtsklet.func)
|
||||
tasklet_kill(&op->thrtsklet);
|
||||
if (op->thrtsklet.func) {
|
||||
while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
|
||||
test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
|
||||
hrtimer_active(&op->thrtimer)) {
|
||||
hrtimer_cancel(&op->thrtimer);
|
||||
tasklet_kill(&op->thrtsklet);
|
||||
}
|
||||
}
|
||||
|
||||
if ((op->frames) && (op->frames != &op->sframe))
|
||||
kfree(op->frames);
|
||||
@@ -1216,7 +1225,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
|
||||
err = can_rx_register(dev, op->can_id,
|
||||
REGMASK(op->can_id),
|
||||
bcm_rx_handler, op,
|
||||
"bcm");
|
||||
"bcm", sk);
|
||||
|
||||
op->rx_reg_dev = dev;
|
||||
dev_put(dev);
|
||||
@@ -1225,7 +1234,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
|
||||
} else
|
||||
err = can_rx_register(NULL, op->can_id,
|
||||
REGMASK(op->can_id),
|
||||
bcm_rx_handler, op, "bcm");
|
||||
bcm_rx_handler, op, "bcm", sk);
|
||||
if (err) {
|
||||
/* this bcm rx op is broken -> remove it */
|
||||
list_del(&op->list);
|
||||
|
||||
+1
-1
@@ -442,7 +442,7 @@ static inline int cgw_register_filter(struct cgw_job *gwj)
|
||||
{
|
||||
return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
|
||||
gwj->ccgw.filter.can_mask, can_can_gw_rcv,
|
||||
gwj, "gw");
|
||||
gwj, "gw", NULL);
|
||||
}
|
||||
|
||||
static inline void cgw_unregister_filter(struct cgw_job *gwj)
|
||||
|
||||
+2
-2
@@ -190,7 +190,7 @@ static int raw_enable_filters(struct net_device *dev, struct sock *sk,
|
||||
for (i = 0; i < count; i++) {
|
||||
err = can_rx_register(dev, filter[i].can_id,
|
||||
filter[i].can_mask,
|
||||
raw_rcv, sk, "raw");
|
||||
raw_rcv, sk, "raw", sk);
|
||||
if (err) {
|
||||
/* clean up successfully registered filters */
|
||||
while (--i >= 0)
|
||||
@@ -211,7 +211,7 @@ static int raw_enable_errfilter(struct net_device *dev, struct sock *sk,
|
||||
|
||||
if (err_mask)
|
||||
err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
|
||||
raw_rcv, sk, "raw");
|
||||
raw_rcv, sk, "raw", sk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2518,9 +2518,11 @@ u32 __tcp_select_window(struct sock *sk)
|
||||
int full_space = min_t(int, tp->window_clamp, allowed_space);
|
||||
int window;
|
||||
|
||||
if (mss > full_space)
|
||||
if (unlikely(mss > full_space)) {
|
||||
mss = full_space;
|
||||
|
||||
if (mss <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (free_space < (full_space >> 1)) {
|
||||
icsk->icsk_ack.quick = 0;
|
||||
|
||||
|
||||
@@ -1344,7 +1344,7 @@ emsgsize:
|
||||
*/
|
||||
if (transhdrlen && sk->sk_protocol == IPPROTO_UDP &&
|
||||
headersize == sizeof(struct ipv6hdr) &&
|
||||
length < mtu - headersize &&
|
||||
length <= mtu - headersize &&
|
||||
!(flags & MSG_MORE) &&
|
||||
rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
|
||||
csummode = CHECKSUM_PARTIAL;
|
||||
|
||||
@@ -441,7 +441,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
|
||||
if (i + sizeof(*tel) > optlen)
|
||||
break;
|
||||
|
||||
tel = (struct ipv6_tlv_tnl_enc_lim *) skb->data + off + i;
|
||||
tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i);
|
||||
/* return index of option if found and valid */
|
||||
if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
|
||||
tel->length == 1)
|
||||
|
||||
@@ -568,9 +568,9 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
|
||||
&mask->icmp.type,
|
||||
TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
|
||||
sizeof(key->icmp.type));
|
||||
fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
|
||||
fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV6_CODE,
|
||||
&mask->icmp.code,
|
||||
TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
|
||||
TCA_FLOWER_KEY_ICMPV6_CODE_MASK,
|
||||
sizeof(key->icmp.code));
|
||||
}
|
||||
|
||||
|
||||
+45
-82
@@ -16,16 +16,11 @@
|
||||
#include <net/sch_generic.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
struct cls_mall_filter {
|
||||
struct cls_mall_head {
|
||||
struct tcf_exts exts;
|
||||
struct tcf_result res;
|
||||
u32 handle;
|
||||
struct rcu_head rcu;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct cls_mall_head {
|
||||
struct cls_mall_filter *filter;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
@@ -33,38 +28,29 @@ static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
|
||||
struct tcf_result *res)
|
||||
{
|
||||
struct cls_mall_head *head = rcu_dereference_bh(tp->root);
|
||||
struct cls_mall_filter *f = head->filter;
|
||||
|
||||
if (tc_skip_sw(f->flags))
|
||||
if (tc_skip_sw(head->flags))
|
||||
return -1;
|
||||
|
||||
return tcf_exts_exec(skb, &f->exts, res);
|
||||
return tcf_exts_exec(skb, &head->exts, res);
|
||||
}
|
||||
|
||||
static int mall_init(struct tcf_proto *tp)
|
||||
{
|
||||
struct cls_mall_head *head;
|
||||
|
||||
head = kzalloc(sizeof(*head), GFP_KERNEL);
|
||||
if (!head)
|
||||
return -ENOBUFS;
|
||||
|
||||
rcu_assign_pointer(tp->root, head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mall_destroy_filter(struct rcu_head *head)
|
||||
static void mall_destroy_rcu(struct rcu_head *rcu)
|
||||
{
|
||||
struct cls_mall_filter *f = container_of(head, struct cls_mall_filter, rcu);
|
||||
struct cls_mall_head *head = container_of(rcu, struct cls_mall_head,
|
||||
rcu);
|
||||
|
||||
tcf_exts_destroy(&f->exts);
|
||||
|
||||
kfree(f);
|
||||
tcf_exts_destroy(&head->exts);
|
||||
kfree(head);
|
||||
}
|
||||
|
||||
static int mall_replace_hw_filter(struct tcf_proto *tp,
|
||||
struct cls_mall_filter *f,
|
||||
struct cls_mall_head *head,
|
||||
unsigned long cookie)
|
||||
{
|
||||
struct net_device *dev = tp->q->dev_queue->dev;
|
||||
@@ -74,7 +60,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
|
||||
offload.type = TC_SETUP_MATCHALL;
|
||||
offload.cls_mall = &mall_offload;
|
||||
offload.cls_mall->command = TC_CLSMATCHALL_REPLACE;
|
||||
offload.cls_mall->exts = &f->exts;
|
||||
offload.cls_mall->exts = &head->exts;
|
||||
offload.cls_mall->cookie = cookie;
|
||||
|
||||
return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
|
||||
@@ -82,7 +68,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
|
||||
}
|
||||
|
||||
static void mall_destroy_hw_filter(struct tcf_proto *tp,
|
||||
struct cls_mall_filter *f,
|
||||
struct cls_mall_head *head,
|
||||
unsigned long cookie)
|
||||
{
|
||||
struct net_device *dev = tp->q->dev_queue->dev;
|
||||
@@ -103,29 +89,20 @@ static bool mall_destroy(struct tcf_proto *tp, bool force)
|
||||
{
|
||||
struct cls_mall_head *head = rtnl_dereference(tp->root);
|
||||
struct net_device *dev = tp->q->dev_queue->dev;
|
||||
struct cls_mall_filter *f = head->filter;
|
||||
|
||||
if (!force && f)
|
||||
return false;
|
||||
if (!head)
|
||||
return true;
|
||||
|
||||
if (f) {
|
||||
if (tc_should_offload(dev, tp, f->flags))
|
||||
mall_destroy_hw_filter(tp, f, (unsigned long) f);
|
||||
if (tc_should_offload(dev, tp, head->flags))
|
||||
mall_destroy_hw_filter(tp, head, (unsigned long) head);
|
||||
|
||||
call_rcu(&f->rcu, mall_destroy_filter);
|
||||
}
|
||||
kfree_rcu(head, rcu);
|
||||
call_rcu(&head->rcu, mall_destroy_rcu);
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned long mall_get(struct tcf_proto *tp, u32 handle)
|
||||
{
|
||||
struct cls_mall_head *head = rtnl_dereference(tp->root);
|
||||
struct cls_mall_filter *f = head->filter;
|
||||
|
||||
if (f && f->handle == handle)
|
||||
return (unsigned long) f;
|
||||
return 0;
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
|
||||
@@ -134,7 +111,7 @@ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
|
||||
};
|
||||
|
||||
static int mall_set_parms(struct net *net, struct tcf_proto *tp,
|
||||
struct cls_mall_filter *f,
|
||||
struct cls_mall_head *head,
|
||||
unsigned long base, struct nlattr **tb,
|
||||
struct nlattr *est, bool ovr)
|
||||
{
|
||||
@@ -147,11 +124,11 @@ static int mall_set_parms(struct net *net, struct tcf_proto *tp,
|
||||
return err;
|
||||
|
||||
if (tb[TCA_MATCHALL_CLASSID]) {
|
||||
f->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
|
||||
tcf_bind_filter(tp, &f->res, base);
|
||||
head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
|
||||
tcf_bind_filter(tp, &head->res, base);
|
||||
}
|
||||
|
||||
tcf_exts_change(tp, &f->exts, &e);
|
||||
tcf_exts_change(tp, &head->exts, &e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -162,21 +139,17 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
|
||||
unsigned long *arg, bool ovr)
|
||||
{
|
||||
struct cls_mall_head *head = rtnl_dereference(tp->root);
|
||||
struct cls_mall_filter *fold = (struct cls_mall_filter *) *arg;
|
||||
struct net_device *dev = tp->q->dev_queue->dev;
|
||||
struct cls_mall_filter *f;
|
||||
struct nlattr *tb[TCA_MATCHALL_MAX + 1];
|
||||
struct cls_mall_head *new;
|
||||
u32 flags = 0;
|
||||
int err;
|
||||
|
||||
if (!tca[TCA_OPTIONS])
|
||||
return -EINVAL;
|
||||
|
||||
if (head->filter)
|
||||
return -EBUSY;
|
||||
|
||||
if (fold)
|
||||
return -EINVAL;
|
||||
if (head)
|
||||
return -EEXIST;
|
||||
|
||||
err = nla_parse_nested(tb, TCA_MATCHALL_MAX,
|
||||
tca[TCA_OPTIONS], mall_policy);
|
||||
@@ -189,23 +162,23 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f = kzalloc(sizeof(*f), GFP_KERNEL);
|
||||
if (!f)
|
||||
new = kzalloc(sizeof(*new), GFP_KERNEL);
|
||||
if (!new)
|
||||
return -ENOBUFS;
|
||||
|
||||
tcf_exts_init(&f->exts, TCA_MATCHALL_ACT, 0);
|
||||
tcf_exts_init(&new->exts, TCA_MATCHALL_ACT, 0);
|
||||
|
||||
if (!handle)
|
||||
handle = 1;
|
||||
f->handle = handle;
|
||||
f->flags = flags;
|
||||
new->handle = handle;
|
||||
new->flags = flags;
|
||||
|
||||
err = mall_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
|
||||
err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
if (tc_should_offload(dev, tp, flags)) {
|
||||
err = mall_replace_hw_filter(tp, f, (unsigned long) f);
|
||||
err = mall_replace_hw_filter(tp, new, (unsigned long) new);
|
||||
if (err) {
|
||||
if (tc_skip_sw(flags))
|
||||
goto errout;
|
||||
@@ -214,39 +187,29 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
|
||||
}
|
||||
}
|
||||
|
||||
*arg = (unsigned long) f;
|
||||
rcu_assign_pointer(head->filter, f);
|
||||
|
||||
*arg = (unsigned long) head;
|
||||
rcu_assign_pointer(tp->root, new);
|
||||
if (head)
|
||||
call_rcu(&head->rcu, mall_destroy_rcu);
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
kfree(f);
|
||||
kfree(new);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mall_delete(struct tcf_proto *tp, unsigned long arg)
|
||||
{
|
||||
struct cls_mall_head *head = rtnl_dereference(tp->root);
|
||||
struct cls_mall_filter *f = (struct cls_mall_filter *) arg;
|
||||
struct net_device *dev = tp->q->dev_queue->dev;
|
||||
|
||||
if (tc_should_offload(dev, tp, f->flags))
|
||||
mall_destroy_hw_filter(tp, f, (unsigned long) f);
|
||||
|
||||
RCU_INIT_POINTER(head->filter, NULL);
|
||||
tcf_unbind_filter(tp, &f->res);
|
||||
call_rcu(&f->rcu, mall_destroy_filter);
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg)
|
||||
{
|
||||
struct cls_mall_head *head = rtnl_dereference(tp->root);
|
||||
struct cls_mall_filter *f = head->filter;
|
||||
|
||||
if (arg->count < arg->skip)
|
||||
goto skip;
|
||||
if (arg->fn(tp, (unsigned long) f, arg) < 0)
|
||||
if (arg->fn(tp, (unsigned long) head, arg) < 0)
|
||||
arg->stop = 1;
|
||||
skip:
|
||||
arg->count++;
|
||||
@@ -255,28 +218,28 @@ skip:
|
||||
static int mall_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
|
||||
struct sk_buff *skb, struct tcmsg *t)
|
||||
{
|
||||
struct cls_mall_filter *f = (struct cls_mall_filter *) fh;
|
||||
struct cls_mall_head *head = (struct cls_mall_head *) fh;
|
||||
struct nlattr *nest;
|
||||
|
||||
if (!f)
|
||||
if (!head)
|
||||
return skb->len;
|
||||
|
||||
t->tcm_handle = f->handle;
|
||||
t->tcm_handle = head->handle;
|
||||
|
||||
nest = nla_nest_start(skb, TCA_OPTIONS);
|
||||
if (!nest)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (f->res.classid &&
|
||||
nla_put_u32(skb, TCA_MATCHALL_CLASSID, f->res.classid))
|
||||
if (head->res.classid &&
|
||||
nla_put_u32(skb, TCA_MATCHALL_CLASSID, head->res.classid))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (tcf_exts_dump(skb, &f->exts))
|
||||
if (tcf_exts_dump(skb, &head->exts))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(skb, nest);
|
||||
|
||||
if (tcf_exts_dump_stats(skb, &f->exts) < 0)
|
||||
if (tcf_exts_dump_stats(skb, &head->exts) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
return skb->len;
|
||||
|
||||
Reference in New Issue
Block a user