From patchwork Wed Dec 10 19:07:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 5471481 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 3C1DDBEEA8 for ; Wed, 10 Dec 2014 19:10:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 32ED020160 for ; Wed, 10 Dec 2014 19:10:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E8B7A2015A for ; Wed, 10 Dec 2014 19:10:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933049AbaLJTKG (ORCPT ); Wed, 10 Dec 2014 14:10:06 -0500 Received: from mail-qa0-f53.google.com ([209.85.216.53]:51151 "EHLO mail-qa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932947AbaLJTIZ (ORCPT ); Wed, 10 Dec 2014 14:08:25 -0500 Received: by mail-qa0-f53.google.com with SMTP id bm13so2426817qab.26 for ; Wed, 10 Dec 2014 11:08:24 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=Iknbpd1tWoudJ4yjQqorfIqzQxQF9kfEB+xe5px/css=; b=LIXucQT6wpRZ+mtZ8jtNuF2eFler0aEFgIf9rmPzxAR2exeRaoQwJ2DYr4GNpY6oXn kuNVu50hXGp8zCQ0ZQHlOV436d4FuWOlkrHTZWe2UMpcyHTBNh2cm2vz0SF1PTpW+iIu 7c6yT+zhxuveLt2eVD+G66yGbWeXi1IQDabvCgCDcNOtXY3a7n0zLAqnfrg+yCxpfAWj lx2SnsBeQ7K0C/MnoD5sPrXE/J5uzdwBwVfQnEDvLtfYMLAo6PxSQiL6WBjW2c7WQ2E/ 4lyzhXze1irT2kDDpyHQlEwdzC5fNECUrTBCb4IbnbdP6QAw2VXuEqejWX7gV14u7QR5 XbVg== X-Gm-Message-State: ALoCoQl0yTLJfdd8hgtYYtvJgNXJGEgz8ozNs3qPWNRUKgDbIIiNhOik15rIVNSTSxduusFGiqaf X-Received: by 10.224.121.1 with SMTP id f1mr11614499qar.76.1418238504657; Wed, 10 Dec 2014 11:08:24 -0800 (PST) Received: from tlielax.poochiereds.net ([2001:470:8:d63:3a60:77ff:fe93:a95d]) by mx.google.com with ESMTPSA id l11sm5027345qaj.23.2014.12.10.11.08.23 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 Dec 2014 11:08:23 -0800 (PST) From: Jeff Layton To: bfields@fieldses.org Cc: linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, Tejun Heo , Al Viro , NeilBrown Subject: [PATCH v2 11/16] nfsd: keep a reference to the fs_struct in svc_rqst Date: Wed, 10 Dec 2014 14:07:55 -0500 Message-Id: <1418238480-18857-12-git-send-email-jlayton@primarydata.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1418238480-18857-1-git-send-email-jlayton@primarydata.com> References: <1418238480-18857-1-git-send-email-jlayton@primarydata.com> Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When we convert this code to use a workqueue, we won't want to allocate a new fs_struct to handle each RPC. Doing so might also be problematic since we'd be swapping out the ->fs value on a "public" workqueue kthread. Change the code to allocate an fs struct when when allocating a svc_rqst and then switch to using that in the "nfsd" function. Once we add workqueue support, we'll have the work function switch to the new fs struct when doing the work and then switch it back. Cc: Al Viro Signed-off-by: Jeff Layton --- fs/fs_struct.c | 59 +++++++++++++++++++++++++++++++++++++++------- fs/nfsd/nfssvc.c | 17 ++++++------- include/linux/fs_struct.h | 3 +++ include/linux/sunrpc/svc.h | 1 + net/sunrpc/svc.c | 8 +++++++ 5 files changed, 69 insertions(+), 19 deletions(-) diff --git a/fs/fs_struct.c b/fs/fs_struct.c index 7dca743b2ce1..9bc08ea2f433 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -127,26 +127,67 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) } return fs; } +EXPORT_SYMBOL_GPL(copy_fs_struct); -int unshare_fs_struct(void) +/* Replace current fs struct with one given. Return a pointer to old one. */ +static struct fs_struct * +swap_fs_struct(struct fs_struct *new_fs) { - struct fs_struct *fs = current->fs; - struct fs_struct *new_fs = copy_fs_struct(fs); - int kill; - - if (!new_fs) - return -ENOMEM; + struct fs_struct *old_fs; task_lock(current); + old_fs = current->fs; + current->fs = new_fs; + task_unlock(current); + + return old_fs; +} + +/* Put a reference to a fs_struct. */ +void put_fs_struct(struct fs_struct *fs) +{ + bool kill; + spin_lock(&fs->lock); kill = !--fs->users; - current->fs = new_fs; spin_unlock(&fs->lock); - task_unlock(current); if (kill) free_fs_struct(fs); +} +EXPORT_SYMBOL_GPL(put_fs_struct); + +/* Take an extra reference to a fs_struct. Caller must already hold one! */ +struct fs_struct * +get_fs_struct(struct fs_struct *fs) +{ + spin_lock(&fs->lock); + ++fs->users; + spin_unlock(&fs->lock); + return fs; +} +EXPORT_SYMBOL_GPL(get_fs_struct); + +/* + * Swap in a new fs_struct and drop the reference on the old one. + * Caller must have already taken the reference to the new one. + */ +void replace_fs_struct(struct fs_struct *new_fs) +{ + struct fs_struct *old_fs = swap_fs_struct(new_fs); + + put_fs_struct(old_fs); +} +EXPORT_SYMBOL_GPL(replace_fs_struct); + +int unshare_fs_struct(void) +{ + struct fs_struct *new_fs = copy_fs_struct(current->fs); + + if (!new_fs) + return -ENOMEM; + replace_fs_struct(new_fs); return 0; } EXPORT_SYMBOL_GPL(unshare_fs_struct); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 71e7b180c0d9..f37bd7db2176 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -582,15 +582,13 @@ nfsd(void *vrqstp) /* Lock module and set up kernel thread */ mutex_lock(&nfsd_mutex); - /* At this point, the thread shares current->fs - * with the init process. We need to create files with a - * umask of 0 instead of init's umask. */ - if (unshare_fs_struct() < 0) { - printk("Unable to start nfsd thread: out of memory\n"); - goto out; - } - - current->fs->umask = 0; + /* + * At this point, the thread shares current->fs with the init process. + * We need to create files with a umask of 0 instead of init's umask, + * so switch to the fs_struct associated with the rqstp. + */ + get_fs_struct(rqstp->rq_fs); + replace_fs_struct(rqstp->rq_fs); /* * thread is spawned with all signals set to SIG_IGN, re-enable @@ -632,7 +630,6 @@ nfsd(void *vrqstp) mutex_lock(&nfsd_mutex); nfsdstats.th_cnt --; -out: rqstp->rq_server = NULL; /* Release the thread */ diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index 0efc3e62843a..d2b7a1942790 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h @@ -21,7 +21,10 @@ extern void set_fs_root(struct fs_struct *, const struct path *); extern void set_fs_pwd(struct fs_struct *, const struct path *); extern struct fs_struct *copy_fs_struct(struct fs_struct *); extern void free_fs_struct(struct fs_struct *); +extern void replace_fs_struct(struct fs_struct *); extern int unshare_fs_struct(void); +struct fs_struct *get_fs_struct(struct fs_struct *); +void put_fs_struct(struct fs_struct *); static inline void get_fs_root(struct fs_struct *fs, struct path *root) { diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 43efdaae943a..695bc989c007 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -298,6 +298,7 @@ struct svc_rqst { struct svc_cacherep * rq_cacherep; /* cache info */ struct task_struct *rq_task; /* service thread */ spinlock_t rq_lock; /* per-request lock */ + struct fs_struct *rq_fs; struct work_struct rq_work; /* per-request work */ }; diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 9aad6619aa56..78395f790b54 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -622,6 +623,11 @@ svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node)) goto out_enomem; + rqstp->rq_fs = copy_fs_struct(current->fs); + if (!rqstp->rq_fs) + goto out_enomem; + + rqstp->rq_fs->umask = 0; return rqstp; out_enomem: svc_rqst_free(rqstp); @@ -784,6 +790,8 @@ svc_rqst_free(struct svc_rqst *rqstp) kfree(rqstp->rq_resp); kfree(rqstp->rq_argp); kfree(rqstp->rq_auth_data); + if (rqstp->rq_fs) + put_fs_struct(rqstp->rq_fs); kfree_rcu(rqstp, rq_rcu_head); } EXPORT_SYMBOL_GPL(svc_rqst_free);