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 <bankarsandhya...@gmail.com>
Signed-off-by: Matthew Wilcox <mawil...@microsoft.com>
---
 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);
-- 
1.8.3.1

Reply via email to