Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 8/8] net: Implement socketat.
From: Pavel Emelyanov @ 2010-09-23 11:53 UTC (permalink / raw)
  To: hadi
  Cc: Eric W. Biederman, linux-kernel, Linux Containers, netdev,
	netfilter-devel, linux-fsdevel, Daniel Lezcano, Linus Torvalds,
	Michael Kerrisk, Ulrich Drepper, Al Viro, David Miller,
	Serge E. Hallyn, Pavel Emelyanov, Ben Greear, Matt Helsley,
	Jonathan Corbet, Sukadev Bhattiprolu, Jan Engelhardt,
	Patrick McHardy
In-Reply-To: <1285242055.5036.9.camel@bigi>

On 09/23/2010 03:40 PM, jamal wrote:
> On Thu, 2010-09-23 at 15:33 +0400, Pavel Emelyanov wrote:
> 
>> This particular usecase is unneeded once you have the "enter" ability.
> 
> Is that cheaper from a syscall count/cost?

Why does it matter? You told, that the usage scenario was to
add routes to container. If I do 2 syscalls instead of 1, is
it THAT worse?

> i.e do I have to enter every time i want to write/read this fd?

No - you enter once, create a socket and do whatever you need
withing the enterned namespace.

> How does poll/select work in that enter scenario?

Just like it used to before the enter.

> cheers,
> jamal
> 
> 


^ permalink raw reply

* [PATCH] br2684: fix scheduling while atomic
From: Karl Hiramoto @ 2010-09-23 11:50 UTC (permalink / raw)
  To: netdev, mmvinni; +Cc: davem, chas, Karl Hiramoto
In-Reply-To: <20100922144329.0cb3cf86@thirdoffive.cmf.nrl.navy.mil>

You can't call atomic_notifier_chain_unregister() while in atomic context.

Fix, call un/register_atmdevice_notifier in module __init and __exit.

Bug report:
http://comments.gmane.org/gmane.linux.network/172603

Signed-off-by: Karl Hiramoto <karl@hiramoto.org>
---
 net/atm/br2684.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 651babd..ad2b232 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -399,12 +399,6 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
 			unregister_netdev(net_dev);
 			free_netdev(net_dev);
 		}
-		read_lock_irq(&devs_lock);
-		if (list_empty(&br2684_devs)) {
-			/* last br2684 device */
-			unregister_atmdevice_notifier(&atm_dev_notifier);
-		}
-		read_unlock_irq(&devs_lock);
 		return;
 	}
 
@@ -675,7 +669,6 @@ static int br2684_create(void __user *arg)
 
 	if (list_empty(&br2684_devs)) {
 		/* 1st br2684 device */
-		register_atmdevice_notifier(&atm_dev_notifier);
 		brdev->number = 1;
 	} else
 		brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
@@ -815,6 +808,7 @@ static int __init br2684_init(void)
 		return -ENOMEM;
 #endif
 	register_atm_ioctl(&br2684_ioctl_ops);
+	register_atmdevice_notifier(&atm_dev_notifier);
 	return 0;
 }
 
@@ -830,9 +824,7 @@ static void __exit br2684_exit(void)
 #endif
 
 
-	/* if not already empty */
-	if (!list_empty(&br2684_devs))
-		unregister_atmdevice_notifier(&atm_dev_notifier);
+	unregister_atmdevice_notifier(&atm_dev_notifier);
 
 	while (!list_empty(&br2684_devs)) {
 		net_dev = list_entry_brdev(br2684_devs.next);
-- 
1.7.2.2


^ permalink raw reply related

* Re: [PATCH v4 2/2] Bluetooth: hidp: Add support for hidraw HIDIOCGFEATURE  and HIDIOCSFEATURE
From: Ville Tervo @ 2010-09-23 11:51 UTC (permalink / raw)
  To: ext Alan Ott
  Cc: Jiri Kosina, Stefan Achatz, Antonio Ospite, Alexey Dobriyan,
	Tejun Heo, Alan Stern, Greg Kroah-Hartman, Marcel Holtmann,
	Stephane Chatty, Michael Poole, David S. Miller, Bastien Nocera,
	Eric Dumazet, linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-bluetooth-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1281990059-3562-3-git-send-email-alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>

Hi Alan,

One comment.

On Mon, Aug 16, 2010 at 10:20:59PM +0200, ext Alan Ott wrote:
> This patch adds support or getting and setting feature reports for bluetooth
> HID devices from HIDRAW.
> 
> Signed-off-by: Alan Ott <alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
> ---
>  net/bluetooth/hidp/core.c |  114 +++++++++++++++++++++++++++++++++++++++++++--
>  net/bluetooth/hidp/hidp.h |    8 +++
>  2 files changed, 118 insertions(+), 4 deletions(-)
> 
> diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> index bfe641b..0e4880e 100644
> --- a/net/bluetooth/hidp/core.c
> +++ b/net/bluetooth/hidp/core.c
> @@ -36,6 +36,7 @@
>  #include <linux/file.h>
>  #include <linux/init.h>
>  #include <linux/wait.h>
> +#include <linux/mutex.h>
>  #include <net/sock.h>
>  
>  #include <linux/input.h>
> @@ -313,6 +314,86 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
>  	return hidp_queue_report(session, buf, rsize);
>  }
>  
> +static int hidp_get_raw_report(struct hid_device *hid,
> +		unsigned char report_number,
> +		unsigned char *data, size_t count,
> +		unsigned char report_type)
> +{
> +	struct hidp_session *session = hid->driver_data;
> +	struct sk_buff *skb;
> +	size_t len;
> +	int numbered_reports = hid->report_enum[report_type].numbered;
> +
> +	switch (report_type) {
> +	case HID_FEATURE_REPORT:
> +		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
> +		break;
> +	case HID_INPUT_REPORT:
> +		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
> +		break;
> +	case HID_OUTPUT_REPORT:
> +		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (mutex_lock_interruptible(&session->report_mutex))
> +		return -ERESTARTSYS;
> +
> +	/* Set up our wait, and send the report request to the device. */
> +	session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
> +	session->waiting_report_number = numbered_reports ? report_number : -1;
> +	set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> +	data[0] = report_number;
> +	if (hidp_send_ctrl_message(hid->driver_data, report_type, data, 1))
> +		goto err_eio;
> +
> +	/* Wait for the return of the report. The returned report
> +	   gets put in session->report_return.  */
> +	while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
> +		int res;
> +
> +		res = wait_event_interruptible_timeout(session->report_queue,
> +			!test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
> +			5*HZ);
> +		if (res == 0) {
> +			/* timeout */
> +			goto err_eio;
> +		}
> +		if (res < 0) {
> +			/* signal */
> +			goto err_restartsys;
> +		}
> +	}
> +
> +	skb = session->report_return;
> +	if (skb) {
> +		len = skb->len < count ? skb->len : count;
> +		memcpy(data, skb->data, len);
> +
> +		kfree_skb(skb);
> +		session->report_return = NULL;
> +	} else {
> +		/* Device returned a HANDSHAKE, indicating  protocol error. */
> +		len = -EIO;
> +	}
> +
> +	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> +	mutex_unlock(&session->report_mutex);
> +
> +	return len;
> +
> +err_restartsys:
> +	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> +	mutex_unlock(&session->report_mutex);
> +	return -ERESTARTSYS;
> +err_eio:
> +	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> +	mutex_unlock(&session->report_mutex);
> +	return -EIO;
> +}

How about a variable called ret and using that to return len or errno? It
would eliminate code dublication.

-- 
Ville

^ permalink raw reply

* Re: [PATCH 20/20] net: change to new flag variable
From: Sjur Brændeland @ 2010-09-23 11:48 UTC (permalink / raw)
  To: matt mooney
  Cc: David S. Miller, John W. Linville, netdev, linux-kernel,
	kernel-janitors
In-Reply-To: <1285224715-30137-1-git-send-email-mfm@muteddisk.com>

matt mooney wrote:
> Replace EXTRA_CFLAGS with ccflags-y.
Thank you,
CAIF parts looks good to me.

Acked-by: Sjur Braendeland <sjur.brandeland@stericsson.com>

^ permalink raw reply

* Re: idr_get_new_exact ?
From: Tejun Heo @ 2010-09-23 11:46 UTC (permalink / raw)
  To: Paul Mundt
  Cc: Roland Dreier, Ohad Ben-Cohen, linux-kernel,
	Jean Delvare (PC drivers, core), Ben Dooks (embedded platforms),
	Roland Dreier, Sean Hefty, Hal Rosenstock, Steve Wise, Neil Brown,
	Paul Mackerras, linux-i2c, linux-rdma, dm-devel, linux-raid,
	linux-ppp, netdev, Andrew Morton, Alasdair G Kergon
In-Reply-To: <20100923114255.GB27960@linux-sh.org>

Hello,

On 09/23/2010 01:42 PM, Paul Mundt wrote:
> On Mon, Sep 20, 2010 at 11:26:47PM +0200, Tejun Heo wrote:
>> Hello,
>>
>> On 09/20/2010 10:35 PM, Roland Dreier wrote:
>>> Looks fine to me as an improvement over the status quo, but I wonder how
>>> many of these places could use the radix_tree stuff instead?  If you're
>>> not using the ability of the idr code to assign an id for you, then it
>>> seems the radix_tree API is a better fit.
>>
>> I agree.  Wouldn't those users better off simply using radix tree?
>>
> It could go either way. I was about to write the same function when
> playing with it for IRQ mapping, the idea being to propagate the initial
> tree with sparse static vectors and then switch over to dynamic IDs for
> virtual IRQ creation. I ended up going with a radix tree for other
> reasons, though.

I see.  If there are use cases where fixed and dynamic IDs need to be
mixed, no objection from me.

Thanks.

-- 
tejun

^ permalink raw reply

* Re: idr_get_new_exact ?
From: Paul Mundt @ 2010-09-23 11:42 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Roland Dreier, Ohad Ben-Cohen,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Jean Delvare (PC drivers, core), Ben Dooks (embedded platforms),
	Roland Dreier, Sean Hefty, Hal Rosenstock, Steve Wise, Neil Brown,
	Paul Mackerras, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	dm-devel-H+wXaHxf7aLQT0dZR+AlfA,
	linux-raid-u79uwXL29TY76Z2rM5mHXA,
	linux-ppp-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
In-Reply-To: <4C97D197.9070703-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Mon, Sep 20, 2010 at 11:26:47PM +0200, Tejun Heo wrote:
> Hello,
> 
> On 09/20/2010 10:35 PM, Roland Dreier wrote:
> > Looks fine to me as an improvement over the status quo, but I wonder how
> > many of these places could use the radix_tree stuff instead?  If you're
> > not using the ability of the idr code to assign an id for you, then it
> > seems the radix_tree API is a better fit.
> 
> I agree.  Wouldn't those users better off simply using radix tree?
> 
It could go either way. I was about to write the same function when
playing with it for IRQ mapping, the idea being to propagate the initial
tree with sparse static vectors and then switch over to dynamic IDs for
virtual IRQ creation. I ended up going with a radix tree for other
reasons, though.

^ permalink raw reply

* Re: [PATCH 8/8] net: Implement socketat.
From: jamal @ 2010-09-23 11:40 UTC (permalink / raw)
  To: Pavel Emelyanov
  Cc: Sukadev Bhattiprolu, Pavel Emelyanov, Jonathan Corbet,
	Ulrich Drepper, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jan Engelhardt,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA, Al Viro,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA, Eric W. Biederman,
	Linux Containers, Ben Greear, Linus Torvalds, David Miller,
	Michael Kerrisk
In-Reply-To: <4C9B3B06.900-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>

On Thu, 2010-09-23 at 15:33 +0400, Pavel Emelyanov wrote:

> This particular usecase is unneeded once you have the "enter" ability.

Is that cheaper from a syscall count/cost?
i.e do I have to enter every time i want to write/read this fd?
How does poll/select work in that enter scenario?

cheers,
jamal

^ permalink raw reply

* Re: [PATCH 12/13] net/sunrpc/rpc_pipe.c: Remove unnecessary casts of private_data
From: Jiri Kosina @ 2010-09-23 11:40 UTC (permalink / raw)
  To: Joe Perches
  Cc: J. Bruce Fields, Neil Brown, Trond Myklebust, David S. Miller,
	linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <dda96f0e94bd038179ae11dab4d73a7ab704276b.1283650107.git.joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>

On Sat, 4 Sep 2010, Joe Perches wrote:

> Signed-off-by: Joe Perches <joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>
> ---
>  net/sunrpc/rpc_pipe.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
> index 95ccbcf..1f7fc50 100644
> --- a/net/sunrpc/rpc_pipe.c
> +++ b/net/sunrpc/rpc_pipe.c
> @@ -204,7 +204,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
>  	mutex_lock(&inode->i_mutex);
>  	if (rpci->ops == NULL)
>  		goto out;
> -	msg = (struct rpc_pipe_msg *)filp->private_data;
> +	msg = filp->private_data;
>  	if (msg != NULL) {
>  		spin_lock(&inode->i_lock);
>  		msg->errno = -EAGAIN;
> @@ -322,7 +322,7 @@ rpc_pipe_ioctl_unlocked(struct file *filp, unsigned int cmd, unsigned long arg)
>  		len = rpci->pipelen;
>  		if (filp->private_data) {
>  			struct rpc_pipe_msg *msg;
> -			msg = (struct rpc_pipe_msg *)filp->private_data;
> +			msg = filp->private_data;
>  			len += msg->len - msg->copied;
>  		}
>  		return put_user(len, (int __user *)arg);

Not present in linux-next as of today. Applying to trivial queue.

-- 
Jiri Kosina
SUSE Labs, Novell Inc.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" 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 8/8] net: Implement socketat.
From: Pavel Emelyanov @ 2010-09-23 11:33 UTC (permalink / raw)
  To: hadi
  Cc: Eric W. Biederman, linux-kernel, Linux Containers, netdev,
	netfilter-devel, linux-fsdevel, Daniel Lezcano, Linus Torvalds,
	Michael Kerrisk, Ulrich Drepper, Al Viro, David Miller,
	Serge E. Hallyn, Pavel Emelyanov, Ben Greear, Matt Helsley,
	Jonathan Corbet, Sukadev Bhattiprolu, Jan Engelhardt,
	Patrick McHardy
In-Reply-To: <1285240797.5036.5.camel@bigi>

On 09/23/2010 03:19 PM, jamal wrote:
> On Thu, 2010-09-23 at 12:56 +0400, Pavel Emelyanov wrote:
>> On 09/23/2010 12:51 PM, Eric W. Biederman wrote:
>>>
>>> Add a system call for creating sockets in a specified network namespace.
>>
>> What for?
> 
> I can see many uses if my understanding is correct..
> ex, from mother namespace:
> fdx = open socket at namespace blah
> from mother namespace, read/write/poll fdx 
> (eg add route with netlink socket)

This particular usecase is unneeded once you have the "enter" ability.

> cheers,
> jamal
> 
> 


^ permalink raw reply

* Re: [PATCH 3/8] ns proc: Add support for the network namespace.
From: Louis Rilling @ 2010-09-23 11:27 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: linux-kernel, Linux Containers, netdev, netfilter-devel,
	linux-fsdevel, jamal, Daniel Lezcano, Linus Torvalds,
	Michael Kerrisk, Ulrich Drepper, Al Viro, David Miller,
	Serge E. Hallyn, Pavel Emelyanov, Pavel Emelyanov, Ben Greear,
	Matt Helsley, Jonathan Corbet, Sukadev Bhattiprolu,
	Jan Engelhardt, Patrick McHardy
In-Reply-To: <m17hicrglt.fsf@fess.ebiederm.org>

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

On 23/09/10  1:47 -0700, Eric W. Biederman wrote:
> 
> Implementing file descriptors for the network namespace is simple and
> straight forward.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

[...]

> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index c988e68..581a088 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -571,3 +571,33 @@ void unregister_pernet_device(struct pernet_operations *ops)
>  	mutex_unlock(&net_mutex);
>  }
>  EXPORT_SYMBOL_GPL(unregister_pernet_device);
> +
> +#ifdef CONFIG_NET_NS
> +static void *netns_get(struct task_struct *task)
> +{
> +	struct net *net;
> +	rcu_read_lock();
> +	net = get_net(task->nsproxy->net_ns);

task could be exiting, so task->nsproxy could be NULL, right?
Maybe make proc_ns_instantiate() rcu_dereference task->nsproxy, check for it
being not NULL, and pass task->nsproxy to ns_ops->get()?

That could be an issue for the user namespace since it is not in nsproxy, but
maybe no reasonable usage of ns_ops with user namespaces is envisioned.
Otherwise, checking that task is alive with RCU locked in proc_ns_instantiate() should be enough to be
rely on task->cred when calling ns_ops->get().

Thanks,

Louis

> +	rcu_read_unlock();
> +	return net;
> +}
> +
> +static void netns_put(void *ns)
> +{
> +	put_net(ns);
> +}
> +
> +static int netns_install(struct nsproxy *nsproxy, void *ns)
> +{
> +	put_net(nsproxy->net_ns);
> +	nsproxy->net_ns = get_net(ns);
> +	return 0;
> +}
> +
> +const struct proc_ns_operations netns_operations = {
> +	.name		= PROC_NSNAME("net"),
> +	.get		= netns_get,
> +	.put		= netns_put,
> +	.install	= netns_install,
> +};
> +#endif
> -- 
> 1.6.5.2.143.g8cc62
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Dr Louis Rilling			Kerlabs
Skype: louis.rilling			Batiment Germanium
Phone: (+33|0) 6 80 89 08 23		80 avenue des Buttes de Coesmes
http://www.kerlabs.com/			35700 Rennes

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH 7/8] net: Allow setting the network namespace by fd
From: jamal @ 2010-09-23 11:22 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: linux-kernel, Linux Containers, netdev, netfilter-devel,
	linux-fsdevel, Daniel Lezcano, Linus Torvalds, Michael Kerrisk,
	Ulrich Drepper, Al Viro, David Miller, Serge E. Hallyn,
	Pavel Emelyanov, Pavel Emelyanov, Ben Greear, Matt Helsley,
	Jonathan Corbet, Sukadev Bhattiprolu, Jan Engelhardt,
	Patrick McHardy
In-Reply-To: <m1hbhgq1v1.fsf@fess.ebiederm.org>

On Thu, 2010-09-23 at 01:51 -0700, Eric W. Biederman wrote:
> Take advantage of the new abstraction and allow network devices
> to be placed in any network namespace that we have a fd to talk
> about.
> 

So ... why just netdevice? could you allow migration of other
net "items" eg a route table since they are all tagged by
netns?

cheers,
jamal


^ permalink raw reply

* Re: [PATCH 8/8] net: Implement socketat.
From: jamal @ 2010-09-23 11:19 UTC (permalink / raw)
  To: Pavel Emelyanov
  Cc: Eric W. Biederman, linux-kernel, Linux Containers, netdev,
	netfilter-devel, linux-fsdevel, Daniel Lezcano, Linus Torvalds,
	Michael Kerrisk, Ulrich Drepper, Al Viro, David Miller,
	Serge E. Hallyn, Pavel Emelyanov, Ben Greear, Matt Helsley,
	Jonathan Corbet, Sukadev Bhattiprolu, Jan Engelhardt,
	Patrick McHardy
In-Reply-To: <4C9B162E.7040201@parallels.com>

On Thu, 2010-09-23 at 12:56 +0400, Pavel Emelyanov wrote:
> On 09/23/2010 12:51 PM, Eric W. Biederman wrote:
> > 
> > Add a system call for creating sockets in a specified network namespace.
> 
> What for?

I can see many uses if my understanding is correct..
ex, from mother namespace:
fdx = open socket at namespace blah
from mother namespace, read/write/poll fdx 
(eg add route with netlink socket)

cheers,
jamal


^ permalink raw reply

* [PATCH net-next-2.6] net: propagate NETIF_F_HIGHDMA to vlans
From: Eric Dumazet @ 2010-09-23 10:46 UTC (permalink / raw)
  To: Jeff Kirsher, David Miller; +Cc: netdev, gospo, bphilips, yi.zou
In-Reply-To: <1285222405.2380.80.camel@edumazet-laptop>

Automatically allows vlans to get NETIF_F_HIGHDMA if underlying device
supports it.

On 32bit arches (and more precisely if CONFIG_HIGHMEM is enabled), it
can help to reduce cost of illegal_highdma() and __skb_linearize()
calls.

Tested on tg3 , bnx2, bonding, this worked very well.

This is a generalization of a patch provided by Yi Zou & Jeff Kirsher.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 net/core/dev.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 2c7934f..e0c0b86 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5058,10 +5058,11 @@ int register_netdevice(struct net_device *dev)
 	if (dev->features & NETIF_F_SG)
 		dev->features |= NETIF_F_GSO;
 
-	/* Enable GRO for vlans by default if dev->features has GRO also.
-	 * vlan_dev_init() will do the dev->features check.
+	/* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
+	 * vlan_dev_init() will do the dev->features check, so these features
+	 * are enabled only if supported by underlying device.
 	 */
-	dev->vlan_features |= NETIF_F_GRO;
+	dev->vlan_features |= (NETIF_F_GRO | NETIF_F_HIGHDMA);
 
 	ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
 	ret = notifier_to_errno(ret);



^ permalink raw reply related

* [PATCH v3] net: af_packet: don't call tpacket_destruct_skb() until the skb is sent out
From: Changli Gao @ 2010-09-23 10:15 UTC (permalink / raw)
  To: David S. Miller
  Cc: Eric Dumazet, Oliver Hartkopp, Michael S. Tsirkin, netdev,
	Changli Gao

Since skb->destructor() is used to account socket memory, and maybe called
before the skb is sent out, a corrupt skb maybe sent out finally.

A new destructor is added into structure skb_shared_info(), and it won't
be called until the last reference to the data of an skb is put. af_packet
uses this destructor instead.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
---
v3: rename destructor to data_destructor, destructor_arg to data_destructor_arg,
    fix splice the skbs generated by AF_PACKET socket to the pipe.
v2: avoid kmalloc/kfree
 include/linux/skbuff.h |    7 ++++---
 net/core/skbuff.c      |   29 ++++++++++++++++++++---------
 net/packet/af_packet.c |   25 ++++++++++++-------------
 3 files changed, 36 insertions(+), 25 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9e8085a..0854135 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -191,15 +191,16 @@ struct skb_shared_info {
 	__u8		tx_flags;
 	struct sk_buff	*frag_list;
 	struct skb_shared_hwtstamps hwtstamps;
+	void		(*data_destructor)(struct sk_buff *skb);
 
 	/*
 	 * Warning : all fields before dataref are cleared in __alloc_skb()
 	 */
 	atomic_t	dataref;
 
-	/* Intermediate layers must ensure that destructor_arg
-	 * remains valid until skb destructor */
-	void *		destructor_arg;
+	/* Intermediate layers must ensure that data_destructor_arg
+	 * remains valid until skb data destructor */
+	void		*data_destructor_arg[2];
 	/* must be last field, see pskb_expand_head() */
 	skb_frag_t	frags[MAX_SKB_FRAGS];
 };
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 752c197..95a48fb 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -332,10 +332,14 @@ static void skb_release_data(struct sk_buff *skb)
 	if (!skb->cloned ||
 	    !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
 			       &skb_shinfo(skb)->dataref)) {
-		if (skb_shinfo(skb)->nr_frags) {
+		struct skb_shared_info *shinfo = skb_shinfo(skb);
+
+		if (shinfo->data_destructor)
+			shinfo->data_destructor(skb);
+		if (shinfo->nr_frags) {
 			int i;
-			for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-				put_page(skb_shinfo(skb)->frags[i].page);
+			for (i = 0; i < shinfo->nr_frags; i++)
+				put_page(shinfo->frags[i].page);
 		}
 
 		if (skb_has_frag_list(skb))
@@ -497,9 +501,12 @@ bool skb_recycle_check(struct sk_buff *skb, int skb_size)
 	if (skb_shared(skb) || skb_cloned(skb))
 		return false;
 
+	shinfo = skb_shinfo(skb);
+	if (shinfo->data_destructor)
+		return false;
+
 	skb_release_head_state(skb);
 
-	shinfo = skb_shinfo(skb);
 	memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
 	atomic_set(&shinfo->dataref, 1);
 
@@ -799,7 +806,9 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
 
 	memcpy((struct skb_shared_info *)(data + size),
 	       skb_shinfo(skb),
-	       offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
+	       offsetof(struct skb_shared_info,
+			frags[skb_shinfo(skb)->nr_frags]));
+	skb_shinfo(skb)->data_destructor = NULL;
 
 	/* Check if we can avoid taking references on fragments if we own
 	 * the last reference on skb->head. (see skb_release_data())
@@ -1408,7 +1417,7 @@ new_page:
 static inline int spd_fill_page(struct splice_pipe_desc *spd,
 				struct pipe_inode_info *pipe, struct page *page,
 				unsigned int *len, unsigned int offset,
-				struct sk_buff *skb, int linear,
+				struct sk_buff *skb, bool linear,
 				struct sock *sk)
 {
 	if (unlikely(spd->nr_pages == pipe->buffers))
@@ -1446,7 +1455,7 @@ static inline void __segment_seek(struct page **page, unsigned int *poff,
 static inline int __splice_segment(struct page *page, unsigned int poff,
 				   unsigned int plen, unsigned int *off,
 				   unsigned int *len, struct sk_buff *skb,
-				   struct splice_pipe_desc *spd, int linear,
+				   struct splice_pipe_desc *spd, bool linear,
 				   struct sock *sk,
 				   struct pipe_inode_info *pipe)
 {
@@ -1498,7 +1507,7 @@ static int __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
 	if (__splice_segment(virt_to_page(skb->data),
 			     (unsigned long) skb->data & (PAGE_SIZE - 1),
 			     skb_headlen(skb),
-			     offset, len, skb, spd, 1, sk, pipe))
+			     offset, len, skb, spd, true, sk, pipe))
 		return 1;
 
 	/*
@@ -1508,7 +1517,9 @@ static int __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
 		const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
 
 		if (__splice_segment(f->page, f->page_offset, f->size,
-				     offset, len, skb, spd, 0, sk, pipe))
+				     offset, len, skb, spd,
+				     skb_shinfo(skb)->data_destructor != NULL,
+				     sk, pipe))
 			return 1;
 	}
 
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 3616f27..ecf57c7 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -825,19 +825,19 @@ ring_is_full:
 
 static void tpacket_destruct_skb(struct sk_buff *skb)
 {
-	struct packet_sock *po = pkt_sk(skb->sk);
-	void *ph;
-
-	BUG_ON(skb == NULL);
+	struct packet_sock *po;
 
+	po = pkt_sk(skb_shinfo(skb)->data_destructor_arg[0]);
 	if (likely(po->tx_ring.pg_vec)) {
-		ph = skb_shinfo(skb)->destructor_arg;
+		void *ph = skb_shinfo(skb)->data_destructor_arg[1];
+
 		BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING);
 		BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
 		atomic_dec(&po->tx_ring.pending);
 		__packet_set_status(po, ph, TP_STATUS_AVAILABLE);
 	}
 
+	skb->sk = &po->sk;
 	sock_wfree(skb);
 }
 
@@ -862,7 +862,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 	skb->dev = dev;
 	skb->priority = po->sk.sk_priority;
 	skb->mark = po->sk.sk_mark;
-	skb_shinfo(skb)->destructor_arg = ph.raw;
 
 	switch (po->tp_version) {
 	case TPACKET_V2:
@@ -884,9 +883,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 	to_write = tp_len;
 
 	if (sock->type == SOCK_DGRAM) {
-		err = dev_hard_header(skb, dev, ntohs(proto), addr,
-				NULL, tp_len);
-		if (unlikely(err < 0))
+		if (unlikely(dev_hard_header(skb, dev, ntohs(proto), addr,
+					     NULL, tp_len) < 0))
 			return -EINVAL;
 	} else if (dev->hard_header_len) {
 		/* net device doesn't like empty head */
@@ -897,8 +895,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 		}
 
 		skb_push(skb, dev->hard_header_len);
-		err = skb_store_bits(skb, 0, data,
-				dev->hard_header_len);
+		err = skb_store_bits(skb, 0, data, dev->hard_header_len);
 		if (unlikely(err))
 			return err;
 
@@ -906,7 +903,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 		to_write -= dev->hard_header_len;
 	}
 
-	err = -EFAULT;
 	page = virt_to_page(data);
 	offset = offset_in_page(data);
 	len_max = PAGE_SIZE - offset;
@@ -1028,7 +1024,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 			}
 		}
 
-		skb->destructor = tpacket_destruct_skb;
+		skb_shinfo(skb)->data_destructor_arg[0] = &po->sk;
+		skb_shinfo(skb)->data_destructor_arg[1] = ph;
+		skb->destructor = NULL;
+		skb_shinfo(skb)->data_destructor = tpacket_destruct_skb;
 		__packet_set_status(po, ph, TP_STATUS_SENDING);
 		atomic_inc(&po->tx_ring.pending);
 

^ permalink raw reply related

* Re: [PATCH 7/8] net: Allow setting the network namespace by fd
From: Eric Dumazet @ 2010-09-23  9:41 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: linux-kernel, Linux Containers, netdev, netfilter-devel,
	linux-fsdevel, jamal, Daniel Lezcano, Linus Torvalds,
	Michael Kerrisk, Ulrich Drepper, Al Viro, David Miller,
	Serge E. Hallyn, Pavel Emelyanov, Pavel Emelyanov, Ben Greear,
	Matt Helsley, Jonathan Corbet, Sukadev Bhattiprolu,
	Jan Engelhardt, Patrick McHardy
In-Reply-To: <m1hbhgq1v1.fsf@fess.ebiederm.org>

Le jeudi 23 septembre 2010 à 01:51 -0700, Eric W. Biederman a écrit :
> Take advantage of the new abstraction and allow network devices
> to be placed in any network namespace that we have a fd to talk
> about.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
> ---
>  include/linux/if_link.h     |    1 +
>  include/net/net_namespace.h |    1 +
>  net/core/net_namespace.c    |   26 ++++++++++++++++++++++++++
>  net/core/rtnetlink.c        |    4 +++-
>  4 files changed, 31 insertions(+), 1 deletions(-)
> 
> diff --git a/include/linux/if_link.h b/include/linux/if_link.h
> index 2fc66dd..ae73d5e 100644
> --- a/include/linux/if_link.h
> +++ b/include/linux/if_link.h
> @@ -116,6 +116,7 @@ enum {
>  	IFLA_STATS64,
>  	IFLA_VF_PORTS,
>  	IFLA_PORT_SELF,
> +	IFLA_NET_NS_FD,
>  	__IFLA_MAX
>  };
>  
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index bd10a79..68672ce 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -114,6 +114,7 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
>  extern struct list_head net_namespace_list;
>  
>  extern struct net *get_net_ns_by_pid(pid_t pid);
> +extern struct net *get_net_ns_by_fd(int pid);
>  
>  #ifdef CONFIG_NET_NS
>  extern void __put_net(struct net *net);
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index 581a088..a9b54a7 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -8,6 +8,8 @@
>  #include <linux/idr.h>
>  #include <linux/rculist.h>
>  #include <linux/nsproxy.h>
> +#include <linux/proc_fs.h>
> +#include <linux/file.h>
>  #include <net/net_namespace.h>
>  #include <net/netns/generic.h>
>  
> @@ -341,6 +343,30 @@ struct net *get_net_ns_by_pid(pid_t pid)
>  }
>  EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
>  
> +struct net *get_net_ns_by_fd(int fd)
> +{
> +	struct proc_inode *ei;
> +	struct file *file;
> +	struct net *net;
> +
> +	file = NULL;
> +	net = ERR_PTR(-EINVAL);
> +	file = proc_ns_fget(fd);
> +	if (!fd)
> +		goto out;
> +		return ERR_PTR(-EINVAL);
> +
> +	ei = PROC_I(file->f_dentry->d_inode);
> +	if (ei->ns_ops != &netns_operations)
> +		goto out;
> +
> +	net = get_net(ei->ns);
> +out:
> +	if (file)
> +		fput(file);
> +	return net;
> +}
> +
>  static int __init net_ns_init(void)
>  {
>  	struct net_generic *ng;
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index f78d821..771d8be 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -1003,6 +1003,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
>  	 */
>  	if (tb[IFLA_NET_NS_PID])
>  		net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
> +	else if (tb[IFLA_NET_NS_FD])
> +		net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
>  	else
>  		net = get_net(src_net);
>  	return net;
> @@ -1077,7 +1079,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
>  	int send_addr_notify = 0;
>  	int err;
>  
> -	if (tb[IFLA_NET_NS_PID]) {
> +	if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
>  		struct net *net = rtnl_link_get_net(dev_net(dev), tb);
>  		if (IS_ERR(net)) {
>  			err = PTR_ERR(net);

You probably want to add following chunk :

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b2a718d..35bb6de 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -927,6 +927,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_LINKMODE]		= { .type = NLA_U8 },
 	[IFLA_LINKINFO]		= { .type = NLA_NESTED },
 	[IFLA_NET_NS_PID]	= { .type = NLA_U32 },
+	[IFLA_NET_NS_FD]	= { .type = NLA_U32 },
 	[IFLA_IFALIAS]	        = { .type = NLA_STRING, .len = IFALIASZ-1 },
 	[IFLA_VFINFO_LIST]	= {. type = NLA_NESTED },
 	[IFLA_VF_PORTS]		= { .type = NLA_NESTED },


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH 8/8] net: Implement socketat.
From: Pavel Emelyanov @ 2010-09-23  8:56 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: linux-kernel, Linux Containers, netdev, netfilter-devel,
	linux-fsdevel, jamal, Daniel Lezcano, Linus Torvalds,
	Michael Kerrisk, Ulrich Drepper, Al Viro, David Miller,
	Serge E. Hallyn, Pavel Emelyanov, Ben Greear, Matt Helsley,
	Jonathan Corbet, Sukadev Bhattiprolu, Jan Engelhardt,
	Patrick McHardy
In-Reply-To: <m1bp7oq1u8.fsf@fess.ebiederm.org>

On 09/23/2010 12:51 PM, Eric W. Biederman wrote:
> 
> Add a system call for creating sockets in a specified network namespace.

What for?

^ permalink raw reply

* [PATCH 8/8] net: Implement socketat.
From: Eric W. Biederman @ 2010-09-23  8:51 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sukadev Bhattiprolu, Pavel Emelyanov, Pavel Emelyanov,
	Ulrich Drepper, netdev-u79uwXL29TY76Z2rM5mHXA, Jonathan Corbet,
	Jan Engelhardt, linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA, Michael Kerrisk,
	Linux Containers, Ben Greear, Linus Torvalds, David Miller,
	Al Viro
In-Reply-To: <m1ocborgq7.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>


Add a system call for creating sockets in a specified network namespace.

Signed-off-by: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
---
 net/socket.c |   26 ++++++++++++++++++++++++--
 1 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 2270b94..1116f3c 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1269,7 +1269,7 @@ int sock_create_kern(int family, int type, int protocol, struct socket **res)
 }
 EXPORT_SYMBOL(sock_create_kern);
 
-SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
+static int do_socket(struct net *net, int family, int type, int protocol)
 {
 	int retval;
 	struct socket *sock;
@@ -1289,7 +1289,7 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
 
-	retval = sock_create(family, type, protocol, &sock);
+	retval = __sock_create(net, family, type, protocol, &sock, 0);
 	if (retval < 0)
 		goto out;
 
@@ -1306,6 +1306,28 @@ out_release:
 	return retval;
 }
 
+SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
+{
+	return do_socket(current->nsproxy->net_ns, family, type, protocol);
+}
+
+SYSCALL_DEFINE4(socketat, int, fd, int, family, int, type, int, protocol)
+{
+	struct net *net;
+	int retval;
+
+	if (fd == -1) {
+		net = get_net(current->nsproxy->net_ns);
+	} else {
+		net = get_net_ns_by_fd(fd);
+		if (IS_ERR(net))
+			return  PTR_ERR(net);
+	}
+	retval = do_socket(net, family, type, protocol);
+	put_net(net);
+	return retval;
+}
+
 /*
  *	Create a pair of connected sockets.
  */
-- 
1.6.5.2.143.g8cc62

^ permalink raw reply related

* [PATCH 7/8] net: Allow setting the network namespace by fd
From: Eric W. Biederman @ 2010-09-23  8:51 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Sukadev Bhattiprolu, Pavel Emelyanov, Pavel Emelyanov,
	Ulrich Drepper, netdev-u79uwXL29TY76Z2rM5mHXA, Jonathan Corbet,
	Jan Engelhardt, linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA, Michael Kerrisk,
	Linux Containers, Ben Greear, Linus Torvalds, David Miller,
	Al Viro
In-Reply-To: <m1ocborgq7.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>


Take advantage of the new abstraction and allow network devices
to be placed in any network namespace that we have a fd to talk
about.

Signed-off-by: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
---
 include/linux/if_link.h     |    1 +
 include/net/net_namespace.h |    1 +
 net/core/net_namespace.c    |   26 ++++++++++++++++++++++++++
 net/core/rtnetlink.c        |    4 +++-
 4 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 2fc66dd..ae73d5e 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -116,6 +116,7 @@ enum {
 	IFLA_STATS64,
 	IFLA_VF_PORTS,
 	IFLA_PORT_SELF,
+	IFLA_NET_NS_FD,
 	__IFLA_MAX
 };
 
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index bd10a79..68672ce 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -114,6 +114,7 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
 extern struct list_head net_namespace_list;
 
 extern struct net *get_net_ns_by_pid(pid_t pid);
+extern struct net *get_net_ns_by_fd(int pid);
 
 #ifdef CONFIG_NET_NS
 extern void __put_net(struct net *net);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 581a088..a9b54a7 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -8,6 +8,8 @@
 #include <linux/idr.h>
 #include <linux/rculist.h>
 #include <linux/nsproxy.h>
+#include <linux/proc_fs.h>
+#include <linux/file.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
@@ -341,6 +343,30 @@ struct net *get_net_ns_by_pid(pid_t pid)
 }
 EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
 
+struct net *get_net_ns_by_fd(int fd)
+{
+	struct proc_inode *ei;
+	struct file *file;
+	struct net *net;
+
+	file = NULL;
+	net = ERR_PTR(-EINVAL);
+	file = proc_ns_fget(fd);
+	if (!fd)
+		goto out;
+		return ERR_PTR(-EINVAL);
+
+	ei = PROC_I(file->f_dentry->d_inode);
+	if (ei->ns_ops != &netns_operations)
+		goto out;
+
+	net = get_net(ei->ns);
+out:
+	if (file)
+		fput(file);
+	return net;
+}
+
 static int __init net_ns_init(void)
 {
 	struct net_generic *ng;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index f78d821..771d8be 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1003,6 +1003,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
 	 */
 	if (tb[IFLA_NET_NS_PID])
 		net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
+	else if (tb[IFLA_NET_NS_FD])
+		net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
 	else
 		net = get_net(src_net);
 	return net;
@@ -1077,7 +1079,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 	int send_addr_notify = 0;
 	int err;
 
-	if (tb[IFLA_NET_NS_PID]) {
+	if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
 		struct net *net = rtnl_link_get_net(dev_net(dev), tb);
 		if (IS_ERR(net)) {
 			err = PTR_ERR(net);
-- 
1.6.5.2.143.g8cc62

^ permalink raw reply related

* [PATCH 6/8] ns proc: Add support for the mount namespace
From: Eric W. Biederman @ 2010-09-23  8:50 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linux Containers, netdev, netfilter-devel, linux-fsdevel, jamal,
	Daniel Lezcano, Linus Torvalds, Michael Kerrisk, Ulrich Drepper,
	Al Viro, David Miller, Serge E. Hallyn, Pavel Emelyanov,
	Pavel Emelyanov, Ben Greear, Matt Helsley, Jonathan Corbet,
	Sukadev Bhattiprolu, Jan Engelhardt, Patrick McHardy
In-Reply-To: <m1ocborgq7.fsf@fess.ebiederm.org>


The mount namespace is a little tricky as an arbitrary
decision must be made about what to set fs->root and
fs->pwd to, as there is no expectation of a relationship
between the two mount namespaces.

Therefor I arbitrary find the root mount point, and follow
every mount on top of it to find the top of the mount stack.
Then I set fs->root and fs->pwd to that location.

The topmost root of the mount stack seems like a reasonable place to be.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 fs/namespace.c          |   57 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/proc/namespaces.c    |    1 +
 include/linux/proc_fs.h |    1 +
 3 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index a72eaab..ed11bac 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -32,6 +32,7 @@
 #include <linux/idr.h>
 #include <linux/fs_struct.h>
 #include <linux/fsnotify.h>
+#include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include "pnode.h"
@@ -2418,3 +2419,59 @@ void put_mnt_ns(struct mnt_namespace *ns)
 	kfree(ns);
 }
 EXPORT_SYMBOL(put_mnt_ns);
+
+
+static void *mntns_get(struct task_struct *task)
+{
+	struct mnt_namespace *ns;
+	rcu_read_lock();
+	ns = task->nsproxy->mnt_ns;
+	get_mnt_ns(ns);
+	rcu_read_unlock();
+	return ns;
+}
+
+static void mntns_put(void *ns)
+{
+	put_mnt_ns(ns);
+}
+
+static int mntns_install(struct nsproxy *nsproxy, void *ns)
+{
+	struct fs_struct *fs = current->fs;
+	struct mnt_namespace *mnt_ns = ns;
+	struct path root;
+
+	if (fs->users != 1)
+		return -EINVAL;
+
+	get_mnt_ns(mnt_ns);
+	put_mnt_ns(nsproxy->mnt_ns);
+	nsproxy->mnt_ns = mnt_ns;
+
+	/* Find the root */
+	root.mnt    = mnt_ns->root;
+	root.dentry = mnt_ns->root->mnt_root;
+	path_get(&root);
+	while(d_mountpoint(root.dentry) && follow_down(&root))
+		;
+
+	/* Update the pwd and root */
+	path_get(&root);
+	path_get(&root);
+	path_put(&fs->root);
+	path_put(&fs->pwd);
+	fs->root = root;
+	fs->pwd  = root;
+	path_put(&root);
+
+	return 0;
+}
+
+const struct proc_ns_operations mntns_operations = {
+	.name		= PROC_NSNAME("mnt"),
+	.get		= mntns_get,
+	.put		= mntns_put,
+	.install	= mntns_install,
+};
+
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 2f503b5..c5956ad 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -25,6 +25,7 @@ static const struct proc_ns_operations *ns_entries[] = {
 #ifdef CONFIG_IPC_NS
 	&ipcns_operations,
 #endif
+	&mntns_operations,
 };
 
 static const struct file_operations ns_file_operations = {
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 9a9ef31..8a260b0 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -265,6 +265,7 @@ struct proc_ns_operations {
 extern const struct proc_ns_operations netns_operations;
 extern const struct proc_ns_operations utsns_operations;
 extern const struct proc_ns_operations ipcns_operations;
+extern const struct proc_ns_operations mntns_operations;
 extern struct file *proc_ns_fget(int fd);
 
 union proc_op {
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related

* [PATCH 5/8] ns proc: Add support for the ipc namespace
From: Eric W. Biederman @ 2010-09-23  8:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linux Containers, netdev, netfilter-devel, linux-fsdevel, jamal,
	Daniel Lezcano, Linus Torvalds, Michael Kerrisk, Ulrich Drepper,
	Al Viro, David Miller, Serge E. Hallyn, Pavel Emelyanov,
	Pavel Emelyanov, Ben Greear, Matt Helsley, Jonathan Corbet,
	Sukadev Bhattiprolu, Jan Engelhardt, Patrick McHardy
In-Reply-To: <m1ocborgq7.fsf@fess.ebiederm.org>


Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 fs/proc/namespaces.c    |    3 +++
 include/linux/proc_fs.h |    1 +
 ipc/namespace.c         |   31 +++++++++++++++++++++++++++++++
 3 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 902443e..2f503b5 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -22,6 +22,9 @@ static const struct proc_ns_operations *ns_entries[] = {
 #ifdef CONFIG_UTS_NS
 	&utsns_operations,
 #endif
+#ifdef CONFIG_IPC_NS
+	&ipcns_operations,
+#endif
 };
 
 static const struct file_operations ns_file_operations = {
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 28b4ffd..9a9ef31 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -264,6 +264,7 @@ struct proc_ns_operations {
 #define PROC_NSNAME(NAME) { .name = (NAME), .len = (sizeof(NAME) - 1), }
 extern const struct proc_ns_operations netns_operations;
 extern const struct proc_ns_operations utsns_operations;
+extern const struct proc_ns_operations ipcns_operations;
 extern struct file *proc_ns_fget(int fd);
 
 union proc_op {
diff --git a/ipc/namespace.c b/ipc/namespace.c
index a1094ff..2c5947f 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
+#include <linux/proc_fs.h>
 
 #include "util.h"
 
@@ -132,3 +133,33 @@ void put_ipc_ns(struct ipc_namespace *ns)
 		free_ipc_ns(ns);
 	}
 }
+
+static void *ipcns_get(struct task_struct *task)
+{
+	struct ipc_namespace *ns;
+	rcu_read_lock();
+	ns = get_ipc_ns(task->nsproxy->ipc_ns);
+	rcu_read_unlock();
+	return ns;
+}
+
+static void ipcns_put(void *ns)
+{
+	return put_ipc_ns(ns);
+}
+
+static int ipcns_install(struct nsproxy *nsproxy, void *ns)
+{
+	/* Ditch state from the old ipc namespace */
+	exit_sem(current);
+	put_ipc_ns(nsproxy->ipc_ns);
+	nsproxy->ipc_ns = get_ipc_ns(ns);
+	return 0;
+}
+
+const struct proc_ns_operations ipcns_operations = {
+	.name		= PROC_NSNAME("ipc"),
+	.get		= ipcns_get,
+	.put		= ipcns_put,
+	.install	= ipcns_install,
+};
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related

* [PATCH 4/8] ns proc: Add support for the uts namespace
From: Eric W. Biederman @ 2010-09-23  8:48 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linux Containers, netdev, netfilter-devel, linux-fsdevel, jamal,
	Daniel Lezcano, Linus Torvalds, Michael Kerrisk, Ulrich Drepper,
	Al Viro, David Miller, Serge E. Hallyn, Pavel Emelyanov,
	Pavel Emelyanov, Ben Greear, Matt Helsley, Jonathan Corbet,
	Sukadev Bhattiprolu, Jan Engelhardt, Patrick McHardy
In-Reply-To: <m1ocborgq7.fsf@fess.ebiederm.org>


Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 fs/proc/namespaces.c    |    3 +++
 include/linux/proc_fs.h |    1 +
 kernel/utsname.c        |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 31e32f3..902443e 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -19,6 +19,9 @@ static const struct proc_ns_operations *ns_entries[] = {
 #ifdef CONFIG_NET_NS
 	&netns_operations,
 #endif
+#ifdef CONFIG_UTS_NS
+	&utsns_operations,
+#endif
 };
 
 static const struct file_operations ns_file_operations = {
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 9cd3fae..28b4ffd 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -263,6 +263,7 @@ struct proc_ns_operations {
 };
 #define PROC_NSNAME(NAME) { .name = (NAME), .len = (sizeof(NAME) - 1), }
 extern const struct proc_ns_operations netns_operations;
+extern const struct proc_ns_operations utsns_operations;
 extern struct file *proc_ns_fget(int fd);
 
 union proc_op {
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 8a82b4b..ff06086 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -14,6 +14,7 @@
 #include <linux/utsname.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/proc_fs.h>
 
 static struct uts_namespace *create_uts_ns(void)
 {
@@ -73,3 +74,34 @@ void free_uts_ns(struct kref *kref)
 	ns = container_of(kref, struct uts_namespace, kref);
 	kfree(ns);
 }
+
+static void *utsns_get(struct task_struct *task)
+{
+	struct uts_namespace *ns;
+	rcu_read_lock();
+	ns = task->nsproxy->uts_ns;
+	get_uts_ns(ns);
+	rcu_read_unlock();
+	return ns;
+}
+
+static void utsns_put(void *ns)
+{
+	put_uts_ns(ns);
+}
+
+static int utsns_install(struct nsproxy *nsproxy, void *ns)
+{
+	get_uts_ns(ns);
+	put_uts_ns(nsproxy->uts_ns);
+	nsproxy->uts_ns = ns;
+	return 0;
+}
+
+const struct proc_ns_operations utsns_operations = {
+	.name		= PROC_NSNAME("uts"),
+	.get		= utsns_get,
+	.put		= utsns_put,
+	.install	= utsns_install,
+};
+
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related

* [PATCH 3/8] ns proc: Add support for the network namespace.
From: Eric W. Biederman @ 2010-09-23  8:47 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linux Containers, netdev, netfilter-devel, linux-fsdevel, jamal,
	Daniel Lezcano, Linus Torvalds, Michael Kerrisk, Ulrich Drepper,
	Al Viro, David Miller, Serge E. Hallyn, Pavel Emelyanov,
	Pavel Emelyanov, Ben Greear, Matt Helsley, Jonathan Corbet,
	Sukadev Bhattiprolu, Jan Engelhardt, Patrick McHardy
In-Reply-To: <m1ocborgq7.fsf@fess.ebiederm.org>


Implementing file descriptors for the network namespace is simple and
straight forward.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 fs/proc/namespaces.c     |    3 +++
 include/linux/proc_fs.h  |    1 +
 net/core/net_namespace.c |   30 ++++++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index f33537f..31e32f3 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -16,6 +16,9 @@
 
 
 static const struct proc_ns_operations *ns_entries[] = {
+#ifdef CONFIG_NET_NS
+	&netns_operations,
+#endif
 };
 
 static const struct file_operations ns_file_operations = {
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index a6c26f0..9cd3fae 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -262,6 +262,7 @@ struct proc_ns_operations {
 	int (*install)(struct nsproxy *nsproxy, void *ns);
 };
 #define PROC_NSNAME(NAME) { .name = (NAME), .len = (sizeof(NAME) - 1), }
+extern const struct proc_ns_operations netns_operations;
 extern struct file *proc_ns_fget(int fd);
 
 union proc_op {
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index c988e68..581a088 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -571,3 +571,33 @@ void unregister_pernet_device(struct pernet_operations *ops)
 	mutex_unlock(&net_mutex);
 }
 EXPORT_SYMBOL_GPL(unregister_pernet_device);
+
+#ifdef CONFIG_NET_NS
+static void *netns_get(struct task_struct *task)
+{
+	struct net *net;
+	rcu_read_lock();
+	net = get_net(task->nsproxy->net_ns);
+	rcu_read_unlock();
+	return net;
+}
+
+static void netns_put(void *ns)
+{
+	put_net(ns);
+}
+
+static int netns_install(struct nsproxy *nsproxy, void *ns)
+{
+	put_net(nsproxy->net_ns);
+	nsproxy->net_ns = get_net(ns);
+	return 0;
+}
+
+const struct proc_ns_operations netns_operations = {
+	.name		= PROC_NSNAME("net"),
+	.get		= netns_get,
+	.put		= netns_put,
+	.install	= netns_install,
+};
+#endif
-- 
1.6.5.2.143.g8cc62

^ permalink raw reply related

* [PATCH 2/8] ns: Introduce the setns syscall
From: Eric W. Biederman @ 2010-09-23  8:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linux Containers, netdev, netfilter-devel, linux-fsdevel, jamal,
	Daniel Lezcano, Linus Torvalds, Michael Kerrisk, Ulrich Drepper,
	Al Viro, David Miller, Serge E. Hallyn, Pavel Emelyanov,
	Pavel Emelyanov, Ben Greear, Matt Helsley, Jonathan Corbet,
	Sukadev Bhattiprolu, Jan Engelhardt, Patrick McHardy
In-Reply-To: <m1ocborgq7.fsf@fess.ebiederm.org>


With the networking stack today there is demand to handle
multiple network stacks at a time.  Not in the context
of containers but in the context of people doing interesting
things with routing.

There is also demand in the context of containers to have
an efficient way to execute some code in the container itself.
If nothing else it is very useful ad a debugging technique.

Both problems can be solved by starting some form of login
daemon in the namespaces people want access to, or you
can play games by ptracing a process and getting the
traced process to do things you want it to do. However
it turns out that a login daemon or a ptrace puppet
controller are more code, they are more prone to
failure, and generally they are less efficient than
simply changing the namespace of a process to a
specified one.

Pieces of this puzzle can also be solved by instead of
coming up with a general purpose system call coming up
with targed system calls perhaps socketat that solve
a subset of the larger problem.  Overall that appears
to be more work for less reward.

int setns(unsigned int nstype, int fd);

In the setns system call the nstype is 0 or specifies
an the name of the namespace you think you are changing,
to prevent changing a namespace unintentionally.

The fd argument is a file descriptor referring to a proc
file of the namespace you want to switch the process to.

v2: Most of the architecture support added by Daniel Lezcano <dlezcano@fr.ibm.com>
v3: ported to v2.6.36-rc4 by: Eric W. Biederman <ebiederm@xmission.com>
v4: Moved wiring up of the system call to another patch

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 kernel/nsproxy.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index f74e6c0..0bf2dba 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -22,6 +22,9 @@
 #include <linux/pid_namespace.h>
 #include <net/net_namespace.h>
 #include <linux/ipc_namespace.h>
+#include <linux/proc_fs.h>
+#include <linux/file.h>
+#include <linux/syscalls.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
@@ -233,6 +236,42 @@ void exit_task_namespaces(struct task_struct *p)
 	switch_task_namespaces(p, NULL);
 }
 
+SYSCALL_DEFINE2(setns, unsigned int, nstype, int, fd)
+{
+	const struct proc_ns_operations *ops;
+	struct task_struct *tsk = current;
+	struct nsproxy *new_nsproxy;
+	struct proc_inode *ei;
+	struct file *file;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	file = proc_ns_fget(fd);
+	if (IS_ERR(file))
+		return PTR_ERR(file);
+
+	err = -EINVAL;
+	ei = PROC_I(file->f_dentry->d_inode);
+	ops = ei->ns_ops;
+	if (nstype &&
+	    ((ops->name.len >= sizeof(nstype)) ||
+	    memcmp(&nstype, ops->name.name, ops->name.len)))
+		goto out;
+
+	new_nsproxy = create_new_namespaces(0, tsk, tsk->fs);
+	err = ops->install(new_nsproxy, ei->ns);
+	if (err) {
+		free_nsproxy(new_nsproxy);
+		goto out;
+	}
+	switch_task_namespaces(tsk, new_nsproxy);
+out:
+	fput(file);
+	return err;
+}
+
 static int __init nsproxy_cache_init(void)
 {
 	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
-- 
1.6.5.2.143.g8cc62

^ permalink raw reply related

* [PATCH 1/8] ns: proc files for namespace naming policy.
From: Eric W. Biederman @ 2010-09-23  8:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linux Containers, netdev, netfilter-devel, linux-fsdevel, jamal,
	Daniel Lezcano, Linus Torvalds, Michael Kerrisk, Ulrich Drepper,
	Al Viro, David Miller, Serge E. Hallyn, Pavel Emelyanov,
	Pavel Emelyanov, Ben Greear, Matt Helsley, Jonathan Corbet,
	Sukadev Bhattiprolu, Jan Engelhardt, Patrick McHardy
In-Reply-To: <m1ocborgq7.fsf@fess.ebiederm.org>


Create files under /proc/<pid>/ns/ to allow controlling the
namespaces of a process.

This addresses three specific problems that can make namespaces hard to
work with.
- Namespaces require a dedicated process to pin them in memory.
- It is not possible to use a namespace unless you are the child
  of the original creator.
- Namespaces don't have names that userspace can use to talk about
  them.

The namespace files under /proc/<pid>/ns/ can be opened and the
file descriptor can be used to talk about a specific namespace, and
to keep the specified namespace alive.

A namespace can be kept alive by either holding the file descriptor
open or bind mounting the file someplace else.  aka:
mount --bind /proc/self/ns/net /some/filesystem/path
mount --bind /proc/self/fd/<N> /some/filesystem/path

This allows namespaces to be named with userspace policy.

It requires additional support to make use of these filedescriptors
and that will be comming in the following patches.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 fs/proc/Makefile        |    1 +
 fs/proc/base.c          |   22 +++---
 fs/proc/inode.c         |    7 ++
 fs/proc/internal.h      |   18 +++++
 fs/proc/namespaces.c    |  183 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/proc_fs.h |   16 ++++
 6 files changed, 236 insertions(+), 11 deletions(-)
 create mode 100644 fs/proc/namespaces.c

diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 2758e2a..3cf2529 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -19,6 +19,7 @@ proc-y	+= stat.o
 proc-y	+= uptime.o
 proc-y	+= version.o
 proc-y	+= softirqs.o
+proc-y	+= namespaces.o
 proc-$(CONFIG_PROC_SYSCTL)	+= proc_sysctl.o
 proc-$(CONFIG_NET)		+= proc_net.o
 proc-$(CONFIG_PROC_KCORE)	+= kcore.o
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a1c43e7..30b9384 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -550,7 +550,7 @@ static int proc_fd_access_allowed(struct inode *inode)
 	return allowed;
 }
 
-static int proc_setattr(struct dentry *dentry, struct iattr *attr)
+int proc_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	int error;
 	struct inode *inode = dentry->d_inode;
@@ -1585,8 +1585,7 @@ static int task_dumpable(struct task_struct *task)
 	return 0;
 }
 
-
-static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
+struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
 {
 	struct inode * inode;
 	struct proc_inode *ei;
@@ -1627,7 +1626,7 @@ out_unlock:
 	return NULL;
 }
 
-static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
 	struct inode *inode = dentry->d_inode;
 	struct task_struct *task;
@@ -1668,7 +1667,7 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
  * made this apply to all per process world readable and executable
  * directories.
  */
-static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
+int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
 	struct task_struct *task = get_proc_task(inode);
@@ -1704,7 +1703,7 @@ static int pid_delete_dentry(struct dentry * dentry)
 	return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
 }
 
-static const struct dentry_operations pid_dentry_operations =
+const struct dentry_operations pid_dentry_operations =
 {
 	.d_revalidate	= pid_revalidate,
 	.d_delete	= pid_delete_dentry,
@@ -1712,9 +1711,6 @@ static const struct dentry_operations pid_dentry_operations =
 
 /* Lookups */
 
-typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
-				struct task_struct *, const void *);
-
 /*
  * Fill a directory entry.
  *
@@ -1727,8 +1723,8 @@ typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
  * reported by readdir in sync with the inode numbers reported
  * by stat.
  */
-static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-	char *name, int len,
+int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+	const char *name, int len,
 	instantiate_t instantiate, struct task_struct *task, const void *ptr)
 {
 	struct dentry *child, *dir = filp->f_path.dentry;
@@ -2360,6 +2356,8 @@ static const struct inode_operations proc_attr_dir_inode_operations = {
 
 #endif
 
+
+
 #ifdef CONFIG_ELF_CORE
 static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
 					 size_t count, loff_t *ppos)
@@ -2668,6 +2666,7 @@ static const struct pid_entry tgid_base_stuff[] = {
 	DIR("task",       S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations),
 	DIR("fd",         S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
 	DIR("fdinfo",     S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
+	DIR("ns",	  S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
 #ifdef CONFIG_NET
 	DIR("net",        S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
 #endif
@@ -3007,6 +3006,7 @@ out_no_task:
 static const struct pid_entry tid_base_stuff[] = {
 	DIR("fd",        S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
 	DIR("fdinfo",    S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
+	DIR("ns",	 S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
 	REG("environ",   S_IRUSR, proc_environ_operations),
 	INF("auxv",      S_IRUSR, proc_pid_auxv),
 	ONE("status",    S_IRUGO, proc_pid_status),
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 9c2b5f4..1e3e720 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -28,6 +28,7 @@
 static void proc_evict_inode(struct inode *inode)
 {
 	struct proc_dir_entry *de;
+	const struct proc_ns_operations *ns_ops;
 
 	truncate_inode_pages(&inode->i_data, 0);
 	end_writeback(inode);
@@ -41,6 +42,10 @@ static void proc_evict_inode(struct inode *inode)
 		pde_put(de);
 	if (PROC_I(inode)->sysctl)
 		sysctl_head_put(PROC_I(inode)->sysctl);
+	/* Release any associated namespace */
+	ns_ops = PROC_I(inode)->ns_ops;
+	if (ns_ops && ns_ops->put)
+		ns_ops->put(PROC_I(inode)->ns);
 }
 
 struct vfsmount *proc_mnt;
@@ -61,6 +66,8 @@ static struct inode *proc_alloc_inode(struct super_block *sb)
 	ei->pde = NULL;
 	ei->sysctl = NULL;
 	ei->sysctl_entry = NULL;
+	ei->ns = NULL;
+	ei->ns_ops = NULL;
 	inode = &ei->vfs_inode;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	return inode;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 1f24a3e..6b61c7f 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -119,3 +119,21 @@ struct inode *proc_get_inode(struct super_block *, unsigned int, struct proc_dir
  */
 int proc_readdir(struct file *, void *, filldir_t);
 struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
+
+
+
+/* Lookups */
+typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
+				struct task_struct *, const void *);
+int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+	const char *name, int len,
+	instantiate_t instantiate, struct task_struct *task, const void *ptr);
+int pid_revalidate(struct dentry *dentry, struct nameidata *nd);
+struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task);
+extern const struct dentry_operations pid_dentry_operations;
+int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
+int proc_setattr(struct dentry *dentry, struct iattr *attr);
+
+extern const struct inode_operations proc_ns_dir_inode_operations;
+extern const struct file_operations proc_ns_dir_operations;
+
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
new file mode 100644
index 0000000..f33537f
--- /dev/null
+++ b/fs/proc/namespaces.c
@@ -0,0 +1,183 @@
+#include <linux/proc_fs.h>
+#include <linux/nsproxy.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/fs_struct.h>
+#include <linux/mount.h>
+#include <linux/path.h>
+#include <linux/namei.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+#include <net/net_namespace.h>
+#include <linux/mnt_namespace.h>
+#include <linux/ipc_namespace.h>
+#include <linux/pid_namespace.h>
+#include "internal.h"
+
+
+static const struct proc_ns_operations *ns_entries[] = {
+};
+
+static const struct file_operations ns_file_operations = {
+	.llseek		= no_llseek,
+};
+
+static struct dentry *proc_ns_instantiate(struct inode *dir,
+	struct dentry *dentry, struct task_struct *task, const void *ptr)
+{
+	const struct proc_ns_operations *ns_ops = ptr;
+	struct inode *inode;
+	struct proc_inode *ei;
+	struct dentry *error = ERR_PTR(-ENOENT);
+
+	inode = proc_pid_make_inode(dir->i_sb, task);
+	if (!inode)
+		goto out;
+
+	ei = PROC_I(inode);
+	inode->i_mode = S_IFREG|S_IRUSR;
+	inode->i_fop  = &ns_file_operations;
+	ei->ns_ops    = ns_ops;
+	ei->ns	      = ns_ops->get(task);
+
+	dentry->d_op = &pid_dentry_operations;
+	d_add(dentry, inode);
+	/* Close the race of the process dying before we return the dentry */
+	if (pid_revalidate(dentry, NULL))
+		error = NULL;
+out:
+	return error;
+}
+
+static int proc_ns_fill_cache(struct file *filp, void *dirent,
+	filldir_t filldir, struct task_struct *task,
+	const struct proc_ns_operations *ops)
+{
+	return proc_fill_cache(filp, dirent, filldir,
+				ops->name.name, ops->name.len,
+				proc_ns_instantiate, task, ops);
+}
+
+static int proc_ns_dir_readdir(struct file *filp, void *dirent,
+				filldir_t filldir)
+{
+	int i;
+	struct dentry *dentry = filp->f_path.dentry;
+	struct inode *inode = dentry->d_inode;
+	struct task_struct *task = get_proc_task(inode);
+	const struct proc_ns_operations **entry, **last;
+	ino_t ino;
+	int ret;
+
+	ret = -ENOENT;
+	if (!task)
+		goto out_no_task;
+
+	ret = -EPERM;
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out;
+
+	ret = 0;
+	i = filp->f_pos;
+	switch (i) {
+	case 0:
+		ino = inode->i_ino;
+		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+			goto out;
+		i++;
+		filp->f_pos++;
+		/* fall through */
+	case 1:
+		ino = parent_ino(dentry);
+		if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+			goto out;
+		i++;
+		filp->f_pos++;
+		/* fall through */
+	default:
+		i -= 2;
+		if (i >= ARRAY_SIZE(ns_entries)) {
+			ret = 1;
+			goto out;
+		}
+		entry = ns_entries + i;
+		last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
+		while (entry <= last) {
+			if (proc_ns_fill_cache(filp, dirent, filldir,
+						task, *entry) < 0)
+				goto out;
+			filp->f_pos++;
+			entry++;
+		}
+	}
+
+	ret = 1;
+out:
+	put_task_struct(task);
+out_no_task:
+	return ret;
+}
+
+const struct file_operations proc_ns_dir_operations = {
+	.read		= generic_read_dir,
+	.readdir	= proc_ns_dir_readdir,
+};
+
+static struct dentry *proc_ns_dir_lookup(struct inode *dir,
+				struct dentry *dentry, struct nameidata *nd)
+{
+	struct dentry *error;
+	struct task_struct *task = get_proc_task(dir);
+	const struct proc_ns_operations **entry, **last;
+	unsigned int len = dentry->d_name.len;
+
+	error = ERR_PTR(-ENOENT);
+
+	if (!task)
+		goto out_no_task;
+
+	error = ERR_PTR(-EPERM);
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out;
+
+	last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
+	for (entry = ns_entries; entry <= last; entry++) {
+		if ((*entry)->name.len != len)
+			continue;
+		if (!memcmp(dentry->d_name.name, (*entry)->name.name, len))
+			break;
+	}
+	if (entry > last)
+		goto out;
+
+	error = proc_ns_instantiate(dir, dentry, task, *entry);
+out:
+	put_task_struct(task);
+out_no_task:
+	return error;
+}
+
+const struct inode_operations proc_ns_dir_inode_operations = {
+	.lookup		= proc_ns_dir_lookup,
+	.getattr	= pid_getattr,
+	.setattr	= proc_setattr,
+};
+
+struct file *proc_ns_fget(int fd)
+{
+	struct file *file;
+
+	file = fget(fd);
+	if (!file)
+		return ERR_PTR(-EBADF);
+
+	if (file->f_op != &ns_file_operations)
+		goto out_invalid;
+
+	return file;
+
+out_invalid:
+	fput(file);
+	return ERR_PTR(-EINVAL);
+}
+
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 379eaed..a6c26f0 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -250,6 +250,20 @@ kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
 extern void kclist_add(struct kcore_list *, void *, size_t, int type);
 #endif
 
+struct nsproxy;
+struct proc_ns_operations {
+	struct {
+		unsigned int len;
+		const char *name;
+	} name;
+	unsigned int name_len;
+	void *(*get)(struct task_struct *task);
+	void (*put)(void *ns);
+	int (*install)(struct nsproxy *nsproxy, void *ns);
+};
+#define PROC_NSNAME(NAME) { .name = (NAME), .len = (sizeof(NAME) - 1), }
+extern struct file *proc_ns_fget(int fd);
+
 union proc_op {
 	int (*proc_get_link)(struct inode *, struct path *);
 	int (*proc_read)(struct task_struct *task, char *page);
@@ -268,6 +282,8 @@ struct proc_inode {
 	struct proc_dir_entry *pde;
 	struct ctl_table_header *sysctl;
 	struct ctl_table *sysctl_entry;
+	void *ns;
+	const struct proc_ns_operations *ns_ops;
 	struct inode vfs_inode;
 };
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related

* [ABI REVIEW][PATCH 0/8] Namespace file descriptors
From: Eric W. Biederman @ 2010-09-23  8:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linux Containers, netdev, netfilter-devel, linux-fsdevel, jamal,
	Daniel Lezcano, Linus Torvalds, Michael Kerrisk, Ulrich Drepper,
	Al Viro, David Miller, Serge E. Hallyn, Pavel Emelyanov,
	Pavel Emelyanov, Ben Greear, Matt Helsley, Jonathan Corbet,
	Sukadev Bhattiprolu, Jan Engelhardt, Patrick McHardy


Introduce file for manipulating namespaces and related syscalls.
files:
/proc/self/ns/<nstype>

syscalls:
int setns(unsigned long nstype, int fd);
socketat(int nsfd, int family, int type, int protocol);

Netlink attribute:
IFLA_NS_FD int fd.

Name space file descriptors address three specific problems that
can make namespaces hard to work with.
- Namespaces require a dedicated process to pin them in memory.
- It is not possible to use a namespace unless you are the child of the
  original creator.
- Namespaces don't have names that userspace can use to talk about them.

Opening of the /proc/self/ns/<nstype> files return a file descriptor
that can be used to talk about a specific namespace, and to keep the
specified namespace alive.

/proc/self/ns/<nstype> can be bind mounted as:
mount --bind /proc/self/ns/net /some/filesystem/path
to keep the namespace alive as long as the mount exists.

setns() as a companion to unshare allows changing the namespace
of the current process, being able to unshare the namespace is
a requirement.

There are two primary envisioned uses for this functionality.
o ``Entering'' an existing container.
o Allowing multiple network namespaces to be in use at once on
  the same machine, without requiring elaborate infrastructure.

Overall this received positive reviews on the containers list but this
needs a wider review of the ABI as this is pretty fundamental kernel
functionality.


I have left out the pid namespaces bits for the moment because the pid
namespace still needs work before it is safe to unshare, and my concern
at the moment is ensuring the system calls seem reasonable.

Eric W. Biederman (8):
      ns: proc files for namespace naming policy.
      ns: Introduce the setns syscall
      ns proc: Add support for the network namespace.
      ns proc: Add support for the uts namespace
      ns proc: Add support for the ipc namespace
      ns proc: Add support for the mount namespace
      net: Allow setting the network namespace by fd
      net: Implement socketat.

---
 fs/namespace.c              |   57 +++++++++++++
 fs/proc/Makefile            |    1 +
 fs/proc/base.c              |   22 +++---
 fs/proc/inode.c             |    7 ++
 fs/proc/internal.h          |   18 ++++
 fs/proc/namespaces.c        |  193 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/if_link.h     |    1 +
 include/linux/proc_fs.h     |   20 +++++
 include/net/net_namespace.h |    1 +
 ipc/namespace.c             |   31 +++++++
 kernel/nsproxy.c            |   39 +++++++++
 kernel/utsname.c            |   32 +++++++
 net/core/net_namespace.c    |   56 +++++++++++++
 net/core/rtnetlink.c        |    4 +-
 net/socket.c                |   26 ++++++-
 15 files changed, 494 insertions(+), 14 deletions(-)

^ 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