[Debian] Re: lenny updates (patch error!)
Kir Kolyshkin
kir at openvz.org
Sat Mar 14 18:17:29 EDT 2009
Ola Lundqvist wrote:
> Hi Kir
>
> One of the patches do not work...
>
> I 2 0016-nfs-fix-nfs-clinet-in-VE-finally.pa [text/plain, 7bit, us-ascii, 35K]
> Ok.
>
> I 3 0018-nfs-add-missed-ve_nfs.h-file.patch [text/plain, 7bit, us-ascii, 1,3K]
> Ok.
>
> I 4 0050-nfs-Fix-access-to-freed-memory.patc [text/plain, 7bit, us-ascii, 2,5K]
> Ok.
>
> I 5 0051-NFS-NFS-super-blocks-in-different-V [text/plain, 7bit, us-ascii, 1,1K]
> Ok.
>
> I 6 0056-nfs-Fix-nfs_match_client.patch [text/plain, 7bit, us-ascii, 1,0K]
> Ok.
>
> I 7 0060-nfs-use-kthread_run_ve-to-start-loc [text/plain, 7bit, us-ascii, 1,1K]
> Not OK!
> I get a build error for this one. It seems like there is something else missing here!
> The function kthread_run_ve must have been defined by some other patch that is not applied.
> Do you know where it was defined?
>
Sorry, this prerequires another patch introducing the needed function:
http://git.openvz.org/?p=linux-2.6.26-openvz;a=commit;h=d4988b6efbdfb1b2416288c362d60351e1c5e5ff
> LD fs/lockd/built-in.o
> CC [M] fs/lockd/clntlock.o
> CC [M] fs/lockd/clntproc.o
> CC [M] fs/lockd/host.o
> CC [M] fs/lockd/svc.o
> fs/lockd/svc.c: In function ‘lockd_up’:
> fs/lockd/svc.c:310: error: implicit declaration of function ‘kthread_run_ve’
> fs/lockd/svc.c:310: warning: assignment makes pointer from integer without a cast
> make[4]: *** [fs/lockd/svc.o] Error 1
> make[3]: *** [fs/lockd] Error 2
> make[2]: *** [fs] Error 2
> make[2]: Leaving directory `/home/ola/build/debian/kernel/linux-2.6-2.6.26/debian/build/build_i386_openvz_686'
> make[1]: *** [debian/stamps/build_i386_openvz_686_plain] Error 2
> make[1]: Leaving directory `/home/ola/build/debian/kernel/linux-2.6-2.6.26'
> make: *** [binary-arch_i386_openvz_686_real] Error 2
>
> Best regards,
>
> // Ola
>
> On Tue, Mar 10, 2009 at 12:36:49AM +0300, Kir Kolyshkin wrote:
>
>> Ola Lundqvist wrote:
>>
>>> Hi Dann
>>>
>>> I have to ask Kir about some of the things. Kir, please comment on the
>>> below.
>>>
>>>
>>>
>>>>>>> #501985:
>>>>>>> From: maximilian attems
>>>>>>> the upstream nfs fixes are abi breakers and thus can't be integrated
>>>>>>> at this point they will be for the first point release were abi
>>>>>>> breaking will be allowed again.
>>>>>>>
>>>>>>>
>>>>>> What is the fix for this - does upstream openvz include it?
>>>>>>
>>>>>>
>>>>> Yes it is found upstream. See the file
>>>>> http://download.openvz.org/kernel/branches/2.6.26/current/patches/patch-chekhov.1-combined.gz
>>>>> The current patch do not touch any nfs/ files and upstream does. The
>>>>> patch
>>>>> now in use was not fully completed when it was incorporated by
>>>>> Maximilian.
>>>>>
>>>>>
>>>> I see - so we need to identify which additional changes are needed.
>>>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=66ec7f7f493fb98e8baa6591e9225086ae640fb8
>>>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=39bb1ee59237272cd20e1f8696cefbd6a787cfc8
>>>>
>>>> Is this severe enough to fix in a stable release? If we consider this
>>>> a regression from etch (since kernel-patch-openvz supplied this), than
>>>> maybe so. Is the risk of regression low? Well - these patches would
>>>> only get applied on openvz kernels which currently don't support nfs
>>>> at all so, assuming these changes are nfs-specific, risk should be
>>>> low.
>>>>
>>>>
>>> This is where I need to ask Kir. Kir do you know the answer to this
>>> question?
>>>
>> If we do want to have working NFS from a container, the following
>> patches are a must:
>>
>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=66ec7f7f493fb98e8baa6591e9225086ae640fb8
>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=2a083801fe1655bf9e403469c494b83a72186f56
>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=b8b70c37c8b114780a02492703c9682d8b09a14b
>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=840ea01d953ca0ad7629ea66ca0f50685ca06921
>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=39bb1ee59237272cd20e1f8696cefbd6a787cfc8
>> http://git.openvz.org/?p=linux-2.6.26-openvz;a=commitdiff;h=ba0ce90476e6267f6c035f9c9ef7c45d6195ec6e
>>
>> Those patches are also attached for your convenience.
>>
>> Also, while I am at it... I am currently checking all the ~80 patches
>> that are not in openvz lenny kernel. Looks like most are really needed.
>> Let me suggest some in a few emails I will send as a reply to this one.
>>
>
>
>> From 66ec7f7f493fb98e8baa6591e9225086ae640fb8 Mon Sep 17 00:00:00 2001
>> From: Denis Lunev <den at openvz.org>
>> Date: Tue, 9 Sep 2008 18:32:50 +0400
>> Subject: [PATCH] nfs: fix nfs clinet in VE (finally)
>>
>> Ah! Thanks to our Den we now have an NFS client back!
>>
>> It turned out, that while going the 2.6.18->2.6.20->...->2.6.26
>> NFS changed too much and we didn't test it properly (nobody
>> required it badly) in the intermediate states, lost many hunks
>> and that's why the patch is *that* big.
>>
>> Signed-off-by: Denis Lunev <den at openvz.org>
>> Signed-off-by: Pavel Emelyanov <xemul at openvz.org>
>> ---
>> fs/lockd/clntproc.c | 4 ++
>> fs/lockd/host.c | 52 +++++++++++++++++++
>> fs/lockd/svc.c | 54 ++++++++++++++++----
>> fs/lockd/svcsubs.c | 3 +
>> fs/nfs/client.c | 11 ++++
>> fs/nfs/super.c | 70 +++++++++++++++++++++++++-
>> fs/super.c | 2 +
>> include/linux/lockd/lockd.h | 8 ++-
>> include/linux/nfs_fs_sb.h | 1 +
>> include/linux/sunrpc/clnt.h | 2 +
>> include/linux/sunrpc/xprt.h | 9 +++
>> include/linux/ve.h | 12 ++++
>> include/linux/vzcalluser.h | 1 +
>> include/net/sock.h | 7 +++
>> net/socket.c | 2 +-
>> net/sunrpc/clnt.c | 117 +++++++++++++++++++++++++++++++++++++++++-
>> net/sunrpc/rpc_pipe.c | 1 +
>> net/sunrpc/sched.c | 10 +++-
>> net/sunrpc/sunrpc_syms.c | 5 ++
>> net/sunrpc/svcsock.c | 21 ++------
>> net/sunrpc/xprt.c | 8 +++
>> net/sunrpc/xprtsock.c | 61 ++++++++++++++++++++--
>> 22 files changed, 417 insertions(+), 44 deletions(-)
>>
>> diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
>> index 5df517b..d05fcba 100644
>> --- a/fs/lockd/clntproc.c
>> +++ b/fs/lockd/clntproc.c
>> @@ -156,12 +156,15 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
>> {
>> struct nlm_rqst *call;
>> int status;
>> + struct ve_struct *ve;
>>
>> nlm_get_host(host);
>> call = nlm_alloc_call(host);
>> if (call == NULL)
>> return -ENOMEM;
>>
>> + ve = set_exec_env(host->owner_env);
>> +
>> nlmclnt_locks_init_private(fl, host);
>> /* Set up the argument struct */
>> nlmclnt_setlockargs(call, fl);
>> @@ -181,6 +184,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
>> fl->fl_ops = NULL;
>>
>> dprintk("lockd: clnt proc returns %d\n", status);
>> + (void)set_exec_env(ve);
>> return status;
>> }
>> EXPORT_SYMBOL_GPL(nlmclnt_proc);
>> diff --git a/fs/lockd/host.c b/fs/lockd/host.c
>> index a17664c..cfa0cf3 100644
>> --- a/fs/lockd/host.c
>> +++ b/fs/lockd/host.c
>> @@ -53,6 +53,7 @@ static struct nlm_host *nlm_lookup_host(int server,
>> struct nlm_host *host;
>> struct nsm_handle *nsm = NULL;
>> int hash;
>> + struct ve_struct *ve;
>>
>> dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
>> ", p=%d, v=%u, my role=%s, name=%.*s)\n",
>> @@ -78,10 +79,14 @@ static struct nlm_host *nlm_lookup_host(int server,
>> * different NLM rpc_clients into one single nlm_host object.
>> * This would allow us to have one nlm_host per address.
>> */
>> +
>> + ve = get_exec_env();
>> chain = &nlm_hosts[hash];
>> hlist_for_each_entry(host, pos, chain, h_hash) {
>> if (!nlm_cmp_addr(&host->h_addr, sin))
>> continue;
>> + if (!ve_accessible_strict(host->owner_env, ve))
>> + continue;
>>
>> /* See if we have an NSM handle for this client */
>> if (!nsm)
>> @@ -141,6 +146,7 @@ static struct nlm_host *nlm_lookup_host(int server,
>> spin_lock_init(&host->h_lock);
>> INIT_LIST_HEAD(&host->h_granted);
>> INIT_LIST_HEAD(&host->h_reclaim);
>> + host->owner_env = ve;
>>
>> nrhosts++;
>> out:
>> @@ -454,6 +460,52 @@ nlm_gc_hosts(void)
>> next_gc = jiffies + NLM_HOST_COLLECT;
>> }
>>
>> +#ifdef CONFIG_VE
>> +void ve_nlm_shutdown_hosts(struct ve_struct *ve)
>> +{
>> + envid_t veid = ve->veid;
>> + int i;
>> +
>> + dprintk("lockd: shutting down host module for ve %d\n", veid);
>> + mutex_lock(&nlm_host_mutex);
>> +
>> + /* Perform a garbage collection pass */
>> + for (i = 0; i < NLM_HOST_NRHASH; i++) {
>> + struct nlm_host *host;
>> + struct hlist_node *pos;
>> +
>> + hlist_for_each_entry(host, pos, &nlm_hosts[i], h_hash) {
>> + struct rpc_clnt *clnt;
>> +
>> + if (ve != host->owner_env)
>> + continue;
>> +
>> + hlist_del(&host->h_hash);
>> + if (host->h_nsmhandle)
>> + host->h_nsmhandle->sm_monitored = 0;
>> + dprintk("lockd: delete host %s ve %d\n", host->h_name,
>> + veid);
>> + if ((clnt = host->h_rpcclnt) != NULL) {
>> + if (!list_empty(&clnt->cl_tasks)) {
>> + struct rpc_xprt *xprt;
>> +
>> + printk(KERN_WARNING
>> + "lockd: active RPC handle\n");
>> + rpc_killall_tasks(clnt);
>> + xprt = clnt->cl_xprt;
>> + xprt_disconnect_done(xprt);
>> + xprt->ops->close(xprt);
>> + } else
>> + rpc_shutdown_client(clnt);
>> + }
>> + kfree(host);
>> + nrhosts--;
>> + }
>> + }
>> +
>> + mutex_unlock(&nlm_host_mutex);
>> +}
>> +#endif
>>
>> /*
>> * Manage NSM handles
>> diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
>> index 2169af4..f9f02fc 100644
>> --- a/fs/lockd/svc.c
>> +++ b/fs/lockd/svc.c
>> @@ -27,6 +27,7 @@
>> #include <linux/mutex.h>
>> #include <linux/kthread.h>
>> #include <linux/freezer.h>
>> +#include <linux/ve_proto.h>
>>
>> #include <linux/sunrpc/types.h>
>> #include <linux/sunrpc/stats.h>
>> @@ -48,11 +49,13 @@ struct nlmsvc_binding * nlmsvc_ops;
>> EXPORT_SYMBOL(nlmsvc_ops);
>>
>> static DEFINE_MUTEX(nlmsvc_mutex);
>> -static unsigned int nlmsvc_users;
>> -static struct task_struct *nlmsvc_task;
>> -static struct svc_serv *nlmsvc_serv;
>> -int nlmsvc_grace_period;
>> -unsigned long nlmsvc_timeout;
>> +#ifndef CONFIG_VE
>> +static unsigned int _nlmsvc_users;
>> +static struct task_struct *_nlmsvc_task;
>> +int _nlmsvc_grace_period;
>> +unsigned long _nlmsvc_timeout;
>> +static struct svc_serv *_nlmsvc_serv;
>> +#endif
>>
>> /*
>> * These can be set at insmod time (useful for NFS as root filesystem),
>> @@ -175,6 +178,10 @@ lockd(void *vrqstp)
>> */
>> err = svc_recv(rqstp, timeout);
>> if (err == -EAGAIN || err == -EINTR) {
>> +#ifdef CONFIG_VE
>> + if (!get_exec_env()->is_running)
>> + break;
>> +#endif
>> preverr = err;
>> continue;
>> }
>> @@ -338,12 +345,12 @@ lockd_down(void)
>> } else {
>> printk(KERN_ERR "lockd_down: no users! task=%p\n",
>> nlmsvc_task);
>> - BUG();
>> + goto out;
>> }
>>
>> if (!nlmsvc_task) {
>> printk(KERN_ERR "lockd_down: no lockd running.\n");
>> - BUG();
>> + goto out;
>> }
>> kthread_stop(nlmsvc_task);
>> out:
>> @@ -485,6 +492,29 @@ static int lockd_authenticate(struct svc_rqst *rqstp)
>> return SVC_DENIED;
>> }
>>
>> +#ifdef CONFIG_VE
>> +extern void ve_nlm_shutdown_hosts(struct ve_struct *ve);
>> +
>> +static int ve_lockd_start(void *data)
>> +{
>> + return 0;
>> +}
>> +
>> +static void ve_lockd_stop(void *data)
>> +{
>> + struct ve_struct *ve = (struct ve_struct *)data;
>> +
>> + ve_nlm_shutdown_hosts(ve);
>> + flush_scheduled_work();
>> +}
>> +
>> +static struct ve_hook lockd_hook = {
>> + .init = ve_lockd_start,
>> + .fini = ve_lockd_stop,
>> + .owner = THIS_MODULE,
>> + .priority = HOOK_PRIO_FS,
>> +};
>> +#endif
>>
>> param_set_min_max(port, int, simple_strtol, 0, 65535)
>> param_set_min_max(grace_period, unsigned long, simple_strtoul,
>> @@ -512,16 +542,20 @@ module_param(nsm_use_hostnames, bool, 0644);
>>
>> static int __init init_nlm(void)
>> {
>> + ve_hook_register(VE_SS_CHAIN, &lockd_hook);
>> #ifdef CONFIG_SYSCTL
>> nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
>> - return nlm_sysctl_table ? 0 : -ENOMEM;
>> -#else
>> - return 0;
>> + if (nlm_sysctl_table == NULL) {
>> + ve_hook_unregister(&lockd_hook);
>> + return -ENOMEM;
>> + }
>> #endif
>> + return 0;
>> }
>>
>> static void __exit exit_nlm(void)
>> {
>> + ve_hook_unregister(&lockd_hook);
>> /* FIXME: delete all NLM clients */
>> nlm_shutdown_hosts();
>> #ifdef CONFIG_SYSCTL
>> diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
>> index d1c48b5..c226c9d 100644
>> --- a/fs/lockd/svcsubs.c
>> +++ b/fs/lockd/svcsubs.c
>> @@ -335,6 +335,9 @@ nlmsvc_is_client(void *data, struct nlm_host *dummy)
>> {
>> struct nlm_host *host = data;
>>
>> + if (!ve_accessible_strict(host->owner_env, get_exec_env()))
>> + return 0;
>> +
>> if (host->h_server) {
>> /* we are destroying locks even though the client
>> * hasn't asked us too, so don't unmonitor the
>> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
>> index f2a092c..3366257 100644
>> --- a/fs/nfs/client.c
>> +++ b/fs/nfs/client.c
>> @@ -127,6 +127,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
>>
>> atomic_set(&clp->cl_count, 1);
>> clp->cl_cons_state = NFS_CS_INITING;
>> + clp->owner_env = get_exec_env();
>>
>> memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen);
>> clp->cl_addrlen = cl_init->addrlen;
>> @@ -257,6 +258,7 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
>> struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
>> {
>> struct nfs_client *clp;
>> + struct ve_struct *ve = get_exec_env();
>>
>> spin_lock(&nfs_client_lock);
>> list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
>> @@ -272,6 +274,9 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
>>
>> if (addr->sa_family != clap->sa_family)
>> continue;
>> + if (!ve_accessible_strict(clp->owner_env, ve))
>> + continue;
>> +
>> /* Match only the IP address, not the port number */
>> if (!nfs_sockaddr_match_ipaddr(addr, clap))
>> continue;
>> @@ -292,6 +297,7 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
>> {
>> struct sockaddr *sap = (struct sockaddr *)&clp->cl_addr;
>> u32 nfsvers = clp->rpc_ops->version;
>> + struct ve_struct *ve = get_exec_env();
>>
>> spin_lock(&nfs_client_lock);
>> list_for_each_entry_continue(clp, &nfs_client_list, cl_share_link) {
>> @@ -307,6 +313,9 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
>>
>> if (sap->sa_family != clap->sa_family)
>> continue;
>> + if (!ve_accessible_strict(clp->owner_env, ve))
>> + continue;
>> +
>> /* Match only the IP address, not the port number */
>> if (!nfs_sockaddr_match_ipaddr(sap, clap))
>> continue;
>> @@ -326,7 +335,9 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
>> static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
>> {
>> struct nfs_client *clp;
>> + struct ve_struct *ve;
>>
>> + ve = get_exec_env();
>> list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
>> /* Don't match clients that failed to initialise properly */
>> if (clp->cl_cons_state < 0)
>> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
>> index 614efee..cb4e28a 100644
>> --- a/fs/nfs/super.c
>> +++ b/fs/nfs/super.c
>> @@ -50,6 +50,9 @@
>> #include <linux/nfs_xdr.h>
>> #include <linux/magic.h>
>> #include <linux/parser.h>
>> +#include <linux/ve_proto.h>
>> +#include <linux/vzcalluser.h>
>> +#include <linux/ve_nfs.h>
>>
>> #include <asm/system.h>
>> #include <asm/uaccess.h>
>> @@ -213,7 +216,8 @@ static struct file_system_type nfs_fs_type = {
>> .name = "nfs",
>> .get_sb = nfs_get_sb,
>> .kill_sb = nfs_kill_super,
>> - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
>> + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|
>> + FS_BINARY_MOUNTDATA|FS_VIRTUALIZED,
>> };
>>
>> struct file_system_type nfs_xdev_fs_type = {
>> @@ -221,7 +225,8 @@ struct file_system_type nfs_xdev_fs_type = {
>> .name = "nfs",
>> .get_sb = nfs_xdev_get_sb,
>> .kill_sb = nfs_kill_super,
>> - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
>> + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|
>> + FS_BINARY_MOUNTDATA|FS_VIRTUALIZED,
>> };
>>
>> static const struct super_operations nfs_sops = {
>> @@ -286,6 +291,55 @@ static struct shrinker acl_shrinker = {
>> .seeks = DEFAULT_SEEKS,
>> };
>>
>> +#ifdef CONFIG_VE
>> +static int ve_nfs_start(void *data)
>> +{
>> + return 0;
>> +}
>> +
>> +static void ve_nfs_stop(void *data)
>> +{
>> + struct ve_struct *ve;
>> + struct super_block *sb;
>> +
>> + flush_scheduled_work();
>> +
>> + ve = (struct ve_struct *)data;
>> + /* Basically, on a valid stop we can be here iff NFS was mounted
>> + read-only. In such a case client force-stop is not a problem.
>> + If we are here and NFS is read-write, we are in a FORCE stop, so
>> + force the client to stop.
>> + Lock daemon is already dead.
>> + Only superblock client remains. Den */
>> + spin_lock(&sb_lock);
>> + list_for_each_entry(sb, &super_blocks, s_list) {
>> + struct rpc_clnt *clnt;
>> + struct rpc_xprt *xprt;
>> + if (sb->s_type != &nfs_fs_type)
>> + continue;
>> + clnt = NFS_SB(sb)->client;
>> + if (!ve_accessible_strict(clnt->cl_xprt->owner_env, ve))
>> + continue;
>> + clnt->cl_broken = 1;
>> + rpc_killall_tasks(clnt);
>> +
>> + xprt = clnt->cl_xprt;
>> + xprt_disconnect_done(xprt);
>> + xprt->ops->close(xprt);
>> + }
>> + spin_unlock(&sb_lock);
>> +
>> + flush_scheduled_work();
>> +}
>> +
>> +static struct ve_hook nfs_hook = {
>> + .init = ve_nfs_start,
>> + .fini = ve_nfs_stop,
>> + .owner = THIS_MODULE,
>> + .priority = HOOK_PRIO_NET_POST,
>> +};
>> +#endif
>> +
>> /*
>> * Register the NFS filesystems
>> */
>> @@ -306,6 +360,7 @@ int __init register_nfs_fs(void)
>> goto error_2;
>> #endif
>> register_shrinker(&acl_shrinker);
>> + ve_hook_register(VE_SS_CHAIN, &nfs_hook);
>> return 0;
>>
>> #ifdef CONFIG_NFS_V4
>> @@ -324,6 +379,7 @@ error_0:
>> void __exit unregister_nfs_fs(void)
>> {
>> unregister_shrinker(&acl_shrinker);
>> + ve_hook_unregister(&nfs_hook);
>> #ifdef CONFIG_NFS_V4
>> unregister_filesystem(&nfs4_fs_type);
>> #endif
>> @@ -1591,6 +1647,11 @@ static int nfs_get_sb(struct file_system_type *fs_type,
>> .mntflags = flags,
>> };
>> int error = -ENOMEM;
>> + struct ve_struct *ve;
>> +
>> + ve = get_exec_env();
>> + if (!ve_is_super(ve) && !(ve->features & VE_FEATURE_NFS))
>> + return -ENODEV;
>>
>> data = kzalloc(sizeof(*data), GFP_KERNEL);
>> mntfh = kzalloc(sizeof(*mntfh), GFP_KERNEL);
>> @@ -1700,6 +1761,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
>> .mntflags = flags,
>> };
>> int error;
>> + struct ve_struct *ve;
>> +
>> + ve = get_exec_env();
>> + if (!ve_is_super(ve) && !(ve->features & VE_FEATURE_NFS))
>> + return -ENODEV;
>>
>> dprintk("--> nfs_xdev_get_sb()\n");
>>
>> diff --git a/fs/super.c b/fs/super.c
>> index 55ce500..960317f 100644
>> --- a/fs/super.c
>> +++ b/fs/super.c
>> @@ -44,7 +44,9 @@
>>
>>
>> LIST_HEAD(super_blocks);
>> +EXPORT_SYMBOL_GPL(super_blocks);
>> DEFINE_SPINLOCK(sb_lock);
>> +EXPORT_SYMBOL_GPL(sb_lock);
>>
>> /**
>> * alloc_super - create new superblock
>> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
>> index 102d928..7ef434d 100644
>> --- a/include/linux/lockd/lockd.h
>> +++ b/include/linux/lockd/lockd.h
>> @@ -61,6 +61,7 @@ struct nlm_host {
>> struct list_head h_granted; /* Locks in GRANTED state */
>> struct list_head h_reclaim; /* Locks in RECLAIM state */
>> struct nsm_handle * h_nsmhandle; /* NSM status handle */
>> + struct ve_struct * owner_env; /* VE owning the host */
>> };
>>
>> struct nsm_handle {
>> @@ -152,8 +153,11 @@ extern struct svc_procedure nlmsvc_procedures[];
>> #ifdef CONFIG_LOCKD_V4
>> extern struct svc_procedure nlmsvc_procedures4[];
>> #endif
>> -extern int nlmsvc_grace_period;
>> -extern unsigned long nlmsvc_timeout;
>> +
>> +#include <linux/ve_nfs.h>
>> +extern int _nlmsvc_grace_period;
>> +extern unsigned long _nlmsvc_timeout;
>> +
>> extern int nsm_use_hostnames;
>>
>> /*
>> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
>> index c9beacd..cb87ca2 100644
>> --- a/include/linux/nfs_fs_sb.h
>> +++ b/include/linux/nfs_fs_sb.h
>> @@ -70,6 +70,7 @@ struct nfs_client {
>> char cl_ipaddr[48];
>> unsigned char cl_id_uniquifier;
>> #endif
>> + struct ve_struct *owner_env;
>> };
>>
>> /*
>> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
>> index 6fff7f8..7b4d4cf 100644
>> --- a/include/linux/sunrpc/clnt.h
>> +++ b/include/linux/sunrpc/clnt.h
>> @@ -43,6 +43,7 @@ struct rpc_clnt {
>> unsigned int cl_softrtry : 1,/* soft timeouts */
>> cl_discrtry : 1,/* disconnect before retry */
>> cl_autobind : 1;/* use getport() */
>> + unsigned int cl_broken : 1;/* no responce for too long */
>>
>> struct rpc_rtt * cl_rtt; /* RTO estimator data */
>> const struct rpc_timeout *cl_timeout; /* Timeout strategy */
>> @@ -56,6 +57,7 @@ struct rpc_clnt {
>> struct rpc_rtt cl_rtt_default;
>> struct rpc_timeout cl_timeout_default;
>> struct rpc_program * cl_program;
>> + unsigned long cl_pr_time;
>> char cl_inline_name[32];
>> };
>>
>> diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
>> index 4d80a11..ceee9a3 100644
>> --- a/include/linux/sunrpc/xprt.h
>> +++ b/include/linux/sunrpc/xprt.h
>> @@ -24,6 +24,14 @@
>> #define RPC_MAX_SLOT_TABLE (128U)
>>
>> /*
>> + * Grand abort timeout (stop the client if occures)
>> + */
>> +extern int xprt_abort_timeout;
>> +
>> +#define RPC_MIN_ABORT_TIMEOUT 300
>> +#define RPC_MAX_ABORT_TIMEOUT INT_MAX
>> +
>> +/*
>> * This describes a timeout strategy
>> */
>> struct rpc_timeout {
>> @@ -123,6 +131,7 @@ struct rpc_xprt_ops {
>> struct rpc_xprt {
>> struct kref kref; /* Reference count */
>> struct rpc_xprt_ops * ops; /* transport methods */
>> + struct ve_struct * owner_env; /* VE owner of mount */
>>
>> const struct rpc_timeout *timeout; /* timeout parms */
>> struct sockaddr_storage addr; /* server address */
>> diff --git a/include/linux/ve.h b/include/linux/ve.h
>> index 7025716..970aadc 100644
>> --- a/include/linux/ve.h
>> +++ b/include/linux/ve.h
>> @@ -139,6 +139,7 @@ struct ve_cpu_stats {
>>
>> struct ve_ipt_recent;
>> struct ve_xt_hashlimit;
>> +struct svc_serv;
>>
>> struct cgroup;
>> struct css_set;
>> @@ -183,6 +184,8 @@ struct ve_struct {
>> struct devpts_config *devpts_config;
>> #endif
>>
>> + struct ve_nfs_context *nfs_context;
>> +
>> struct file_system_type *shmem_fstype;
>> struct vfsmount *shmem_mnt;
>> #ifdef CONFIG_SYSFS
>> @@ -274,6 +277,15 @@ struct ve_struct {
>> struct proc_dir_entry *monitor_proc;
>> unsigned long meminfo_val;
>>
>> +#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE) \
>> + || defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
>> + unsigned int _nlmsvc_users;
>> + struct task_struct* _nlmsvc_task;
>> + int _nlmsvc_grace_period;
>> + unsigned long _nlmsvc_timeout;
>> + struct svc_serv* _nlmsvc_serv;
>> +#endif
>> +
>> struct nsproxy *ve_ns;
>> struct net *ve_netns;
>> struct cgroup *ve_cgroup;
>> diff --git a/include/linux/vzcalluser.h b/include/linux/vzcalluser.h
>> index 9736479..a62b84c 100644
>> --- a/include/linux/vzcalluser.h
>> +++ b/include/linux/vzcalluser.h
>> @@ -102,6 +102,7 @@ struct env_create_param3 {
>> };
>>
>> #define VE_FEATURE_SYSFS (1ULL << 0)
>> +#define VE_FEATURE_NFS (1ULL << 1)
>> #define VE_FEATURE_DEF_PERMS (1ULL << 2)
>>
>> #define VE_FEATURES_OLD (VE_FEATURE_SYSFS)
>> diff --git a/include/net/sock.h b/include/net/sock.h
>> index 873caf6..718e410 100644
>> --- a/include/net/sock.h
>> +++ b/include/net/sock.h
>> @@ -1334,6 +1334,13 @@ static inline void sk_change_net(struct sock *sk, struct net *net)
>> sock_net_set(sk, hold_net(net));
>> }
>>
>> +static inline void sk_change_net_get(struct sock *sk, struct net *net)
>> +{
>> + struct net *old_net = sock_net(sk);
>> + sock_net_set(sk, get_net(net));
>> + put_net(old_net);
>> +}
>> +
>> extern void sock_enable_timestamp(struct sock *sk);
>> extern int sock_get_timestamp(struct sock *, struct timeval __user *);
>> extern int sock_get_timestampns(struct sock *, struct timespec __user *);
>> diff --git a/net/socket.c b/net/socket.c
>> index 09d8fc5..799f3c9 100644
>> --- a/net/socket.c
>> +++ b/net/socket.c
>> @@ -2363,7 +2363,7 @@ int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
>> struct ve_struct *old_env;
>>
>> set_fs(KERNEL_DS);
>> - old_env = set_exec_env(get_ve0());
>> + old_env = set_exec_env(sock->sk->owner_env);
>> err = sock->ops->ioctl(sock, cmd, arg);
>> (void)set_exec_env(old_env);
>> set_fs(oldfs);
>> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
>> index 8945307..f303e1d 100644
>> --- a/net/sunrpc/clnt.c
>> +++ b/net/sunrpc/clnt.c
>> @@ -31,6 +31,7 @@
>> #include <linux/utsname.h>
>> #include <linux/workqueue.h>
>> #include <linux/in6.h>
>> +#include <linux/ve_proto.h>
>>
>> #include <linux/sunrpc/clnt.h>
>> #include <linux/sunrpc/rpc_pipe_fs.h>
>> @@ -89,6 +90,35 @@ static void rpc_unregister_client(struct rpc_clnt *clnt)
>> spin_unlock(&rpc_client_lock);
>> }
>>
>> +/*
>> + * Grand abort timeout (stop the client if occures)
>> + */
>> +int xprt_abort_timeout = RPC_MAX_ABORT_TIMEOUT;
>> +
>> +static int rpc_abort_hard(struct rpc_task *task)
>> +{
>> + struct rpc_clnt *clnt;
>> + clnt = task->tk_client;
>> +
>> + if (clnt->cl_pr_time == 0) {
>> + clnt->cl_pr_time = jiffies;
>> + return 0;
>> + }
>> + if (xprt_abort_timeout == RPC_MAX_ABORT_TIMEOUT)
>> + return 0;
>> + if (time_before(jiffies, clnt->cl_pr_time + xprt_abort_timeout * HZ))
>> + return 0;
>> +
>> + clnt->cl_broken = 1;
>> + rpc_killall_tasks(clnt);
>> + return -ETIMEDOUT;
>> +}
>> +
>> +static void rpc_abort_clear(struct rpc_task *task)
>> +{
>> + task->tk_client->cl_pr_time = 0;
>> +}
>> +
>> static int
>> rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
>> {
>> @@ -178,6 +208,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
>> clnt->cl_vers = version->number;
>> clnt->cl_stats = program->stats;
>> clnt->cl_metrics = rpc_alloc_iostats(clnt);
>> + clnt->cl_broken = 0;
>> err = -ENOMEM;
>> if (clnt->cl_metrics == NULL)
>> goto out_no_stats;
>> @@ -293,6 +324,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
>> xprt = xprt_create_transport(&xprtargs);
>> if (IS_ERR(xprt))
>> return (struct rpc_clnt *)xprt;
>> + xprt->owner_env = get_ve(get_exec_env());
>>
>> /*
>> * By default, kernel RPC client connects from a reserved port.
>> @@ -305,13 +337,16 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
>> xprt->resvport = 0;
>>
>> clnt = rpc_new_client(args, xprt);
>> - if (IS_ERR(clnt))
>> + if (IS_ERR(clnt)) {
>> + put_ve(xprt->owner_env);
>> return clnt;
>> + }
>>
>> if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
>> int err = rpc_ping(clnt, RPC_TASK_SOFT);
>> if (err != 0) {
>> rpc_shutdown_client(clnt);
>> + put_ve(xprt->owner_env);
>> return ERR_PTR(err);
>> }
>> }
>> @@ -517,6 +552,9 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
>> {
>> struct rpc_task *task, *ret;
>>
>> + if (task_setup_data->rpc_client->cl_broken)
>> + return ERR_PTR(-EIO);
>> +
>> task = rpc_new_task(task_setup_data);
>> if (task == NULL) {
>> rpc_release_calldata(task_setup_data->callback_ops,
>> @@ -923,6 +961,7 @@ call_bind_status(struct rpc_task *task)
>>
>> if (task->tk_status >= 0) {
>> dprint_status(task);
>> + rpc_abort_clear(task);
>> task->tk_status = 0;
>> task->tk_action = call_connect;
>> return;
>> @@ -948,6 +987,10 @@ call_bind_status(struct rpc_task *task)
>> case -ETIMEDOUT:
>> dprintk("RPC: %5u rpcbind request timed out\n",
>> task->tk_pid);
>> + if (rpc_abort_hard(task)) {
>> + status = -EIO;
>> + break;
>> + }
>> goto retry_timeout;
>> case -EPFNOSUPPORT:
>> /* server doesn't support any rpcbind version we know of */
>> @@ -1013,6 +1056,8 @@ call_connect_status(struct rpc_task *task)
>>
>> /* Something failed: remote service port may have changed */
>> rpc_force_rebind(clnt);
>> + if (rpc_abort_hard(task))
>> + goto exit;
>>
>> switch (status) {
>> case -ENOTCONN:
>> @@ -1025,6 +1070,7 @@ call_connect_status(struct rpc_task *task)
>> task->tk_action = call_timeout;
>> return;
>> }
>> +exit:
>> rpc_exit(task, -EIO);
>> }
>>
>> @@ -1156,7 +1202,7 @@ call_timeout(struct rpc_task *task)
>> dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
>> task->tk_timeouts++;
>>
>> - if (RPC_IS_SOFT(task)) {
>> + if (RPC_IS_SOFT(task) || rpc_abort_hard(task)) {
>> printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
>> clnt->cl_protname, clnt->cl_server);
>> rpc_exit(task, -EIO);
>> @@ -1201,6 +1247,7 @@ call_decode(struct rpc_task *task)
>> task->tk_flags &= ~RPC_CALL_MAJORSEEN;
>> }
>>
>> + rpc_abort_clear(task);
>> /*
>> * Ensure that we see all writes made by xprt_complete_rqst()
>> * before it changed req->rq_received.
>> @@ -1213,7 +1260,7 @@ call_decode(struct rpc_task *task)
>> sizeof(req->rq_rcv_buf)) != 0);
>>
>> if (req->rq_rcv_buf.len < 12) {
>> - if (!RPC_IS_SOFT(task)) {
>> + if (!RPC_IS_SOFT(task) && !rpc_abort_hard(task)) {
>> task->tk_action = call_bind;
>> clnt->cl_stats->rpcretrans++;
>> goto out_retry;
>> @@ -1558,3 +1605,67 @@ out:
>> spin_unlock(&rpc_client_lock);
>> }
>> #endif
>> +
>> +#ifdef CONFIG_VE
>> +static int ve_sunrpc_start(void *data)
>> +{
>> + return 0;
>> +}
>> +
>> +void ve_sunrpc_stop(void *data)
>> +{
>> + struct ve_struct *ve = (struct ve_struct *)data;
>> + struct rpc_clnt *clnt;
>> + struct rpc_task *rovr;
>> +
>> + dprintk("RPC: killing all tasks for VE %d\n", ve->veid);
>> +
>> + spin_lock(&rpc_client_lock);
>> + list_for_each_entry(clnt, &all_clients, cl_clients) {
>> + if (clnt->cl_xprt->owner_env != ve)
>> + continue;
>> +
>> + spin_lock(&clnt->cl_lock);
>> + list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) {
>> + if (!RPC_IS_ACTIVATED(rovr))
>> + continue;
>> + printk(KERN_WARNING "RPC: Killing task %d client %p\n",
>> + rovr->tk_pid, clnt);
>> +
>> + rovr->tk_flags |= RPC_TASK_KILLED;
>> + rpc_exit(rovr, -EIO);
>> + rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr);
>> + }
>> + schedule_work(&clnt->cl_xprt->task_cleanup);
>> + spin_unlock(&clnt->cl_lock);
>> + }
>> + spin_unlock(&rpc_client_lock);
>> +
>> + flush_scheduled_work();
>> +}
>> +
>> +static struct ve_hook sunrpc_hook = {
>> + .init = ve_sunrpc_start,
>> + .fini = ve_sunrpc_stop,
>> + .owner = THIS_MODULE,
>> + .priority = HOOK_PRIO_NET_PRE,
>> +};
>> +
>> +void ve_sunrpc_hook_register(void)
>> +{
>> + ve_hook_register(VE_SS_CHAIN, &sunrpc_hook);
>> +}
>> +
>> +void ve_sunrpc_hook_unregister(void)
>> +{
>> + ve_hook_unregister(&sunrpc_hook);
>> +}
>> +#else
>> +void ve_sunrpc_hook_register(void)
>> +{
>> +}
>> +
>> +void ve_sunrpc_hook_unregister(void)
>> +{
>> +}
>> +#endif
>> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
>> index 5a9b0e7..ab6bf80 100644
>> --- a/net/sunrpc/rpc_pipe.c
>> +++ b/net/sunrpc/rpc_pipe.c
>> @@ -894,6 +894,7 @@ static struct file_system_type rpc_pipe_fs_type = {
>> .name = "rpc_pipefs",
>> .get_sb = rpc_get_sb,
>> .kill_sb = kill_litter_super,
>> + .fs_flags = FS_VIRTUALIZED,
>> };
>>
>> static void
>> diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
>> index 4fba93a..265296d 100644
>> --- a/net/sunrpc/sched.c
>> +++ b/net/sunrpc/sched.c
>> @@ -617,7 +617,7 @@ static void __rpc_execute(struct rpc_task *task)
>> int status = 0;
>> struct ve_struct *env;
>>
>> - env = set_exec_env(get_ve0());
>> + env = set_exec_env(task->tk_client->cl_xprt->owner_env);
>> dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
>> task->tk_pid, task->tk_flags);
>>
>> @@ -663,10 +663,14 @@ static void __rpc_execute(struct rpc_task *task)
>> rpc_clear_running(task);
>> if (RPC_IS_ASYNC(task)) {
>> /* Careful! we may have raced... */
>> - if (RPC_IS_QUEUED(task))
>> + if (RPC_IS_QUEUED(task)) {
>> + (void)set_exec_env(env);
>> return;
>> - if (rpc_test_and_set_running(task))
>> + }
>> + if (rpc_test_and_set_running(task)) {
>> + (void)set_exec_env(env);
>> return;
>> + }
>> continue;
>> }
>>
>> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
>> index 843629f..94c3fb0 100644
>> --- a/net/sunrpc/sunrpc_syms.c
>> +++ b/net/sunrpc/sunrpc_syms.c
>> @@ -24,6 +24,9 @@
>>
>> extern struct cache_detail ip_map_cache, unix_gid_cache;
>>
>> +extern void ve_sunrpc_hook_register(void);
>> +extern void ve_sunrpc_hook_unregister(void);
>> +
>> static int __init
>> init_sunrpc(void)
>> {
>> @@ -46,6 +49,7 @@ init_sunrpc(void)
>> svc_init_xprt_sock(); /* svc sock transport */
>> init_socket_xprt(); /* clnt sock transport */
>> rpcauth_init_module();
>> + ve_sunrpc_hook_register();
>> out:
>> return err;
>> }
>> @@ -53,6 +57,7 @@ out:
>> static void __exit
>> cleanup_sunrpc(void)
>> {
>> + ve_sunrpc_hook_unregister();
>> rpcauth_remove_module();
>> cleanup_socket_xprt();
>> svc_cleanup_xprt_sock();
>> diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
>> index 029c673..0d49dfc 100644
>> --- a/net/sunrpc/svcsock.c
>> +++ b/net/sunrpc/svcsock.c
>> @@ -180,7 +180,7 @@ static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
>> RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
>> struct ve_struct *old_env;
>>
>> - old_env = set_exec_env(get_ve0());
>> + old_env = set_exec_env(sock->sk->owner_env);
>>
>> slen = xdr->len;
>>
>> @@ -321,14 +321,11 @@ static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr,
>> .msg_flags = MSG_DONTWAIT,
>> };
>> int len;
>> - struct ve_struct *old_env;
>>
>> rqstp->rq_xprt_hlen = 0;
>>
>> - old_env = set_exec_env(get_ve0());
>> len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
>> msg.msg_flags);
>> - (void)set_exec_env(get_ve0());
>>
>> dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
>> svsk, iov[0].iov_base, iov[0].iov_len, len);
>> @@ -727,13 +724,11 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
>> struct svc_sock *newsvsk;
>> int err, slen;
>> RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
>> - struct ve_struct *old_env;
>>
>> dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
>> if (!sock)
>> return NULL;
>>
>> - old_env = set_exec_env(get_ve0());
>> clear_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags);
>> err = kernel_accept(sock, &newsock, O_NONBLOCK);
>> if (err < 0) {
>> @@ -743,7 +738,7 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
>> else if (err != -EAGAIN && net_ratelimit())
>> printk(KERN_WARNING "%s: accept failed (err %d)!\n",
>> serv->sv_name, -err);
>> - goto restore;
>> + return NULL;
>> }
>> set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags);
>>
>> @@ -784,8 +779,6 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
>> }
>> svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen);
>>
>> - (void)set_exec_env(old_env);
>> -
>> if (serv->sv_stats)
>> serv->sv_stats->nettcpconn++;
>>
>> @@ -793,8 +786,6 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
>>
>> failed:
>> sock_release(newsock);
>> -restore:
>> - (void)set_exec_env(old_env);
>> return NULL;
>> }
>>
>> @@ -1225,7 +1216,6 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
>> struct sockaddr *newsin = (struct sockaddr *)&addr;
>> int newlen;
>> RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
>> - struct ve_struct *old_env;
>>
>> dprintk("svc: svc_create_socket(%s, %d, %s)\n",
>> serv->sv_program->pg_name, protocol,
>> @@ -1238,11 +1228,11 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
>> }
>> type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
>>
>> - old_env = set_exec_env(get_ve0());
>> error = sock_create_kern(sin->sa_family, type, protocol, &sock);
>> if (error < 0)
>> - goto restore;
>> + return ERR_PTR(-ENOMEM);
>>
>> + sk_change_net_get(sock->sk, get_exec_env()->ve_netns);
>> svc_reclassify_socket(sock);
>>
>> if (type == SOCK_STREAM)
>> @@ -1263,15 +1253,12 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
>>
>> if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
>> svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
>> - (void)set_exec_env(old_env);
>> return (struct svc_xprt *)svsk;
>> }
>>
>> bummer:
>> dprintk("svc: svc_create_socket error = %d\n", -error);
>> sock_release(sock);
>> -restore:
>> - (void)set_exec_env(old_env);
>> return ERR_PTR(error);
>> }
>>
>> diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
>> index e1770f7..831ad1b 100644
>> --- a/net/sunrpc/xprt.c
>> +++ b/net/sunrpc/xprt.c
>> @@ -568,10 +568,13 @@ static void xprt_autoclose(struct work_struct *work)
>> {
>> struct rpc_xprt *xprt =
>> container_of(work, struct rpc_xprt, task_cleanup);
>> + struct ve_struct *ve;
>>
>> + ve = set_exec_env(xprt->owner_env);
>> xprt->ops->close(xprt);
>> clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
>> xprt_release_write(xprt, NULL);
>> + (void)set_exec_env(ve);
>> }
>>
>> /**
>> @@ -638,7 +641,9 @@ static void
>> xprt_init_autodisconnect(unsigned long data)
>> {
>> struct rpc_xprt *xprt = (struct rpc_xprt *)data;
>> + struct ve_struct *ve;
>>
>> + ve = set_exec_env(xprt->owner_env);
>> spin_lock(&xprt->transport_lock);
>> if (!list_empty(&xprt->recv) || xprt->shutdown)
>> goto out_abort;
>> @@ -649,9 +654,11 @@ xprt_init_autodisconnect(unsigned long data)
>> xprt_release_write(xprt, NULL);
>> else
>> queue_work(rpciod_workqueue, &xprt->task_cleanup);
>> + (void)set_exec_env(ve);
>> return;
>> out_abort:
>> spin_unlock(&xprt->transport_lock);
>> + (void)set_exec_env(ve);
>> }
>>
>> /**
>> @@ -1049,6 +1056,7 @@ found:
>> xprt->last_used = jiffies;
>> xprt->cwnd = RPC_INITCWND;
>> xprt->bind_index = 0;
>> + xprt->owner_env = get_exec_env();
>>
>> rpc_init_wait_queue(&xprt->binding, "xprt_binding");
>> rpc_init_wait_queue(&xprt->pending, "xprt_pending");
>> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
>> index ddbe981..7ade3e3 100644
>> --- a/net/sunrpc/xprtsock.c
>> +++ b/net/sunrpc/xprtsock.c
>> @@ -64,6 +64,8 @@ static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
>> static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
>> static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
>> static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
>> +static int xprt_min_abort_timeout = RPC_MIN_ABORT_TIMEOUT;
>> +static int xprt_max_abort_timeout = RPC_MAX_ABORT_TIMEOUT;
>>
>> static struct ctl_table_header *sunrpc_table_header;
>>
>> @@ -117,6 +119,16 @@ static ctl_table xs_tunables_table[] = {
>> .extra2 = &xprt_max_resvport_limit
>> },
>> {
>> + .procname = "abort_timeout",
>> + .data = &xprt_abort_timeout,
>> + .maxlen = sizeof(unsigned int),
>> + .mode = 0644,
>> + .proc_handler = &proc_dointvec_minmax,
>> + .strategy = &sysctl_intvec,
>> + .extra1 = &xprt_min_abort_timeout,
>> + .extra2 = &xprt_max_abort_timeout
>> + },
>> + {
>> .ctl_name = 0,
>> },
>> };
>> @@ -754,18 +766,23 @@ out_release:
>> static void xs_close(struct rpc_xprt *xprt)
>> {
>> struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
>> - struct socket *sock = transport->sock;
>> - struct sock *sk = transport->inet;
>> -
>> - if (!sk)
>> - goto clear_close_wait;
>> + struct socket *sock;
>> + struct sock *sk;
>>
>> dprintk("RPC: xs_close xprt %p\n", xprt);
>>
>> - write_lock_bh(&sk->sk_callback_lock);
>> + spin_lock_bh(&xprt->transport_lock);
>> + if (transport->sock == NULL) {
>> + spin_unlock_bh(&xprt->transport_lock);
>> + goto clear_close_wait;
>> + }
>> + sock = transport->sock;
>> + sk = transport->inet;
>> transport->inet = NULL;
>> transport->sock = NULL;
>> + spin_unlock_bh(&xprt->transport_lock);
>>
>> + write_lock_bh(&sk->sk_callback_lock);
>> sk->sk_user_data = NULL;
>> sk->sk_data_ready = transport->old_data_ready;
>> sk->sk_state_change = transport->old_state_change;
>> @@ -1489,7 +1506,12 @@ static void xs_udp_connect_worker4(struct work_struct *work)
>> struct rpc_xprt *xprt = &transport->xprt;
>> struct socket *sock = transport->sock;
>> int err, status = -EIO;
>> + struct ve_struct *ve;
>>
>> + ve = set_exec_env(xprt->owner_env);
>> + down_read(&xprt->owner_env->op_sem);
>> + if (!xprt->owner_env->is_running)
>> + goto out;
>> if (xprt->shutdown || !xprt_bound(xprt))
>> goto out;
>>
>> @@ -1500,6 +1522,7 @@ static void xs_udp_connect_worker4(struct work_struct *work)
>> dprintk("RPC: can't create UDP transport socket (%d).\n", -err);
>> goto out;
>> }
>> + sk_change_net_get(sock->sk, xprt->owner_env->ve_netns);
>> xs_reclassify_socket4(sock);
>>
>> if (xs_bind4(transport, sock)) {
>> @@ -1515,6 +1538,8 @@ static void xs_udp_connect_worker4(struct work_struct *work)
>> out:
>> xprt_wake_pending_tasks(xprt, status);
>> xprt_clear_connecting(xprt);
>> + up_read(&xprt->owner_env->op_sem);
>> + (void)set_exec_env(ve);
>> }
>>
>> /**
>> @@ -1530,7 +1555,12 @@ static void xs_udp_connect_worker6(struct work_struct *work)
>> struct rpc_xprt *xprt = &transport->xprt;
>> struct socket *sock = transport->sock;
>> int err, status = -EIO;
>> + struct ve_struct *ve;
>>
>> + ve = set_exec_env(xprt->owner_env);
>> + down_read(&xprt->owner_env->op_sem);
>> + if (!xprt->owner_env->is_running)
>> + goto out;
>> if (xprt->shutdown || !xprt_bound(xprt))
>> goto out;
>>
>> @@ -1541,6 +1571,7 @@ static void xs_udp_connect_worker6(struct work_struct *work)
>> dprintk("RPC: can't create UDP transport socket (%d).\n", -err);
>> goto out;
>> }
>> + sk_change_net_get(sock->sk, xprt->owner_env->ve_netns);
>> xs_reclassify_socket6(sock);
>>
>> if (xs_bind6(transport, sock) < 0) {
>> @@ -1556,6 +1587,8 @@ static void xs_udp_connect_worker6(struct work_struct *work)
>> out:
>> xprt_wake_pending_tasks(xprt, status);
>> xprt_clear_connecting(xprt);
>> + up_read(&xprt->owner_env->op_sem);
>> + (void)set_exec_env(ve);
>> }
>>
>> /*
>> @@ -1634,7 +1667,12 @@ static void xs_tcp_connect_worker4(struct work_struct *work)
>> struct rpc_xprt *xprt = &transport->xprt;
>> struct socket *sock = transport->sock;
>> int err, status = -EIO;
>> + struct ve_struct *ve;
>>
>> + ve = set_exec_env(xprt->owner_env);
>> + down_read(&xprt->owner_env->op_sem);
>> + if (!xprt->owner_env->is_running)
>> + goto out;
>> if (xprt->shutdown || !xprt_bound(xprt))
>> goto out;
>>
>> @@ -1644,6 +1682,7 @@ static void xs_tcp_connect_worker4(struct work_struct *work)
>> dprintk("RPC: can't create TCP transport socket (%d).\n", -err);
>> goto out;
>> }
>> + sk_change_net_get(sock->sk, xprt->owner_env->ve_netns);
>> xs_reclassify_socket4(sock);
>>
>> if (xs_bind4(transport, sock) < 0) {
>> @@ -1679,6 +1718,8 @@ out:
>> xprt_wake_pending_tasks(xprt, status);
>> out_clear:
>> xprt_clear_connecting(xprt);
>> + up_read(&xprt->owner_env->op_sem);
>> + (void)set_exec_env(ve);
>> }
>>
>> /**
>> @@ -1694,7 +1735,12 @@ static void xs_tcp_connect_worker6(struct work_struct *work)
>> struct rpc_xprt *xprt = &transport->xprt;
>> struct socket *sock = transport->sock;
>> int err, status = -EIO;
>> + struct ve_struct *ve;
>>
>> + ve = set_exec_env(xprt->owner_env);
>> + down_read(&xprt->owner_env->op_sem);
>> + if (!xprt->owner_env->is_running)
>> + goto out;
>> if (xprt->shutdown || !xprt_bound(xprt))
>> goto out;
>>
>> @@ -1704,6 +1750,7 @@ static void xs_tcp_connect_worker6(struct work_struct *work)
>> dprintk("RPC: can't create TCP transport socket (%d).\n", -err);
>> goto out;
>> }
>> + sk_change_net_get(sock->sk, xprt->owner_env->ve_netns);
>> xs_reclassify_socket6(sock);
>>
>> if (xs_bind6(transport, sock) < 0) {
>> @@ -1738,6 +1785,8 @@ out:
>> xprt_wake_pending_tasks(xprt, status);
>> out_clear:
>> xprt_clear_connecting(xprt);
>> + up_read(&xprt->owner_env->op_sem);
>> + (void)set_exec_env(ve);
>> }
>>
>> /**
>> --
>> 1.6.0.6
>>
>>
>
>
>> From 2a083801fe1655bf9e403469c494b83a72186f56 Mon Sep 17 00:00:00 2001
>> From: Denis Lunev <den at openvz.org>
>> Date: Wed, 10 Sep 2008 12:02:33 +0400
>> Subject: [PATCH] nfs: add missed ve_nfs.h file
>>
>> Lost when committing 66ec7f7f493fb98e8baa6591e9225086ae640fb8
>>
>> Signed-off-by: Denis Lunev <den at openvz.org>
>> Signed-off-by: Pavel Emelyanov <xemul at openvz.org>
>> ---
>> include/linux/ve_nfs.h | 30 ++++++++++++++++++++++++++++++
>> 1 files changed, 30 insertions(+), 0 deletions(-)
>> create mode 100644 include/linux/ve_nfs.h
>>
>> diff --git a/include/linux/ve_nfs.h b/include/linux/ve_nfs.h
>> new file mode 100644
>> index 0000000..4ed5105
>> --- /dev/null
>> +++ b/include/linux/ve_nfs.h
>> @@ -0,0 +1,30 @@
>> +/*
>> + * linux/include/ve_nfs.h
>> + *
>> + * VE context for NFS
>> + *
>> + * Copyright (C) 2007 SWsoft
>> + */
>> +
>> +#ifndef __VE_NFS_H__
>> +#define __VE_NFS_H__
>> +
>> +#ifdef CONFIG_VE
>> +
>> +#include <linux/ve.h>
>> +
>> +#define NFS_CTX_FIELD(arg) (get_exec_env()->_##arg)
>> +
>> +#else /* CONFIG_VE */
>> +
>> +#define NFS_CTX_FIELD(arg) _##arg
>> +
>> +#endif /* CONFIG_VE */
>> +
>> +#define nlmsvc_grace_period NFS_CTX_FIELD(nlmsvc_grace_period)
>> +#define nlmsvc_timeout NFS_CTX_FIELD(nlmsvc_timeout)
>> +#define nlmsvc_users NFS_CTX_FIELD(nlmsvc_users)
>> +#define nlmsvc_task NFS_CTX_FIELD(nlmsvc_task)
>> +#define nlmsvc_serv NFS_CTX_FIELD(nlmsvc_serv)
>> +
>> +#endif
>> --
>> 1.6.0.6
>>
>>
>
>
>> From b8b70c37c8b114780a02492703c9682d8b09a14b Mon Sep 17 00:00:00 2001
>> From: Vitaliy Gusev <vgusev at openvz.org>
>> Date: Wed, 24 Dec 2008 20:32:43 +0300
>> Subject: [PATCH] nfs: Fix access to freed memory
>>
>> rpc_shutdown_client() frees xprt, so we can't use this xprt.
>> So move put_ve() to xprt::destroy level.
>>
>> Bug https://bugzilla.sw.ru/show_bug.cgi?id=265628
>>
>> Signed-off-by: Vitaliy Gusev <vgusev at openvz.org>
>> Signed-off-by: Pavel Emelyanov <xemul at openvz.org>
>> ---
>> net/sunrpc/clnt.c | 2 --
>> net/sunrpc/xprt.c | 2 +-
>> net/sunrpc/xprtrdma/transport.c | 1 +
>> net/sunrpc/xprtsock.c | 1 +
>> 4 files changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
>> index f303e1d..b6f53f1 100644
>> --- a/net/sunrpc/clnt.c
>> +++ b/net/sunrpc/clnt.c
>> @@ -324,7 +324,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
>> xprt = xprt_create_transport(&xprtargs);
>> if (IS_ERR(xprt))
>> return (struct rpc_clnt *)xprt;
>> - xprt->owner_env = get_ve(get_exec_env());
>>
>> /*
>> * By default, kernel RPC client connects from a reserved port.
>> @@ -346,7 +345,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
>> int err = rpc_ping(clnt, RPC_TASK_SOFT);
>> if (err != 0) {
>> rpc_shutdown_client(clnt);
>> - put_ve(xprt->owner_env);
>> return ERR_PTR(err);
>> }
>> }
>> diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
>> index 831ad1b..23ce2ce 100644
>> --- a/net/sunrpc/xprt.c
>> +++ b/net/sunrpc/xprt.c
>> @@ -1056,7 +1056,7 @@ found:
>> xprt->last_used = jiffies;
>> xprt->cwnd = RPC_INITCWND;
>> xprt->bind_index = 0;
>> - xprt->owner_env = get_exec_env();
>> + xprt->owner_env = get_ve(get_exec_env());
>>
>> rpc_init_wait_queue(&xprt->binding, "xprt_binding");
>> rpc_init_wait_queue(&xprt->pending, "xprt_pending");
>> diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
>> index a564c1a..77714e3 100644
>> --- a/net/sunrpc/xprtrdma/transport.c
>> +++ b/net/sunrpc/xprtrdma/transport.c
>> @@ -286,6 +286,7 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
>>
>> kfree(xprt->slot);
>> xprt->slot = NULL;
>> + put_ve(xprt->owner_env);
>> kfree(xprt);
>>
>> dprintk("RPC: %s: returning\n", __func__);
>> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
>> index 7ade3e3..27e62dd 100644
>> --- a/net/sunrpc/xprtsock.c
>> +++ b/net/sunrpc/xprtsock.c
>> @@ -816,6 +816,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
>> xs_close(xprt);
>> xs_free_peer_addresses(xprt);
>> kfree(xprt->slot);
>> + put_ve(xprt->owner_env);
>> kfree(xprt);
>> module_put(THIS_MODULE);
>> }
>> --
>> 1.6.0.6
>>
>>
>
>
>> From 840ea01d953ca0ad7629ea66ca0f50685ca06921 Mon Sep 17 00:00:00 2001
>> From: Denis Lunev <den at openvz.org>
>> Date: Mon, 29 Dec 2008 20:34:32 +0300
>> Subject: [PATCH] NFS: NFS super blocks in different VEs should be different
>>
>> NFS: NFS super blocks in different VEs should be different
>>
>> Teach nfs_compare_super to this
>>
>> Bug #265926
>>
>> Signed-off-by: Denis V. Lunev <den at openvz.org>
>> Signed-off-by: Vitaliy Gusev <vgusev at openvz.org>
>> Signed-off-by: Pavel Emelyanov <xemul at openvz.org>
>> ---
>> fs/nfs/super.c | 4 ++++
>> 1 files changed, 4 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
>> index cb4e28a..cf38e22 100644
>> --- a/fs/nfs/super.c
>> +++ b/fs/nfs/super.c
>> @@ -1619,6 +1619,10 @@ static int nfs_compare_super(struct super_block *sb, void *data)
>> struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
>> int mntflags = sb_mntdata->mntflags;
>>
>> + if (!ve_accessible_strict(old->client->cl_xprt->owner_env,
>> + get_exec_env()))
>> + return 0;
>> +
>> if (!nfs_compare_super_address(old, server))
>> return 0;
>> /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
>> --
>> 1.6.0.6
>>
>>
>
>
>> From 39bb1ee59237272cd20e1f8696cefbd6a787cfc8 Mon Sep 17 00:00:00 2001
>> From: Vitaliy Gusev <vgusev at openvz.org>
>> Date: Mon, 12 Jan 2009 17:29:54 +0300
>> Subject: [PATCH] nfs: Fix nfs_match_client()
>>
>> nfs_match_client() can return nfs_client from other VE.
>>
>> Bug https://bugzilla.sw.ru/show_bug.cgi?id=266951
>>
>> Original-patch-by: Denis Lunev <den at openvz.org>
>> Signed-off-by: Vitaliy Gusev <vgusev at openvz.org>
>> Signed-off-by: Pavel Emelyanov <xemul at openvz.org>
>> ---
>> fs/nfs/client.c | 3 +++
>> 1 files changed, 3 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
>> index 3366257..d773ed5 100644
>> --- a/fs/nfs/client.c
>> +++ b/fs/nfs/client.c
>> @@ -343,6 +343,9 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
>> if (clp->cl_cons_state < 0)
>> continue;
>>
>> + if (!ve_accessible_strict(clp->owner_env, ve))
>> + continue;
>> +
>> /* Different NFS versions cannot share the same nfs_client */
>> if (clp->rpc_ops != data->rpc_ops)
>> continue;
>> --
>> 1.6.0.6
>>
>>
>
>
>> From ba0ce90476e6267f6c035f9c9ef7c45d6195ec6e Mon Sep 17 00:00:00 2001
>> From: Vitaliy Gusev <vgusev at openvz.org>
>> Date: Tue, 13 Jan 2009 18:23:56 +0300
>> Subject: [PATCH] nfs: use kthread_run_ve to start lockd
>>
>> Lockd is virtualized, so must be created in VE context.
>> The reason it worked before (in 2.6.18 kernel for example) is that lockd is
>> rewritten to use new kthread API, which was not capable for creating threads
>> in containers.
>>
>> Signed-off-by: Vitaliy Gusev <vgusev at openvz.org>
>> Signed-off-by: Pavel Emelyanov <xemul at openvz.org>
>> ---
>> fs/lockd/svc.c | 2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
>> index f9f02fc..50b29d5 100644
>> --- a/fs/lockd/svc.c
>> +++ b/fs/lockd/svc.c
>> @@ -307,7 +307,7 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
>> svc_sock_update_bufs(serv);
>> nlmsvc_serv = rqstp->rq_server;
>>
>> - nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name);
>> + nlmsvc_task = kthread_run_ve(get_exec_env(), lockd, rqstp, serv->sv_name);
>> if (IS_ERR(nlmsvc_task)) {
>> error = PTR_ERR(nlmsvc_task);
>> nlmsvc_task = NULL;
>> --
>> 1.6.0.6
>>
>>
>
>
>
More information about the Debian
mailing list