From patchwork Thu Apr 27 19:14:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandhya Bankar X-Patchwork-Id: 9705713 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2C967602BE for ; Sat, 29 Apr 2017 07:48:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1ABCE28671 for ; Sat, 29 Apr 2017 07:48:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0F12228681; Sat, 29 Apr 2017 07:48:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.7 required=2.0 tests=BAYES_00, DATE_IN_PAST_24_48, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6730928671 for ; Sat, 29 Apr 2017 07:48:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1425958AbdD2Hru (ORCPT ); Sat, 29 Apr 2017 03:47:50 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:36808 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1425872AbdD2Hrs (ORCPT ); Sat, 29 Apr 2017 03:47:48 -0400 Received: by mail-pf0-f193.google.com with SMTP id v14so20541887pfd.3; Sat, 29 Apr 2017 00:47:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=bKV+PhPTP34mc7xI5cU5Gbfcy928LGjg7EXt/MPh55I=; b=T471NkzE1hOioT6ObsQHq8+Dl4hCxCn2ng1rAYF+/ClIINn2BgJ4iF+9f5sI7COMtY /7V0AI3lT/p128t0rWJV9tJZ9uCU/hgyY5/dNhWwZQVLRA3bM/G256PHp42EYo1LjHZP SZ9YuXZsNxkjoLLTzwsM/QF7rQhQdpyuybaBg2vigo3qX9gIgVmtec/flR0ZnpCmDA33 PuhcDH2k6ASEHRY0YE0ecFF7aRP77zkwNyuDl7S+/c94ALP1thhwbLGTCTrA/WLg/p7i XhggFBmam8SqSaG23siyulRJqkMhcMEmK0YPin3UfCikPXXQ6hk8TJZxkcisLKWs7a7a l6pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=bKV+PhPTP34mc7xI5cU5Gbfcy928LGjg7EXt/MPh55I=; b=V6s5UQ38j8FEfMUJnULkKNOzDcIaBM59R8s2A//dc0qd96bIZno+aNo61VeM9rEcKo wjIA6biXxbNYH3JK+vHzztpV0fkucGEnEbDXrnDickB+HM1Vi5vl/meYSAfxTx4zTZn+ 7k+QBhAmClH1On4M+0mJRiwP2rph5XBR1HZkcn9zlturX8yVcC70R365JdgvceWtu2LE rSNgzff8GZNchxGKdZI1PG8YBH6L6OBkmknTpgEchD3OBgO/gRLKo+waQhBl5tvG2EkH XLCr3bvrCnYZN2vcB7CL0MUNxnyq6/iDUAa++YgCdU4tWdioh/boeLNbBvnmNjP9DBwN 8yxA== X-Gm-Message-State: AN3rC/676anzTBvI+wDmj5QMUN7DZVdgr0HNLVTt01Y8SZmKMJ1Dnmm6 5qrcRYzuRmmD9Q== X-Received: by 10.99.6.70 with SMTP id 67mr16169353pgg.122.1493452068120; Sat, 29 Apr 2017 00:47:48 -0700 (PDT) Received: from localhost.localdomain ([223.229.187.11]) by smtp.gmail.com with ESMTPSA id h7sm18267847pfc.99.2017.04.29.00.47.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 29 Apr 2017 00:47:47 -0700 (PDT) Date: Fri, 28 Apr 2017 00:44:45 +0530 From: Sandhya Bankar To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, mawmilcox@microsoft.com, keescook@chromium.org, adobriyan@gmail.com, re.emese@gmail.com, riel@surriel.com Subject: [PATCH 10/13] vfs: Replace close_on_exec bitmap with an IDR tag Message-ID: <16d35dab49415ac74ec161406b5634ddf35e1290.1493315290.git.bankarsandhya512@gmail.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Replace close_on_exec with idr_(get,set,clear)_tag(). Through this patch, added new IDR tag FD_TAG_CLOEXEC which is passing to idr_(get,set,clear)_tag() to achieve close_on_exec functionality. Also removed get_close_on_exec() and using close_on_exec() instead of that. Signed-off-by: Sandhya Bankar Signed-off-by: Matthew Wilcox --- fs/exec.c | 2 +- fs/fcntl.c | 2 +- fs/file.c | 85 +++++++++++++++---------------------------------- fs/proc/fd.c | 4 +-- include/linux/fdtable.h | 19 +++++++---- include/linux/file.h | 1 - 6 files changed, 41 insertions(+), 72 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 65145a3..2070bc6 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1728,7 +1728,7 @@ static int do_execveat_common(int fd, struct filename *filename, * inaccessible after exec. Relies on having exclusive access to * current->files (due to unshare_files above). */ - if (close_on_exec(fd, rcu_dereference_raw(current->files->fdt))) + if (close_on_exec(fd, current->files)) bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; bprm->filename = pathbuf; } diff --git a/fs/fcntl.c b/fs/fcntl.c index be8fbe2..9c2061b 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -255,7 +255,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, err = f_dupfd(arg, filp, O_CLOEXEC); break; case F_GETFD: - err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; + err = close_on_exec(fd, current->files) ? FD_CLOEXEC : 0; break; case F_SETFD: err = 0; diff --git a/fs/file.c b/fs/file.c index 8cd77c5..56c5731 100644 --- a/fs/file.c +++ b/fs/file.c @@ -70,8 +70,6 @@ static void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt, set = (nfdt->max_fds - count) / BITS_PER_BYTE; memcpy(nfdt->open_fds, ofdt->open_fds, cpy); memset((char *)nfdt->open_fds + cpy, 0, set); - memcpy(nfdt->close_on_exec, ofdt->close_on_exec, cpy); - memset((char *)nfdt->close_on_exec + cpy, 0, set); } /* @@ -115,13 +113,10 @@ static struct fdtable * alloc_fdtable(unsigned int nr) goto out; fdt->max_fds = nr; - data = alloc_fdmem(max_t(size_t, - 2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES)); + data = alloc_fdmem(max_t(size_t, nr / BITS_PER_BYTE, L1_CACHE_BYTES)); if (!data) goto out_fdt; fdt->open_fds = data; - data += nr / BITS_PER_BYTE; - fdt->close_on_exec = data; return fdt; @@ -227,15 +222,16 @@ static inline bool fd_is_open(unsigned int fd, struct files_struct *files) return !idr_tag_get(&files->fd_idr, fd, IDR_FREE); } -static inline void __set_close_on_exec(unsigned int fd, struct fdtable *fdt) +static inline void __set_close_on_exec(unsigned int fd, + struct files_struct *files) { - __set_bit(fd, fdt->close_on_exec); + idr_tag_set(&files->fd_idr, fd, FD_TAG_CLOEXEC); } -static inline void __clear_close_on_exec(unsigned int fd, struct fdtable *fdt) +static inline void __clear_close_on_exec(unsigned int fd, + struct files_struct *files) { - if (test_bit(fd, fdt->close_on_exec)) - __clear_bit(fd, fdt->close_on_exec); + idr_tag_clear(&files->fd_idr, fd, FD_TAG_CLOEXEC); } static inline void __set_open_fd(unsigned int fd, struct fdtable *fdt) @@ -287,7 +283,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) init_waitqueue_head(&newf->resize_wait); new_fdt = &newf->fdtab; new_fdt->max_fds = NR_OPEN_DEFAULT; - new_fdt->close_on_exec = newf->close_on_exec_init; new_fdt->open_fds = newf->open_fds_init; restart: @@ -347,6 +342,9 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) spin_unlock(&oldf->file_lock); goto out; } + + if (idr_tag_get(&oldf->fd_idr, i, FD_TAG_CLOEXEC)) + idr_tag_set(&newf->fd_idr, i, FD_TAG_CLOEXEC); } spin_unlock(&oldf->file_lock); @@ -445,7 +443,6 @@ struct files_struct init_files = { .fdt = &init_files.fdtab, .fdtab = { .max_fds = NR_OPEN_DEFAULT, - .close_on_exec = init_files.close_on_exec_init, .open_fds = init_files.open_fds_init, }, .file_lock = __SPIN_LOCK_UNLOCKED(init_files.file_lock), @@ -482,9 +479,9 @@ int __alloc_fd(struct files_struct *files, fdt = files_fdtable(files); __set_open_fd(fd, fdt); if (flags & O_CLOEXEC) - __set_close_on_exec(fd, fdt); + __set_close_on_exec(fd, files); else - __clear_close_on_exec(fd, fdt); + __clear_close_on_exec(fd, files); error = fd; out: @@ -571,7 +568,7 @@ int __close_fd(struct files_struct *files, unsigned fd) file = idr_remove(&files->fd_idr, fd); if (!file) goto out_unlock; - __clear_close_on_exec(fd, fdt); + __clear_close_on_exec(fd, files); __put_unused_fd(files, fd); spin_unlock(&files->file_lock); return filp_close(file, files); @@ -583,35 +580,19 @@ int __close_fd(struct files_struct *files, unsigned fd) void do_close_on_exec(struct files_struct *files) { - unsigned i; - struct fdtable *fdt; + struct file *file; + unsigned int fd; /* exec unshares first */ spin_lock(&files->file_lock); - for (i = 0; ; i++) { - unsigned long set; - unsigned fd = i * BITS_PER_LONG; - fdt = files_fdtable(files); - if (fd >= fdt->max_fds) - break; - set = fdt->close_on_exec[i]; - if (!set) - continue; - fdt->close_on_exec[i] = 0; - for ( ; set ; fd++, set >>= 1) { - struct file *file; - if (!(set & 1)) - continue; - file = idr_remove(&files->fd_idr, fd); - if (!file) - continue; - __put_unused_fd(files, fd); - spin_unlock(&files->file_lock); - filp_close(file, files); - cond_resched(); - spin_lock(&files->file_lock); - } + idr_for_each_entry_tagged(&files->fd_idr, file, fd, FD_TAG_CLOEXEC) { + idr_remove(&files->fd_idr, fd); + __put_unused_fd(files, fd); + spin_unlock(&files->file_lock); + filp_close(file, files); + cond_resched(); + spin_lock(&files->file_lock); } spin_unlock(&files->file_lock); } @@ -723,28 +704,14 @@ void __f_unlock_pos(struct file *f) void set_close_on_exec(unsigned int fd, int flag) { struct files_struct *files = current->files; - struct fdtable *fdt; spin_lock(&files->file_lock); - fdt = files_fdtable(files); if (flag) - __set_close_on_exec(fd, fdt); + __set_close_on_exec(fd, files); else - __clear_close_on_exec(fd, fdt); + __clear_close_on_exec(fd, files); spin_unlock(&files->file_lock); } -bool get_close_on_exec(unsigned int fd) -{ - struct files_struct *files = current->files; - struct fdtable *fdt; - bool res; - rcu_read_lock(); - fdt = files_fdtable(files); - res = close_on_exec(fd, fdt); - rcu_read_unlock(); - return res; -} - static int do_dup2(struct files_struct *files, struct file *file, unsigned fd, unsigned flags) __releases(&files->file_lock) @@ -783,9 +750,9 @@ static int do_dup2(struct files_struct *files, } __set_open_fd(fd, fdt); if (flags & O_CLOEXEC) - __set_close_on_exec(fd, fdt); + __set_close_on_exec(fd, files); else - __clear_close_on_exec(fd, fdt); + __clear_close_on_exec(fd, files); spin_unlock(&files->file_lock); idr_preload_end(); diff --git a/fs/proc/fd.c b/fs/proc/fd.c index c330495..2735ccc 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -36,10 +36,8 @@ static int seq_show(struct seq_file *m, void *v) spin_lock(&files->file_lock); file = fcheck_files(files, fd); if (file) { - struct fdtable *fdt = files_fdtable(files); - f_flags = file->f_flags; - if (close_on_exec(fd, fdt)) + if (close_on_exec(fd, files)) f_flags |= O_CLOEXEC; get_file(file); diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 67259f4..7f1ab82 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -22,18 +22,14 @@ */ #define NR_OPEN_DEFAULT BITS_PER_LONG +#define FD_TAG_CLOEXEC 1 + struct fdtable { unsigned int max_fds; - unsigned long *close_on_exec; unsigned long *open_fds; struct rcu_head rcu; }; -static inline bool close_on_exec(unsigned int fd, const struct fdtable *fdt) -{ - return test_bit(fd, fdt->close_on_exec); -} - /* * Open file table structure */ @@ -52,7 +48,6 @@ struct files_struct { * written part on a separate cache line in SMP */ spinlock_t file_lock ____cacheline_aligned_in_smp; - unsigned long close_on_exec_init[1]; unsigned long open_fds_init[1]; }; @@ -82,6 +77,16 @@ static inline struct file *fcheck_files(struct files_struct *files, unsigned int return __fcheck_files(files, fd); } +static inline bool close_on_exec(unsigned int fd, struct files_struct *files) +{ + bool res; + + rcu_read_lock(); + res = idr_tag_get(&files->fd_idr, fd, FD_TAG_CLOEXEC); + rcu_read_unlock(); + return res; +} + /* * Check whether the specified fd has an open file. */ diff --git a/include/linux/file.h b/include/linux/file.h index 61eb82c..1856bbf 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -76,7 +76,6 @@ static inline void fdput_pos(struct fd f) extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); extern int replace_fd(unsigned fd, struct file *file, unsigned flags); extern void set_close_on_exec(unsigned int fd, int flag); -extern bool get_close_on_exec(unsigned int fd); extern void put_filp(struct file *); extern int get_unused_fd_flags(unsigned flags); extern void put_unused_fd(unsigned int fd);