Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Several cases of overlapping changes, except the packet scheduler conflicts which deal with the addition of the free list parameter to qdisc_enqueue(). Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -1122,7 +1122,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
nla_nest_end(skb, nest);
|
||||
ret = skb->len;
|
||||
} else
|
||||
nla_nest_cancel(skb, nest);
|
||||
nlmsg_trim(skb, b);
|
||||
|
||||
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
|
||||
if (NETLINK_CB(cb->skb).portid && ret)
|
||||
|
@@ -106,9 +106,9 @@ int ife_get_meta_u16(struct sk_buff *skb, struct tcf_meta_info *mi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ife_get_meta_u16);
|
||||
|
||||
int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval)
|
||||
int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval, gfp_t gfp)
|
||||
{
|
||||
mi->metaval = kmemdup(metaval, sizeof(u32), GFP_KERNEL);
|
||||
mi->metaval = kmemdup(metaval, sizeof(u32), gfp);
|
||||
if (!mi->metaval)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -116,9 +116,9 @@ int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ife_alloc_meta_u32);
|
||||
|
||||
int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval)
|
||||
int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval, gfp_t gfp)
|
||||
{
|
||||
mi->metaval = kmemdup(metaval, sizeof(u16), GFP_KERNEL);
|
||||
mi->metaval = kmemdup(metaval, sizeof(u16), gfp);
|
||||
if (!mi->metaval)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -240,10 +240,10 @@ static int ife_validate_metatype(struct tcf_meta_ops *ops, void *val, int len)
|
||||
}
|
||||
|
||||
/* called when adding new meta information
|
||||
* under ife->tcf_lock
|
||||
* under ife->tcf_lock for existing action
|
||||
*/
|
||||
static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
|
||||
void *val, int len)
|
||||
void *val, int len, bool exists)
|
||||
{
|
||||
struct tcf_meta_ops *ops = find_ife_oplist(metaid);
|
||||
int ret = 0;
|
||||
@@ -251,11 +251,13 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
|
||||
if (!ops) {
|
||||
ret = -ENOENT;
|
||||
#ifdef CONFIG_MODULES
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
if (exists)
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
rtnl_unlock();
|
||||
request_module("ifemeta%u", metaid);
|
||||
rtnl_lock();
|
||||
spin_lock_bh(&ife->tcf_lock);
|
||||
if (exists)
|
||||
spin_lock_bh(&ife->tcf_lock);
|
||||
ops = find_ife_oplist(metaid);
|
||||
#endif
|
||||
}
|
||||
@@ -272,10 +274,10 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
|
||||
}
|
||||
|
||||
/* called when adding new meta information
|
||||
* under ife->tcf_lock
|
||||
* under ife->tcf_lock for existing action
|
||||
*/
|
||||
static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
|
||||
int len)
|
||||
int len, bool atomic)
|
||||
{
|
||||
struct tcf_meta_info *mi = NULL;
|
||||
struct tcf_meta_ops *ops = find_ife_oplist(metaid);
|
||||
@@ -284,7 +286,7 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
|
||||
if (!ops)
|
||||
return -ENOENT;
|
||||
|
||||
mi = kzalloc(sizeof(*mi), GFP_KERNEL);
|
||||
mi = kzalloc(sizeof(*mi), atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (!mi) {
|
||||
/*put back what find_ife_oplist took */
|
||||
module_put(ops->owner);
|
||||
@@ -294,7 +296,7 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
|
||||
mi->metaid = metaid;
|
||||
mi->ops = ops;
|
||||
if (len > 0) {
|
||||
ret = ops->alloc(mi, metaval);
|
||||
ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (ret != 0) {
|
||||
kfree(mi);
|
||||
module_put(ops->owner);
|
||||
@@ -313,11 +315,13 @@ static int use_all_metadata(struct tcf_ife_info *ife)
|
||||
int rc = 0;
|
||||
int installed = 0;
|
||||
|
||||
read_lock(&ife_mod_lock);
|
||||
list_for_each_entry(o, &ifeoplist, list) {
|
||||
rc = add_metainfo(ife, o->metaid, NULL, 0);
|
||||
rc = add_metainfo(ife, o->metaid, NULL, 0, true);
|
||||
if (rc == 0)
|
||||
installed += 1;
|
||||
}
|
||||
read_unlock(&ife_mod_lock);
|
||||
|
||||
if (installed)
|
||||
return 0;
|
||||
@@ -385,8 +389,9 @@ static void tcf_ife_cleanup(struct tc_action *a, int bind)
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
}
|
||||
|
||||
/* under ife->tcf_lock */
|
||||
static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb)
|
||||
/* under ife->tcf_lock for existing action */
|
||||
static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
|
||||
bool exists)
|
||||
{
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
@@ -398,11 +403,11 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb)
|
||||
val = nla_data(tb[i]);
|
||||
len = nla_len(tb[i]);
|
||||
|
||||
rc = load_metaops_and_vet(ife, i, val, len);
|
||||
rc = load_metaops_and_vet(ife, i, val, len, exists);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
rc = add_metainfo(ife, i, val, len);
|
||||
rc = add_metainfo(ife, i, val, len, exists);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@@ -475,7 +480,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
|
||||
saddr = nla_data(tb[TCA_IFE_SMAC]);
|
||||
}
|
||||
|
||||
spin_lock_bh(&ife->tcf_lock);
|
||||
if (exists)
|
||||
spin_lock_bh(&ife->tcf_lock);
|
||||
ife->tcf_action = parm->action;
|
||||
|
||||
if (parm->flags & IFE_ENCODE) {
|
||||
@@ -505,11 +511,12 @@ metadata_parse_err:
|
||||
if (ret == ACT_P_CREATED)
|
||||
_tcf_ife_cleanup(a, bind);
|
||||
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
if (exists)
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = populate_metalist(ife, tb2);
|
||||
err = populate_metalist(ife, tb2, exists);
|
||||
if (err)
|
||||
goto metadata_parse_err;
|
||||
|
||||
@@ -524,12 +531,14 @@ metadata_parse_err:
|
||||
if (ret == ACT_P_CREATED)
|
||||
_tcf_ife_cleanup(a, bind);
|
||||
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
if (exists)
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
if (exists)
|
||||
spin_unlock_bh(&ife->tcf_lock);
|
||||
|
||||
if (ret == ACT_P_CREATED)
|
||||
tcf_hash_insert(tn, a);
|
||||
|
@@ -123,10 +123,13 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
|
||||
}
|
||||
|
||||
td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
|
||||
if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size)
|
||||
if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) {
|
||||
if (exists)
|
||||
tcf_hash_release(a, bind);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!tcf_hash_check(tn, index, a, bind)) {
|
||||
if (!exists) {
|
||||
ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind,
|
||||
false);
|
||||
if (ret)
|
||||
|
@@ -40,14 +40,18 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
||||
static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
||||
struct sk_buff **to_free)
|
||||
{
|
||||
unsigned int prev_backlog;
|
||||
|
||||
if (likely(skb_queue_len(&sch->q) < sch->limit))
|
||||
return qdisc_enqueue_tail(skb, sch);
|
||||
|
||||
prev_backlog = sch->qstats.backlog;
|
||||
/* queue full, remove one skb to fulfill the limit */
|
||||
__qdisc_queue_drop_head(sch, &sch->q, to_free);
|
||||
qdisc_qstats_drop(sch);
|
||||
qdisc_enqueue_tail(skb, sch);
|
||||
|
||||
qdisc_tree_reduce_backlog(sch, 0, prev_backlog - sch->qstats.backlog);
|
||||
return NET_XMIT_CN;
|
||||
}
|
||||
|
||||
|
@@ -984,7 +984,9 @@ static void htb_work_func(struct work_struct *work)
|
||||
struct htb_sched *q = container_of(work, struct htb_sched, work);
|
||||
struct Qdisc *sch = q->watchdog.qdisc;
|
||||
|
||||
rcu_read_lock();
|
||||
__netif_schedule(qdisc_root(sch));
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int htb_init(struct Qdisc *sch, struct nlattr *opt)
|
||||
|
@@ -621,17 +621,17 @@ deliver:
|
||||
#endif
|
||||
|
||||
if (q->qdisc) {
|
||||
unsigned int pkt_len = qdisc_pkt_len(skb);
|
||||
struct sk_buff *to_free = NULL;
|
||||
int err;
|
||||
|
||||
err = qdisc_enqueue(skb, q->qdisc, &to_free);
|
||||
kfree_skb_list(to_free);
|
||||
if (unlikely(err != NET_XMIT_SUCCESS)) {
|
||||
if (net_xmit_drop_count(err)) {
|
||||
qdisc_qstats_drop(sch);
|
||||
qdisc_tree_reduce_backlog(sch, 1,
|
||||
qdisc_pkt_len(skb));
|
||||
}
|
||||
if (err != NET_XMIT_SUCCESS &&
|
||||
net_xmit_drop_count(err)) {
|
||||
qdisc_qstats_drop(sch);
|
||||
qdisc_tree_reduce_backlog(sch, 1,
|
||||
pkt_len);
|
||||
}
|
||||
goto tfifo_dequeue;
|
||||
}
|
||||
|
@@ -153,8 +153,9 @@ prio_destroy(struct Qdisc *sch)
|
||||
static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
|
||||
{
|
||||
struct prio_sched_data *q = qdisc_priv(sch);
|
||||
struct Qdisc *queues[TCQ_PRIO_BANDS];
|
||||
int oldbands = q->bands, i;
|
||||
struct tc_prio_qopt *qopt;
|
||||
int i;
|
||||
|
||||
if (nla_len(opt) < sizeof(*qopt))
|
||||
return -EINVAL;
|
||||
@@ -168,62 +169,42 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Before commit, make sure we can allocate all new qdiscs */
|
||||
for (i = oldbands; i < qopt->bands; i++) {
|
||||
queues[i] = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
|
||||
TC_H_MAKE(sch->handle, i + 1));
|
||||
if (!queues[i]) {
|
||||
while (i > oldbands)
|
||||
qdisc_destroy(queues[--i]);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
sch_tree_lock(sch);
|
||||
q->bands = qopt->bands;
|
||||
memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
|
||||
|
||||
for (i = q->bands; i < TCQ_PRIO_BANDS; i++) {
|
||||
for (i = q->bands; i < oldbands; i++) {
|
||||
struct Qdisc *child = q->queues[i];
|
||||
q->queues[i] = &noop_qdisc;
|
||||
if (child != &noop_qdisc) {
|
||||
qdisc_tree_reduce_backlog(child, child->q.qlen, child->qstats.backlog);
|
||||
qdisc_destroy(child);
|
||||
}
|
||||
|
||||
qdisc_tree_reduce_backlog(child, child->q.qlen,
|
||||
child->qstats.backlog);
|
||||
qdisc_destroy(child);
|
||||
}
|
||||
|
||||
for (i = oldbands; i < q->bands; i++)
|
||||
q->queues[i] = queues[i];
|
||||
|
||||
sch_tree_unlock(sch);
|
||||
|
||||
for (i = 0; i < q->bands; i++) {
|
||||
if (q->queues[i] == &noop_qdisc) {
|
||||
struct Qdisc *child, *old;
|
||||
|
||||
child = qdisc_create_dflt(sch->dev_queue,
|
||||
&pfifo_qdisc_ops,
|
||||
TC_H_MAKE(sch->handle, i + 1));
|
||||
if (child) {
|
||||
sch_tree_lock(sch);
|
||||
old = q->queues[i];
|
||||
q->queues[i] = child;
|
||||
|
||||
if (old != &noop_qdisc) {
|
||||
qdisc_tree_reduce_backlog(old,
|
||||
old->q.qlen,
|
||||
old->qstats.backlog);
|
||||
qdisc_destroy(old);
|
||||
}
|
||||
sch_tree_unlock(sch);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prio_init(struct Qdisc *sch, struct nlattr *opt)
|
||||
{
|
||||
struct prio_sched_data *q = qdisc_priv(sch);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TCQ_PRIO_BANDS; i++)
|
||||
q->queues[i] = &noop_qdisc;
|
||||
|
||||
if (opt == NULL) {
|
||||
if (!opt)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
int err;
|
||||
|
||||
if ((err = prio_tune(sch, opt)) != 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
return prio_tune(sch, opt);
|
||||
}
|
||||
|
||||
static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||
|
Reference in New Issue
Block a user