Netdev List
 help / color / mirror / Atom feed
* Re: Device tree property names for MDIO bus multiplexer. Was: Re: [PATCH 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
From: Grant Likely @ 2011-09-15  0:41 UTC (permalink / raw)
  To: David Daney
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ralf-6z/3iImG2C8G8FEW9MqTrA,
	rob.herring-bsGFqQB8/DxBDgjK7y7TUQ, David S. Miller
In-Reply-To: <4E711F59.6000801-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 4562 bytes --]

On Sep 14, 2011 3:40 PM, "David Daney" <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org> wrote:
>
> Well, I would really like to get an official maintainer's take on the name
of the parent MDIO bus property.  Prehaps Grant or Rob could opine on the
matter.
>
> Sooner would be better than later as I am about to start shipping boards
with this burnt into the bootloader.  If it needs changing, I could do it in
the next couple of days, but after that it escapes into the wild.

Considering that the parent bus should be either implicit in the node
topology, or if not then part of something like an i2c controlled bus
multiplexer, I don't think this is even remotely a big deal. Each bus
multiplexer will still likely have it's own binding, and therefore her to
make its own decision.

That said, in the interest of commonality, I think mdio-parent-bus would be
just fine.  parent-bus is probably too generic.

g.

>
> Thanks in advance,
> David Daney
>
>
> On 09/14/2011 01:42 PM, Kumar Gala wrote:
>>
>>
>> On Sep 13, 2011, at 6:23 PM, David Daney wrote:
>>
>>> On 09/13/2011 04:07 PM, Kumar Gala wrote:
>>>>
>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt
b/Documentation/devicetree/bindings/net/mdio-mux.txt
>>>>> new file mode 100644
>>>>> index 0000000..a908312
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
>>>>> @@ -0,0 +1,132 @@
>>>>> +Common MDIO bus multiplexer/switch properties.
>>>>> +
>>>>> +An MDIO bus multiplexer/switch will have several child busses that
are
>>>>> +numbered uniquely in a device dependent manner.  The nodes for an
MDIO
>>>>> +bus multiplexer/switch will have one child node for each child bus.
>>>>> +
>>>>> +Required properties:
>>>>> +- parent-bus : phandle to the parent MDIO bus.
>>>>
>>>>
>>>> Should probably be mdio-parent-bus
>>>
>>>
>>> Why?  We know it is MDIO.
>>>
>>> Serial bus multiplexing is not a concept limited to MDIO.  We would want
to use "parent-bus" for some I2C multiplexers as well.
>>
>>
>>> From many years of dealing with device trees.  We typically don't name
things overlay generically unless they will be used over and over again as a
common idiom (like reg, interrupt, etc.).
>>
>>
>> We don't really use 'bus' generically today.
>>
>>>
>>>>
>>>>> +
>>>>> +Optional properties:
>>>>> +- Other properties specific to the multiplexer/switch hardware.
>>>>> +
>>>>> +Required properties for child nodes:
>>>>> +- #address-cells =<1>;
>>>>> +- #size-cells =<0>;
>>>>> +- cell-index : The sub-bus number.
>>>>
>>>>
>>>> What does sub-bus number mean?
>>>
>>>
>>> There are N child buses (or sub-buses) coming out of the multiplexer.
The cell-index is used as a handle or identifier for each of these.
>>>
>>> The concrete example in Patch 3/3 is a multiplexer with four child
buses.  The happen to have cell-indexes of 0, 1, 2 and 3.
>>>
>>> In the GPIO case of patch 3/3, these directly correspond the the state
of the two GPIO pins controlling the multiplexer.  The driver then uses the
cell-index property to determine the state of the GPIO to connect any given
child.
>>>
>>> It is possible that the documentation part of the patch could be made
more clear about this.
>>>
>>>>
>>>>> +
>>>>> +
>>>>> +Example :
>>>>
>>>>
>>> [...]
>>>>>
>>>>> +
>>>>> +int mdio_mux_probe(struct platform_device *pdev,
>>>>> +                  int (*switch_fn)(int cur, int desired, void *data),
>>>>> +                  void *data)
>>>>> +{
>>>>> +       struct device_node *parent_bus_node;
>>>>> +       struct device_node *child_bus_node;
>>>>> +       int r, n, ret_val;
>>>>> +       struct mii_bus *parent_bus;
>>>>> +       struct mdio_mux_parent_bus *pb;
>>>>> +       struct mdio_mux_child_bus *cb;
>>>>> +
>>>>> +       if (!pdev->dev.of_node)
>>>>> +               return -ENODEV;
>>>>> +
>>>>> +       parent_bus_node = of_parse_phandle(pdev->dev.of_node,
"parent-bus", 0);
>>>>> +
>>>>> +       if (!parent_bus_node)
>>>>> +               return -ENODEV;
>>>>> +
>>>>> +       parent_bus = of_mdio_find_bus(parent_bus_node);
>>>>
>>>>
>>>>
>>>> So what happens if the parent bus probe happens after the mux probe?
>>>>
>>>
>>> The whole house of cards collapses.
>>>
>>> Grant Likely has a patch to deal with this by retrying the probing,  but
as far as I know, it has not been merged yet.
>>
>>
>> - k--
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>

[-- Attachment #1.2: Type: text/html, Size: 6732 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply

* Re: [PATCH 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
From: Grant Likely @ 2011-09-15  0:51 UTC (permalink / raw)
  To: David Daney, David Daney
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ralf-6z/3iImG2C8G8FEW9MqTrA,
	David S. Miller
In-Reply-To: <1314820906-14004-3-git-send-email-david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 3530 bytes --]

On Aug 31, 2011 2:01 PM, "David Daney" <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org> wrote:
>
> This patch adds a somewhat generic framework for MDIO bus
> multiplexers.  It is modeled on the I2C multiplexer.
>
> The multiplexer is needed if there are multiple PHYs with the same
> address connected to the same MDIO bus adepter, or if there is
> insufficient electrical drive capability for all the connected PHY
> devices.
>
> Conceptually it could look something like this:
>
>                   ------------------
>                   | Control Signal |
>                   --------+---------
>                           |
>  ---------------   --------+------
>  | MDIO MASTER |---| Multiplexer |
>  ---------------   --+-------+----
>                     |       |
>                     C       C
>                     h       h
>                     i       i
>                     l       l
>                     d       d
>                     |       |
>     ---------       A       B   ---------
>     |       |       |       |   |       |
>     | PHY@1 +-------+       +---+ PHY@1 |
>     |       |       |       |   |       |
>     ---------       |       |   ---------
>     ---------       |       |   ---------
>     |       |       |       |   |       |
>     | PHY@2 +-------+       +---+ PHY@2 |
>     |       |                   |       |
>     ---------                   ---------
>
> This framework configures the bus topology from device tree data.  The
> mechanics of switching the multiplexer is left to device specific
> drivers.
>
> The follow-on patch contains a multiplexer driven by GPIO lines.
>
> Signed-off-by: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/net/mdio-mux.txt |  132 ++++++++++++++
>  drivers/net/phy/Kconfig                            |    8 +
>  drivers/net/phy/Makefile                           |    1 +
>  drivers/net/phy/mdio-mux.c                         |  182
++++++++++++++++++++
>  include/linux/mdio-mux.h                           |   18 ++
>  5 files changed, 341 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
>  create mode 100644 drivers/net/phy/mdio-mux.c
>  create mode 100644 include/linux/mdio-mux.h
>
> diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt
b/Documentation/devicetree/bindings/net/mdio-mux.txt
> new file mode 100644
> index 0000000..a908312
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
> @@ -0,0 +1,132 @@
> +Common MDIO bus multiplexer/switch properties.
> +
> +An MDIO bus multiplexer/switch will have several child busses that are
> +numbered uniquely in a device dependent manner.  The nodes for an MDIO
> +bus multiplexer/switch will have one child node for each child bus.
> +
> +Required properties:
> +- parent-bus : phandle to the parent MDIO bus.

As discussed, I like mdio-parent-bus.

> +
> +Optional properties:
> +- Other properties specific to the multiplexer/switch hardware.
> +
> +Required properties for child nodes:
> +- #address-cells = <1>;
> +- #size-cells = <0>;
> +- cell-index : The sub-bus number.

Use reg, not cell-index. That is what it is there for. And add the
appropriate #address/size-cells in the parent.

I've not reviewed the implementation, but with the changes. I'm okay with
the binding.

g.

[-- Attachment #1.2: Type: text/html, Size: 4530 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply

* [PATCH v2 0/7] per-cgroup tcp buffer pressure settings
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm

This patch introduces per-cgroup tcp buffers limitation. This allows
sysadmins to specify a maximum amount of kernel memory that
tcp connections can use at any point in time. TCP is the main interest
in this work, but extending it to other protocols would be easy.

For this to work, I am hooking it into memcg, after the introdution of
an extension for tracking and controlling objects in kernel memory.
Since they are usually not found in page granularity, and are fundamentally
different from userspace memory (not swappable, can't overcommit), they
need their special place inside the Memory Controller.

Right now, the kmem extension is quite basic, and just lays down the
basic infrastucture for the ongoing work. 

Although it does not account kernel memory allocated - I preferred to
keep this series simple and leave accounting to the slab allocations when
they arrive.

What it does is to piggyback in the memory control mechanism already present in
/proc/sys/net/ipv4/tcp_mem. There is a soft limit, and a hard limit,
that will suppress allocation when reached. For each cgroup, however,
the file kmem.tcp_maxmem will be used to cap those values. 

The usage I have in mind here is containers. Each container will
define its own values for soft and hard limits, but none of them will
be possibly bigger than the value the box' sysadmin specified from
the outside.

To test for any performance impacts of this patch, I used netperf's
TCP_RR benchmark on localhost, so we can have both recv and snd in action.

Command line used was ./src/netperf -t TCP_RR -H localhost, and the
results:

Without the patch
=================

Socket Size   Request  Resp.   Elapsed  Trans.
Send   Recv   Size     Size    Time     Rate
bytes  Bytes  bytes    bytes   secs.    per sec

16384  87380  1        1       10.00    26996.35
16384  87380

With the patch
===============

Local /Remote
Socket Size   Request  Resp.   Elapsed  Trans.
Send   Recv   Size     Size    Time     Rate
bytes  Bytes  bytes    bytes   secs.    per sec

16384  87380  1        1       10.00    27291.86
16384  87380

The difference is within a one-percent range.

Nesting cgroups doesn't seem to be the dominating factor as well,
with nestings up to 10 levels not showing a significant performance
difference.


Glauber Costa (7):
  Basic kernel memory functionality for the Memory Controller
  socket: initial cgroup code.
  foundations of per-cgroup memory pressure controlling.
  per-cgroup tcp buffers control
  per-netns ipv4 sysctl_tcp_mem
  tcp buffer limitation: per-cgroup limit
  Display current tcp memory allocation in kmem cgroup

 Documentation/cgroups/memory.txt |   31 +++-
 crypto/af_alg.c                  |    7 +-
 include/linux/memcontrol.h       |   84 +++++++++
 include/net/netns/ipv4.h         |    1 +
 include/net/sock.h               |  126 +++++++++++++-
 include/net/tcp.h                |   14 +-
 include/net/udp.h                |    3 +-
 include/trace/events/sock.h      |   10 +-
 init/Kconfig                     |   11 ++
 mm/memcontrol.c                  |  354 +++++++++++++++++++++++++++++++++++++-
 net/core/sock.c                  |   93 +++++++---
 net/decnet/af_decnet.c           |   21 ++-
 net/ipv4/proc.c                  |    7 +-
 net/ipv4/sysctl_net_ipv4.c       |   71 +++++++-
 net/ipv4/tcp.c                   |   58 ++++---
 net/ipv4/tcp_input.c             |   12 +-
 net/ipv4/tcp_ipv4.c              |   18 ++-
 net/ipv4/tcp_output.c            |    2 +-
 net/ipv4/tcp_timer.c             |    2 +-
 net/ipv4/udp.c                   |   20 ++-
 net/ipv6/tcp_ipv6.c              |   16 +-
 net/ipv6/udp.c                   |    4 +-
 net/sctp/socket.c                |   35 +++-
 23 files changed, 876 insertions(+), 124 deletions(-)

-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [PATCH v2 1/7] Basic kernel memory functionality for the Memory Controller
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, Glauber Costa
In-Reply-To: <1316051175-17780-1-git-send-email-glommer@parallels.com>

This patch lays down the foundation for the kernel memory component
of the Memory Controller.

As of today, I am only laying down the following files:

 * memory.independent_kmem_limit
 * memory.kmem.limit_in_bytes (currently ignored)
 * memory.kmem.usage_in_bytes (always zero)

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: Paul Menage <paul@paulmenage.org>
CC: Greg Thelen <gthelen@google.com>
---
 Documentation/cgroups/memory.txt |   29 ++++++++++-
 init/Kconfig                     |   11 ++++
 mm/memcontrol.c                  |  105 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 140 insertions(+), 5 deletions(-)

diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 6f3c598..ca58eff 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -44,8 +44,9 @@ Features:
  - oom-killer disable knob and oom-notifier
  - Root cgroup has no limit controls.
 
- Kernel memory and Hugepages are not under control yet. We just manage
- pages on LRU. To add more controls, we have to take care of performance.
+ Hugepages is not under control yet. We just manage pages on LRU. To add more
+ controls, we have to take care of performance. Kernel memory support is work
+ in progress, and the current version provides basically functionality.
 
 Brief summary of control files.
 
@@ -56,8 +57,11 @@ Brief summary of control files.
 				 (See 5.5 for details)
  memory.memsw.usage_in_bytes	 # show current res_counter usage for memory+Swap
 				 (See 5.5 for details)
+ memory.kmem.usage_in_bytes	 # show current res_counter usage for kmem only.
+				 (See 2.7 for details)
  memory.limit_in_bytes		 # set/show limit of memory usage
  memory.memsw.limit_in_bytes	 # set/show limit of memory+Swap usage
+ memory.kmem.limit_in_bytes	 # if allowed, set/show limit of kernel memory
  memory.failcnt			 # show the number of memory usage hits limits
  memory.memsw.failcnt		 # show the number of memory+Swap hits limits
  memory.max_usage_in_bytes	 # show max memory usage recorded
@@ -72,6 +76,9 @@ Brief summary of control files.
  memory.oom_control		 # set/show oom controls.
  memory.numa_stat		 # show the number of memory usage per numa node
 
+ memory.independent_kmem_limit	 # select whether or not kernel memory limits are
+				   independent of user limits
+
 1. History
 
 The memory controller has a long history. A request for comments for the memory
@@ -255,6 +262,24 @@ When oom event notifier is registered, event will be delivered.
   per-zone-per-cgroup LRU (cgroup's private LRU) is just guarded by
   zone->lru_lock, it has no lock of its own.
 
+2.7 Kernel Memory Extension (CONFIG_CGROUP_MEM_RES_CTLR_KMEM)
+
+ With the Kernel memory extension, the Memory Controller is able to limit
+the amount of kernel memory used by the system. Kernel memory is fundamentally
+different than user memory, since it can't be swapped out, which makes it
+possible to DoS the system by consuming too much of this precious resource.
+
+Memory limits as specified by the standard Memory Controller may or may not
+take kernel memory into consideration. This is achieved through the file
+memory.independent_kmem_limit. A Value different than 0 will allow for kernel
+memory to be controlled separately.
+
+When kernel memory limits are not independent, the limit values set in
+memory.kmem files are ignored.
+
+Currently no soft limit is implemented for kernel memory. It is future work
+to trigger slab reclaim when those limits are reached.
+
 3. User Interface
 
 0. Configuration
diff --git a/init/Kconfig b/init/Kconfig
index d627783..49e5839 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -689,6 +689,17 @@ config CGROUP_MEM_RES_CTLR_SWAP_ENABLED
 	  For those who want to have the feature enabled by default should
 	  select this option (if, for some reason, they need to disable it
 	  then swapaccount=0 does the trick).
+config CGROUP_MEM_RES_CTLR_KMEM
+	bool "Memory Resource Controller Kernel Memory accounting"
+	depends on CGROUP_MEM_RES_CTLR
+	default y
+	help
+	  The Kernel Memory extension for Memory Resource Controller can limit
+	  the amount of memory used by kernel objects in the system. Those are
+	  fundamentally different from the entities handled by the standard
+	  Memory Controller, which are page-based, and can be swapped. Users of
+	  the kmem extension can use it to guarantee that no group of processes
+	  will ever exhaust kernel resources alone.
 
 config CGROUP_PERF
 	bool "Enable perf_event per-cpu per-container group (cgroup) monitoring"
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index ebd1e86..1c5d01a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -73,7 +73,11 @@ static int really_do_swap_account __initdata = 0;
 #define do_swap_account		(0)
 #endif
 
-
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+int do_kmem_account __read_mostly = 1;
+#else
+#define do_kmem_account		(0)
+#endif
 /*
  * Statistics for memory cgroup.
  */
@@ -270,6 +274,10 @@ struct mem_cgroup {
 	 */
 	struct res_counter memsw;
 	/*
+	 * the counter to account for kmem usage.
+	 */
+	struct res_counter kmem;
+	/*
 	 * Per cgroup active and inactive list, similar to the
 	 * per zone LRU lists.
 	 */
@@ -321,6 +329,11 @@ struct mem_cgroup {
 	 */
 	unsigned long 	move_charge_at_immigrate;
 	/*
+	 * Should kernel memory limits be stabilished independently
+	 * from user memory ?
+	 */
+	int		kmem_independent;
+	/*
 	 * percpu counter.
 	 */
 	struct mem_cgroup_stat_cpu *stat;
@@ -391,6 +404,7 @@ enum charge_type {
 #define _MEM			(0)
 #define _MEMSWAP		(1)
 #define _OOM_TYPE		(2)
+#define _KMEM			(3)
 #define MEMFILE_PRIVATE(x, val)	(((x) << 16) | (val))
 #define MEMFILE_TYPE(val)	(((val) >> 16) & 0xffff)
 #define MEMFILE_ATTR(val)	((val) & 0xffff)
@@ -3941,12 +3955,18 @@ static unsigned long mem_cgroup_recursive_stat(struct mem_cgroup *mem,
 static inline u64 mem_cgroup_usage(struct mem_cgroup *mem, bool swap)
 {
 	u64 val;
+	u64 kmem = 0;
+
+	if (!mem->kmem_independent)
+		kmem = res_counter_read_u64(&mem->kmem, RES_USAGE);
 
 	if (!mem_cgroup_is_root(mem)) {
 		if (!swap)
-			return res_counter_read_u64(&mem->res, RES_USAGE);
+			kmem += res_counter_read_u64(&mem->res, RES_USAGE);
 		else
-			return res_counter_read_u64(&mem->memsw, RES_USAGE);
+			kmem += res_counter_read_u64(&mem->memsw, RES_USAGE);
+
+		return kmem;
 	}
 
 	val = mem_cgroup_recursive_stat(mem, MEM_CGROUP_STAT_CACHE);
@@ -3979,6 +3999,10 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
 		else
 			val = res_counter_read_u64(&mem->memsw, name);
 		break;
+	case _KMEM:
+		val = res_counter_read_u64(&mem->kmem, name);
+		break;
+
 	default:
 		BUG();
 		break;
@@ -4756,6 +4780,21 @@ static int mem_cgroup_reset_vmscan_stat(struct cgroup *cgrp,
 	return 0;
 }
 
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+static u64 kmem_limit_independent_read(struct cgroup *cont, struct cftype *cft)
+{
+	return mem_cgroup_from_cont(cont)->kmem_independent;
+}
+
+static int kmem_limit_independent_write(struct cgroup *cont, struct cftype *cft,
+					u64 val)
+{
+	cgroup_lock();
+	mem_cgroup_from_cont(cont)->kmem_independent = !!val;
+	cgroup_unlock();
+	return 0;
+}
+#endif
 
 static struct cftype mem_cgroup_files[] = {
 	{
@@ -4877,6 +4916,46 @@ static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
 }
 #endif
 
+
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+static struct cftype kmem_cgroup_files[] = {
+	{
+		.name = "independent_kmem_limit",
+		.read_u64 = kmem_limit_independent_read,
+		.write_u64 = kmem_limit_independent_write,
+	},
+	{
+		.name = "kmem.usage_in_bytes",
+		.private = MEMFILE_PRIVATE(_KMEM, RES_USAGE),
+		.read_u64 = mem_cgroup_read,
+		.register_event = mem_cgroup_usage_register_event,
+		.unregister_event = mem_cgroup_usage_unregister_event,
+	},
+	{
+		.name = "kmem.limit_in_bytes",
+		.private = MEMFILE_PRIVATE(_KMEM, RES_LIMIT),
+		.read_u64 = mem_cgroup_read,
+		.register_event = mem_cgroup_usage_register_event,
+		.unregister_event = mem_cgroup_usage_unregister_event,
+	},
+};
+
+static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss)
+{
+	if (!do_kmem_account)
+		return 0;
+
+	return cgroup_add_files(cont, ss, kmem_cgroup_files,
+				ARRAY_SIZE(kmem_cgroup_files));
+};
+
+#else
+static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss)
+{
+	return 0;
+}
+#endif
+
 static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
 {
 	struct mem_cgroup_per_node *pn;
@@ -5075,6 +5154,7 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 	if (parent && parent->use_hierarchy) {
 		res_counter_init(&mem->res, &parent->res);
 		res_counter_init(&mem->memsw, &parent->memsw);
+		res_counter_init(&mem->kmem, &parent->kmem);
 		/*
 		 * We increment refcnt of the parent to ensure that we can
 		 * safely access it on res_counter_charge/uncharge.
@@ -5085,6 +5165,7 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 	} else {
 		res_counter_init(&mem->res, NULL);
 		res_counter_init(&mem->memsw, NULL);
+		res_counter_init(&mem->kmem, NULL);
 	}
 	mem->last_scanned_child = 0;
 	mem->last_scanned_node = MAX_NUMNODES;
@@ -5129,6 +5210,10 @@ static int mem_cgroup_populate(struct cgroup_subsys *ss,
 
 	if (!ret)
 		ret = register_memsw_files(cont, ss);
+
+	if (!ret)
+		ret = register_kmem_files(cont, ss);
+
 	return ret;
 }
 
@@ -5665,3 +5750,17 @@ static int __init enable_swap_account(char *s)
 __setup("swapaccount=", enable_swap_account);
 
 #endif
+
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+static int __init disable_kmem_account(char *s)
+{
+	/* consider enabled if no parameter or 1 is given */
+	if (!strcmp(s, "1"))
+		do_kmem_account = 1;
+	else if (!strcmp(s, "0"))
+		do_kmem_account = 0;
+	return 1;
+}
+__setup("kmemaccount=", disable_kmem_account);
+
+#endif
-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH v2 2/7] socket: initial cgroup code.
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, Glauber Costa
In-Reply-To: <1316051175-17780-1-git-send-email-glommer@parallels.com>

We aim to control the amount of kernel memory pinned at any
time by tcp sockets. To lay the foundations for this work,
this patch adds a pointer to the kmem_cgroup to the socket
structure.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: David S. Miller <davem@davemloft.net>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
---
 include/linux/memcontrol.h |   38 ++++++++++++++++++++++++++++++++++++++
 include/net/sock.h         |    2 ++
 net/core/sock.c            |    3 +++
 3 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 3b535db..be457ce 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -395,5 +395,43 @@ mem_cgroup_print_bad_page(struct page *page)
 }
 #endif
 
+#ifdef CONFIG_INET
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+#include <net/sock.h>
+static inline void sock_update_memcg(struct sock *sk)
+{
+	/* right now a socket spends its whole life in the same cgroup */
+	BUG_ON(sk->sk_cgrp);
+
+	rcu_read_lock();
+	sk->sk_cgrp = mem_cgroup_from_task(current);
+
+	/*
+	 * We don't need to protect against anything task-related, because
+	 * we are basically stuck with the sock pointer that won't change,
+	 * even if the task that originated the socket changes cgroups.
+	 *
+	 * What we do have to guarantee, is that the chain leading us to
+	 * the top level won't change under our noses. Incrementing the
+	 * reference count via cgroup_exclude_rmdir guarantees that.
+	 */
+	cgroup_exclude_rmdir(mem_cgroup_css(sk->sk_cgrp));
+	rcu_read_unlock();
+}
+
+static inline void sock_release_memcg(struct sock *sk)
+{
+	cgroup_release_and_wakeup_rmdir(mem_cgroup_css(sk->sk_cgrp));
+}
+#else
+#include <net/sock.h>
+static inline void sock_update_memcg(struct sock *sk)
+{
+}
+static inline void sock_release_memcg(struct sock *sk)
+{
+}
+#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
+#endif /* CONFIG_INET */
 #endif /* _LINUX_MEMCONTROL_H */
 
diff --git a/include/net/sock.h b/include/net/sock.h
index 8e4062f..afe1467 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -228,6 +228,7 @@ struct sock_common {
   *	@sk_security: used by security modules
   *	@sk_mark: generic packet mark
   *	@sk_classid: this socket's cgroup classid
+  *	@sk_cgrp: this socket's kernel memory (kmem) cgroup
   *	@sk_write_pending: a write to stream socket waits to start
   *	@sk_state_change: callback to indicate change in the state of the sock
   *	@sk_data_ready: callback to indicate there is data to be processed
@@ -339,6 +340,7 @@ struct sock {
 #endif
 	__u32			sk_mark;
 	u32			sk_classid;
+	struct mem_cgroup	*sk_cgrp;
 	void			(*sk_state_change)(struct sock *sk);
 	void			(*sk_data_ready)(struct sock *sk, int bytes);
 	void			(*sk_write_space)(struct sock *sk);
diff --git a/net/core/sock.c b/net/core/sock.c
index 3449df8..54ec8ac 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -125,6 +125,7 @@
 #include <net/xfrm.h>
 #include <linux/ipsec.h>
 #include <net/cls_cgroup.h>
+#include <linux/memcontrol.h>
 
 #include <linux/filter.h>
 
@@ -1139,6 +1140,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
 		atomic_set(&sk->sk_wmem_alloc, 1);
 
 		sock_update_classid(sk);
+		sock_update_memcg(sk);
 	}
 
 	return sk;
@@ -1170,6 +1172,7 @@ static void __sk_free(struct sock *sk)
 		put_cred(sk->sk_peer_cred);
 	put_pid(sk->sk_peer_pid);
 	put_net(sock_net(sk));
+	sock_release_memcg(sk);
 	sk_prot_free(sk->sk_prot_creator, sk);
 }
 
-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH v2 3/7] foundations of per-cgroup memory pressure controlling.
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, Glauber Costa
In-Reply-To: <1316051175-17780-1-git-send-email-glommer@parallels.com>

This patch converts struct sock fields memory_pressure,
memory_allocated, sockets_allocated, and sysctl_mem (now prot_mem)
to function pointers, receiving a struct mem_cgroup parameter.

enter_memory_pressure is kept the same, since all its callers
have socket a context, and the kmem_cgroup can be derived from
the socket itself.

To keep things working, the patch convert all users of those fields
to use acessor functions.

In my benchmarks I didn't see a significant performance difference
with this patch applied compared to a baseline (around 1 % diff, thus
inside error margin).

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: David S. Miller <davem@davemloft.net>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
---
 crypto/af_alg.c             |    7 ++-
 include/linux/memcontrol.h  |   27 ++++++++++
 include/net/sock.h          |  112 +++++++++++++++++++++++++++++++++++++++++--
 include/net/tcp.h           |   11 +++--
 include/net/udp.h           |    3 +-
 include/trace/events/sock.h |   10 ++--
 mm/memcontrol.c             |   51 +++++++++++++++++++-
 net/core/sock.c             |   62 ++++++++++++++----------
 net/decnet/af_decnet.c      |   21 +++++++-
 net/ipv4/proc.c             |    7 ++-
 net/ipv4/tcp.c              |   27 +++++++++-
 net/ipv4/tcp_input.c        |   12 ++--
 net/ipv4/tcp_ipv4.c         |   12 ++--
 net/ipv4/tcp_output.c       |    2 +-
 net/ipv4/tcp_timer.c        |    2 +-
 net/ipv4/udp.c              |   20 ++++++--
 net/ipv6/tcp_ipv6.c         |   10 ++--
 net/ipv6/udp.c              |    4 +-
 net/sctp/socket.c           |   35 ++++++++++---
 19 files changed, 350 insertions(+), 85 deletions(-)

diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index ac33d5f..c21351c 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -29,10 +29,15 @@ struct alg_type_list {
 
 static atomic_long_t alg_memory_allocated;
 
+static atomic_long_t *memory_allocated_alg(struct mem_cgroup *sg)
+{
+	return &alg_memory_allocated;
+}
+
 static struct proto alg_proto = {
 	.name			= "ALG",
 	.owner			= THIS_MODULE,
-	.memory_allocated	= &alg_memory_allocated,
+	.memory_allocated	= memory_allocated_alg,
 	.obj_size		= sizeof(struct alg_sock),
 };
 
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index be457ce..15c337f 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -396,8 +396,16 @@ mem_cgroup_print_bad_page(struct page *page)
 #endif
 
 #ifdef CONFIG_INET
+struct proto;
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+void memcg_sock_mem_alloc(struct mem_cgroup *mem, struct proto *prot,
+			  int amt, int *parent_failure);
+void memcg_sock_mem_free(struct mem_cgroup *mem, struct proto *prot, int amt);
+void memcg_sockets_allocated_dec(struct mem_cgroup *mem, struct proto *prot);
+void memcg_sockets_allocated_inc(struct mem_cgroup *mem, struct proto *prot);
 #include <net/sock.h>
+
 static inline void sock_update_memcg(struct sock *sk)
 {
 	/* right now a socket spends its whole life in the same cgroup */
@@ -424,6 +432,25 @@ static inline void sock_release_memcg(struct sock *sk)
 	cgroup_release_and_wakeup_rmdir(mem_cgroup_css(sk->sk_cgrp));
 }
 #else
+/* memcontrol includes sockets.h, that includes memcontrol.h ... */
+static inline void memcg_sock_mem_alloc(struct mem_cgroup *mem,
+					struct proto *prot, int amt,
+					int *parent_failure)
+{
+}
+static inline void memcg_sock_mem_free(struct mem_cgroup *mem,
+				       struct proto *prot, int amt)
+{
+}
+static inline void memcg_sockets_allocated_dec(struct mem_cgroup *mem,
+					       struct proto *prot)
+{
+}
+static inline void memcg_sockets_allocated_inc(struct mem_cgroup *mem,
+					       struct proto *prot)
+{
+}
+
 #include <net/sock.h>
 static inline void sock_update_memcg(struct sock *sk)
 {
diff --git a/include/net/sock.h b/include/net/sock.h
index afe1467..78832f9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -54,6 +54,7 @@
 #include <linux/security.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/cgroup.h>
 
 #include <linux/filter.h>
 #include <linux/rculist_nulls.h>
@@ -168,6 +169,8 @@ struct sock_common {
 	/* public: */
 };
 
+struct mem_cgroup;
+
 /**
   *	struct sock - network layer representation of sockets
   *	@__sk_common: shared layout with inet_timewait_sock
@@ -786,18 +789,32 @@ struct proto {
 	unsigned int		inuse_idx;
 #endif
 
+	/*
+	 * per-cgroup memory tracking:
+	 *
+	 * The following functions track memory consumption of network buffers
+	 * by cgroup (kmem_cgroup) for the current protocol. As of the rest
+	 * of the fields in this structure, not all protocols are required
+	 * to implement them. Protocols that don't want to do per-cgroup
+	 * memory pressure management, can just assume the root cgroup is used.
+	 *
+	 */
 	/* Memory pressure */
 	void			(*enter_memory_pressure)(struct sock *sk);
-	atomic_long_t		*memory_allocated;	/* Current allocated memory. */
-	struct percpu_counter	*sockets_allocated;	/* Current number of sockets. */
+	/* Pointer to the current memory allocation of this cgroup. */
+	atomic_long_t		*(*memory_allocated)(struct mem_cgroup *sg);
+	/* Pointer to the current number of sockets in this cgroup. */
+	struct percpu_counter	*(*sockets_allocated)(struct mem_cgroup *sg);
 	/*
-	 * Pressure flag: try to collapse.
+	 * Per cgroup pointer to the pressure flag: try to collapse.
 	 * Technical note: it is used by multiple contexts non atomically.
 	 * All the __sk_mem_schedule() is of this nature: accounting
 	 * is strict, actions are advisory and have some latency.
 	 */
-	int			*memory_pressure;
-	long			*sysctl_mem;
+	int			*(*memory_pressure)(struct mem_cgroup *sg);
+	/* Pointer to the per-cgroup version of the the sysctl_mem field */
+	long			*(*prot_mem)(struct mem_cgroup *sg);
+
 	int			*sysctl_wmem;
 	int			*sysctl_rmem;
 	int			max_header;
@@ -856,6 +873,91 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
 #define sk_refcnt_debug_release(sk) do { } while (0)
 #endif /* SOCK_REFCNT_DEBUG */
 
+#include <linux/memcontrol.h>
+static inline int *sk_memory_pressure(struct sock *sk)
+{
+	int *ret = NULL;
+	if (sk->sk_prot->memory_pressure)
+		ret = sk->sk_prot->memory_pressure(sk->sk_cgrp);
+	return ret;
+}
+
+static inline long sk_prot_mem(struct sock *sk, int index)
+{
+	long *prot = sk->sk_prot->prot_mem(sk->sk_cgrp);
+	return prot[index];
+}
+
+static inline long
+sk_memory_allocated(struct sock *sk)
+{
+	struct proto *prot = sk->sk_prot;
+	struct mem_cgroup *cg = sk->sk_cgrp;
+
+	return atomic_long_read(prot->memory_allocated(cg));
+}
+
+static inline long
+sk_memory_allocated_add(struct sock *sk, int amt, int *parent_failure)
+{
+	struct proto *prot = sk->sk_prot;
+	struct mem_cgroup *cg = sk->sk_cgrp;
+	long allocated;
+
+	allocated = atomic_long_add_return(amt, prot->memory_allocated(cg));
+	memcg_sock_mem_alloc(cg, prot, amt, parent_failure);
+	return allocated;
+}
+
+static inline void
+sk_memory_allocated_sub(struct sock *sk, int amt)
+{
+	struct proto *prot = sk->sk_prot;
+	struct mem_cgroup *cg = sk->sk_cgrp;
+
+	atomic_long_sub(amt, prot->memory_allocated(cg));
+	memcg_sock_mem_free(cg, prot, amt);
+}
+
+static inline void sk_sockets_allocated_dec(struct sock *sk)
+{
+	struct proto *prot = sk->sk_prot;
+	struct mem_cgroup *cg = sk->sk_cgrp;
+
+	percpu_counter_dec(prot->sockets_allocated(cg));
+	memcg_sockets_allocated_dec(cg, prot);
+}
+
+static inline void sk_sockets_allocated_inc(struct sock *sk)
+{
+	struct proto *prot = sk->sk_prot;
+	struct mem_cgroup *cg = sk->sk_cgrp;
+
+	percpu_counter_inc(prot->sockets_allocated(cg));
+	memcg_sockets_allocated_inc(cg, prot);
+}
+
+static inline int
+sk_sockets_allocated_read_positive(struct sock *sk)
+{
+	struct proto *prot = sk->sk_prot;
+	struct mem_cgroup *cg = sk->sk_cgrp;
+
+	return percpu_counter_sum_positive(prot->sockets_allocated(cg));
+}
+
+static inline int
+kcg_sockets_allocated_sum_positive(struct proto *prot, struct mem_cgroup *cg)
+{
+	return percpu_counter_sum_positive(prot->sockets_allocated(cg));
+}
+
+static inline long
+kcg_memory_allocated(struct proto *prot, struct mem_cgroup *cg)
+{
+	return atomic_long_read(prot->memory_allocated(cg));
+}
+
 
 #ifdef CONFIG_PROC_FS
 /* Called with local bh disabled */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 149a415..c835ae3 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -45,6 +45,7 @@
 #include <net/dst.h>
 
 #include <linux/seq_file.h>
+#include <linux/memcontrol.h>
 
 extern struct inet_hashinfo tcp_hashinfo;
 
@@ -253,9 +254,11 @@ extern int sysctl_tcp_cookie_size;
 extern int sysctl_tcp_thin_linear_timeouts;
 extern int sysctl_tcp_thin_dupack;
 
-extern atomic_long_t tcp_memory_allocated;
-extern struct percpu_counter tcp_sockets_allocated;
-extern int tcp_memory_pressure;
+struct mem_cgroup;
+extern long *tcp_sysctl_mem(struct mem_cgroup *sg);
+struct percpu_counter *sockets_allocated_tcp(struct mem_cgroup *sg);
+int *memory_pressure_tcp(struct mem_cgroup *sg);
+atomic_long_t *memory_allocated_tcp(struct mem_cgroup *sg);
 
 /*
  * The next routines deal with comparing 32 bit unsigned ints
@@ -286,7 +289,7 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
 	}
 
 	if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
-	    atomic_long_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
+	    sk_memory_allocated(sk) > sk_prot_mem(sk, 2))
 		return true;
 	return false;
 }
diff --git a/include/net/udp.h b/include/net/udp.h
index 67ea6fc..6ed4cc6 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -105,7 +105,8 @@ static inline struct udp_hslot *udp_hashslot2(struct udp_table *table,
 
 extern struct proto udp_prot;
 
-extern atomic_long_t udp_memory_allocated;
+atomic_long_t *memory_allocated_udp(struct mem_cgroup *sg);
+long *udp_sysctl_mem(struct mem_cgroup *sg);
 
 /* sysctl variables for udp */
 extern long sysctl_udp_mem[3];
diff --git a/include/trace/events/sock.h b/include/trace/events/sock.h
index 779abb9..12a6083 100644
--- a/include/trace/events/sock.h
+++ b/include/trace/events/sock.h
@@ -37,7 +37,7 @@ TRACE_EVENT(sock_exceed_buf_limit,
 
 	TP_STRUCT__entry(
 		__array(char, name, 32)
-		__field(long *, sysctl_mem)
+		__field(long *, prot_mem)
 		__field(long, allocated)
 		__field(int, sysctl_rmem)
 		__field(int, rmem_alloc)
@@ -45,7 +45,7 @@ TRACE_EVENT(sock_exceed_buf_limit,
 
 	TP_fast_assign(
 		strncpy(__entry->name, prot->name, 32);
-		__entry->sysctl_mem = prot->sysctl_mem;
+		__entry->prot_mem = sk->sk_prot->prot_mem(sk->sk_cgrp);
 		__entry->allocated = allocated;
 		__entry->sysctl_rmem = prot->sysctl_rmem[0];
 		__entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
@@ -54,9 +54,9 @@ TRACE_EVENT(sock_exceed_buf_limit,
 	TP_printk("proto:%s sysctl_mem=%ld,%ld,%ld allocated=%ld "
 		"sysctl_rmem=%d rmem_alloc=%d",
 		__entry->name,
-		__entry->sysctl_mem[0],
-		__entry->sysctl_mem[1],
-		__entry->sysctl_mem[2],
+		__entry->prot_mem[0],
+		__entry->prot_mem[1],
+		__entry->prot_mem[2],
 		__entry->allocated,
 		__entry->sysctl_rmem,
 		__entry->rmem_alloc)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 1c5d01a..289fc2c 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -345,6 +345,56 @@ struct mem_cgroup {
 	spinlock_t pcp_counter_lock;
 };
 
+static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
+/* Writing them here to avoid exposing memcg's inner layout */
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+#ifdef CONFIG_INET
+
+void memcg_sock_mem_alloc(struct mem_cgroup *mem, struct proto *prot,
+			  int amt, int *parent_failure)
+{
+	mem = parent_mem_cgroup(mem);
+	for (; mem != NULL; mem = parent_mem_cgroup(mem)) {
+		long alloc;
+		long *prot_mem = prot->prot_mem(mem);
+		/*
+		 * Large nestings are not the common case, and stopping in the
+		 * middle would be complicated enough, that we bill it all the
+		 * way through the root, and if needed, unbill everything later
+		 */
+		alloc = atomic_long_add_return(amt,
+					       prot->memory_allocated(mem));
+		*parent_failure |= (alloc > prot_mem[2]);
+	}
+}
+EXPORT_SYMBOL(memcg_sock_mem_alloc);
+
+void memcg_sock_mem_free(struct mem_cgroup *mem, struct proto *prot, int amt)
+{
+	mem = parent_mem_cgroup(mem);
+	for (; mem != NULL; mem = parent_mem_cgroup(mem))
+		atomic_long_sub(amt, prot->memory_allocated(mem));
+}
+EXPORT_SYMBOL(memcg_sock_mem_free);
+
+void memcg_sockets_allocated_dec(struct mem_cgroup *mem, struct proto *prot)
+{
+	mem = parent_mem_cgroup(mem);
+	for (; mem; mem = parent_mem_cgroup(mem))
+		percpu_counter_dec(prot->sockets_allocated(mem));
+}
+EXPORT_SYMBOL(memcg_sockets_allocated_dec);
+
+void memcg_sockets_allocated_inc(struct mem_cgroup *mem, struct proto *prot)
+{
+	mem = parent_mem_cgroup(mem);
+	for (; mem; mem = parent_mem_cgroup(mem))
+		percpu_counter_inc(prot->sockets_allocated(mem));
+}
+EXPORT_SYMBOL(memcg_sockets_allocated_inc);
+#endif /* CONFIG_INET */
+#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
+
 /* Stuffs for move charges at task migration. */
 /*
  * Types of charges to be moved. "move_charge_at_immitgrate" is treated as a
@@ -423,7 +473,6 @@ enum charge_type {
 
 static void mem_cgroup_get(struct mem_cgroup *mem);
 static void mem_cgroup_put(struct mem_cgroup *mem);
-static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
 static void drain_all_stock_async(struct mem_cgroup *mem);
 
 static struct mem_cgroup_per_zone *
diff --git a/net/core/sock.c b/net/core/sock.c
index 54ec8ac..338d572 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1291,7 +1291,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
 		newsk->sk_wq = NULL;
 
 		if (newsk->sk_prot->sockets_allocated)
-			percpu_counter_inc(newsk->sk_prot->sockets_allocated);
+			sk_sockets_allocated_inc(newsk);
 
 		if (sock_flag(newsk, SOCK_TIMESTAMP) ||
 		    sock_flag(newsk, SOCK_TIMESTAMPING_RX_SOFTWARE))
@@ -1682,30 +1682,33 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
 	struct proto *prot = sk->sk_prot;
 	int amt = sk_mem_pages(size);
 	long allocated;
+	int *memory_pressure;
+	int parent_failure = 0;
 
 	sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
-	allocated = atomic_long_add_return(amt, prot->memory_allocated);
+
+	memory_pressure = sk_memory_pressure(sk);
+	allocated = sk_memory_allocated_add(sk, amt, &parent_failure);
+
+	/* Over hard limit (we, or our parents) */
+	if (parent_failure || (allocated > sk_prot_mem(sk, 2)))
+		goto suppress_allocation;
 
 	/* Under limit. */
-	if (allocated <= prot->sysctl_mem[0]) {
-		if (prot->memory_pressure && *prot->memory_pressure)
-			*prot->memory_pressure = 0;
-		return 1;
-	}
+	if (allocated <= sk_prot_mem(sk, 0))
+		if (memory_pressure && *memory_pressure)
+			*memory_pressure = 0;
 
 	/* Under pressure. */
-	if (allocated > prot->sysctl_mem[1])
+	if (allocated > sk_prot_mem(sk, 1))
 		if (prot->enter_memory_pressure)
 			prot->enter_memory_pressure(sk);
 
-	/* Over hard limit. */
-	if (allocated > prot->sysctl_mem[2])
-		goto suppress_allocation;
-
 	/* guarantee minimum buffer size under pressure */
 	if (kind == SK_MEM_RECV) {
 		if (atomic_read(&sk->sk_rmem_alloc) < prot->sysctl_rmem[0])
 			return 1;
+
 	} else { /* SK_MEM_SEND */
 		if (sk->sk_type == SOCK_STREAM) {
 			if (sk->sk_wmem_queued < prot->sysctl_wmem[0])
@@ -1715,13 +1718,13 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
 				return 1;
 	}
 
-	if (prot->memory_pressure) {
+	if (memory_pressure) {
 		int alloc;
 
-		if (!*prot->memory_pressure)
+		if (!*memory_pressure)
 			return 1;
-		alloc = percpu_counter_read_positive(prot->sockets_allocated);
-		if (prot->sysctl_mem[2] > alloc *
+		alloc = sk_sockets_allocated_read_positive(sk);
+		if (sk_prot_mem(sk, 2) > alloc *
 		    sk_mem_pages(sk->sk_wmem_queued +
 				 atomic_read(&sk->sk_rmem_alloc) +
 				 sk->sk_forward_alloc))
@@ -1744,7 +1747,9 @@ suppress_allocation:
 
 	/* Alas. Undo changes. */
 	sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
-	atomic_long_sub(amt, prot->memory_allocated);
+
+	sk_memory_allocated_sub(sk, amt);
+
 	return 0;
 }
 EXPORT_SYMBOL(__sk_mem_schedule);
@@ -1755,15 +1760,15 @@ EXPORT_SYMBOL(__sk_mem_schedule);
  */
 void __sk_mem_reclaim(struct sock *sk)
 {
-	struct proto *prot = sk->sk_prot;
+	int *memory_pressure = sk_memory_pressure(sk);
 
-	atomic_long_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT,
-		   prot->memory_allocated);
+	sk_memory_allocated_sub(sk,
+				sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT);
 	sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1;
 
-	if (prot->memory_pressure && *prot->memory_pressure &&
-	    (atomic_long_read(prot->memory_allocated) < prot->sysctl_mem[0]))
-		*prot->memory_pressure = 0;
+	if (memory_pressure && *memory_pressure &&
+	    (sk_memory_allocated(sk) < sk_prot_mem(sk, 0)))
+		*memory_pressure = 0;
 }
 EXPORT_SYMBOL(__sk_mem_reclaim);
 
@@ -2482,13 +2487,20 @@ static char proto_method_implemented(const void *method)
 
 static void proto_seq_printf(struct seq_file *seq, struct proto *proto)
 {
+	struct mem_cgroup *cg = mem_cgroup_from_task(current);
+	int *memory_pressure = NULL;
+
+	if (proto->memory_pressure)
+		memory_pressure = proto->memory_pressure(cg);
+
 	seq_printf(seq, "%-9s %4u %6d  %6ld   %-3s %6u   %-3s  %-10s "
 			"%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n",
 		   proto->name,
 		   proto->obj_size,
 		   sock_prot_inuse_get(seq_file_net(seq), proto),
-		   proto->memory_allocated != NULL ? atomic_long_read(proto->memory_allocated) : -1L,
-		   proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI",
+		   proto->memory_allocated != NULL ?
+			kcg_memory_allocated(proto, cg) : -1L,
+		   memory_pressure != NULL ? *memory_pressure ? "yes" : "no" : "NI",
 		   proto->max_header,
 		   proto->slab == NULL ? "no" : "yes",
 		   module_name(proto->owner),
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 19acd00..4752118 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -458,13 +458,28 @@ static void dn_enter_memory_pressure(struct sock *sk)
 	}
 }
 
+static atomic_long_t *memory_allocated_dn(struct mem_cgroup *sg)
+{
+	return &decnet_memory_allocated;
+}
+
+static int *memory_pressure_dn(struct mem_cgroup *sg)
+{
+	return &dn_memory_pressure;
+}
+
+static long *dn_sysctl_mem(struct mem_cgroup *sg)
+{
+	return sysctl_decnet_mem;
+}
+
 static struct proto dn_proto = {
 	.name			= "NSP",
 	.owner			= THIS_MODULE,
 	.enter_memory_pressure	= dn_enter_memory_pressure,
-	.memory_pressure	= &dn_memory_pressure,
-	.memory_allocated	= &decnet_memory_allocated,
-	.sysctl_mem		= sysctl_decnet_mem,
+	.memory_pressure	= memory_pressure_dn,
+	.memory_allocated	= memory_allocated_dn,
+	.prot_mem		= dn_sysctl_mem,
 	.sysctl_wmem		= sysctl_decnet_wmem,
 	.sysctl_rmem		= sysctl_decnet_rmem,
 	.max_header		= DN_MAX_NSP_DATA_HEADER + 64,
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index b14ec7d..ba56702 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -52,20 +52,21 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
 {
 	struct net *net = seq->private;
 	int orphans, sockets;
+	struct mem_cgroup *cg = mem_cgroup_from_task(current);
 
 	local_bh_disable();
 	orphans = percpu_counter_sum_positive(&tcp_orphan_count);
-	sockets = percpu_counter_sum_positive(&tcp_sockets_allocated);
+	sockets = kcg_sockets_allocated_sum_positive(&tcp_prot, cg);
 	local_bh_enable();
 
 	socket_seq_show(seq);
 	seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %ld\n",
 		   sock_prot_inuse_get(net, &tcp_prot), orphans,
 		   tcp_death_row.tw_count, sockets,
-		   atomic_long_read(&tcp_memory_allocated));
+		   kcg_memory_allocated(&tcp_prot, cg));
 	seq_printf(seq, "UDP: inuse %d mem %ld\n",
 		   sock_prot_inuse_get(net, &udp_prot),
-		   atomic_long_read(&udp_memory_allocated));
+		   kcg_memory_allocated(&udp_prot, cg));
 	seq_printf(seq, "UDPLITE: inuse %d\n",
 		   sock_prot_inuse_get(net, &udplite_prot));
 	seq_printf(seq, "RAW: inuse %d\n",
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 46febca..452245f 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -291,13 +291,11 @@ EXPORT_SYMBOL(sysctl_tcp_rmem);
 EXPORT_SYMBOL(sysctl_tcp_wmem);
 
 atomic_long_t tcp_memory_allocated;	/* Current allocated memory. */
-EXPORT_SYMBOL(tcp_memory_allocated);
 
 /*
  * Current number of TCP sockets.
  */
 struct percpu_counter tcp_sockets_allocated;
-EXPORT_SYMBOL(tcp_sockets_allocated);
 
 /*
  * TCP splice context
@@ -315,7 +313,18 @@ struct tcp_splice_state {
  * is strict, actions are advisory and have some latency.
  */
 int tcp_memory_pressure __read_mostly;
-EXPORT_SYMBOL(tcp_memory_pressure);
+
+int *memory_pressure_tcp(struct mem_cgroup *sg)
+{
+	return &tcp_memory_pressure;
+}
+EXPORT_SYMBOL(memory_pressure_tcp);
+
+struct percpu_counter *sockets_allocated_tcp(struct mem_cgroup *sg)
+{
+	return &tcp_sockets_allocated;
+}
+EXPORT_SYMBOL(sockets_allocated_tcp);
 
 void tcp_enter_memory_pressure(struct sock *sk)
 {
@@ -326,6 +335,18 @@ void tcp_enter_memory_pressure(struct sock *sk)
 }
 EXPORT_SYMBOL(tcp_enter_memory_pressure);
 
+long *tcp_sysctl_mem(struct mem_cgroup *sg)
+{
+	return sysctl_tcp_mem;
+}
+EXPORT_SYMBOL(tcp_sysctl_mem);
+
+atomic_long_t *memory_allocated_tcp(struct mem_cgroup *sg)
+{
+	return &tcp_memory_allocated;
+}
+EXPORT_SYMBOL(memory_allocated_tcp);
+
 /* Convert seconds to retransmits based on initial and max timeout */
 static u8 secs_to_retrans(int seconds, int timeout, int rto_max)
 {
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ea0d218..3f17423 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -316,7 +316,7 @@ static void tcp_grow_window(struct sock *sk, struct sk_buff *skb)
 	/* Check #1 */
 	if (tp->rcv_ssthresh < tp->window_clamp &&
 	    (int)tp->rcv_ssthresh < tcp_space(sk) &&
-	    !tcp_memory_pressure) {
+	    !sk_memory_pressure(sk)) {
 		int incr;
 
 		/* Check #2. Increase window, if skb with such overhead
@@ -398,8 +398,8 @@ static void tcp_clamp_window(struct sock *sk)
 
 	if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] &&
 	    !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) &&
-	    !tcp_memory_pressure &&
-	    atomic_long_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
+	    !sk_memory_pressure(sk) &&
+	    sk_memory_allocated(sk) < sk_prot_mem(sk, 0)) {
 		sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc),
 				    sysctl_tcp_rmem[2]);
 	}
@@ -4806,7 +4806,7 @@ static int tcp_prune_queue(struct sock *sk)
 
 	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
 		tcp_clamp_window(sk);
-	else if (tcp_memory_pressure)
+	else if (sk_memory_pressure(sk))
 		tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
 
 	tcp_collapse_ofo_queue(sk);
@@ -4872,11 +4872,11 @@ static int tcp_should_expand_sndbuf(struct sock *sk)
 		return 0;
 
 	/* If we are under global TCP memory pressure, do not expand.  */
-	if (tcp_memory_pressure)
+	if (sk_memory_pressure(sk))
 		return 0;
 
 	/* If we are under soft global TCP memory pressure, do not expand.  */
-	if (atomic_long_read(&tcp_memory_allocated) >= sysctl_tcp_mem[0])
+	if (sk_memory_allocated(sk) >= sk_prot_mem(sk, 0))
 		return 0;
 
 	/* If we filled the congestion window, do not expand.  */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1c12b8e..cbb0d5e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1901,7 +1901,7 @@ static int tcp_v4_init_sock(struct sock *sk)
 	sk->sk_rcvbuf = sysctl_tcp_rmem[1];
 
 	local_bh_disable();
-	percpu_counter_inc(&tcp_sockets_allocated);
+	sk_sockets_allocated_inc(sk);
 	local_bh_enable();
 
 	return 0;
@@ -1957,7 +1957,7 @@ void tcp_v4_destroy_sock(struct sock *sk)
 		tp->cookie_values = NULL;
 	}
 
-	percpu_counter_dec(&tcp_sockets_allocated);
+	sk_sockets_allocated_dec(sk);
 }
 EXPORT_SYMBOL(tcp_v4_destroy_sock);
 
@@ -2598,11 +2598,11 @@ struct proto tcp_prot = {
 	.unhash			= inet_unhash,
 	.get_port		= inet_csk_get_port,
 	.enter_memory_pressure	= tcp_enter_memory_pressure,
-	.sockets_allocated	= &tcp_sockets_allocated,
+	.memory_pressure	= memory_pressure_tcp,
+	.sockets_allocated	= sockets_allocated_tcp,
 	.orphan_count		= &tcp_orphan_count,
-	.memory_allocated	= &tcp_memory_allocated,
-	.memory_pressure	= &tcp_memory_pressure,
-	.sysctl_mem		= sysctl_tcp_mem,
+	.memory_allocated	= memory_allocated_tcp,
+	.prot_mem		= tcp_sysctl_mem,
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 882e0b0..06aeb31 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1912,7 +1912,7 @@ u32 __tcp_select_window(struct sock *sk)
 	if (free_space < (full_space >> 1)) {
 		icsk->icsk_ack.quick = 0;
 
-		if (tcp_memory_pressure)
+		if (sk_memory_pressure(sk))
 			tp->rcv_ssthresh = min(tp->rcv_ssthresh,
 					       4U * tp->advmss);
 
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index ecd44b0..2c67617 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -261,7 +261,7 @@ static void tcp_delack_timer(unsigned long data)
 	}
 
 out:
-	if (tcp_memory_pressure)
+	if (sk_memory_pressure(sk))
 		sk_mem_reclaim(sk);
 out_unlock:
 	bh_unlock_sock(sk);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1b5a193..cc7627b 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -120,9 +120,6 @@ EXPORT_SYMBOL(sysctl_udp_rmem_min);
 int sysctl_udp_wmem_min __read_mostly;
 EXPORT_SYMBOL(sysctl_udp_wmem_min);
 
-atomic_long_t udp_memory_allocated;
-EXPORT_SYMBOL(udp_memory_allocated);
-
 #define MAX_UDP_PORTS 65536
 #define PORTS_PER_CHAIN (MAX_UDP_PORTS / UDP_HTABLE_SIZE_MIN)
 
@@ -1918,6 +1915,19 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
 }
 EXPORT_SYMBOL(udp_poll);
 
+static atomic_long_t udp_memory_allocated;
+atomic_long_t *memory_allocated_udp(struct mem_cgroup *sg)
+{
+	return &udp_memory_allocated;
+}
+EXPORT_SYMBOL(memory_allocated_udp);
+
+long *udp_sysctl_mem(struct mem_cgroup *sg)
+{
+	return sysctl_udp_mem;
+}
+EXPORT_SYMBOL(udp_sysctl_mem);
+
 struct proto udp_prot = {
 	.name		   = "UDP",
 	.owner		   = THIS_MODULE,
@@ -1936,8 +1946,8 @@ struct proto udp_prot = {
 	.unhash		   = udp_lib_unhash,
 	.rehash		   = udp_v4_rehash,
 	.get_port	   = udp_v4_get_port,
-	.memory_allocated  = &udp_memory_allocated,
-	.sysctl_mem	   = sysctl_udp_mem,
+	.memory_allocated  = &memory_allocated_udp,
+	.prot_mem	   = udp_sysctl_mem,
 	.sysctl_wmem	   = &sysctl_udp_wmem_min,
 	.sysctl_rmem	   = &sysctl_udp_rmem_min,
 	.obj_size	   = sizeof(struct udp_sock),
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d1fb63f..807797a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2012,7 +2012,7 @@ static int tcp_v6_init_sock(struct sock *sk)
 	sk->sk_rcvbuf = sysctl_tcp_rmem[1];
 
 	local_bh_disable();
-	percpu_counter_inc(&tcp_sockets_allocated);
+	sk_sockets_allocated_inc(sk);
 	local_bh_enable();
 
 	return 0;
@@ -2221,11 +2221,11 @@ struct proto tcpv6_prot = {
 	.unhash			= inet_unhash,
 	.get_port		= inet_csk_get_port,
 	.enter_memory_pressure	= tcp_enter_memory_pressure,
-	.sockets_allocated	= &tcp_sockets_allocated,
-	.memory_allocated	= &tcp_memory_allocated,
-	.memory_pressure	= &tcp_memory_pressure,
+	.sockets_allocated	= sockets_allocated_tcp,
+	.memory_allocated	= memory_allocated_tcp,
+	.memory_pressure	= memory_pressure_tcp,
 	.orphan_count		= &tcp_orphan_count,
-	.sysctl_mem		= sysctl_tcp_mem,
+	.prot_mem		= tcp_sysctl_mem,
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 29213b5..ef4b5b3 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1465,8 +1465,8 @@ struct proto udpv6_prot = {
 	.unhash		   = udp_lib_unhash,
 	.rehash		   = udp_v6_rehash,
 	.get_port	   = udp_v6_get_port,
-	.memory_allocated  = &udp_memory_allocated,
-	.sysctl_mem	   = sysctl_udp_mem,
+	.memory_allocated  = memory_allocated_udp,
+	.prot_mem	   = udp_sysctl_mem,
 	.sysctl_wmem	   = &sysctl_udp_wmem_min,
 	.sysctl_rmem	   = &sysctl_udp_rmem_min,
 	.obj_size	   = sizeof(struct udp6_sock),
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 836aa63..0ddf561 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -119,11 +119,30 @@ static int sctp_memory_pressure;
 static atomic_long_t sctp_memory_allocated;
 struct percpu_counter sctp_sockets_allocated;
 
+static long *sctp_sysctl_mem(struct mem_cgroup *sg)
+{
+	return sysctl_sctp_mem;
+}
+
 static void sctp_enter_memory_pressure(struct sock *sk)
 {
 	sctp_memory_pressure = 1;
 }
 
+static int *memory_pressure_sctp(struct mem_cgroup *sg)
+{
+	return &sctp_memory_pressure;
+}
+
+static atomic_long_t *memory_allocated_sctp(struct mem_cgroup *sg)
+{
+	return &sctp_memory_allocated;
+}
+
+static struct percpu_counter *sockets_allocated_sctp(struct mem_cgroup *sg)
+{
+	return &sctp_sockets_allocated;
+}
 
 /* Get the sndbuf space available at the time on the association.  */
 static inline int sctp_wspace(struct sctp_association *asoc)
@@ -6831,13 +6850,13 @@ struct proto sctp_prot = {
 	.unhash      =	sctp_unhash,
 	.get_port    =	sctp_get_port,
 	.obj_size    =  sizeof(struct sctp_sock),
-	.sysctl_mem  =  sysctl_sctp_mem,
+	.prot_mem    =  sctp_sysctl_mem,
 	.sysctl_rmem =  sysctl_sctp_rmem,
 	.sysctl_wmem =  sysctl_sctp_wmem,
-	.memory_pressure = &sctp_memory_pressure,
+	.memory_pressure = memory_pressure_sctp,
 	.enter_memory_pressure = sctp_enter_memory_pressure,
-	.memory_allocated = &sctp_memory_allocated,
-	.sockets_allocated = &sctp_sockets_allocated,
+	.memory_allocated = memory_allocated_sctp,
+	.sockets_allocated = sockets_allocated_sctp,
 };
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -6863,12 +6882,12 @@ struct proto sctpv6_prot = {
 	.unhash		= sctp_unhash,
 	.get_port	= sctp_get_port,
 	.obj_size	= sizeof(struct sctp6_sock),
-	.sysctl_mem	= sysctl_sctp_mem,
+	.prot_mem	= sctp_sysctl_mem,
 	.sysctl_rmem	= sysctl_sctp_rmem,
 	.sysctl_wmem	= sysctl_sctp_wmem,
-	.memory_pressure = &sctp_memory_pressure,
+	.memory_pressure = memory_pressure_sctp,
 	.enter_memory_pressure = sctp_enter_memory_pressure,
-	.memory_allocated = &sctp_memory_allocated,
-	.sockets_allocated = &sctp_sockets_allocated,
+	.memory_allocated = memory_allocated_sctp,
+	.sockets_allocated = sockets_allocated_sctp,
 };
 #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH v2 4/7] per-cgroup tcp buffers control
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, Glauber Costa
In-Reply-To: <1316051175-17780-1-git-send-email-glommer@parallels.com>

With all the infrastructure in place, this patch implements
per-cgroup control for tcp memory pressure handling.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: David S. Miller <davem@davemloft.net>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
---
 include/linux/memcontrol.h |    8 +++
 include/net/sock.h         |   14 +++++-
 include/net/tcp.h          |   10 ++--
 mm/memcontrol.c            |  115 +++++++++++++++++++++++++++++++++++++++++++-
 net/core/sock.c            |   28 ++++++++++-
 net/ipv4/tcp.c             |   44 ++++++++---------
 net/ipv4/tcp_ipv4.c        |   14 ++++--
 net/ipv6/tcp_ipv6.c        |   14 ++++--
 8 files changed, 203 insertions(+), 44 deletions(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 15c337f..47e05ba 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -404,6 +404,14 @@ void memcg_sock_mem_alloc(struct mem_cgroup *mem, struct proto *prot,
 void memcg_sock_mem_free(struct mem_cgroup *mem, struct proto *prot, int amt);
 void memcg_sockets_allocated_dec(struct mem_cgroup *mem, struct proto *prot);
 void memcg_sockets_allocated_inc(struct mem_cgroup *mem, struct proto *prot);
+int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
+		    struct cgroup_subsys *ss);
+int tcp_init_cgroup_fill(struct proto *prot, struct cgroup *cgrp,
+			 struct cgroup_subsys *ss);
+void tcp_destroy_cgroup(struct proto *prot, struct cgroup *cgrp,
+			struct cgroup_subsys *ss);
+void tcp_destroy_cgroup_fill(struct proto *prot, struct cgroup *cgrp,
+			     struct cgroup_subsys *ss);
 #include <net/sock.h>
 
 static inline void sock_update_memcg(struct sock *sk)
diff --git a/include/net/sock.h b/include/net/sock.h
index 78832f9..ec3c7fa 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -64,6 +64,7 @@
 #include <net/dst.h>
 #include <net/checksum.h>
 
+int sockets_populate(struct cgroup *cgrp, struct cgroup_subsys *ss);
 /*
  * This structure really needs to be cleaned up.
  * Most of it is for TCP, and not used by any of
@@ -814,7 +815,18 @@ struct proto {
 	int			*(*memory_pressure)(struct mem_cgroup *sg);
 	/* Pointer to the per-cgroup version of the the sysctl_mem field */
 	long			*(*prot_mem)(struct mem_cgroup *sg);
-
+	/*
+	 * cgroup specific init/deinit functions. Called once for all
+	 * protocols that implement it, from cgroups populate function.
+	 * This function has to setup any files the protocol want to
+	 * appear in the kmem cgroup filesystem.
+	 */
+	int			(*init_cgroup)(struct proto *prot,
+					       struct cgroup *cgrp,
+					       struct cgroup_subsys *ss);
+	void			(*destroy_cgroup)(struct proto *prot,
+						  struct cgroup *cgrp,
+						  struct cgroup_subsys *ss);
 	int			*sysctl_wmem;
 	int			*sysctl_rmem;
 	int			max_header;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index c835ae3..ce3c211 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -255,10 +255,10 @@ extern int sysctl_tcp_thin_linear_timeouts;
 extern int sysctl_tcp_thin_dupack;
 
 struct mem_cgroup;
-extern long *tcp_sysctl_mem(struct mem_cgroup *sg);
-struct percpu_counter *sockets_allocated_tcp(struct mem_cgroup *sg);
-int *memory_pressure_tcp(struct mem_cgroup *sg);
-atomic_long_t *memory_allocated_tcp(struct mem_cgroup *sg);
+extern long *tcp_sysctl_mem_nocg(struct mem_cgroup *sg);
+struct percpu_counter *sockets_allocated_tcp_nocg(struct mem_cgroup *sg);
+int *memory_pressure_tcp_nocg(struct mem_cgroup *sg);
+atomic_long_t *memory_allocated_tcp_nocg(struct mem_cgroup *sg);
 
 /*
  * The next routines deal with comparing 32 bit unsigned ints
@@ -1002,7 +1002,7 @@ static inline void tcp_openreq_init(struct request_sock *req,
 	ireq->loc_port = tcp_hdr(skb)->dest;
 }
 
-extern void tcp_enter_memory_pressure(struct sock *sk);
+extern void tcp_enter_memory_pressure_nocg(struct sock *sk);
 
 static inline int keepalive_intvl_when(const struct tcp_sock *tp)
 {
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 289fc2c..7db430c 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -343,13 +343,21 @@ struct mem_cgroup {
 	 */
 	struct mem_cgroup_stat_cpu nocpu_base;
 	spinlock_t pcp_counter_lock;
+
+	/* per-cgroup tcp memory pressure knobs */
+	atomic_long_t tcp_memory_allocated;
+	struct percpu_counter tcp_sockets_allocated;
+	/* those two are read-mostly, leave them at the end */
+	long tcp_prot_mem[3];
+	int tcp_memory_pressure;
 };
 
 static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
 /* Writing them here to avoid exposing memcg's inner layout */
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
 #ifdef CONFIG_INET
-
+#include <net/tcp.h>
+#include <net/ip.h>
 void memcg_sock_mem_alloc(struct mem_cgroup *mem, struct proto *prot,
 			  int amt, int *parent_failure)
 {
@@ -392,6 +400,102 @@ void memcg_sockets_allocated_inc(struct mem_cgroup *mem, struct proto *prot)
 		percpu_counter_inc(prot->sockets_allocated(mem));
 }
 EXPORT_SYMBOL(memcg_sockets_allocated_inc);
+
+static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont);
+/*
+ * Pressure flag: try to collapse.
+ * Technical note: it is used by multiple contexts non atomically.
+ * All the __sk_mem_schedule() is of this nature: accounting
+ * is strict, actions are advisory and have some latency.
+ */
+void tcp_enter_memory_pressure(struct sock *sk)
+{
+	struct mem_cgroup *sg = sk->sk_cgrp;
+	if (!sg->tcp_memory_pressure) {
+		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURES);
+		sg->tcp_memory_pressure = 1;
+	}
+}
+
+long *tcp_sysctl_mem(struct mem_cgroup *cg)
+{
+	return cg->tcp_prot_mem;
+}
+
+atomic_long_t *memory_allocated_tcp(struct mem_cgroup *cg)
+{
+	return &(cg->tcp_memory_allocated);
+}
+
+int *memory_pressure_tcp(struct mem_cgroup *sg)
+{
+	return &sg->tcp_memory_pressure;
+}
+
+struct percpu_counter *sockets_allocated_tcp(struct mem_cgroup *sg)
+{
+	return &sg->tcp_sockets_allocated;
+}
+
+/*
+ * For ipv6, we only need to fill in the function pointers (can't initialize
+ * things twice). So keep it separated
+ */
+int tcp_init_cgroup_fill(struct proto *prot, struct cgroup *cgrp,
+			 struct cgroup_subsys *ss)
+{
+	prot->enter_memory_pressure	= tcp_enter_memory_pressure;
+	prot->memory_allocated		= memory_allocated_tcp;
+	prot->prot_mem			= tcp_sysctl_mem;
+	prot->sockets_allocated		= sockets_allocated_tcp;
+	prot->memory_pressure		= memory_pressure_tcp;
+
+	return 0;
+}
+EXPORT_SYMBOL(tcp_init_cgroup_fill);
+
+void tcp_destroy_cgroup_fill(struct proto *prot, struct cgroup *cgrp,
+			     struct cgroup_subsys *ss)
+{
+	prot->enter_memory_pressure	= tcp_enter_memory_pressure_nocg;
+	prot->memory_allocated		= memory_allocated_tcp_nocg;
+	prot->prot_mem			= tcp_sysctl_mem_nocg;
+	prot->sockets_allocated		= sockets_allocated_tcp_nocg;
+	prot->memory_pressure		= memory_pressure_tcp_nocg;
+}
+EXPORT_SYMBOL(tcp_destroy_cgroup_fill);
+
+int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
+		    struct cgroup_subsys *ss)
+{
+	struct mem_cgroup *cg = mem_cgroup_from_cont(cgrp);
+	unsigned long limit;
+
+	cg->tcp_memory_pressure = 0;
+	atomic_long_set(&cg->tcp_memory_allocated, 0);
+	percpu_counter_init(&cg->tcp_sockets_allocated, 0);
+
+	limit = nr_free_buffer_pages() / 8;
+	limit = max(limit, 128UL);
+
+	cg->tcp_prot_mem[0] = sysctl_tcp_mem[0];
+	cg->tcp_prot_mem[1] = sysctl_tcp_mem[1];
+	cg->tcp_prot_mem[2] = sysctl_tcp_mem[2];
+
+	tcp_init_cgroup_fill(prot, cgrp, ss);
+	return 0;
+}
+EXPORT_SYMBOL(tcp_init_cgroup);
+
+void tcp_destroy_cgroup(struct proto *prot, struct cgroup *cgrp,
+			struct cgroup_subsys *ss)
+{
+	struct mem_cgroup *cg = mem_cgroup_from_cont(cgrp);
+
+	percpu_counter_destroy(&cg->tcp_sockets_allocated);
+	tcp_destroy_cgroup_fill(prot, cgrp, ss);
+}
+EXPORT_SYMBOL(tcp_destroy_cgroup);
 #endif /* CONFIG_INET */
 #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
 
@@ -4991,11 +5095,18 @@ static struct cftype kmem_cgroup_files[] = {
 
 static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss)
 {
+	int ret;
+
 	if (!do_kmem_account)
 		return 0;
 
-	return cgroup_add_files(cont, ss, kmem_cgroup_files,
+	ret = cgroup_add_files(cont, ss, kmem_cgroup_files,
 				ARRAY_SIZE(kmem_cgroup_files));
+	if (!ret)
+		ret = sockets_populate(cont, ss);
+
+	return ret;
+
 };
 
 #else
diff --git a/net/core/sock.c b/net/core/sock.c
index 338d572..78bea26 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -135,6 +135,31 @@
 #include <net/tcp.h>
 #endif
 
+static DEFINE_RWLOCK(proto_list_lock);
+static LIST_HEAD(proto_list);
+
+int sockets_populate(struct cgroup *cgrp, struct cgroup_subsys *ss)
+{
+	struct proto *proto;
+	int ret = 0;
+
+	read_lock(&proto_list_lock);
+	list_for_each_entry(proto, &proto_list, node) {
+		if (proto->init_cgroup)
+			ret |= proto->init_cgroup(proto, cgrp, ss);
+	}
+	if (!ret)
+		goto out;
+
+	list_for_each_entry_continue_reverse(proto, &proto_list, node)
+		if (proto->destroy_cgroup)
+			proto->destroy_cgroup(proto, cgrp, ss);
+
+out:
+	read_unlock(&proto_list_lock);
+	return ret;
+}
+
 /*
  * Each address family might have different locking rules, so we have
  * one slock key per address family:
@@ -2260,9 +2285,6 @@ void sk_common_release(struct sock *sk)
 }
 EXPORT_SYMBOL(sk_common_release);
 
-static DEFINE_RWLOCK(proto_list_lock);
-static LIST_HEAD(proto_list);
-
 #ifdef CONFIG_PROC_FS
 #define PROTO_INUSE_NR	64	/* should be enough for the first time */
 struct prot_inuse {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 452245f..156b836 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -290,13 +290,6 @@ EXPORT_SYMBOL(sysctl_tcp_mem);
 EXPORT_SYMBOL(sysctl_tcp_rmem);
 EXPORT_SYMBOL(sysctl_tcp_wmem);
 
-atomic_long_t tcp_memory_allocated;	/* Current allocated memory. */
-
-/*
- * Current number of TCP sockets.
- */
-struct percpu_counter tcp_sockets_allocated;
-
 /*
  * TCP splice context
  */
@@ -306,46 +299,49 @@ struct tcp_splice_state {
 	unsigned int flags;
 };
 
-/*
- * Pressure flag: try to collapse.
- * Technical note: it is used by multiple contexts non atomically.
- * All the __sk_mem_schedule() is of this nature: accounting
- * is strict, actions are advisory and have some latency.
- */
+/* Current number of TCP sockets. */
+struct percpu_counter tcp_sockets_allocated;
+atomic_long_t tcp_memory_allocated;	/* Current allocated memory. */
 int tcp_memory_pressure __read_mostly;
 
-int *memory_pressure_tcp(struct mem_cgroup *sg)
+int *memory_pressure_tcp_nocg(struct mem_cgroup *sg)
 {
 	return &tcp_memory_pressure;
 }
-EXPORT_SYMBOL(memory_pressure_tcp);
+EXPORT_SYMBOL(memory_pressure_tcp_nocg);
 
-struct percpu_counter *sockets_allocated_tcp(struct mem_cgroup *sg)
+struct percpu_counter *sockets_allocated_tcp_nocg(struct mem_cgroup *sg)
 {
 	return &tcp_sockets_allocated;
 }
-EXPORT_SYMBOL(sockets_allocated_tcp);
+EXPORT_SYMBOL(sockets_allocated_tcp_nocg);
 
-void tcp_enter_memory_pressure(struct sock *sk)
+/*
+ * Pressure flag: try to collapse.
+ * Technical note: it is used by multiple contexts non atomically.
+ * All the __sk_mem_schedule() is of this nature: accounting
+ * is strict, actions are advisory and have some latency.
+ */
+void tcp_enter_memory_pressure_nocg(struct sock *sk)
 {
 	if (!tcp_memory_pressure) {
 		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURES);
 		tcp_memory_pressure = 1;
 	}
 }
-EXPORT_SYMBOL(tcp_enter_memory_pressure);
+EXPORT_SYMBOL(tcp_enter_memory_pressure_nocg);
 
-long *tcp_sysctl_mem(struct mem_cgroup *sg)
+long *tcp_sysctl_mem_nocg(struct mem_cgroup *sg)
 {
 	return sysctl_tcp_mem;
 }
-EXPORT_SYMBOL(tcp_sysctl_mem);
+EXPORT_SYMBOL(tcp_sysctl_mem_nocg);
 
-atomic_long_t *memory_allocated_tcp(struct mem_cgroup *sg)
+atomic_long_t *memory_allocated_tcp_nocg(struct mem_cgroup *sg)
 {
 	return &tcp_memory_allocated;
 }
-EXPORT_SYMBOL(memory_allocated_tcp);
+EXPORT_SYMBOL(memory_allocated_tcp_nocg);
 
 /* Convert seconds to retransmits based on initial and max timeout */
 static u8 secs_to_retrans(int seconds, int timeout, int rto_max)
@@ -3247,7 +3243,9 @@ void __init tcp_init(void)
 
 	BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
 
+#ifndef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
 	percpu_counter_init(&tcp_sockets_allocated, 0);
+#endif
 	percpu_counter_init(&tcp_orphan_count, 0);
 	tcp_hashinfo.bind_bucket_cachep =
 		kmem_cache_create("tcp_bind_bucket",
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index cbb0d5e..c857baf 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2597,12 +2597,16 @@ struct proto tcp_prot = {
 	.hash			= inet_hash,
 	.unhash			= inet_unhash,
 	.get_port		= inet_csk_get_port,
-	.enter_memory_pressure	= tcp_enter_memory_pressure,
-	.memory_pressure	= memory_pressure_tcp,
-	.sockets_allocated	= sockets_allocated_tcp,
+	.enter_memory_pressure	= tcp_enter_memory_pressure_nocg,
+	.memory_pressure	= memory_pressure_tcp_nocg,
+	.sockets_allocated	= sockets_allocated_tcp_nocg,
 	.orphan_count		= &tcp_orphan_count,
-	.memory_allocated	= memory_allocated_tcp,
-	.prot_mem		= tcp_sysctl_mem,
+	.memory_allocated	= memory_allocated_tcp_nocg,
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+	.init_cgroup		= tcp_init_cgroup,
+	.destroy_cgroup		= tcp_destroy_cgroup,
+#endif
+	.prot_mem		= tcp_sysctl_mem_nocg,
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 807797a..b2a2350 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2220,12 +2220,16 @@ struct proto tcpv6_prot = {
 	.hash			= tcp_v6_hash,
 	.unhash			= inet_unhash,
 	.get_port		= inet_csk_get_port,
-	.enter_memory_pressure	= tcp_enter_memory_pressure,
-	.sockets_allocated	= sockets_allocated_tcp,
-	.memory_allocated	= memory_allocated_tcp,
-	.memory_pressure	= memory_pressure_tcp,
+	.enter_memory_pressure	= tcp_enter_memory_pressure_nocg,
+	.sockets_allocated	= sockets_allocated_tcp_nocg,
+	.memory_allocated	= memory_allocated_tcp_nocg,
+	.memory_pressure	= memory_pressure_tcp_nocg,
 	.orphan_count		= &tcp_orphan_count,
-	.prot_mem		= tcp_sysctl_mem,
+	.prot_mem		= tcp_sysctl_mem_nocg,
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+	.init_cgroup		= tcp_init_cgroup_fill,
+	.destroy_cgroup		= tcp_destroy_cgroup_fill,
+#endif
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH v2 5/7] per-netns ipv4 sysctl_tcp_mem
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, Glauber Costa
In-Reply-To: <1316051175-17780-1-git-send-email-glommer@parallels.com>

This patch allows each namespace to independently set up
its levels for tcp memory pressure thresholds. This patch
alone does not buy much: we need to make this values
per group of process somehow. This is achieved in the
patches that follows in this patchset.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: David S. Miller <davem@davemloft.net>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
---
 include/net/netns/ipv4.h   |    1 +
 include/net/tcp.h          |    1 -
 mm/memcontrol.c            |    9 +++++--
 net/ipv4/sysctl_net_ipv4.c |   51 +++++++++++++++++++++++++++++++++++++------
 net/ipv4/tcp.c             |   13 ++--------
 5 files changed, 54 insertions(+), 21 deletions(-)

diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index d786b4f..bbd023a 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -55,6 +55,7 @@ struct netns_ipv4 {
 	int current_rt_cache_rebuild_count;
 
 	unsigned int sysctl_ping_group_range[2];
+	long sysctl_tcp_mem[3];
 
 	atomic_t rt_genid;
 	atomic_t dev_addr_genid;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index ce3c211..257e1f9 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -231,7 +231,6 @@ extern int sysctl_tcp_fack;
 extern int sysctl_tcp_reordering;
 extern int sysctl_tcp_ecn;
 extern int sysctl_tcp_dsack;
-extern long sysctl_tcp_mem[3];
 extern int sysctl_tcp_wmem[3];
 extern int sysctl_tcp_rmem[3];
 extern int sysctl_tcp_app_win;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 7db430c..039cb79 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -358,6 +358,8 @@ static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
 #ifdef CONFIG_INET
 #include <net/tcp.h>
 #include <net/ip.h>
+#include <linux/nsproxy.h>
+
 void memcg_sock_mem_alloc(struct mem_cgroup *mem, struct proto *prot,
 			  int amt, int *parent_failure)
 {
@@ -470,6 +472,7 @@ int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
 {
 	struct mem_cgroup *cg = mem_cgroup_from_cont(cgrp);
 	unsigned long limit;
+	struct net *net = current->nsproxy->net_ns;
 
 	cg->tcp_memory_pressure = 0;
 	atomic_long_set(&cg->tcp_memory_allocated, 0);
@@ -478,9 +481,9 @@ int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
 	limit = nr_free_buffer_pages() / 8;
 	limit = max(limit, 128UL);
 
-	cg->tcp_prot_mem[0] = sysctl_tcp_mem[0];
-	cg->tcp_prot_mem[1] = sysctl_tcp_mem[1];
-	cg->tcp_prot_mem[2] = sysctl_tcp_mem[2];
+	cg->tcp_prot_mem[0] = net->ipv4.sysctl_tcp_mem[0];
+	cg->tcp_prot_mem[1] = net->ipv4.sysctl_tcp_mem[1];
+	cg->tcp_prot_mem[2] = net->ipv4.sysctl_tcp_mem[2];
 
 	tcp_init_cgroup_fill(prot, cgrp, ss);
 	return 0;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 69fd720..bbd67ab 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/nsproxy.h>
+#include <linux/swap.h>
 #include <net/snmp.h>
 #include <net/icmp.h>
 #include <net/ip.h>
@@ -174,6 +175,36 @@ static int proc_allowed_congestion_control(ctl_table *ctl,
 	return ret;
 }
 
+static int ipv4_tcp_mem(ctl_table *ctl, int write,
+			   void __user *buffer, size_t *lenp,
+			   loff_t *ppos)
+{
+	int ret;
+	unsigned long vec[3];
+	struct net *net = current->nsproxy->net_ns;
+
+	ctl_table tmp = {
+		.data = &vec,
+		.maxlen = sizeof(vec),
+		.mode = ctl->mode,
+	};
+
+	if (!write) {
+		ctl->data = &net->ipv4.sysctl_tcp_mem;
+		return proc_doulongvec_minmax(ctl, write, buffer, lenp, ppos);
+	}
+
+	ret = proc_doulongvec_minmax(&tmp, write, buffer, lenp, ppos);
+	if (ret)
+		return ret;
+
+	net->ipv4.sysctl_tcp_mem[0] = vec[0];
+	net->ipv4.sysctl_tcp_mem[1] = vec[1];
+	net->ipv4.sysctl_tcp_mem[2] = vec[2];
+
+	return 0;
+}
+
 static struct ctl_table ipv4_table[] = {
 	{
 		.procname	= "tcp_timestamps",
@@ -433,13 +464,6 @@ static struct ctl_table ipv4_table[] = {
 		.proc_handler	= proc_dointvec
 	},
 	{
-		.procname	= "tcp_mem",
-		.data		= &sysctl_tcp_mem,
-		.maxlen		= sizeof(sysctl_tcp_mem),
-		.mode		= 0644,
-		.proc_handler	= proc_doulongvec_minmax
-	},
-	{
 		.procname	= "tcp_wmem",
 		.data		= &sysctl_tcp_wmem,
 		.maxlen		= sizeof(sysctl_tcp_wmem),
@@ -721,6 +745,12 @@ static struct ctl_table ipv4_net_table[] = {
 		.mode		= 0644,
 		.proc_handler	= ipv4_ping_group_range,
 	},
+	{
+		.procname	= "tcp_mem",
+		.maxlen		= sizeof(init_net.ipv4.sysctl_tcp_mem),
+		.mode		= 0644,
+		.proc_handler	= ipv4_tcp_mem,
+	},
 	{ }
 };
 
@@ -734,6 +764,7 @@ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);
 static __net_init int ipv4_sysctl_init_net(struct net *net)
 {
 	struct ctl_table *table;
+	unsigned long limit;
 
 	table = ipv4_net_table;
 	if (!net_eq(net, &init_net)) {
@@ -769,6 +800,12 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
 
 	net->ipv4.sysctl_rt_cache_rebuild_count = 4;
 
+	limit = nr_free_buffer_pages() / 8;
+	limit = max(limit, 128UL);
+	net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
+	net->ipv4.sysctl_tcp_mem[1] = limit;
+	net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;
+
 	net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
 			net_ipv4_ctl_path, table);
 	if (net->ipv4.ipv4_hdr == NULL)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 156b836..a94a0f1 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -282,11 +282,9 @@ int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT;
 struct percpu_counter tcp_orphan_count;
 EXPORT_SYMBOL_GPL(tcp_orphan_count);
 
-long sysctl_tcp_mem[3] __read_mostly;
 int sysctl_tcp_wmem[3] __read_mostly;
 int sysctl_tcp_rmem[3] __read_mostly;
 
-EXPORT_SYMBOL(sysctl_tcp_mem);
 EXPORT_SYMBOL(sysctl_tcp_rmem);
 EXPORT_SYMBOL(sysctl_tcp_wmem);
 
@@ -333,7 +331,7 @@ EXPORT_SYMBOL(tcp_enter_memory_pressure_nocg);
 
 long *tcp_sysctl_mem_nocg(struct mem_cgroup *sg)
 {
-	return sysctl_tcp_mem;
+	return init_net.ipv4.sysctl_tcp_mem;
 }
 EXPORT_SYMBOL(tcp_sysctl_mem_nocg);
 
@@ -3296,14 +3294,9 @@ void __init tcp_init(void)
 	sysctl_tcp_max_orphans = cnt / 2;
 	sysctl_max_syn_backlog = max(128, cnt / 256);
 
-	limit = nr_free_buffer_pages() / 8;
-	limit = max(limit, 128UL);
-	sysctl_tcp_mem[0] = limit / 4 * 3;
-	sysctl_tcp_mem[1] = limit;
-	sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
-
 	/* Set per-socket limits to no more than 1/128 the pressure threshold */
-	limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
+	limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1])
+		<< (PAGE_SHIFT - 7);
 	max_share = min(4UL*1024*1024, limit);
 
 	sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH v2 6/7] tcp buffer limitation: per-cgroup limit
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, Glauber Costa
In-Reply-To: <1316051175-17780-1-git-send-email-glommer@parallels.com>

This patch uses the "tcp_max_mem" field of the kmem_cgroup to
effectively control the amount of kernel memory pinned by a cgroup.

We have to make sure that none of the memory pressure thresholds
specified in the namespace are bigger than the current cgroup.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: David S. Miller <davem@davemloft.net>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
---
 Documentation/cgroups/memory.txt |    1 +
 include/linux/memcontrol.h       |   11 ++++++
 mm/memcontrol.c                  |   69 +++++++++++++++++++++++++++++++++++++-
 net/ipv4/sysctl_net_ipv4.c       |   20 +++++++++++
 4 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index ca58eff..ce825ee 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -78,6 +78,7 @@ Brief summary of control files.
 
  memory.independent_kmem_limit	 # select whether or not kernel memory limits are
 				   independent of user limits
+ memory.kmem.tcp.max_memory      # set/show hard limit for tcp buf memory
 
 1. History
 
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 47e05ba..a859399 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -439,6 +439,10 @@ static inline void sock_release_memcg(struct sock *sk)
 {
 	cgroup_release_and_wakeup_rmdir(mem_cgroup_css(sk->sk_cgrp));
 }
+
+unsigned long tcp_max_memory(struct mem_cgroup *cg);
+void tcp_prot_mem(struct mem_cgroup *cg, long val, int idx);
+
 #else
 /* memcontrol includes sockets.h, that includes memcontrol.h ... */
 static inline void memcg_sock_mem_alloc(struct mem_cgroup *mem,
@@ -466,6 +470,13 @@ static inline void sock_update_memcg(struct sock *sk)
 static inline void sock_release_memcg(struct sock *sk)
 {
 }
+static inline unsigned long tcp_max_memory(struct mem_cgroup *cg)
+{
+	return 0;
+}
+static inline void tcp_prot_mem(struct mem_cgroup *cg, long val, int idx)
+{
+}
 #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
 #endif /* CONFIG_INET */
 #endif /* _LINUX_MEMCONTROL_H */
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 039cb79..b48e517 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -345,6 +345,7 @@ struct mem_cgroup {
 	spinlock_t pcp_counter_lock;
 
 	/* per-cgroup tcp memory pressure knobs */
+	int tcp_max_memory;
 	atomic_long_t tcp_memory_allocated;
 	struct percpu_counter tcp_sockets_allocated;
 	/* those two are read-mostly, leave them at the end */
@@ -439,6 +440,56 @@ struct percpu_counter *sockets_allocated_tcp(struct mem_cgroup *sg)
 	return &sg->tcp_sockets_allocated;
 }
 
+static int tcp_write_maxmem(struct cgroup *cgrp, struct cftype *cft, u64 val)
+{
+	struct mem_cgroup *sg = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup *parent = parent_mem_cgroup(sg);
+	struct net *net = current->nsproxy->net_ns;
+	int i;
+
+	if (!cgroup_lock_live_group(cgrp))
+		return -ENODEV;
+
+	/*
+	 * We can't allow more memory than our parents. Since this
+	 * will be tested for all calls, by induction, there is no need
+	 * to test any parent other than our own
+	 * */
+	if (parent && (val > parent->tcp_max_memory))
+		val = parent->tcp_max_memory;
+
+	sg->tcp_max_memory = val;
+
+	for (i = 0; i < 3; i++)
+		sg->tcp_prot_mem[i]  = min_t(long, val,
+					     net->ipv4.sysctl_tcp_mem[i]);
+
+	cgroup_unlock();
+
+	return 0;
+}
+
+static u64 tcp_read_maxmem(struct cgroup *cgrp, struct cftype *cft)
+{
+	struct mem_cgroup *sg = mem_cgroup_from_cont(cgrp);
+	u64 ret;
+
+	if (!cgroup_lock_live_group(cgrp))
+		return -ENODEV;
+	ret = sg->tcp_max_memory;
+
+	cgroup_unlock();
+	return ret;
+}
+
+static struct cftype tcp_files[] = {
+	{
+		.name = "kmem.tcp.max_memory",
+		.write_u64 = tcp_write_maxmem,
+		.read_u64 = tcp_read_maxmem,
+	},
+};
+
 /*
  * For ipv6, we only need to fill in the function pointers (can't initialize
  * things twice). So keep it separated
@@ -471,6 +522,7 @@ int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
 		    struct cgroup_subsys *ss)
 {
 	struct mem_cgroup *cg = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup *parent = parent_mem_cgroup(cg);
 	unsigned long limit;
 	struct net *net = current->nsproxy->net_ns;
 
@@ -481,12 +533,17 @@ int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
 	limit = nr_free_buffer_pages() / 8;
 	limit = max(limit, 128UL);
 
+	if (parent)
+		cg->tcp_max_memory = parent->tcp_max_memory;
+	else
+		cg->tcp_max_memory = limit * 2;
+
 	cg->tcp_prot_mem[0] = net->ipv4.sysctl_tcp_mem[0];
 	cg->tcp_prot_mem[1] = net->ipv4.sysctl_tcp_mem[1];
 	cg->tcp_prot_mem[2] = net->ipv4.sysctl_tcp_mem[2];
 
 	tcp_init_cgroup_fill(prot, cgrp, ss);
-	return 0;
+	return cgroup_add_files(cgrp, ss, tcp_files, ARRAY_SIZE(tcp_files));
 }
 EXPORT_SYMBOL(tcp_init_cgroup);
 
@@ -499,6 +556,16 @@ void tcp_destroy_cgroup(struct proto *prot, struct cgroup *cgrp,
 	tcp_destroy_cgroup_fill(prot, cgrp, ss);
 }
 EXPORT_SYMBOL(tcp_destroy_cgroup);
+
+unsigned long tcp_max_memory(struct mem_cgroup *cg)
+{
+	return cg->tcp_max_memory;
+}
+
+void tcp_prot_mem(struct mem_cgroup *cg, long val, int idx)
+{
+	cg->tcp_prot_mem[idx] = val;
+}
 #endif /* CONFIG_INET */
 #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
 
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index bbd67ab..cdc35f6 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/nsproxy.h>
+#include <linux/memcontrol.h>
 #include <linux/swap.h>
 #include <net/snmp.h>
 #include <net/icmp.h>
@@ -182,6 +183,10 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write,
 	int ret;
 	unsigned long vec[3];
 	struct net *net = current->nsproxy->net_ns;
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+	int i;
+	struct mem_cgroup *cg;
+#endif
 
 	ctl_table tmp = {
 		.data = &vec,
@@ -198,6 +203,21 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write,
 	if (ret)
 		return ret;
 
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+	rcu_read_lock();
+	cg = mem_cgroup_from_task(current);
+	for (i = 0; i < 3; i++)
+		if (vec[i] > tcp_max_memory(cg)) {
+			rcu_read_unlock();
+			return -EINVAL;
+		}
+
+	tcp_prot_mem(cg, vec[0], 0);
+	tcp_prot_mem(cg, vec[1], 1);
+	tcp_prot_mem(cg, vec[2], 2);
+	rcu_read_unlock();
+#endif
+
 	net->ipv4.sysctl_tcp_mem[0] = vec[0];
 	net->ipv4.sysctl_tcp_mem[1] = vec[1];
 	net->ipv4.sysctl_tcp_mem[2] = vec[2];
-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH v2 7/7] Display current tcp memory allocation in kmem cgroup
From: Glauber Costa @ 2011-09-15  1:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, Glauber Costa
In-Reply-To: <1316051175-17780-1-git-send-email-glommer@parallels.com>

This patch introduces kmem.tcp_current_memory file, living in the
kmem_cgroup filesystem. It is a simple read-only file that displays the
amount of kernel memory currently consumed by the cgroup.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: David S. Miller <davem@davemloft.net>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
---
 Documentation/cgroups/memory.txt |    1 +
 mm/memcontrol.c                  |   17 +++++++++++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index ce825ee..59d9416 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -79,6 +79,7 @@ Brief summary of control files.
  memory.independent_kmem_limit	 # select whether or not kernel memory limits are
 				   independent of user limits
  memory.kmem.tcp.max_memory      # set/show hard limit for tcp buf memory
+ memory.kmem.tcp.current_memory  # show current tcp buf memory allocation
 
 1. History
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index b48e517..dd0121f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -482,12 +482,29 @@ static u64 tcp_read_maxmem(struct cgroup *cgrp, struct cftype *cft)
 	return ret;
 }
 
+static u64 tcp_read_curmem(struct cgroup *cgrp, struct cftype *cft)
+{
+	struct mem_cgroup *sg = mem_cgroup_from_cont(cgrp);
+	u64 ret;
+
+	if (!cgroup_lock_live_group(cgrp))
+		return -ENODEV;
+	ret = atomic_long_read(&sg->tcp_memory_allocated);
+
+	cgroup_unlock();
+	return ret;
+}
+
 static struct cftype tcp_files[] = {
 	{
 		.name = "kmem.tcp.max_memory",
 		.write_u64 = tcp_write_maxmem,
 		.read_u64 = tcp_read_maxmem,
 	},
+	{
+		.name = "kmem.tcp.current_memory",
+		.read_u64 = tcp_read_curmem,
+	},
 };
 
 /*
-- 
1.7.6

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* Re: Draft manpage for recvmmsg
From: Michael Kerrisk @ 2011-09-15  4:15 UTC (permalink / raw)
  To: Andi Kleen
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	acme-H+wXaHxf7aLQT0dZR+AlfA, Stephan Mueller, Anton Blanchard,
	Linux API
In-Reply-To: <20101123101551.GA20431-u0/ZJuX+froe6aEkudXLsA@public.gmane.org>

[CC list expanded]

Hi Andi, (and Arnaldo)

As noted in an earlier mail, I still need to know what copyright and
license to attach to the page before I can release it.

See below for further comments.

On Tue, Nov 23, 2010 at 11:15 AM, Andi Kleen <andi-Vw/NltI1exuRpAAqCnN02g@public.gmane.org> wrote:
>
> Here's a draft manpage for recvmmsg(2), which is one
> of the last undocumented syscalls currently.
> Please review and comment.
>
> -Andi
>
>
> .TH RECVMMSG 2 2010-11-23 "Linux" "Linux Programmer's Manual"
> .SH NAME
> recvmmsg \- receive multiple messages on a socket
> .SH SYNOPSIS
> .BI "#include <sys/socket.h>"
> .br
> .BI "int recvmmsg(int " fd ", struct mmsghdr *" mmsghdr \
> ", unsigned int " vlen ","
> .br
> .BI "             unsigned int " flags ", struct timespec *" timeout ");"
> .SH DESCRIPTION
> The
> .B recvmmsg
> system call receives multiple messages in a socket.
> It acts similar to
> .B recvmsg(2),
> but allows to batch multiple receive operations into a single syscall.
> In addition it support an explicit timeout.
>
> .B fd
> is the file descriptor of the socket to receive data from.
> .B mmsghdr
> is a pointer to an array with length
> .B vlen
> of
> .I mmsghdr
> structures.
> .I struct mmsg
> is defined in
> .I sys/socket.h
> as:
> .in +4n
> .nf
> struct mmsghdr {
>    struct msghdr msg_hdr;  /* Message header */
>    unsigned int  msg_len;  /* Number of received bytes for header */
> };
> .fi
> .in
> .PP
> .B msg_hdr
> is a struct
> .I msghdr
> as described in
> .I recvmsg(2).
> .B msg_len
> is the number of bytes returned for the message in the entry.
> This field has the same value as the return value of a single
> .I recvmsg(2)
> on the header.
>
> .B flags
> contains flags ored together. The flags are the same
> as documented for
> .I recvmsg(2).
> The additional
> .B MSG_WAITFORONE
> turns one
> .I MSG_DONTWAIT
> after the first message has been received.
>
> .B timeout
> points to a
> .I struct timespec
> (see
> .I clock_gettime(2)
> )
> defining a timeout for receiving, or
> .I NULL
> for no timeout. When the timeout expires
> .I recvmmsg
> returns.
> .SH RETURN VALUE
> .I recvmmsg
> returns the number of messages received in
> .I mmsghdr
> or
> -1
> when an error occurs. The
> .I msg_len
> members of
> .I mmsghdr
> are updated for each received message,
> in addition to other fields in the msg_hdr for each message,
> as described in
> .I recvmsg(2).
> .SH SEE ALSO
> .B recvmsg(2),
> .B sendmsg(2),
> .B socket(7),
> .B socket(2),
> .B clock_gettime(2)
> .SH VERSIONS
> The
> .I recvmmsg
> syscall was added with kernel 2.6.32.
> Support in glibc was added with 2.6.12.
> On earlier glibcs the function can be called
> manually using
> .I syscall(2).

I reworked a number of pieces of text, and added several other pieces.
Could you please take a look (for others interested: "man -l <file>")
at the version below and let me know of inaccuracies

Thanks,

Michael

.TH RECVMMSG 2 2011-09-09 "Linux" "Linux Programmer's Manual"
.SH NAME
recvmmsg \- receive multiple messages on a socket
.SH SYNOPSIS
.nf
.B "#define _GNU_SOURCE"
.BI "#include <sys/socket.h>"

.BI "int recvmmsg(int " sockfd ", struct mmsghdr *" msgvec \
", unsigned int " vlen ","
.br
.BI "             unsigned int " flags ", struct timespec *" timeout ");"
.fi
.SH DESCRIPTION
The
.BR recvmmsg ()
system call is an extension of
.BR recvmsg (2)
that allows the caller to receive multiple messages from a socket
using a single system call.
(This has performance benefits for some applications.)
A further extension over
.BR recvmsg (2)
is support for a timeout on the receive operation.

The
.I sockfd
argument is the file descriptor of the socket to receive data from.

The
.I msgvec
argument is a pointer to an array of
.I mmsghdr
structures.
The size of this array is specified in
.IR vlen .

The
.I mmsghdr
structure is defined in
.I <sys/socket.h>
as:

.in +4n
.nf
struct mmsghdr {
    struct msghdr msg_hdr;  /* Message header */
    unsigned int  msg_len;  /* Number of received bytes for header */
};
.fi
.in
.PP
The
.I msg_hdr
field is a
.I msghdr
structure, as described in
.BR recvmsg (2).
The
.I msg_len
field is the number of bytes returned for the message in the entry.
This field has the same value as the return value of a single
.BR recvmsg (2)
on the header.

The
.I flags
argument contains flags ORed together.
The flags are the same as documented for
.BR recvmsg (2),
with the following addition:
.TP
.B MSG_WAITFORONE
Turns on
.B MSG_DONTWAIT
after the first message has been received.
.PP
The
.I timeout
argument points to a
.I struct timespec
(see
.BR clock_gettime (2))
defining a timeout (seconds plus nanoseconds) for the receive operation.
If
.I timeout
is
.I NULL
then the operation blocks indefinitely.

A blocking
.BR recvmmsg ()
call blocks until
.I vlen
messages have been received
or until the timeout expires.
A nonblocking call reads as many messages as are available
(up to the limit specified by
.IR vlen )
and returns immediately.

On return from
.BR recvmmsg (),
successive elements of
.IR msgvec
are updated to contain information about each received message:
.I msg_len
contains the size of the received message;
the subfields of
.I msg_hdr
are updated as described in
.BR recvmsg (2).
The return value of the call indicates the number of elements of
.I msgvec
that have been updated.
.SH RETURN VALUE
On success,
.BR recvmmsg ()
returns the number of messages received in
.IR msgvec ;
on error, \-1 is returned, and
.I errno
is set to indicate the error.
.SH ERRORS
Errors are as for
.BR recvmsg (2).
In addition, the following error can occur:
.TP
.B EINVAL
.I timeout
is invalid.
.SH VERSIONS
The
.BR recvmmsg ()
system call was added in Linux 2.6.32.
Support in glibc was added in version 2.12.
.SH CONFORMING TO
.BR recvmmsg ()
is Linux-specific.
.SH SEE ALSO
.BR clock_gettime (2),
.BR recvmsg (2),
.BR sendmmsg (2),
.BR sendmsg (2),
.BR socket (2),
.BR socket (7)

-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/

^ permalink raw reply

* Re: [PATCH 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
From: David Daney @ 2011-09-15  4:16 UTC (permalink / raw)
  To: Grant Likely
  Cc: David Daney, David Daney, linux-mips, linux-kernel,
	David S. Miller, netdev, devicetree-discuss, ralf
In-Reply-To: <CACxGe6tA6D9JVf0_K-JAGnKcQmDmD=1ytqqYb6or-KjP9uZNxg@mail.gmail.com>

On 09/14/2011 05:51 PM, Grant Likely wrote:
>
>
> On Aug 31, 2011 2:01 PM, "David Daney" <david.daney@cavium.com 
> <mailto:david.daney@cavium.com>> wrote:
> >
> > This patch adds a somewhat generic framework for MDIO bus
> > multiplexers.  It is modeled on the I2C multiplexer.
> >
>
[...]
>
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
> > @@ -0,0 +1,132 @@
> > +Common MDIO bus multiplexer/switch properties.
> > +
> > +An MDIO bus multiplexer/switch will have several child busses that are
> > +numbered uniquely in a device dependent manner.  The nodes for an MDIO
> > +bus multiplexer/switch will have one child node for each child bus.
> > +
> > +Required properties:
> > +- parent-bus : phandle to the parent MDIO bus.
>
> As discussed, I like mdio-parent-bus.
>
> > +
> > +Optional properties:
> > +- Other properties specific to the multiplexer/switch hardware.
> > +
> > +Required properties for child nodes:
> > +- #address-cells = <1>;
> > +- #size-cells = <0>;
> > +- cell-index : The sub-bus number.
>
> Use reg, not cell-index. That is what it is there for. And add the 
> appropriate #address/size-cells in the parent.
>
> I've not reviewed the implementation, but with the changes. I'm okay 
> with the binding.
>

Thanks for the prompt reply Grant.

I will rework this with the binding changes and send a new version soon.

David Daney

^ permalink raw reply

* sendmmsg(2) draft man pages
From: Michael Kerrisk @ 2011-09-15  4:16 UTC (permalink / raw)
  To: Anton Blanchard
  Cc: linux-man, Andi Kleen, Stephan Mueller, netdev, Linux API,
	Michael Kerrisk

Hello Anton,

Stephan Mueller made an initial shot at a manual page for the
sendmmsg() syscall that you recently added to the kernel. This
inspired me to come up with a more complete version, which I'd like to
get reviewed before including in man-pages. Could you take a look
("man -l <file>") at the version below and let me know any errors or
omissions.

Thanks

Michael Kerrisk

.\" Copyright (c) 2011 by Michael Kerrisk <mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
.\" with some material from a draft by
.\" Stephan Mueller <stephan.mueller-fwYZOkdEjagAvxtiuMwx3w@public.gmane.org>
.\" in turn based on Andi Kleen's recvmmsg.2 page.
.\"
.\" Permission is granted to make and distribute verbatim copies of this
.\" manual provided the copyright notice and this permission notice are
.\" preserved on all copies.
.\"
.\" Permission is granted to copy and distribute modified versions of this
.\" manual under the conditions for verbatim copying, provided that the
.\" entire resulting derived work is distributed under the terms of a
.\" permission notice identical to this one.
.\"
.\" Since the Linux kernel and libraries are constantly changing, this
.\" manual page may be incorrect or out-of-date.  The author(s) assume no
.\" responsibility for errors or omissions, or for damages resulting from
.\" the use of the information contained herein.  The author(s) may not
.\" have taken the same level of care in the production of this manual,
.\" which is licensed free of charge, as they might when working
.\" professionally.
.\"
.\" Formatted or processed versions of this manual, if unaccompanied by
.\" the source, must acknowledge the copyright and authors of this work.
.\"
.TH SENDMMSG 2 2011-09-09 "Linux" "Linux Programmer's Manual"
.SH NAME
sendmmsg \- send multiple messages on a socket
.SH SYNOPSIS
.nf
.B "#define _GNU_SOURCE"
.BI "#include <sys/socket.h>"

.BI "int sendmmsg(int " sockfd ", struct mmsghdr *" msgvec \
", unsigned int " vlen ","
.BI "             unsigned int " flags ");"
.fi
.SH DESCRIPTION
The
.BR sendmmsg ()
system call is an extension of
.BR sendmsg (2)
that allows the caller to transmit multiple messages on a socket
using a single system call.
(This has performance benefits for some applications.)
.\" See commit 228e548e602061b08ee8e8966f567c12aa079682

The
.I sockfd
argument is the file descriptor of the socket
on which data is to be transmitted.

The
.I msgvec
argument is a pointer to an array of
.I mmsghdr
structures.
The size of this array is specified in
.IR vlen .

The
.I mmsghdr
structure is defined in
.I <sys/socket.h>
as:

.in +4n
.nf
struct mmsghdr {
    struct msghdr msg_hdr;  /* Message header */
    unsigned int  msg_len;  /* Number of bytes transmitted */
};
.fi
.in
.PP
The
.I msg_hdr
field is a
.I msghdr
structure, as described in
.BR sendmsg (2).
The
.I msg_len
field is used to return the number of bytes sent from the message in
.IR msg_hdr
(i.e., the same as the return value from a single
.BR sendmsg (2)
call).

The
.I flags
argument contains flags ORed together.
The flags are the same as for
.BR sendmsg (2).

A blocking
.BR sendmmsg ()
call blocks until
.I vlen
messages have been sent.
A nonblocking call sends as many messages as possible
(up to the limit specified by
.IR vlen )
and returns immediately.

On return from
.BR sendmmsg (),
the
.I msg_len
fields of successive elements of
.IR msgvec
are updated to contain the number of bytes transmitted from the corresponding
.IR msg_hdr .
The return value of the call indicates the number of elements of
.I msgvec
that have been updated.
.SH RETURN VALUE
On success,
.BR sendmmsg ()
returns the number of messages sent from
.IR msgvec ;
if this is less than
.IR vlen ,
the caller can retry with a further
.BR sendmmsg ()
call to send the remaining messages.

On error, \-1 is returned, and
.I errno
is set to indicate the error.
.SH ERRORS
Errors are as for
.BR sendmsg (2).
An error is returned only if no datagrams could be sent.
.\" commit 728ffb86f10873aaf4abd26dde691ee40ae731fe
.\"     ... only return an error if no datagrams could be sent.
.\"     If less than the requested number of messages were sent, the application
.\"     must retry starting at the first failed one and if the problem is
.\"     persistent the error will be returned.
.\"
.\"     This matches the behaviour of other syscalls like read/write - it
.\"     is not an error if less than the requested number of elements are sent.
.SH VERSIONS
The
.BR sendmmsg ()
system call was added in Linux 3.0.
Support in glibc was added in version 2.14.
.SH CONFORMING TO
.BR sendmmsg ()
is Linux-specific.
.SH NOTES
The value specified in
.I vlen
is capped to
.B UIO_MAXIOV
(1024).
.\" commit 98382f419f32d2c12d021943b87dea555677144b
.\"     net: Cap number of elements for sendmmsg
.\"
.\"     To limit the amount of time we can spend in sendmmsg, cap the
.\"     number of elements to UIO_MAXIOV (currently 1024).
.\"
.\"     For error handling an application using sendmmsg needs to retry at
.\"     the first unsent message, so capping is simpler and requires less
.\"     application logic than returning EINVAL.
.SH SEE ALSO
.BR recvmmsg (2),
.BR sendmsg (2),
.BR socket (2),
.BR socket (7)

-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/

^ permalink raw reply

* Re: e1000e: NIC not working, power management issue?
From: Lucas Nussbaum @ 2011-09-15  4:48 UTC (permalink / raw)
  To: John Ronciak; +Cc: Frederik Himpe, netdev, e1000-devel, linux-kernel
In-Reply-To: <CALWPMBEvwFbP-G+Ojfr_vM2riwG9vax3_3cQ1SzBR4OmdnHnsw@mail.gmail.com>

On 14/09/11 at 14:14 -0700, John Ronciak wrote:
> On Wed, Sep 14, 2011 at 1:31 PM, Frederik Himpe <fhimpe@telenet.be> wrote:
> 
> >>
> >> dmesg:
> >> [ 6260.327320] e1000e: Intel(R) PRO/1000 Network Driver - 1.4.4-k
> >> [ 6260.327324] e1000e: Copyright(c) 1999 - 2011 Intel Corporation.
> >> [ 6260.327355] e1000e 0000:00:19.0: PCI INT A -> GSI 22 (level, low) -> IRQ 22
> >> [ 6260.327366] e1000e 0000:00:19.0: setting latency timer to 64
> >> [ 6260.327490] e1000e 0000:00:19.0: irq 43 for MSI/MSI-X
> >> [ 6260.517813] e1000e 0000:00:19.0: eth0: (PCI Express:2.5GT/s:Width x1) 00:24:e8:a7:2c:42
> >> [ 6260.517824] e1000e 0000:00:19.0: eth0: Intel(R) PRO/1000 Network Connection
> >> [ 6260.518077] e1000e 0000:00:19.0: eth0: MAC: 7, PHY: 8, PBA No: 3002FF-0FF
> >> [ 6260.518102] e1000e 0000:00:19.0: PME# enabled
> >> [ 6260.556129] e1000e 0000:00:19.0: BAR 0: set to [mem 0xf6ae0000-0xf6afffff] (PCI address [0xf6ae0000-0xf6afffff])
> >> [ 6260.556139] e1000e 0000:00:19.0: BAR 1: set to [mem 0xf6adb000-0xf6adbfff] (PCI address [0xf6adb000-0xf6adbfff])
> >> [ 6260.556147] e1000e 0000:00:19.0: BAR 2: set to [io  0xefe0-0xefff] (PCI address [0xefe0-0xefff])
> >> [ 6260.556167] e1000e 0000:00:19.0: restoring config space at offset 0xf (was 0x100, writing 0x10a)
> >> [ 6260.556193] e1000e 0000:00:19.0: restoring config space at offset 0x1 (was 0x100000, writing 0x100107)
> >> [ 6260.556253] e1000e 0000:00:19.0: PME# disabled
> >> [ 6260.645141] e1000e 0000:00:19.0: irq 43 for MSI/MSI-X
> >> [ 6260.700393] e1000e 0000:00:19.0: irq 43 for MSI/MSI-X
> >> [ 6260.702222] ADDRCONF(NETDEV_UP): eth0: link is not ready
> It doesn't have link.  Without link nothing can happen on the wire.
> What are you expecting to happen here?
> 
> Have the device get link first.

What do you mean by "get link" ?
A network cable is plugged in the ethernet port, but it doesn't seem to be
detected in Linux 3.0 (while everything works fine in 2.6.32).

Also, it seems that link is detected when the laptop first boots, until a "MAC
Wakeup cause - Link Status Change" message:
[    1.189506] e1000e 0000:00:19.0: eth0: (PCI Express:2.5GT/s:Width x1) 00:24:e8:a7:2c:42
[    1.189579] e1000e 0000:00:19.0: eth0: Intel(R) PRO/1000 Network Connection
[    1.189664] e1000e 0000:00:19.0: eth0: MAC: 7, PHY: 8, PBA No: 3002FF-0FF
[   30.636723] ADDRCONF(NETDEV_UP): eth0: link is not ready
[   33.780901] e1000e: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: Rx/Tx
[   33.783944] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[...]
[ 6255.418398] e1000e 0000:00:19.0: eth0: MAC Wakeup cause - Link Status Change

Lucas

^ permalink raw reply

* malloc() and flushcache
From: liang peng @ 2011-09-15  5:27 UTC (permalink / raw)
  To: david.daney
  Cc: linux-mips, ralf, devicetree-discuss, grant.likely, linux-kernel,
	netdev

[-- Attachment #1: Type: text/plain, Size: 95 bytes --]

Hi, I want to know how to flushcache to the memory allocated by malloc()?
anybody help?
thanks

[-- Attachment #2: Type: text/html, Size: 115 bytes --]

^ permalink raw reply

* [net-next] MII: fix Kconfig dependencies for MII
From: Jeff Kirsher @ 2011-09-15  7:23 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, gospo

MII Kconfig option is apart of the core networking drivers and
by default NET_CORE is enabled so drivers selecting MII will
have MII enabled as well.  It was found using the randconfig
option during testing, MII would be selected but NET_CORE
could be disabled.  This caused a dependency error.

Resolved the dependency by selecting NET_CORE when MII is
selected.

Reported-by: Emil Tantilov <emil.s.tantilov@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
---
 arch/cris/arch-v10/drivers/Kconfig             |    1 +
 arch/cris/arch-v32/drivers/Kconfig             |    1 +
 drivers/net/ethernet/3com/Kconfig              |    1 +
 drivers/net/ethernet/Kconfig                   |    4 ++++
 drivers/net/ethernet/adaptec/Kconfig           |    1 +
 drivers/net/ethernet/adi/Kconfig               |    1 +
 drivers/net/ethernet/amd/Kconfig               |    2 ++
 drivers/net/ethernet/atheros/Kconfig           |    4 ++++
 drivers/net/ethernet/broadcom/Kconfig          |    2 ++
 drivers/net/ethernet/cadence/Kconfig           |    1 +
 drivers/net/ethernet/cirrus/Kconfig            |    1 +
 drivers/net/ethernet/davicom/Kconfig           |    1 +
 drivers/net/ethernet/dec/tulip/Kconfig         |    1 +
 drivers/net/ethernet/dlink/Kconfig             |    1 +
 drivers/net/ethernet/faraday/Kconfig           |    1 +
 drivers/net/ethernet/freescale/fs_enet/Kconfig |    1 +
 drivers/net/ethernet/icplus/Kconfig            |    1 +
 drivers/net/ethernet/intel/Kconfig             |    1 +
 drivers/net/ethernet/micrel/Kconfig            |    4 ++++
 drivers/net/ethernet/nuvoton/Kconfig           |    1 +
 drivers/net/ethernet/oki-semi/pch_gbe/Kconfig  |    1 +
 drivers/net/ethernet/packetengines/Kconfig     |    1 +
 drivers/net/ethernet/rdc/Kconfig               |    1 +
 drivers/net/ethernet/realtek/Kconfig           |    3 +++
 drivers/net/ethernet/renesas/Kconfig           |    1 +
 drivers/net/ethernet/sgi/Kconfig               |    1 +
 drivers/net/ethernet/sis/Kconfig               |    2 ++
 drivers/net/ethernet/smsc/Kconfig              |    5 +++++
 drivers/net/ethernet/stmicro/stmmac/Kconfig    |    1 +
 drivers/net/ethernet/via/Kconfig               |    2 ++
 drivers/net/usb/Kconfig                        |    3 +++
 31 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index 0d72217..32d9086 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -4,6 +4,7 @@ config ETRAX_ETHERNET
 	bool "Ethernet support"
 	depends on ETRAX_ARCH_V10
 	select NET_ETHERNET
+	select NET_CORE
 	select MII
 	help
 	  This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 41a2732..e47e9c3 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -4,6 +4,7 @@ config ETRAX_ETHERNET
 	bool "Ethernet support"
 	depends on ETRAX_ARCH_V32
 	select NET_ETHERNET
+	select NET_CORE
 	select MII
 	help
 	  This option enables the ETRAX FS built-in 10/100Mbit Ethernet
diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig
index a439cbd..a8bb30c 100644
--- a/drivers/net/ethernet/3com/Kconfig
+++ b/drivers/net/ethernet/3com/Kconfig
@@ -81,6 +81,7 @@ config PCMCIA_3C589
 config VORTEX
 	tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
 	depends on (PCI || EISA)
+	select NET_CORE
 	select MII
 	---help---
 	  This option enables driver support for a large number of 10Mbps and
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 1f64747..6dff5a0 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -62,6 +62,7 @@ config JME
 	tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports the PCI-Express gigabit ethernet adapters
@@ -102,6 +103,7 @@ config FEALNX
 	tristate "Myson MTD-8xx PCI Ethernet support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  Say Y here to support the Myson MTD-800 family of PCI-based Ethernet
@@ -112,6 +114,7 @@ source "drivers/net/ethernet/8390/Kconfig"
 
 config NET_NETX
 	tristate "NetX Ethernet support"
+	select NET_CORE
 	select MII
 	depends on ARCH_NETX
 	---help---
@@ -128,6 +131,7 @@ source "drivers/net/ethernet/oki-semi/Kconfig"
 config ETHOC
 	tristate "OpenCores 10/100 Mbps Ethernet MAC support"
 	depends on HAS_IOMEM && HAS_DMA
+	select NET_CORE
 	select MII
 	select PHYLIB
 	select CRC32
diff --git a/drivers/net/ethernet/adaptec/Kconfig b/drivers/net/ethernet/adaptec/Kconfig
index 5c804bb..0bff571 100644
--- a/drivers/net/ethernet/adaptec/Kconfig
+++ b/drivers/net/ethernet/adaptec/Kconfig
@@ -22,6 +22,7 @@ config ADAPTEC_STARFIRE
 	tristate "Adaptec Starfire/DuraLAN support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
index 6de9851..49a30d3 100644
--- a/drivers/net/ethernet/adi/Kconfig
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -23,6 +23,7 @@ config BFIN_MAC
 	tristate "Blackfin on-chip MAC support"
 	depends on (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
 	select CRC32
+	select NET_CORE
 	select MII
 	select PHYLIB
 	select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
index 8af1c93..238b537 100644
--- a/drivers/net/ethernet/amd/Kconfig
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -34,6 +34,7 @@ config AMD8111_ETH
 	tristate "AMD 8111 (new PCI LANCE) support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  If you have an AMD 8111-based PCI LANCE ethernet card,
@@ -59,6 +60,7 @@ config PCNET32
 	tristate "AMD PCnet32 PCI support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
index 26ab8ca..1ed886d 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -22,6 +22,7 @@ config ATL2
 	tristate "Atheros L2 Fast Ethernet support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports the Atheros L2 fast ethernet adapter.
@@ -33,6 +34,7 @@ config ATL1
 	tristate "Atheros/Attansic L1 Gigabit Ethernet support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports the Atheros/Attansic L1 gigabit ethernet
@@ -45,6 +47,7 @@ config ATL1E
 	tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
 	depends on PCI && EXPERIMENTAL
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports the Atheros L1E gigabit ethernet adapter.
@@ -56,6 +59,7 @@ config ATL1C
 	tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
 	depends on PCI && EXPERIMENTAL
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports the Atheros L1C gigabit ethernet adapter.
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index d82ad22..f15e72e 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -22,6 +22,7 @@ config B44
 	tristate "Broadcom 440x/47xx ethernet support"
 	depends on SSB_POSSIBLE && HAS_DMA
 	select SSB
+	select NET_CORE
 	select MII
 	---help---
 	  If you have a network (Ethernet) controller of this type, say Y
@@ -53,6 +54,7 @@ config B44_PCI
 config BCM63XX_ENET
 	tristate "Broadcom 63xx internal mac support"
 	depends on BCM63XX
+	select NET_CORE
 	select MII
 	select PHYLIB
 	help
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index c00e706..98849a1 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -25,6 +25,7 @@ if NET_ATMEL
 config ARM_AT91_ETHER
 	tristate "AT91RM9200 Ethernet support"
 	depends on ARM && ARCH_AT91RM9200
+	select NET_CORE
 	select MII
 	---help---
 	  If you wish to compile a kernel for the AT91RM9200 and enable
diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig
index e0cacf6..e9386ef 100644
--- a/drivers/net/ethernet/cirrus/Kconfig
+++ b/drivers/net/ethernet/cirrus/Kconfig
@@ -21,6 +21,7 @@ if NET_VENDOR_CIRRUS
 config EP93XX_ETH
 	tristate "EP93xx Ethernet support"
 	depends on ARM && ARCH_EP93XX
+	select NET_CORE
 	select MII
 	help
 	  This is a driver for the ethernet hardware included in EP93xx CPUs.
diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig
index 73c5d20..972b62b 100644
--- a/drivers/net/ethernet/davicom/Kconfig
+++ b/drivers/net/ethernet/davicom/Kconfig
@@ -6,6 +6,7 @@ config DM9000
 	tristate "DM9000 support"
 	depends on ARM || BLACKFIN || MIPS
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  Support for DM9000 chipset.
diff --git a/drivers/net/ethernet/dec/tulip/Kconfig b/drivers/net/ethernet/dec/tulip/Kconfig
index f6af772..1203be0 100644
--- a/drivers/net/ethernet/dec/tulip/Kconfig
+++ b/drivers/net/ethernet/dec/tulip/Kconfig
@@ -125,6 +125,7 @@ config WINBOND_840
 	tristate "Winbond W89c840 Ethernet support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver is for the Winbond W89c840 chip.  It also works with 
diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig
index 84a28a6..b5afe21 100644
--- a/drivers/net/ethernet/dlink/Kconfig
+++ b/drivers/net/ethernet/dlink/Kconfig
@@ -66,6 +66,7 @@ config SUNDANCE
 	tristate "Sundance Alta support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver is for the Sundance "Alta" chip.
diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig
index 5918c68..b8974b9 100644
--- a/drivers/net/ethernet/faraday/Kconfig
+++ b/drivers/net/ethernet/faraday/Kconfig
@@ -21,6 +21,7 @@ if NET_VENDOR_FARADAY
 config FTMAC100
 	tristate "Faraday FTMAC100 10/100 Ethernet support"
 	depends on ARM
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports the FTMAC100 10/100 Ethernet controller
diff --git a/drivers/net/ethernet/freescale/fs_enet/Kconfig b/drivers/net/ethernet/freescale/fs_enet/Kconfig
index be92229..268414d 100644
--- a/drivers/net/ethernet/freescale/fs_enet/Kconfig
+++ b/drivers/net/ethernet/freescale/fs_enet/Kconfig
@@ -1,6 +1,7 @@
 config FS_ENET
        tristate "Freescale Ethernet Driver"
        depends on NET_VENDOR_FREESCALE && (CPM1 || CPM2 || PPC_MPC512x)
+       select NET_CORE
        select MII
        select PHYLIB
 
diff --git a/drivers/net/ethernet/icplus/Kconfig b/drivers/net/ethernet/icplus/Kconfig
index e888222..3aff81d 100644
--- a/drivers/net/ethernet/icplus/Kconfig
+++ b/drivers/net/ethernet/icplus/Kconfig
@@ -5,6 +5,7 @@
 config IP1000
 	tristate "IP1000 Gigabit Ethernet support"
 	depends on PCI && EXPERIMENTAL
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports IP1000 gigabit Ethernet cards.
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 4a98e83..61029dc 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -21,6 +21,7 @@ if NET_VENDOR_INTEL
 config E100
 	tristate "Intel(R) PRO/100+ support"
 	depends on PCI
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports Intel(R) PRO/100 family of adapters.
diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
index bd090db..d10c2e1 100644
--- a/drivers/net/ethernet/micrel/Kconfig
+++ b/drivers/net/ethernet/micrel/Kconfig
@@ -22,6 +22,7 @@ if NET_VENDOR_MICREL
 config ARM_KS8695_ETHER
 	tristate "KS8695 Ethernet support"
 	depends on ARM && ARCH_KS8695
+	select NET_CORE
 	select MII
 	---help---
 	  If you wish to compile a kernel for the KS8695 and want to
@@ -38,6 +39,7 @@ config KS8842
 config KS8851
 	tristate "Micrel KS8851 SPI"
 	depends on SPI
+	select NET_CORE
 	select MII
 	select CRC32
 	---help---
@@ -46,6 +48,7 @@ config KS8851
 config KS8851_MLL
 	tristate "Micrel KS8851 MLL"
 	depends on HAS_IOMEM
+	select NET_CORE
 	select MII
 	---help---
 	  This platform driver is for Micrel KS8851 Address/data bus
@@ -54,6 +57,7 @@ config KS8851_MLL
 config KSZ884X_PCI
 	tristate "Micrel KSZ8841/2 PCI"
 	depends on PCI
+	select NET_CORE
 	select MII
 	select CRC32
 	---help---
diff --git a/drivers/net/ethernet/nuvoton/Kconfig b/drivers/net/ethernet/nuvoton/Kconfig
index 01182b5..334c171 100644
--- a/drivers/net/ethernet/nuvoton/Kconfig
+++ b/drivers/net/ethernet/nuvoton/Kconfig
@@ -22,6 +22,7 @@ config W90P910_ETH
 	tristate "Nuvoton w90p910 Ethernet support"
 	depends on ARM && ARCH_W90X900
 	select PHYLIB
+	select NET_CORE
 	select MII
 	---help---
 	  Say Y here if you want to use built-in Ethernet ports
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
index c85709d..7efa624 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -5,6 +5,7 @@
 config PCH_GBE
 	tristate "OKI SEMICONDUCTOR ML7223 IOH GbE (Intel EG20T PCH)"
 	depends on PCI
+	select NET_CORE
 	select MII
 	---help---
 	  This is a gigabit ethernet driver for EG20T PCH.
diff --git a/drivers/net/ethernet/packetengines/Kconfig b/drivers/net/ethernet/packetengines/Kconfig
index 4add1db..b97132d 100644
--- a/drivers/net/ethernet/packetengines/Kconfig
+++ b/drivers/net/ethernet/packetengines/Kconfig
@@ -20,6 +20,7 @@ if NET_PACKET_ENGINE
 config HAMACHI
 	tristate "Packet Engines Hamachi GNIC-II support"
 	depends on PCI
+	select NET_CORE
 	select MII
 	---help---
 	  If you have a Gigabit Ethernet card of this type, say Y and read
diff --git a/drivers/net/ethernet/rdc/Kconfig b/drivers/net/ethernet/rdc/Kconfig
index 2055f7e..c8ba4b3 100644
--- a/drivers/net/ethernet/rdc/Kconfig
+++ b/drivers/net/ethernet/rdc/Kconfig
@@ -22,6 +22,7 @@ config R6040
 	tristate "RDC R6040 Fast Ethernet Adapter support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	select PHYLIB
 	---help---
diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig
index d8df67a..84083ec 100644
--- a/drivers/net/ethernet/realtek/Kconfig
+++ b/drivers/net/ethernet/realtek/Kconfig
@@ -37,6 +37,7 @@ config 8139CP
 	tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
 	depends on PCI && EXPERIMENTAL
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This is a driver for the Fast Ethernet PCI network cards based on
@@ -51,6 +52,7 @@ config 8139TOO
 	tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This is a driver for the Fast Ethernet PCI network cards based on
@@ -105,6 +107,7 @@ config R8169
 	depends on PCI
 	select FW_LOADER
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
index f57ae23..9755b49 100644
--- a/drivers/net/ethernet/renesas/Kconfig
+++ b/drivers/net/ethernet/renesas/Kconfig
@@ -9,6 +9,7 @@ config SH_ETH
 		 CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
 		 CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757)
 	select CRC32
+	select NET_CORE
 	select MII
 	select MDIO_BITBANG
 	select PHYLIB
diff --git a/drivers/net/ethernet/sgi/Kconfig b/drivers/net/ethernet/sgi/Kconfig
index e832f46..c1c4bb8 100644
--- a/drivers/net/ethernet/sgi/Kconfig
+++ b/drivers/net/ethernet/sgi/Kconfig
@@ -22,6 +22,7 @@ config SGI_IOC3_ETH
 	bool "SGI IOC3 Ethernet"
 	depends on PCI && SGI_IP27
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
diff --git a/drivers/net/ethernet/sis/Kconfig b/drivers/net/ethernet/sis/Kconfig
index 68d052b..f1135cc 100644
--- a/drivers/net/ethernet/sis/Kconfig
+++ b/drivers/net/ethernet/sis/Kconfig
@@ -22,6 +22,7 @@ config SIS900
 	tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This is a driver for the Fast Ethernet PCI network cards based on
@@ -38,6 +39,7 @@ config SIS190
 	tristate "SiS190/SiS191 gigabit ethernet support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig
index f961928..1854c88 100644
--- a/drivers/net/ethernet/smsc/Kconfig
+++ b/drivers/net/ethernet/smsc/Kconfig
@@ -37,6 +37,7 @@ config SMC9194
 config SMC91X
 	tristate "SMC 91C9x/91C1xxx support"
 	select CRC32
+	select NET_CORE
 	select MII
 	depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \
 		    MN10300 || COLDFIRE)
@@ -56,6 +57,7 @@ config PCMCIA_SMC91C92
 	tristate "SMC 91Cxx PCMCIA support"
 	depends on PCMCIA
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA
@@ -68,6 +70,7 @@ config EPIC100
 	tristate "SMC EtherPower II"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
@@ -78,6 +81,7 @@ config EPIC100
 config SMC911X
 	tristate "SMSC LAN911[5678] support"
 	select CRC32
+	select NET_CORE
 	select MII
 	depends on (ARM || SUPERH || MN10300)
 	---help---
@@ -95,6 +99,7 @@ config SMSC911X
 	tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
 	depends on (ARM || SUPERH || BLACKFIN || MIPS || MN10300)
 	select CRC32
+	select NET_CORE
 	select MII
 	select PHYLIB
 	---help---
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index cda61e3..2346ba0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -1,6 +1,7 @@
 config STMMAC_ETH
 	tristate "STMicroelectronics 10/100/1000 Ethernet driver"
 	depends on HAS_IOMEM
+	select NET_CORE
 	select MII
 	select PHYLIB
 	select CRC32
diff --git a/drivers/net/ethernet/via/Kconfig b/drivers/net/ethernet/via/Kconfig
index e5d82a5..68a9ba6 100644
--- a/drivers/net/ethernet/via/Kconfig
+++ b/drivers/net/ethernet/via/Kconfig
@@ -22,6 +22,7 @@ config VIA_RHINE
 	tristate "VIA Rhine support"
 	depends on PCI
 	select CRC32
+	select NET_CORE
 	select MII
 	---help---
 	  If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A),
@@ -47,6 +48,7 @@ config VIA_VELOCITY
 	depends on PCI
 	select CRC32
 	select CRC_CCITT
+	select NET_CORE
 	select MII
 	---help---
 	  If you have a VIA "Velocity" based network card say Y here.
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 84d4608..2335761 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -68,6 +68,7 @@ config USB_KAWETH
 
 config USB_PEGASUS
 	tristate "USB Pegasus/Pegasus-II based ethernet device support"
+	select NET_CORE
 	select MII
 	---help---
 	  Say Y here if you know you have Pegasus or Pegasus-II based adapter.
@@ -84,6 +85,7 @@ config USB_PEGASUS
 config USB_RTL8150
 	tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	select NET_CORE
 	select MII
 	help
 	  Say Y here if you have RTL8150 based usb-ethernet adapter.
@@ -95,6 +97,7 @@ config USB_RTL8150
 
 config USB_USBNET
 	tristate "Multi-purpose USB Networking Framework"
+	select NET_CORE
 	select MII
 	---help---
 	  This driver supports several kinds of network links over USB,
-- 
1.7.6

^ permalink raw reply related

* Re: r8169 hard-freezes the system on big network loads
From: Michael Brade @ 2011-09-15 10:26 UTC (permalink / raw)
  To: Francois Romieu; +Cc: netdev, nic_swsd, Hayes
In-Reply-To: <20110915000332.GA13821@electric-eye.fr.zoreil.com>

On Thursday 15 September 2011 02:03:32 Francois Romieu wrote:
> Michael Brade <brade@informatik.uni-muenchen.de> :
> [...]
>
> > ok, good news: I did not experience any freeze anymore even though I
> > transfered 60 GB. And I applied both of your patches and
> >
> > -                   if (status & RxFOVF) {
> > -                           rtl8169_schedule_work(dev,
> > rtl8169_reset_task); -                          
> > dev->stats.rx_fifo_errors++;
> > -                   }
>
> It should not be necessary to remove this part : the status mask is
> supposed to take care of it. One of my patches is wrong if this part
> needs to go away.

ok, I only removed it because you told me so the first time.

> [...]
>
> > so yes but what do you mean with "no real network traffic"? I still get
> > 100 MB/s.
>
> 100 MB/s as 100 Mbyte/s on a gigabit link or 100 Mbit/s on a {gigabit /
> fast} ethernet link ?

100 Mbytes on a gigabit link, so almost 100% usage (with ups and downs, of course; maybe 
between 90 MB/s and 112 MB/s).

thanks,
  Michael

^ permalink raw reply

* Soft vs. hard MTU / 802.3as
From: David Lamparter @ 2011-09-15 10:29 UTC (permalink / raw)
  To: netdev

Hi,


I've been looking at implementing 802.1ad S-VLANs (I posted a patch but
lacked resources to work on it after my laptop died) and I'm running
into problems with the way the MTU is treated currently.

Basically, the code has no way to ascertain hardware maximum frame size
limits for stacked VLAN tags. (Which becomes even more important for
802.1ah, having 18 bytes of extra header...)

So, unless I'm overlooking something here, I'd suggest introducing two
new fields into struct net_device:

	unsigned int hard_mtu;
	unsigned short(?) extra_vlans;

The first one would be the hardware frame size limit on TX/RX. (These
shouldn't differ, if they do it needs to be the minimum).

The second one is a bit non-intuitive (maybe I'm over-thinking this?)
I'm expecting devices that support "1518 bytes plus 1 vlan tag". Those
devices cannot tx/rx 1522 byte frames, but if it is 1518 bytes plus a
1Q tag that's ok. So, basically, this field would be 0 for devices
that have a vlan-agnostic size limit, and 1 for silicon that has
"speshul" vlans. (VLAN accel is independent of this!)

So, if you add a 802.1Q vlan device, it works like this:
	self->hard_mtu = parent->hard_mtu;
	self->extra_vlans = parent->extra_vlans;
	if (parent->extra_vlans)
		self->extra_vlans--;
	else
		self->hard_mtu -= 4;
802.1ad/ah devices would be simpler:
	self->hard_mtu = parent->hard_mtu - 4;
	self->extra_vlans = 0;
(for 802.1ah the value is 16+6 bytes instead of 4)

Introducing these fields might also allow us to clean up MTU checks in
general; the device could be mostly agnostic of whatever is set above it
(though maybe we want to propagate the value for dropping oversized
frames early?).

The mtu field cannot be used for all of those things since layer 2 and
layer 3 MTU need to be distinguished. 802.3as calls for a 2000 byte MTU
but rather clearly says that only 1500 of it is for the higher level
protocol to use. The mtu knob needs to control IP's and IPv6's packet
sizes independently of what's transmitted by some vlan stack.

Comments?
(will come up with some code if i don't get overwhelming negative)


-David


P.S.: quick IEEE number cheat-sheet:
 802.1Q - regular VLANs, protocol 0x8100, 4 byte total overhead
 802.1ad - S(ervice)-VLANs, protocol 0x88a8, 4 byte total ovh.
 802.1ah - MAC-in-MAC, protocol 0x88e7, 18 byte ovh.
 802.3ac - frame size update for 802.3 to 1522 for one .1Q tag
 802.3as - frame size update for 802.3 to 2000 for random stuff

^ permalink raw reply

* Re: [net-next-2.6 PATCH 0/3 RFC] macvlan: MAC Address filtering support for passthru mode
From: Roopa Prabhu @ 2011-09-15 13:46 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Sridhar Samudrala, netdev, dragos.tatulea, arnd, dwang2, benve,
	kaber, davem, eric.dumazet, mchan, kvm
In-Reply-To: <CA93894D.33EF8%roprabhu@cisco.com>



The netlink patch is still in the works. I will post the patches after I
clean it up a bit and also accommodate or find answers to most questions
discussed for non-passthru case. Thought I will post the netlink interface
here to see if anyone has any early comments. I have a
rtnl_link_ops->set_rx_filter defined.

[IFLA_RX_FILTER] = {
    [IFLA_ADDRESS_FILTER] = {
        [IFLA_ADDRESS_FILTER_FLAGS]
        [IFLA_ADDRESS_LIST] = {
            [IFLA_ADDRESS_LIST_ENTRY]
        }
    }    
    [IFLA_VLAN_FILTER] = {
        [IFLA_VLAN_LIST] = {
            [IFLA_VLAN]
        }
    }
}

Some open questions:
    - The VLAN filter above shows a VLAN list. It could also be a bitmap or
the interface could provide both a bitmap and VLAN list for more flexibility
. Like the below  

[IFLA_RX_FILTER] = {
    [IFLA_ADDRESS_FILTER] = {
        [IFLA_ADDRESS_FILTER_FLAGS]
        [IFLA_ADDRESS_LIST] = {
            [IFLA_ADDRESS_LIST_ENTRY]
        }
    }    
    [IFLA_VLAN_FILTER] = {
        [IFLA_VLAN_BITMAP]
        [IFLA_VLAN_LIST] = {
            [IFLA_VLAN]
        }
    }
}

    - Do you see any advantage in keeping Unicast and multicast address list
separate ? Something like the below :
    [IFLA_RX_FILTER] = {
        [IFLA_ADDRESS_FILTER_FLAGS]
        [IFLA_UC_ADDRESS_FILTER] = {
            [IFLA_ADDRESS_LIST] = {
                [IFLA_ADDRESS_LIST_ENTRY]
            }
        }
        [IFLA_MC_ADDRESS_FILTER] = {
            [IFLA_ADDRESS_LIST] = {
                [IFLA_ADDRESS_LIST_ENTRY]
            }
        }
        [IFLA_VLAN_FILTER] = {
            [IFLA_VLAN_LIST] = {
                [IFLA_VLAN]
            }
        }
    } 

    - Is there any need to keep address and vlan filters separate. And have
two rtnl_link_ops, set_rx_address_filter, set_rx_vlan_filter ?. I don't see
one .

    [IFLA_RX_ADDRESS_FILTER] = {
        [IFLA_ADDRESS_FILTER_FLAGS]
        [IFLA_ADDRESS_LIST] = {
            [IFLA_ADDRESS_LIST_ENTRY]
        }
    }
    [IFLA_RX_VLAN_FILTER] = {
        [IFLA_VLAN_LIST] = {
            [IFLA_VLAN]
        }
    } 


Thanks,
Roopa



On 9/12/11 10:02 AM, "Roopa Prabhu" <roprabhu@cisco.com> wrote:

> 
> 
> 
> On 9/11/11 12:03 PM, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
>> On Sun, Sep 11, 2011 at 06:18:01AM -0700, Roopa Prabhu wrote:
>>> 
>>> 
>>> 
>>> On 9/11/11 2:44 AM, "Michael S. Tsirkin" <mst@redhat.com> wrote:
>>> 
>>>> 
>>>> Yes, but what I mean is, if the size of the single filter table
>>>> is limited, we need to decide how many addresses is
>>>> each guest allowed. If we let one guest ask for
>>>> as many as it wants, it can lock others out.
>>> 
>>> Yes true. In these cases ie when the number of unicast addresses being
>>> registered is more than it can handle, The VF driver will put the VF  in
>>> promiscuous mode (Or at least its supposed to do. I think all drivers do
>>> that).
>>> 
>>> 
>>> Thanks,
>>> Roopa
>> 
>> Right, so that works at least but likely performs worse
>> than a hardware filter. So we better allocate it in
>> some fair way, as a minimum. Maybe a way for
>> the admin to control that allocation is useful.
> 
> Yes I think we will have to do something like that. There is a maximum that hw
> can support. Might need to consider that too. But there is no interface to get
> that today. I think the virtualization case gets a little trickier. Virtio-net
> allows upto 64 unicast addresses. But the lowerdev may allow only upto say 10
> unicast addresses (I think intel supports 10 unicast addresses on the VF). Am
> not sure if there is a good way to notify the guest of blocked addresses.
> Maybe putting the lower dev in promiscuous mode could be a policy decision too
> in this case. 
> 
> One other thing, I had indicated that I will look up details on opening my
> patch for non-passthru to enable hw filtering (without adding filtering
> support in macvlan right away. Ie phase1). Turns out in current code in
> macvlan_handle_frame, for non-passthru case, it does not fwd unicast pkts
> destined to macs other than the ones in macvlan hash. So a filter or hash
> lookup there for additional unicast addresses needs to be definitely added for
> non-passthru.
> 
> Thanks,
> Roopa
> 
> 
>  


^ permalink raw reply

* Re: sendmmsg(2) draft man pages
From: Stephan Mueller @ 2011-09-15 15:04 UTC (permalink / raw)
  To: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
  Cc: Anton Blanchard, linux-man, Andi Kleen, netdev, Linux API,
	Michael Kerrisk
In-Reply-To: <CAKgNAkhQu7LdGDh5=CMpTwsnmS03QRqojBpwSpAcFO55WdYWqw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 15.09.2011 06:16:22, +0200, Michael Kerrisk <mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:

Hi Michael,

> Hello Anton,
> 
> Stephan Mueller made an initial shot at a manual page for the
> sendmmsg() syscall that you recently added to the kernel. This
> inspired me to come up with a more complete version, which I'd like to
> get reviewed before including in man-pages. Could you take a look
> ("man -l <file>") at the version below and let me know any errors or
> omissions.

Thank you very much for the update. I have no comments.

Thanks
Stephan
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* URGENT
From: HARRIS ROBIN ESQ @ 2011-09-15 15:08 UTC (permalink / raw)


This is to notify you once again as my previous letter were returned undelivered that late Theo Albrecht made you a beneficiary to his WILL. He left the sum of Thirty Million, One Hundred Thousand Dollars (USD$30,100.000.00) to you in the Codicil and last testament to his WILL.
Please if I reach you as I am hopeful, endeavor to get back to me as soon as possible to enable me conclude my job.
You are advice to contact me with my below Email: harrisrobinschamber@live.co.uk
I await your prompt response.
 
Yours in Service,
BARRISTER HARRIS ROBIN ESQ

^ permalink raw reply

* Re: [PATCH net-next-2.6] e1000: don't enable dma receives until after dma address has been setup
From: Jesse Brandeburg @ 2011-09-15 17:21 UTC (permalink / raw)
  To: Dean Nelson
  Cc: Michael S. Tsirkin, e1000-devel, netdev@vger.kernel.org,
	jesse.brandeburg, Andy Gospodarek
In-Reply-To: <20110915003138.4279.19020.email-sent-by-dnelson@localhost6.localdomain6>

On Wed, 14 Sep 2011 17:31:38 -0700
Dean Nelson <dnelson@redhat.com> wrote:

> Doing an 'ifconfig ethN down' followed by an 'ifconfig ethN up' on a
> qemu-kvm guest system configured with two e1000 NICs can result in an
> 'unable to handle kernel paging request at 0000000100000000' or 'bad
> page map in process ...' or something similar.

<snip>

> The corruption appears to result from the following...
> 
>  . An 'ifconfig ethN down' gets us into e1000_close(), which through
> a number of subfunctions results in:
>      1. E1000_RCTL_EN being cleared in RCTL register.  [e1000_down()]
>      2. dma_free_coherent() being called.  [e1000_free_rx_resources()]
> 
>  . An 'ifconfig ethN up' gets us into e1000_open(), which through a
> number of subfunctions results in:
>      1. dma_alloc_coherent() being called.
> [e1000_setup_rx_resources()] 2. E1000_RCTL_EN being set in RCTL
> register.  [e1000_setup_rctl()] 3. E1000_RCTL_EN being cleared in
> RCTL register.  [e1000_configure_rx()] 4. RDLEN, RDBAH and RDBAL
> registers being set to reflect the dma page allocated in step 1.
> [e1000_configure_rx()] 5. E1000_RCTL_EN being set in RCTL register.
> [e1000_configure_rx()]
> 
> During the 'ifconfig ethN up' there is a window opened, starting in
> step 2 where the receives are enabled up until they are disabled in
> step 3, in which the address of the receive descriptor dma page known
> by the NIC is still the previous one which was freed during the
> 'ifconfig ethN down'. If this memory has been reallocated for some
> other use and the NIC feels so inclined, it will write to that former
> dma page with predictably unpleasant results.
> 
> I realize that in the guest, we're dealing with an e1000 NIC that is
> software emulated by qemu-kvm. The problem doesn't appear to occur on
> bare-metal. Andy suspects that this is because in the emulator
> link-up is essentially instant and traffic can start flowing
> immediately. Whereas on bare-metal, link-up usually seems to take at
> least a few milliseconds. And this might be enough to prevent traffic
> from flowing into the device inside the window where E1000_RCTL_EN is
> set.

nice analysis dean, yes, we shouldn't enable rx before we have the
hardware all ready.

You didn't mention however that the hardware is reset in e1000_down,
which will clear the RDBAL/RDBAH in real hardware.

> 
> So perhaps a modification needs to be made to the qemu-kvm e1000 NIC
> emulator to delay the link-up. But in defense of the emulator, it
> seems like a bad idea to enable dma operations before the address of
> the memory to be involved has been made known.

the hardware reset code in kvm should also reset to default many
registers (almost all of them in fact) which may also end up solving
the problem.

> 
> The following patch no longer enables receives in e1000_setup_rctl()
> but leaves them however they were. It only enables receives in
> e1000_configure_rx(), and only after the dma address has been made
> known to the hardware.

I still like your patch better as it is more correct.  We could also
correct the kvm virtual hardware driver.

> There are two places where e1000_setup_rctl() gets called. The one in
> e1000_configure() is followed immediately by a call to
> e1000_configure_rx(), so there's really no change functionally
> (except for the removal of the problem window. The other is in
> __e1000_shutdown() and is not followed by a call to
> e1000_configure_rx(), so there is a change functionally. But
> consider...
> 
>  . An 'ifconfig ethN down' (just as described above).
> 
>  . A 'suspend' of the system, which (I'm assuming) will find its way
> into e1000_suspend() which calls __e1000_shutdown() resulting in:
>      1. E1000_RCTL_EN being set in RCTL register.
> [e1000_setup_rctl()]
> 
> And again we've re-opened the problem window for some unknown amount
> of time.
> 
> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
> Signed-off-by: Dean Nelson <dnelson@redhat.com>
> 
> ---
> The patch below is Andy's version of a patch I came up with to
> address this problem. I liked his version better. Functionally there
> was no difference between the two.
> 
> Running my version of the patch, the reproducer (see script below)
> ran for 5 days without issue before I stopped it. Without the patch,
> former dma pages were corrupted in a very short timeframe and fairly
> frequently (relatively speaking). Note that I'm also running with a
> debug patch that after step 5 has completed (mentioned above under an
> 'ifconfig ethN up'...), the previous dma page is scanned to see if it
> had been 'corrupted'. So I found a higher percentage of occurrences
> then one would find if one waits for a kernel BUG.
> 
> The reproducer for this problem is:
> cat > reproducer.sh <<EOF
> #!/bin/bash
> typeset -i i=0
> echo eth1:down
> ifconfig eth1 down
> sleep 2
> while :; do
>   i=$i+1
>   ifconfig eth0 down& ifconfig eth1 up&
>   echo "$i | eth0:down eth1:up"
>   wait
>   sleep 2
>   ifconfig eth0 up& ifconfig eth1 down&
>   echo "$i | eth0:up eth1:down"
>   wait
>   sleep 2
> done
> EOF
> 
> The e1000e looks to have the same issue. I don't know about igb. But
> I'm not aware of either having hardware emulation in qemu-kvm. So
> unless this issue is reproducible on bare-metal... it's probably not
> a big deal for them.
> 
>  drivers/net/ethernet/intel/e1000/e1000_main.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c
> b/drivers/net/ethernet/intel/e1000/e1000_main.c index
> 4a32c15..cd26a0a 100644 ---
> a/drivers/net/ethernet/intel/e1000/e1000_main.c +++
> b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -1814,8 +1814,8 @@
> static void e1000_setup_rctl(struct e1000_adapter *adapter) 
>  	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
>  
> -	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
> -		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
> +	rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
> +		E1000_RCTL_RDMTS_HALF |
>  		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
>  
>  	if (hw->tbi_compatibility_on == 1)
> @@ -1917,7 +1917,7 @@ static void e1000_configure_rx(struct
> e1000_adapter *adapter) }
>  
>  	/* Enable Receives */
> -	ew32(RCTL, rctl);
> +	ew32(RCTL, rctl | E1000_RCTL_EN);
>  }
>  
>  /**


generally i like the patch.  We should take it in and test it, and I
don't really see any problems with it.

------------------------------------------------------------------------------
Doing More with Less: The Next Generation Virtual Desktop 
What are the key obstacles that have prevented many mid-market businesses
from deploying virtual desktops?   How do next-generation virtual desktops
provide companies an easier-to-deploy, easier-to-manage and more affordable
virtual desktop model.http://www.accelacomm.com/jaw/sfnl/114/51426474/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* Re: [PATCH net-next-2.6] e1000: don't enable dma receives until after dma address has been setup
From: Dean Nelson @ 2011-09-15 18:22 UTC (permalink / raw)
  To: Jesse Brandeburg
  Cc: netdev@vger.kernel.org, Michael S. Tsirkin, Andy Gospodarek,
	Kirsher, Jeffrey T, tushar.n.dave, e1000-devel
In-Reply-To: <20110915102112.0000146b@unknown>

On 09/15/2011 12:21 PM, Jesse Brandeburg wrote:
> On Wed, 14 Sep 2011 17:31:38 -0700
> Dean Nelson<dnelson@redhat.com>  wrote:
>
>> Doing an 'ifconfig ethN down' followed by an 'ifconfig ethN up' on a
>> qemu-kvm guest system configured with two e1000 NICs can result in an
>> 'unable to handle kernel paging request at 0000000100000000' or 'bad
>> page map in process ...' or something similar.
>
> <snip>
>
>> The corruption appears to result from the following...
>>
<snip>
>>
>> I realize that in the guest, we're dealing with an e1000 NIC that is
>> software emulated by qemu-kvm. The problem doesn't appear to occur on
>> bare-metal. Andy suspects that this is because in the emulator
>> link-up is essentially instant and traffic can start flowing
>> immediately. Whereas on bare-metal, link-up usually seems to take at
>> least a few milliseconds. And this might be enough to prevent traffic
>> from flowing into the device inside the window where E1000_RCTL_EN is
>> set.
>
> nice analysis dean, yes, we shouldn't enable rx before we have the
> hardware all ready.

Thank you.


> You didn't mention however that the hardware is reset in e1000_down,
> which will clear the RDBAL/RDBAH in real hardware.

You are correct, I did fail to mention the reset. And the clearing of
RDBAL/RDHAH was definitely not happening in the qemu-kvm emulator.


>> So perhaps a modification needs to be made to the qemu-kvm e1000 NIC
>> emulator to delay the link-up. But in defense of the emulator, it
>> seems like a bad idea to enable dma operations before the address of
>> the memory to be involved has been made known.
>
> the hardware reset code in kvm should also reset to default many
> registers (almost all of them in fact) which may also end up solving
> the problem.

Agreed.


>> The following patch no longer enables receives in e1000_setup_rctl()
>> but leaves them however they were. It only enables receives in
>> e1000_configure_rx(), and only after the dma address has been made
>> known to the hardware.
>
> I still like your patch better as it is more correct.  We could also
> correct the kvm virtual hardware driver.

The hardware emulator should definitely be doing a proper hardware reset.


>> There are two places where e1000_setup_rctl() gets called. The one in
<snip>
>>
>> The e1000e looks to have the same issue. I don't know about igb. But
>> I'm not aware of either having hardware emulation in qemu-kvm. So
>> unless this issue is reproducible on bare-metal... it's probably not
>> a big deal for them.
>>
<snip>
>
> generally i like the patch.  We should take it in and test it, and I
> don't really see any problems with it.

Thanks.

As mentioned above, the e1000e has a similar algorithm, but the
FLAG2_NO_DISABLE_RX complicates it a bit. I have no idea what happens
if receives are enabled while setting RDBAL and RDBAH. Is there any
possibility that the hardware could try to make use of a half-baked
address?

Thanks much for your review of the patch.

Dean

^ permalink raw reply

* net GIT trees on github
From: David Miller @ 2011-09-15 19:05 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA


I finally broke down and started putting some trees up on github.

The plain 'net' tree is up already:

	git://github.com/davem330/net.git

And a "net-next.git" will be there shortly.

This is a temporary situation so that I can push out the backlog
a little bit until kernel.org is fully back in service.  Once
kernel.org is back I will stop updating these trees.

Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] cls_rsvp.h was outdated
From: David Miller @ 2011-09-15 19:06 UTC (permalink / raw)
  To: igorm; +Cc: netdev, linux-kernel
In-Reply-To: <59e0c7c0ba5282f35b101e7058fb27fa.squirrel@kondor.etf.bg.ac.rs>

From: "Igor Maravić" <igorm@etf.rs>
Date: Tue, 30 Aug 2011 15:12:55 +0200

> File cls_rsvp.h in /net/sched was outdated. I'm sending you patch for this
> file.
> 
> Signed-off-by: Igor Maravić <igorm@etf.rs>

Patch applied, thanks.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox