[RESEND PATCH 13/13] vfs: Delete struct fdtable

2017-07-11 Thread Sandhya Bankar
Completing the conversion of the file descriptor allocation code to use
the IDR.

This patch includes below changes:

 - Move max_fds from struct fdtable to files_struct.
 - Added fill_max_fds() routine to calculate the new value of max_fds
   to matches the old behaviour of alloc_fdtable() code which is
   user-visible through /proc.
 - Remove struct fdtable
 - Removed resize_in_progress, resize_wait from files_struct
 - Delete open_fds() & count_open_files()
 - Use READ_ONCE() instead of rcu_read_lock/unlock(). The rcu_read_lock()/
   unlock() was used to dereference the files->fdt. Now we don't use RCU to
   protect files->max_fds. So using READ_ONCE() macro to read the value of
   files->max_fds.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/compat.c |   6 +-
 fs/file.c   | 354 +++-
 fs/proc/array.c |   2 +-
 fs/proc/fd.c|   2 +-
 fs/select.c |   6 +-
 include/linux/fdtable.h |  31 +
 6 files changed, 54 insertions(+), 347 deletions(-)

diff --git a/fs/compat.c b/fs/compat.c
index c61b506..7483c9c 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1153,17 +1153,13 @@ int compat_core_sys_select(int n, compat_ulong_t __user 
*inp,
fd_set_bits fds;
void *bits;
int size, max_fds, ret = -EINVAL;
-   struct fdtable *fdt;
long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
 
if (n < 0)
goto out_nofds;
 
/* max_fds can increase, so grab it once to avoid race */
-   rcu_read_lock();
-   fdt = files_fdtable(current->files);
-   max_fds = fdt->max_fds;
-   rcu_read_unlock();
+   max_fds = READ_ONCE(current->files->max_fds);
if (n > max_fds)
n = max_fds;
 
diff --git a/fs/file.c b/fs/file.c
index 23f198b..3e6cf10 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -31,191 +31,36 @@
 unsigned int sysctl_nr_open_max =
__const_min(INT_MAX, ~(size_t)0/sizeof(void *)) & -BITS_PER_LONG;
 
-static void *alloc_fdmem(size_t size)
+static int fill_max_fds(struct files_struct *files, unsigned int nr)
 {
-   /*
-* Very large allocations can stress page reclaim, so fall back to
-* vmalloc() if the allocation size will be considered "large" by the 
VM.
-*/
-   if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
-   void *data = kmalloc(size, GFP_KERNEL_ACCOUNT |
-__GFP_NOWARN | __GFP_NORETRY);
-   if (data != NULL)
-   return data;
-   }
-   return __vmalloc(size, GFP_KERNEL_ACCOUNT | __GFP_HIGHMEM, PAGE_KERNEL);
-}
+   unsigned int nr_open;
 
-static void __free_fdtable(struct fdtable *fdt)
-{
-   kvfree(fdt->open_fds);
-   kfree(fdt);
-}
-
-static void free_fdtable_rcu(struct rcu_head *rcu)
-{
-   __free_fdtable(container_of(rcu, struct fdtable, rcu));
-}
-
-/*
- * Copy 'count' fd bits from the old table to the new table and clear the extra
- * space if any.  This does not copy the file pointers.  Called with the files
- * spinlock held for write.
- */
-static void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt,
-   unsigned int count)
-{
-   unsigned int cpy, set;
-
-   cpy = count / BITS_PER_BYTE;
-   set = (nfdt->max_fds - count) / BITS_PER_BYTE;
-   memcpy(nfdt->open_fds, ofdt->open_fds, cpy);
-   memset((char *)nfdt->open_fds + cpy, 0, set);
-}
+   if (likely(nr < files->max_fds))
+   return 0;
 
-/*
- * Copy all file descriptors from the old table to the new, expanded table and
- * clear the extra space.  Called with the files spinlock held for write.
- */
-static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
-{
-   BUG_ON(nfdt->max_fds < ofdt->max_fds);
-   copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds);
-}
+   nr_open = READ_ONCE(sysctl_nr_open);
 
-static struct fdtable * alloc_fdtable(unsigned int nr)
-{
-   struct fdtable *fdt;
-   void *data;
+   if (nr >= nr_open)
+   return -EMFILE;
 
/*
-* Figure out how many fds we actually want to support in this fdtable.
-* Allocation steps are keyed to the size of the fdarray, since it
-* grows far faster than any of the other dynamic data. We try to fit
-* the fdarray into comfortable page-tuned chunks: starting at 1024B
-* and growing in powers of two from there on.
+* This calculation of the new value of max_fds matches the old
+* behaviour of this code which is user-visible through /proc.
+* nr may exceed the sysctl_nr_open value by a small amount.
+* This used to be necessary to keep the bitmaps aligned, and
+* we keep it the same even though the IDR handles the bitmaps now.
 */
+
 

[RESEND PATCH 12/13] vfs: Convert select to use idr_get_tag_batch()

2017-07-11 Thread Sandhya Bankar
Convert select to use idr_get_tag_batch().

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/select.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/select.c b/fs/select.c
index e211227..5d20a14 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -346,32 +346,33 @@ static int poll_select_copy_remaining(struct timespec64 
*end_time,
 
 static int max_select_fd(unsigned long n, fd_set_bits *fds)
 {
-   unsigned long *open_fds;
+   unsigned long bad_fds;
unsigned long set;
int max;
-   struct fdtable *fdt;
+   struct idr *fd_idr = ¤t->files->fd_idr;
 
/* handle last in-complete long-word first */
set = ~(~0UL << (n & (BITS_PER_LONG-1)));
n /= BITS_PER_LONG;
-   fdt = files_fdtable(current->files);
-   open_fds = fdt->open_fds + n;
max = 0;
if (set) {
set &= BITS(fds, n);
if (set) {
-   if (!(set & ~*open_fds))
+   bad_fds = idr_get_tag_batch(fd_idr, (n * BITS_PER_LONG),
+   IDR_FREE);
+   if (!(set & bad_fds))
goto get_max;
return -EBADF;
}
}
while (n) {
-   open_fds--;
n--;
set = BITS(fds, n);
if (!set)
continue;
-   if (set & ~*open_fds)
+   bad_fds = idr_get_tag_batch(fd_idr, (n * BITS_PER_LONG),
+   IDR_FREE);
+   if (set & bad_fds)
return -EBADF;
if (max)
continue;
-- 
1.8.3.1



[RESEND PATCH 10/13] vfs: Replace close_on_exec bitmap with an IDR tag

2017-07-11 Thread Sandhya Bankar
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,

[RESEND PATCH 09/13] vfs: Rewrite close_files()

2017-07-11 Thread Sandhya Bankar
Use the IDR iteration functionality instead of the open_fds bitmap to
call filp_close() for each open file.  Also make close_files() return
void, because it no longer uses the fdtable.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c | 37 +++--
 1 file changed, 11 insertions(+), 26 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index 8d67968..8cd77c5 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -373,37 +373,21 @@ struct files_struct *dup_fd(struct files_struct *oldf, 
int *errorp)
return NULL;
 }
 
-static struct fdtable *close_files(struct files_struct * files)
+static void close_files(struct files_struct * files)
 {
/*
-* It is safe to dereference the fd table without RCU or
-* ->file_lock because this is the last reference to the
-* files structure.
+* No need for RCU or ->file_lock protection because
+* this is the last reference to the files structure.
 */
-   struct fdtable *fdt = rcu_dereference_raw(files->fdt);
-   unsigned int i, j = 0;
+   struct file *file;
+   int fd;
 
-   for (;;) {
-   unsigned long set;
-   i = j * BITS_PER_LONG;
-   if (i >= fdt->max_fds)
-   break;
-   set = fdt->open_fds[j++];
-   while (set) {
-   if (set & 1) {
-   struct file *file;
-   file = idr_remove(&files->fd_idr, i);
-   if (file) {
-   filp_close(file, files);
-   cond_resched_rcu_qs();
-   }
-   }
-   i++;
-   set >>= 1;
-   }
+   idr_for_each_entry(&files->fd_idr, file, fd) {
+   filp_close(file, files);
+   cond_resched_rcu_qs();
}
 
-   return fdt;
+   idr_destroy(&files->fd_idr);
 }
 
 struct files_struct *get_files_struct(struct task_struct *task)
@@ -422,7 +406,8 @@ struct files_struct *get_files_struct(struct task_struct 
*task)
 void put_files_struct(struct files_struct *files)
 {
if (atomic_dec_and_test(&files->count)) {
-   struct fdtable *fdt = close_files(files);
+   struct fdtable *fdt = rcu_dereference_raw(files->fdt);
+   close_files(files);
 
/* free the arrays if they are not embedded */
if (fdt != &files->fdtab)
-- 
1.8.3.1



[RESEND PATCH 08/13] vfs: Use idr_tag_get() in fd_is_open().

2017-07-11 Thread Sandhya Bankar
Use idr_tag_get() in fd_is_open() to know whether a given fd is
allocated.  Also move fd_is_open() to file.c and make it static
as it is only called from one place.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 7 ++-
 include/linux/fdtable.h | 5 -
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index e8c6ada..8d67968 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -222,6 +222,11 @@ static int expand_files(struct files_struct *files, 
unsigned int nr)
return expanded;
 }
 
+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)
 {
__set_bit(fd, fdt->close_on_exec);
@@ -778,7 +783,7 @@ static int do_dup2(struct files_struct *files,
 */
fdt = files_fdtable(files);
tofree = idr_find(&files->fd_idr, fd);
-   if (!tofree && fd_is_open(fd, fdt))
+   if (!tofree && fd_is_open(fd, files))
goto Ebusy;
get_file(file);
if (tofree) {
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 6bece35..67259f4 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -34,11 +34,6 @@ static inline bool close_on_exec(unsigned int fd, const 
struct fdtable *fdt)
return test_bit(fd, fdt->close_on_exec);
 }
 
-static inline bool fd_is_open(unsigned int fd, const struct fdtable *fdt)
-{
-   return test_bit(fd, fdt->open_fds);
-}
-
 /*
  * Open file table structure
  */
-- 
1.8.3.1



[RESEND PATCH 07/13] vfs: Remove full_fds_bits from fd allocation code path.

2017-07-11 Thread Sandhya Bankar
The IDR has removed the need to have full_fds_bits hence removing it.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 18 +-
 include/linux/fdtable.h |  2 --
 2 files changed, 1 insertion(+), 19 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index da3a35b..e8c6ada 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -56,9 +56,6 @@ static void free_fdtable_rcu(struct rcu_head *rcu)
__free_fdtable(container_of(rcu, struct fdtable, rcu));
 }
 
-#define BITBIT_NR(nr)  BITS_TO_LONGS(BITS_TO_LONGS(nr))
-#define BITBIT_SIZE(nr)(BITBIT_NR(nr) * sizeof(long))
-
 /*
  * Copy 'count' fd bits from the old table to the new table and clear the extra
  * space if any.  This does not copy the file pointers.  Called with the files
@@ -75,11 +72,6 @@ static void copy_fd_bitmaps(struct fdtable *nfdt, struct 
fdtable *ofdt,
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);
-
-   cpy = BITBIT_SIZE(count);
-   set = BITBIT_SIZE(nfdt->max_fds) - cpy;
-   memcpy(nfdt->full_fds_bits, ofdt->full_fds_bits, cpy);
-   memset((char *)nfdt->full_fds_bits + cpy, 0, set);
 }
 
 /*
@@ -124,14 +116,12 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
fdt->max_fds = nr;
 
data = alloc_fdmem(max_t(size_t,
-2 * nr / BITS_PER_BYTE + BITBIT_SIZE(nr), 
L1_CACHE_BYTES));
+2 * 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;
-   data += nr / BITS_PER_BYTE;
-   fdt->full_fds_bits = data;
 
return fdt;
 
@@ -246,15 +236,11 @@ static inline void __clear_close_on_exec(unsigned int fd, 
struct fdtable *fdt)
 static inline void __set_open_fd(unsigned int fd, struct fdtable *fdt)
 {
__set_bit(fd, fdt->open_fds);
-   fd /= BITS_PER_LONG;
-   if (!~fdt->open_fds[fd])
-   __set_bit(fd, fdt->full_fds_bits);
 }
 
 static inline void __clear_open_fd(unsigned int fd, struct fdtable *fdt)
 {
__clear_bit(fd, fdt->open_fds);
-   __clear_bit(fd / BITS_PER_LONG, fdt->full_fds_bits);
 }
 
 static unsigned int count_open_files(struct fdtable *fdt)
@@ -298,7 +284,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
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;
-   new_fdt->full_fds_bits = newf->full_fds_bits_init;
 
 restart:
idr_copy_preload(&oldf->fd_idr, GFP_KERNEL);
@@ -472,7 +457,6 @@ struct files_struct init_files = {
.max_fds= NR_OPEN_DEFAULT,
.close_on_exec  = init_files.close_on_exec_init,
.open_fds   = init_files.open_fds_init,
-   .full_fds_bits  = init_files.full_fds_bits_init,
},
.file_lock  = __SPIN_LOCK_UNLOCKED(init_files.file_lock),
.fd_idr = IDR_INIT,
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index c2a53b6..6bece35 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -26,7 +26,6 @@ struct fdtable {
unsigned int max_fds;
unsigned long *close_on_exec;
unsigned long *open_fds;
-   unsigned long *full_fds_bits;
struct rcu_head rcu;
 };
 
@@ -60,7 +59,6 @@ struct files_struct {
spinlock_t file_lock cacheline_aligned_in_smp;
unsigned long close_on_exec_init[1];
unsigned long open_fds_init[1];
-   unsigned long full_fds_bits_init[1];
 };
 
 struct file_operations;
-- 
1.8.3.1



[RESEND PATCH 06/13] vfs: Remove next_fd from fd alloc code path.

2017-07-11 Thread Sandhya Bankar
The IDR is used in file descriptor allocation code to
allocate new file descriptor so, no need of next_fd to
track next file descriptor.
Hence removing it from file descriptor allocation code path.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 6 --
 include/linux/fdtable.h | 1 -
 2 files changed, 7 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index 1c000d8..da3a35b 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -294,7 +294,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
idr_init(&newf->fd_idr);
newf->resize_in_progress = false;
init_waitqueue_head(&newf->resize_wait);
-   newf->next_fd = 0;
new_fdt = &newf->fdtab;
new_fdt->max_fds = NR_OPEN_DEFAULT;
new_fdt->close_on_exec = newf->close_on_exec_init;
@@ -506,9 +505,6 @@ int __alloc_fd(struct files_struct *files,
goto out;
}
 
-   if (start <= files->next_fd)
-   files->next_fd = fd + 1;
-
fdt = files_fdtable(files);
__set_open_fd(fd, fdt);
if (flags & O_CLOEXEC)
@@ -538,8 +534,6 @@ static void __put_unused_fd(struct files_struct *files, 
unsigned int fd)
 {
struct fdtable *fdt = files_fdtable(files);
__clear_open_fd(fd, fdt);
-   if (fd < files->next_fd)
-   files->next_fd = fd;
 }
 
 void put_unused_fd(unsigned int fd)
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 4072f24..c2a53b6 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -58,7 +58,6 @@ struct files_struct {
* written part on a separate cache line in SMP
*/
spinlock_t file_lock cacheline_aligned_in_smp;
-   unsigned int next_fd;
unsigned long close_on_exec_init[1];
unsigned long open_fds_init[1];
unsigned long full_fds_bits_init[1];
-- 
1.8.3.1



[RESEND PATCH 05/13] vfs: Replace array of file pointers with an IDR

2017-07-11 Thread Sandhya Bankar
Instead of storing all the file pointers in a single array, use an
IDR.  It is RCU-safe, and does not need to be reallocated when the
fd array grows.  It also handles allocation of new file descriptors.

Signed-off-by: Sandhya Bankar 
[mawil...@microsoft.com: fixes]
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 180 
 include/linux/fdtable.h |  10 +--
 2 files changed, 79 insertions(+), 111 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index ad6f094..1c000d8 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -47,7 +47,6 @@ static void *alloc_fdmem(size_t size)
 
 static void __free_fdtable(struct fdtable *fdt)
 {
-   kvfree(fdt->fd);
kvfree(fdt->open_fds);
kfree(fdt);
 }
@@ -89,15 +88,7 @@ static void copy_fd_bitmaps(struct fdtable *nfdt, struct 
fdtable *ofdt,
  */
 static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
 {
-   unsigned int cpy, set;
-
BUG_ON(nfdt->max_fds < ofdt->max_fds);
-
-   cpy = ofdt->max_fds * sizeof(struct file *);
-   set = (nfdt->max_fds - ofdt->max_fds) * sizeof(struct file *);
-   memcpy(nfdt->fd, ofdt->fd, cpy);
-   memset((char *)nfdt->fd + cpy, 0, set);
-
copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds);
 }
 
@@ -131,15 +122,11 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
if (!fdt)
goto out;
fdt->max_fds = nr;
-   data = alloc_fdmem(nr * sizeof(struct file *));
-   if (!data)
-   goto out_fdt;
-   fdt->fd = data;
 
data = alloc_fdmem(max_t(size_t,
 2 * nr / BITS_PER_BYTE + BITBIT_SIZE(nr), 
L1_CACHE_BYTES));
if (!data)
-   goto out_arr;
+   goto out_fdt;
fdt->open_fds = data;
data += nr / BITS_PER_BYTE;
fdt->close_on_exec = data;
@@ -148,8 +135,6 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
 
return fdt;
 
-out_arr:
-   kvfree(fdt->fd);
 out_fdt:
kfree(fdt);
 out:
@@ -170,6 +155,7 @@ static int expand_fdtable(struct files_struct *files, 
unsigned int nr)
struct fdtable *new_fdt, *cur_fdt;
 
spin_unlock(&files->file_lock);
+   idr_preload_end();
new_fdt = alloc_fdtable(nr);
 
/* make sure all __fd_install() have seen resize_in_progress
@@ -178,6 +164,7 @@ static int expand_fdtable(struct files_struct *files, 
unsigned int nr)
if (atomic_read(&files->count) > 1)
synchronize_sched();
 
+   idr_preload(GFP_KERNEL);
spin_lock(&files->file_lock);
if (!new_fdt)
return -ENOMEM;
@@ -228,8 +215,10 @@ static int expand_files(struct files_struct *files, 
unsigned int nr)
 
if (unlikely(files->resize_in_progress)) {
spin_unlock(&files->file_lock);
+   idr_preload_end();
expanded = 1;
wait_event(files->resize_wait, !files->resize_in_progress);
+   idr_preload(GFP_KERNEL);
spin_lock(&files->file_lock);
goto repeat;
}
@@ -290,8 +279,8 @@ static unsigned int count_open_files(struct fdtable *fdt)
 struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
 {
struct files_struct *newf;
-   struct file **old_fds, **new_fds;
unsigned int open_files, i;
+   struct file *f;
struct fdtable *old_fdt, *new_fdt;
 
*errorp = -ENOMEM;
@@ -302,6 +291,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
atomic_set(&newf->count, 1);
 
spin_lock_init(&newf->file_lock);
+   idr_init(&newf->fd_idr);
newf->resize_in_progress = false;
init_waitqueue_head(&newf->resize_wait);
newf->next_fd = 0;
@@ -310,8 +300,9 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
new_fdt->close_on_exec = newf->close_on_exec_init;
new_fdt->open_fds = newf->open_fds_init;
new_fdt->full_fds_bits = newf->full_fds_bits_init;
-   new_fdt->fd = &newf->fd_array[0];
 
+restart:
+   idr_copy_preload(&oldf->fd_idr, GFP_KERNEL);
spin_lock(&oldf->file_lock);
old_fdt = files_fdtable(oldf);
open_files = count_open_files(old_fdt);
@@ -321,6 +312,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
 */
while (unlikely(open_files > new_fdt->max_fds)) {
spin_unlock(&oldf->file_lock);
+   idr_preload_end();
 
if (new_fdt != &newf->fdtab)
__free_fdtable(new_fdt);
@@ -343,41 +335,50 @@ struct files_struct *dup_fd(struct files_struct *oldf, 
int *errorp)
 * who knows it may have a new bigger fd table. We need
   

[RESEND PATCH 00/13] vfs: Convert file allocation code to use the IDR

2017-07-11 Thread Sandhya Bankar
Currently the file descriptors are allocated using a custom allocator. 
This patchset replaces the custom code with an IDR. This replacement will 
result in some memory saving for processes with relatively few open files 
and improve performance of workloads with very large numbers of open files.

The performance benchmark needs to be run on this patchset. 

Matthew Wilcox (5):
  idr: Add ability to set/clear tags
  idr: Add idr_for_each_entry_tagged()
  idr, radix-tree: Add get_tag_batch function
  idr, radix-tree: Implement copy_preload
  vfs: Add init_task.h include

Sandhya Bankar (8):
  vfs: Replace array of file pointers with an IDR
  vfs: Remove next_fd from fd alloc code path.
  vfs: Remove full_fds_bits from fd allocation code path.
  vfs: Use idr_tag_get() in fd_is_open().
  vfs: Rewrite close_files()
  vfs: Replace close_on_exec bitmap with an IDR tag
  vfs: Convert select to use idr_get_tag_batch()
  vfs: Delete struct fdtable

 fs/compat.c |   6 +-
 fs/exec.c   |   2 +-
 fs/fcntl.c  |   2 +-
 fs/file.c   | 606 ++--
 fs/proc/array.c |   2 +-
 fs/proc/fd.c|   6 +-
 fs/select.c |  21 +-
 include/linux/fdtable.h |  66 +--
 include/linux/file.h|   1 -
 include/linux/idr.h | 110 -
 include/linux/radix-tree.h  |   5 +
 lib/idr.c   |  30 +-
 lib/radix-tree.c| 169 +++-
 tools/testing/radix-tree/idr-test.c |  85 +++-
 tools/testing/radix-tree/linux/radix-tree.h |   2 +
 tools/testing/radix-tree/main.c |  38 ++
 tools/testing/radix-tree/test.c |   9 +-
 tools/testing/radix-tree/test.h |   3 +-
 18 files changed, 578 insertions(+), 585 deletions(-)

-- 
1.8.3.1



[PATCH 13/13] vfs: Delete struct fdtable

2017-04-29 Thread Sandhya Bankar
Completing the conversion of the file descriptor allocation code to use
the IDR.

This patch includes below changes:

 - Move max_fds from struct fdtable to files_struct.
 - Added fill_max_fds() routine to calculate the new value of max_fds
   to matches the old behaviour of alloc_fdtable() code which is
   user-visible through /proc.
 - Remove struct fdtable
 - Removed resize_in_progress, resize_wait from files_struct
 - Delete open_fds() & count_open_files()
 - Use READ_ONCE() instead of rcu_read_lock/unlock(). The rcu_read_lock()/
   unlock() was used to dereference the files->fdt. Now we don't use RCU to
   protect files->max_fds. So using READ_ONCE() macro to read the value of
   files->max_fds.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/compat.c |   6 +-
 fs/file.c   | 354 +++-
 fs/proc/array.c |   2 +-
 fs/proc/fd.c|   2 +-
 fs/select.c |   6 +-
 include/linux/fdtable.h |  31 +
 6 files changed, 54 insertions(+), 347 deletions(-)

diff --git a/fs/compat.c b/fs/compat.c
index c61b506..7483c9c 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1153,17 +1153,13 @@ int compat_core_sys_select(int n, compat_ulong_t __user 
*inp,
fd_set_bits fds;
void *bits;
int size, max_fds, ret = -EINVAL;
-   struct fdtable *fdt;
long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
 
if (n < 0)
goto out_nofds;
 
/* max_fds can increase, so grab it once to avoid race */
-   rcu_read_lock();
-   fdt = files_fdtable(current->files);
-   max_fds = fdt->max_fds;
-   rcu_read_unlock();
+   max_fds = READ_ONCE(current->files->max_fds);
if (n > max_fds)
n = max_fds;
 
diff --git a/fs/file.c b/fs/file.c
index 23f198b..3e6cf10 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -31,191 +31,36 @@
 unsigned int sysctl_nr_open_max =
__const_min(INT_MAX, ~(size_t)0/sizeof(void *)) & -BITS_PER_LONG;
 
-static void *alloc_fdmem(size_t size)
+static int fill_max_fds(struct files_struct *files, unsigned int nr)
 {
-   /*
-* Very large allocations can stress page reclaim, so fall back to
-* vmalloc() if the allocation size will be considered "large" by the 
VM.
-*/
-   if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
-   void *data = kmalloc(size, GFP_KERNEL_ACCOUNT |
-__GFP_NOWARN | __GFP_NORETRY);
-   if (data != NULL)
-   return data;
-   }
-   return __vmalloc(size, GFP_KERNEL_ACCOUNT | __GFP_HIGHMEM, PAGE_KERNEL);
-}
+   unsigned int nr_open;
 
-static void __free_fdtable(struct fdtable *fdt)
-{
-   kvfree(fdt->open_fds);
-   kfree(fdt);
-}
-
-static void free_fdtable_rcu(struct rcu_head *rcu)
-{
-   __free_fdtable(container_of(rcu, struct fdtable, rcu));
-}
-
-/*
- * Copy 'count' fd bits from the old table to the new table and clear the extra
- * space if any.  This does not copy the file pointers.  Called with the files
- * spinlock held for write.
- */
-static void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt,
-   unsigned int count)
-{
-   unsigned int cpy, set;
-
-   cpy = count / BITS_PER_BYTE;
-   set = (nfdt->max_fds - count) / BITS_PER_BYTE;
-   memcpy(nfdt->open_fds, ofdt->open_fds, cpy);
-   memset((char *)nfdt->open_fds + cpy, 0, set);
-}
+   if (likely(nr < files->max_fds))
+   return 0;
 
-/*
- * Copy all file descriptors from the old table to the new, expanded table and
- * clear the extra space.  Called with the files spinlock held for write.
- */
-static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
-{
-   BUG_ON(nfdt->max_fds < ofdt->max_fds);
-   copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds);
-}
+   nr_open = READ_ONCE(sysctl_nr_open);
 
-static struct fdtable * alloc_fdtable(unsigned int nr)
-{
-   struct fdtable *fdt;
-   void *data;
+   if (nr >= nr_open)
+   return -EMFILE;
 
/*
-* Figure out how many fds we actually want to support in this fdtable.
-* Allocation steps are keyed to the size of the fdarray, since it
-* grows far faster than any of the other dynamic data. We try to fit
-* the fdarray into comfortable page-tuned chunks: starting at 1024B
-* and growing in powers of two from there on.
+* This calculation of the new value of max_fds matches the old
+* behaviour of this code which is user-visible through /proc.
+* nr may exceed the sysctl_nr_open value by a small amount.
+* This used to be necessary to keep the bitmaps aligned, and
+* we keep it the same even though the IDR handles the bitmaps now.
 */
+
 

[PATCH 12/13] vfs: Convert select to use idr_get_tag_batch()

2017-04-29 Thread Sandhya Bankar
Convert select to use idr_get_tag_batch().

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/select.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/select.c b/fs/select.c
index e211227..5d20a14 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -346,32 +346,33 @@ static int poll_select_copy_remaining(struct timespec64 
*end_time,
 
 static int max_select_fd(unsigned long n, fd_set_bits *fds)
 {
-   unsigned long *open_fds;
+   unsigned long bad_fds;
unsigned long set;
int max;
-   struct fdtable *fdt;
+   struct idr *fd_idr = ¤t->files->fd_idr;
 
/* handle last in-complete long-word first */
set = ~(~0UL << (n & (BITS_PER_LONG-1)));
n /= BITS_PER_LONG;
-   fdt = files_fdtable(current->files);
-   open_fds = fdt->open_fds + n;
max = 0;
if (set) {
set &= BITS(fds, n);
if (set) {
-   if (!(set & ~*open_fds))
+   bad_fds = idr_get_tag_batch(fd_idr, (n * BITS_PER_LONG),
+   IDR_FREE);
+   if (!(set & bad_fds))
goto get_max;
return -EBADF;
}
}
while (n) {
-   open_fds--;
n--;
set = BITS(fds, n);
if (!set)
continue;
-   if (set & ~*open_fds)
+   bad_fds = idr_get_tag_batch(fd_idr, (n * BITS_PER_LONG),
+   IDR_FREE);
+   if (set & bad_fds)
return -EBADF;
if (max)
continue;
-- 
1.8.3.1



[PATCH 11/13] vfs: Add init_task.h include

2017-04-29 Thread Sandhya Bankar
Removes a sparse warning about init_files() not being declared.

Signed-off-by: Matthew Wilcox 
---
 fs/file.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/file.c b/fs/file.c
index 56c5731..23f198b 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-- 
1.8.3.1



[PATCH 10/13] vfs: Replace close_on_exec bitmap with an IDR tag

2017-04-29 Thread Sandhya Bankar
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,

[PATCH 09/13] vfs: Rewrite close_files()

2017-04-29 Thread Sandhya Bankar
Use the IDR iteration functionality instead of the open_fds bitmap to
call filp_close() for each open file.  Also make close_files() return
void, because it no longer uses the fdtable.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c | 37 +++--
 1 file changed, 11 insertions(+), 26 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index 8d67968..8cd77c5 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -373,37 +373,21 @@ struct files_struct *dup_fd(struct files_struct *oldf, 
int *errorp)
return NULL;
 }
 
-static struct fdtable *close_files(struct files_struct * files)
+static void close_files(struct files_struct * files)
 {
/*
-* It is safe to dereference the fd table without RCU or
-* ->file_lock because this is the last reference to the
-* files structure.
+* No need for RCU or ->file_lock protection because
+* this is the last reference to the files structure.
 */
-   struct fdtable *fdt = rcu_dereference_raw(files->fdt);
-   unsigned int i, j = 0;
+   struct file *file;
+   int fd;
 
-   for (;;) {
-   unsigned long set;
-   i = j * BITS_PER_LONG;
-   if (i >= fdt->max_fds)
-   break;
-   set = fdt->open_fds[j++];
-   while (set) {
-   if (set & 1) {
-   struct file *file;
-   file = idr_remove(&files->fd_idr, i);
-   if (file) {
-   filp_close(file, files);
-   cond_resched_rcu_qs();
-   }
-   }
-   i++;
-   set >>= 1;
-   }
+   idr_for_each_entry(&files->fd_idr, file, fd) {
+   filp_close(file, files);
+   cond_resched_rcu_qs();
}
 
-   return fdt;
+   idr_destroy(&files->fd_idr);
 }
 
 struct files_struct *get_files_struct(struct task_struct *task)
@@ -422,7 +406,8 @@ struct files_struct *get_files_struct(struct task_struct 
*task)
 void put_files_struct(struct files_struct *files)
 {
if (atomic_dec_and_test(&files->count)) {
-   struct fdtable *fdt = close_files(files);
+   struct fdtable *fdt = rcu_dereference_raw(files->fdt);
+   close_files(files);
 
/* free the arrays if they are not embedded */
if (fdt != &files->fdtab)
-- 
1.8.3.1



[PATCH 08/13] vfs: Use idr_tag_get() in fd_is_open().

2017-04-29 Thread Sandhya Bankar
Use idr_tag_get() in fd_is_open() to know whether a given fd is
allocated.  Also move fd_is_open() to file.c and make it static
as it is only called from one place.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 7 ++-
 include/linux/fdtable.h | 5 -
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index e8c6ada..8d67968 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -222,6 +222,11 @@ static int expand_files(struct files_struct *files, 
unsigned int nr)
return expanded;
 }
 
+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)
 {
__set_bit(fd, fdt->close_on_exec);
@@ -778,7 +783,7 @@ static int do_dup2(struct files_struct *files,
 */
fdt = files_fdtable(files);
tofree = idr_find(&files->fd_idr, fd);
-   if (!tofree && fd_is_open(fd, fdt))
+   if (!tofree && fd_is_open(fd, files))
goto Ebusy;
get_file(file);
if (tofree) {
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 6bece35..67259f4 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -34,11 +34,6 @@ static inline bool close_on_exec(unsigned int fd, const 
struct fdtable *fdt)
return test_bit(fd, fdt->close_on_exec);
 }
 
-static inline bool fd_is_open(unsigned int fd, const struct fdtable *fdt)
-{
-   return test_bit(fd, fdt->open_fds);
-}
-
 /*
  * Open file table structure
  */
-- 
1.8.3.1



[PATCH 06/13] vfs: Remove next_fd from fd alloc code path.

2017-04-29 Thread Sandhya Bankar
The IDR is used in file descriptor allocation code to
allocate new file descriptor so, no need of next_fd to
track next file descriptor.
Hence removing it from file descriptor allocation code path.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 6 --
 include/linux/fdtable.h | 1 -
 2 files changed, 7 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index 1c000d8..da3a35b 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -294,7 +294,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
idr_init(&newf->fd_idr);
newf->resize_in_progress = false;
init_waitqueue_head(&newf->resize_wait);
-   newf->next_fd = 0;
new_fdt = &newf->fdtab;
new_fdt->max_fds = NR_OPEN_DEFAULT;
new_fdt->close_on_exec = newf->close_on_exec_init;
@@ -506,9 +505,6 @@ int __alloc_fd(struct files_struct *files,
goto out;
}
 
-   if (start <= files->next_fd)
-   files->next_fd = fd + 1;
-
fdt = files_fdtable(files);
__set_open_fd(fd, fdt);
if (flags & O_CLOEXEC)
@@ -538,8 +534,6 @@ static void __put_unused_fd(struct files_struct *files, 
unsigned int fd)
 {
struct fdtable *fdt = files_fdtable(files);
__clear_open_fd(fd, fdt);
-   if (fd < files->next_fd)
-   files->next_fd = fd;
 }
 
 void put_unused_fd(unsigned int fd)
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 4072f24..c2a53b6 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -58,7 +58,6 @@ struct files_struct {
* written part on a separate cache line in SMP
*/
spinlock_t file_lock cacheline_aligned_in_smp;
-   unsigned int next_fd;
unsigned long close_on_exec_init[1];
unsigned long open_fds_init[1];
unsigned long full_fds_bits_init[1];
-- 
1.8.3.1



[PATCH 07/13] vfs: Remove full_fds_bits from fd allocation code path.

2017-04-29 Thread Sandhya Bankar
The IDR has removed the need to have full_fds_bits hence removing it.

Signed-off-by: Sandhya Bankar 
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 18 +-
 include/linux/fdtable.h |  2 --
 2 files changed, 1 insertion(+), 19 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index da3a35b..e8c6ada 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -56,9 +56,6 @@ static void free_fdtable_rcu(struct rcu_head *rcu)
__free_fdtable(container_of(rcu, struct fdtable, rcu));
 }
 
-#define BITBIT_NR(nr)  BITS_TO_LONGS(BITS_TO_LONGS(nr))
-#define BITBIT_SIZE(nr)(BITBIT_NR(nr) * sizeof(long))
-
 /*
  * Copy 'count' fd bits from the old table to the new table and clear the extra
  * space if any.  This does not copy the file pointers.  Called with the files
@@ -75,11 +72,6 @@ static void copy_fd_bitmaps(struct fdtable *nfdt, struct 
fdtable *ofdt,
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);
-
-   cpy = BITBIT_SIZE(count);
-   set = BITBIT_SIZE(nfdt->max_fds) - cpy;
-   memcpy(nfdt->full_fds_bits, ofdt->full_fds_bits, cpy);
-   memset((char *)nfdt->full_fds_bits + cpy, 0, set);
 }
 
 /*
@@ -124,14 +116,12 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
fdt->max_fds = nr;
 
data = alloc_fdmem(max_t(size_t,
-2 * nr / BITS_PER_BYTE + BITBIT_SIZE(nr), 
L1_CACHE_BYTES));
+2 * 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;
-   data += nr / BITS_PER_BYTE;
-   fdt->full_fds_bits = data;
 
return fdt;
 
@@ -246,15 +236,11 @@ static inline void __clear_close_on_exec(unsigned int fd, 
struct fdtable *fdt)
 static inline void __set_open_fd(unsigned int fd, struct fdtable *fdt)
 {
__set_bit(fd, fdt->open_fds);
-   fd /= BITS_PER_LONG;
-   if (!~fdt->open_fds[fd])
-   __set_bit(fd, fdt->full_fds_bits);
 }
 
 static inline void __clear_open_fd(unsigned int fd, struct fdtable *fdt)
 {
__clear_bit(fd, fdt->open_fds);
-   __clear_bit(fd / BITS_PER_LONG, fdt->full_fds_bits);
 }
 
 static unsigned int count_open_files(struct fdtable *fdt)
@@ -298,7 +284,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
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;
-   new_fdt->full_fds_bits = newf->full_fds_bits_init;
 
 restart:
idr_copy_preload(&oldf->fd_idr, GFP_KERNEL);
@@ -472,7 +457,6 @@ struct files_struct init_files = {
.max_fds= NR_OPEN_DEFAULT,
.close_on_exec  = init_files.close_on_exec_init,
.open_fds   = init_files.open_fds_init,
-   .full_fds_bits  = init_files.full_fds_bits_init,
},
.file_lock  = __SPIN_LOCK_UNLOCKED(init_files.file_lock),
.fd_idr = IDR_INIT,
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index c2a53b6..6bece35 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -26,7 +26,6 @@ struct fdtable {
unsigned int max_fds;
unsigned long *close_on_exec;
unsigned long *open_fds;
-   unsigned long *full_fds_bits;
struct rcu_head rcu;
 };
 
@@ -60,7 +59,6 @@ struct files_struct {
spinlock_t file_lock cacheline_aligned_in_smp;
unsigned long close_on_exec_init[1];
unsigned long open_fds_init[1];
-   unsigned long full_fds_bits_init[1];
 };
 
 struct file_operations;
-- 
1.8.3.1



[PATCH 05/13] vfs: Replace array of file pointers with an IDR

2017-04-29 Thread Sandhya Bankar
Instead of storing all the file pointers in a single array, use an
IDR.  It is RCU-safe, and does not need to be reallocated when the
fd array grows.  It also handles allocation of new file descriptors.

Signed-off-by: Sandhya Bankar 
[mawil...@microsoft.com: fixes]
Signed-off-by: Matthew Wilcox 
---
 fs/file.c   | 180 
 include/linux/fdtable.h |  10 +--
 2 files changed, 79 insertions(+), 111 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index ad6f094..1c000d8 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -47,7 +47,6 @@ static void *alloc_fdmem(size_t size)
 
 static void __free_fdtable(struct fdtable *fdt)
 {
-   kvfree(fdt->fd);
kvfree(fdt->open_fds);
kfree(fdt);
 }
@@ -89,15 +88,7 @@ static void copy_fd_bitmaps(struct fdtable *nfdt, struct 
fdtable *ofdt,
  */
 static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
 {
-   unsigned int cpy, set;
-
BUG_ON(nfdt->max_fds < ofdt->max_fds);
-
-   cpy = ofdt->max_fds * sizeof(struct file *);
-   set = (nfdt->max_fds - ofdt->max_fds) * sizeof(struct file *);
-   memcpy(nfdt->fd, ofdt->fd, cpy);
-   memset((char *)nfdt->fd + cpy, 0, set);
-
copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds);
 }
 
@@ -131,15 +122,11 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
if (!fdt)
goto out;
fdt->max_fds = nr;
-   data = alloc_fdmem(nr * sizeof(struct file *));
-   if (!data)
-   goto out_fdt;
-   fdt->fd = data;
 
data = alloc_fdmem(max_t(size_t,
 2 * nr / BITS_PER_BYTE + BITBIT_SIZE(nr), 
L1_CACHE_BYTES));
if (!data)
-   goto out_arr;
+   goto out_fdt;
fdt->open_fds = data;
data += nr / BITS_PER_BYTE;
fdt->close_on_exec = data;
@@ -148,8 +135,6 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
 
return fdt;
 
-out_arr:
-   kvfree(fdt->fd);
 out_fdt:
kfree(fdt);
 out:
@@ -170,6 +155,7 @@ static int expand_fdtable(struct files_struct *files, 
unsigned int nr)
struct fdtable *new_fdt, *cur_fdt;
 
spin_unlock(&files->file_lock);
+   idr_preload_end();
new_fdt = alloc_fdtable(nr);
 
/* make sure all __fd_install() have seen resize_in_progress
@@ -178,6 +164,7 @@ static int expand_fdtable(struct files_struct *files, 
unsigned int nr)
if (atomic_read(&files->count) > 1)
synchronize_sched();
 
+   idr_preload(GFP_KERNEL);
spin_lock(&files->file_lock);
if (!new_fdt)
return -ENOMEM;
@@ -228,8 +215,10 @@ static int expand_files(struct files_struct *files, 
unsigned int nr)
 
if (unlikely(files->resize_in_progress)) {
spin_unlock(&files->file_lock);
+   idr_preload_end();
expanded = 1;
wait_event(files->resize_wait, !files->resize_in_progress);
+   idr_preload(GFP_KERNEL);
spin_lock(&files->file_lock);
goto repeat;
}
@@ -290,8 +279,8 @@ static unsigned int count_open_files(struct fdtable *fdt)
 struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
 {
struct files_struct *newf;
-   struct file **old_fds, **new_fds;
unsigned int open_files, i;
+   struct file *f;
struct fdtable *old_fdt, *new_fdt;
 
*errorp = -ENOMEM;
@@ -302,6 +291,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
atomic_set(&newf->count, 1);
 
spin_lock_init(&newf->file_lock);
+   idr_init(&newf->fd_idr);
newf->resize_in_progress = false;
init_waitqueue_head(&newf->resize_wait);
newf->next_fd = 0;
@@ -310,8 +300,9 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
new_fdt->close_on_exec = newf->close_on_exec_init;
new_fdt->open_fds = newf->open_fds_init;
new_fdt->full_fds_bits = newf->full_fds_bits_init;
-   new_fdt->fd = &newf->fd_array[0];
 
+restart:
+   idr_copy_preload(&oldf->fd_idr, GFP_KERNEL);
spin_lock(&oldf->file_lock);
old_fdt = files_fdtable(oldf);
open_files = count_open_files(old_fdt);
@@ -321,6 +312,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int 
*errorp)
 */
while (unlikely(open_files > new_fdt->max_fds)) {
spin_unlock(&oldf->file_lock);
+   idr_preload_end();
 
if (new_fdt != &newf->fdtab)
__free_fdtable(new_fdt);
@@ -343,41 +335,50 @@ struct files_struct *dup_fd(struct files_struct *oldf, 
int *errorp)
 * who knows it may have a new bigger fd table. We need
   

[PATCH 04/13] idr, radix-tree: Implement copy_preload

2017-04-29 Thread Sandhya Bankar
In the file descriptor table duplication code (called at fork()), we
need to duplicate an IDR.  But we have to do it under a lock (so another
thread doesn't open/close a fd in the middle), and there's no suitable
preload operation for this today.  Adding just idr_copy_preload() isn't
enough as another thread could grow the fd table between starting the
preload and acquiring the lock.  We also need idr_check_preload() to be
called after acquiring the lock.

Signed-off-by: Matthew Wilcox 
---
 include/linux/idr.h | 32 +++
 include/linux/radix-tree.h  |  3 ++
 lib/radix-tree.c| 83 +
 tools/testing/radix-tree/idr-test.c | 24 +
 tools/testing/radix-tree/linux/radix-tree.h |  2 +
 tools/testing/radix-tree/main.c | 38 +
 6 files changed, 182 insertions(+)

diff --git a/include/linux/idr.h b/include/linux/idr.h
index d43cf01..eed1c1a 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -166,6 +166,38 @@ static inline bool idr_is_empty(const struct idr *idr)
 }
 
 /**
+ * idr_copy_preload - preload for idr_copy()
+ * @src: IDR to be copied from
+ * @gfp: Allocation mask to use for preloading
+ *
+ * Preallocates enough memory for a call to idr_copy().  This function
+ * returns with preemption disabled.  Call idr_preload_end() once the
+ * copy has completed.
+ *
+ * Return: -ENOMEM if the memory could not be allocated.
+ */
+static inline int idr_copy_preload(const struct idr *src, gfp_t gfp)
+{
+   return radix_tree_copy_preload(&src->idr_rt, gfp);
+}
+
+/**
+ * idr_check_preload - Check the preload is still sufficient
+ * @src: IDR to be copied from
+ *
+ * Between the successful allocation of memory and acquiring the lock that
+ * protects @src, the IDR may have expanded.  If this function returns
+ * false, more memory needs to be preallocated.
+ *
+ * Return: true if enough memory remains allocated, false to retry the
+ * preallocation.
+ */
+static inline bool idr_check_preload(const struct idr *src)
+{
+   return radix_tree_check_preload(&src->idr_rt);
+}
+
+/**
  * idr_preload_end - end preload section started with idr_preload()
  *
  * Each idr_preload() should be matched with an invocation of this
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index f701e0b..f53d004 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -354,6 +354,9 @@ static inline void radix_tree_preload_end(void)
preempt_enable();
 }
 
+int radix_tree_copy_preload(const struct radix_tree_root *, gfp_t);
+bool radix_tree_check_preload(const struct radix_tree_root *);
+
 int radix_tree_split_preload(unsigned old_order, unsigned new_order, gfp_t);
 int radix_tree_split(struct radix_tree_root *, unsigned long index,
unsigned new_order);
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 855ac8e..c1d75224 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -277,6 +277,55 @@ static unsigned long next_index(unsigned long index,
return (index & ~node_maxindex(node)) + (offset << node->shift);
 }
 
+/**
+ * radix_tree_count_nodes - Returns the number of nodes in this tree
+ * @root: radix tree root
+ *
+ * This routine does not examine every node in the tree; it assumes that
+ * all entries in the tree at level 1 are nodes.  It will overestimate
+ * the number of nodes in the tree in the presence of entries of order
+ * RADIX_TREE_MAP_SHIFT or higher.
+ */
+static unsigned long radix_tree_count_nodes(const struct radix_tree_root *root)
+{
+   struct radix_tree_node *node, *child;
+   unsigned long n = 1;
+   void *entry = rcu_dereference_raw(root->rnode);
+   unsigned int offset = 0;
+
+   if (!radix_tree_is_internal_node(entry))
+   return 0;
+
+   node = entry_to_node(entry);
+   if (!node->shift)
+   return n;
+
+   n += node->count;
+   if (node->shift == RADIX_TREE_MAP_SHIFT)
+   return n;
+
+   while (node) {
+   if (offset == RADIX_TREE_MAP_SIZE) {
+   offset = node->offset + 1;
+   node = node->parent;
+   continue;
+   }
+
+   entry = rcu_dereference_raw(node->slots[offset]);
+   offset++;
+   if (!radix_tree_is_internal_node(entry))
+   continue;
+   child = entry_to_node(entry);
+   n += child->count;
+   if (node->shift <= 2 * RADIX_TREE_MAP_SHIFT)
+   continue;
+   offset = 0;
+   node = child;
+   }
+
+   return n;
+}
+
 #ifndef __KERNEL__
 static void dump_node(struct radix_tree_node *node, unsigned long index)
 {
@@ -530,6 +579,40 @@ int radix_tree_maybe_preload(gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(radix_tree_maybe_preload);
 
+/**
+ * radix_tree_copy_preload - preload for radix_tree_

[PATCH 03/13] idr, radix-tree: Add get_tag_batch function

2017-04-29 Thread Sandhya Bankar
To implement select() on top of the IDR, we need to be able to get the
tags which represent the open files in bulk.  For this user, it makes
sense to get a batch of BITS_PER_LONG tags at a time, and until another
user shows up that wants something different, let's enforce that instead
of coping with arbitrary offsets.

Signed-off-by: Matthew Wilcox 
---
 include/linux/idr.h |  6 
 include/linux/radix-tree.h  |  2 ++
 lib/radix-tree.c| 55 -
 tools/testing/radix-tree/idr-test.c | 20 ++
 tools/testing/radix-tree/test.h |  2 +-
 5 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/include/linux/idr.h b/include/linux/idr.h
index 9f71e63..d43cf01 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -147,6 +147,12 @@ static inline bool idr_tag_get(const struct idr *idr, int 
id, unsigned int tag)
return radix_tree_tag_get(&idr->idr_rt, id, tag);
 }
 
+static inline unsigned long idr_get_tag_batch(const struct idr *idr, int id,
+   unsigned int tag)
+{
+   return radix_tree_get_tag_batch(&idr->idr_rt, id, tag);
+}
+
 static inline void idr_init(struct idr *idr)
 {
INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER);
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 3e57350..f701e0b 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -339,6 +339,8 @@ void radix_tree_iter_tag_set(struct radix_tree_root *,
const struct radix_tree_iter *iter, unsigned int tag);
 void radix_tree_iter_tag_clear(struct radix_tree_root *,
const struct radix_tree_iter *iter, unsigned int tag);
+unsigned long radix_tree_get_tag_batch(const struct radix_tree_root *,
+   unsigned long index, unsigned int tag);
 unsigned int radix_tree_gang_lookup_tag(const struct radix_tree_root *,
void **results, unsigned long first_index,
unsigned int max_items, unsigned int tag);
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 6723384..855ac8e 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -181,7 +181,8 @@ static inline void root_tag_clear_all(struct 
radix_tree_root *root)
root->gfp_mask &= (1 << ROOT_TAG_SHIFT) - 1;
 }
 
-static inline int root_tag_get(const struct radix_tree_root *root, unsigned 
tag)
+static inline bool root_tag_get(const struct radix_tree_root *root,
+   unsigned tag)
 {
return (__force int)root->gfp_mask & (1 << (tag + ROOT_TAG_SHIFT));
 }
@@ -1571,6 +1572,58 @@ int radix_tree_tag_get(const struct radix_tree_root 
*root,
 }
 EXPORT_SYMBOL(radix_tree_tag_get);
 
+static unsigned long
+__radix_tree_get_tag_batch(const struct radix_tree_root *root,
+   unsigned long index, unsigned int tag)
+{
+   struct radix_tree_node *node;
+   void __rcu **slot = NULL;
+   bool idr_free = is_idr(root) && (tag == IDR_FREE);
+
+   __radix_tree_lookup(root, index, &node, &slot);
+   if (!slot)
+   return idr_free ? ~0UL : 0;
+   if (!node)
+   return root_tag_get(root, tag) | (idr_free ? ~1UL : 0);
+   if (node->shift)
+   return idr_free ? ~0UL : 0;
+   return node->tags[tag][(index / BITS_PER_LONG) &
+   (RADIX_TREE_TAG_LONGS - 1)];
+}
+
+/**
+ * radix_tree_get_tag_batch() - get a batch of tags
+ * @root: radix tree root
+ * @index: start index of batch
+ * @tag: tag to get
+ *
+ * Get a batch of BITS_PER_LONG tags.  The only values of @index
+ * permitted are multiples of BITS_PER_LONG.
+ *
+ * Return: The tags for the next BITS_PER_LONG indices.
+ */
+unsigned long radix_tree_get_tag_batch(const struct radix_tree_root *root,
+   unsigned long index, unsigned int tag)
+{
+   unsigned long bits = 0;
+   unsigned shift = BITS_PER_LONG > RADIX_TREE_MAP_SIZE ? \
+   RADIX_TREE_MAP_SIZE : 0;
+
+   if (WARN_ON_ONCE(index & (BITS_PER_LONG - 1)))
+   return bits;
+
+   index += BITS_PER_LONG;
+   for (;;) {
+   index -= RADIX_TREE_MAP_SIZE;
+   bits |= __radix_tree_get_tag_batch(root, index, tag);
+   if (!(index & (BITS_PER_LONG - 1)))
+   break;
+   bits <<= shift;
+   }
+
+   return bits;
+}
+
 static inline void __set_iter_shift(struct radix_tree_iter *iter,
unsigned int shift)
 {
diff --git a/tools/testing/radix-tree/idr-test.c 
b/tools/testing/radix-tree/idr-test.c
index 334ce1c..3f9f429 100644
--- a/tools/testing/radix-tree/idr-test.c
+++ b/tools/testing/radix-tree/idr-test.c
@@ -139,6 +139,8 @@ void idr_tag_test(void)
DEFINE_IDR(idr);
struct item *item;
 
+   assert(

[PATCH 02/13] idr: Add idr_for_each_entry_tagged()

2017-04-29 Thread Sandhya Bankar
Add the ability to iterate over tagged entries in the IDR with
idr_get_next_tag() and idr_for_each_entry_tagged().

Signed-off-by: Matthew Wilcox 
---
 include/linux/idr.h | 15 ++-
 lib/idr.c   | 30 +-
 tools/testing/radix-tree/idr-test.c | 18 ++
 tools/testing/radix-tree/test.c |  9 +++--
 tools/testing/radix-tree/test.h |  1 +
 5 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/include/linux/idr.h b/include/linux/idr.h
index 7eb4432..9f71e63 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -84,7 +84,8 @@ static inline void idr_set_cursor(struct idr *idr, unsigned 
int val)
 int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t);
 int idr_for_each(const struct idr *,
 int (*fn)(int id, void *p, void *data), void *data);
-void *idr_get_next(struct idr *, int *nextid);
+void *idr_get_next(const struct idr *, int *nextid);
+void *idr_get_next_tag(const struct idr *, int *nextid, unsigned int tag);
 void *idr_replace(struct idr *, void *, int id);
 void idr_destroy(struct idr *);
 
@@ -213,6 +214,18 @@ static inline void *idr_find(const struct idr *idr, int id)
 entry; \
 ++id, (entry) = idr_get_next((idr), &(id)))
 
+/**
+ * idr_for_each_entry_tagged - iterate over IDs with a set tag
+ * @idr: IDR handle
+ * @entry: The pointer stored in @idr
+ * @id: The index of @entry in @idr
+ * @tag: tag to search for
+ */
+#define idr_for_each_entry_tagged(idr, entry, id, tag) \
+   for (id = 0;\
+((entry) = idr_get_next_tag(idr, &(id), (tag))) != NULL;   \
+++id)
+
 /*
  * IDA - IDR based id allocator, use when translation from id to
  * pointer isn't necessary.
diff --git a/lib/idr.c b/lib/idr.c
index b13682b..68e39c3 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -120,7 +120,7 @@ int idr_for_each(const struct idr *idr,
  * to the ID of the found value.  To use in a loop, the value pointed to by
  * nextid must be incremented by the user.
  */
-void *idr_get_next(struct idr *idr, int *nextid)
+void *idr_get_next(const struct idr *idr, int *nextid)
 {
struct radix_tree_iter iter;
void __rcu **slot;
@@ -135,6 +135,34 @@ void *idr_get_next(struct idr *idr, int *nextid)
 EXPORT_SYMBOL(idr_get_next);
 
 /**
+ * idr_get_next_tag - Find next tagged entry
+ * @idr: idr handle
+ * @nextid: Pointer to lowest possible ID to return
+ * @tag: tag to search for
+ *
+ * Returns the next tagged entry in the tree with an ID greater than
+ * or equal to the value pointed to by @nextid.  On exit, @nextid is updated
+ * to the ID of the found value.  To use in a loop, the value pointed to by
+ * nextid must be incremented by the user.  If a NULL entry is tagged, it
+ * will be returned.
+ */
+void *idr_get_next_tag(const struct idr *idr, int *nextid, unsigned int tag)
+{
+   struct radix_tree_iter iter;
+   void __rcu **slot;
+
+   radix_tree_iter_init(&iter, *nextid);
+   slot = radix_tree_next_chunk(&idr->idr_rt, &iter,
+   RADIX_TREE_ITER_TAGGED | tag);
+   if (!slot)
+   return NULL;
+
+   *nextid = iter.index;
+   return rcu_dereference_raw(*slot);
+}
+EXPORT_UNUSED_SYMBOL(idr_get_next_tag);
+
+/**
  * idr_replace - replace pointer for given id
  * @idr: idr handle
  * @ptr: New pointer to associate with the ID
diff --git a/tools/testing/radix-tree/idr-test.c 
b/tools/testing/radix-tree/idr-test.c
index fd94bee..334ce1c 100644
--- a/tools/testing/radix-tree/idr-test.c
+++ b/tools/testing/radix-tree/idr-test.c
@@ -23,19 +23,15 @@
 
 int item_idr_free(int id, void *p, void *data)
 {
-   struct item *item = p;
-   assert(item->index == id);
-   free(p);
-
+   item_free(p, id);
return 0;
 }
 
 void item_idr_remove(struct idr *idr, int id)
 {
struct item *item = idr_find(idr, id);
-   assert(item->index == id);
idr_remove(idr, id);
-   free(item);
+   item_free(item, id);
 }
 
 void idr_alloc_test(void)
@@ -139,11 +135,13 @@ void idr_null_test(void)
 
 void idr_tag_test(void)
 {
-   unsigned int i;
+   int i;
DEFINE_IDR(idr);
+   struct item *item;
 
for (i = 0; i < 100; i++) {
-   assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == i);
+   item = item_create(i, 0);
+   assert(idr_alloc(&idr, item, 0, 0, GFP_KERNEL) == i);
if (i % 7 == 0)
idr_tag_set(&idr, i, IDR_TEST);
}
@@ -157,6 +155,10 @@ void idr_tag_test(void)
assert(idr_tag_get(&idr, i, IDR_TEST) == (i % 14 == 7));
}
 
+   idr_for_each_entry_tagged(&idr, item, i, IDR_TEST) {
+   assert(item->index % 14 == 7);
+   }
+
idr_for_each(&idr, item_idr_fre

[PATCH 00/13] vfs: Convert file allocation code to use the IDR

2017-04-29 Thread Sandhya Bankar
Currently the file descriptors are allocated using a custom allocator. 
This patchset replaces the custom code with an IDR. This replacement will 
result in some memory saving for processes with relatively few open files 
and improve performance of workloads with very large numbers of open files.

Note: Some more performance benchmark needs to be run on this patchset.
Can anyone please help in runnning benchmark for this patchset.

Matthew Wilcox (5):
  idr: Add ability to set/clear tags
  idr: Add idr_for_each_entry_tagged()
  idr, radix-tree: Add get_tag_batch function
  idr, radix-tree: Implement copy_preload
  vfs: Add init_task.h include

Sandhya Bankar (8):
  vfs: Replace array of file pointers with an IDR
  vfs: Remove next_fd from fd alloc code path.
  vfs: Remove full_fds_bits from fd allocation code path.
  vfs: Use idr_tag_get() in fd_is_open().
  vfs: Rewrite close_files()
  vfs: Replace close_on_exec bitmap with an IDR tag
  vfs: Convert select to use idr_get_tag_batch()
  vfs: Delete struct fdtable

 fs/compat.c |   6 +-
 fs/exec.c   |   2 +-
 fs/fcntl.c  |   2 +-
 fs/file.c   | 606 ++--
 fs/proc/array.c |   2 +-
 fs/proc/fd.c|   6 +-
 fs/select.c |  21 +-
 include/linux/fdtable.h |  66 +--
 include/linux/file.h|   1 -
 include/linux/idr.h | 110 -
 include/linux/radix-tree.h  |   5 +
 lib/idr.c   |  30 +-
 lib/radix-tree.c| 169 +++-
 tools/testing/radix-tree/idr-test.c |  85 +++-
 tools/testing/radix-tree/linux/radix-tree.h |   2 +
 tools/testing/radix-tree/main.c |  38 ++
 tools/testing/radix-tree/test.c |   9 +-
 tools/testing/radix-tree/test.h |   3 +-
 18 files changed, 578 insertions(+), 585 deletions(-)

-- 
1.8.3.1



[PATCH] Staging: sm750fb: Use x instead of x != NULL

2016-09-14 Thread Sandhya Bankar
Use x instead of x != NULL .
This patch removes the explicit NULL comparisons.This issue is found by 
checkpatch.pl script .
CHECK: Comparison to NULL could be written "pCurrentDviCtrl->pfnInit" 

Signed-off-by: Sandhya Bankar 
---
 drivers/staging/sm750fb/ddk750_dvi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/sm750fb/ddk750_dvi.c 
b/drivers/staging/sm750fb/ddk750_dvi.c
index a4a2550..8a39e0e 100644
--- a/drivers/staging/sm750fb/ddk750_dvi.c
+++ b/drivers/staging/sm750fb/ddk750_dvi.c
@@ -45,7 +45,7 @@ int dviInit(
dvi_ctrl_device_t *pCurrentDviCtrl;
 
pCurrentDviCtrl = g_dcftSupportedDviController;
-   if (pCurrentDviCtrl->pfnInit != NULL) {
+   if (pCurrentDviCtrl->pfnInit) {
return pCurrentDviCtrl->pfnInit(edgeSelect, busSelect, 
dualEdgeClkSelect, hsyncEnable,
vsyncEnable, deskewEnable, 
deskewSetting, continuousSyncEnable,
pllFilterEnable, 
pllFilterValue);
-- 
1.8.2.3



[PATCH] usb: musbhsdma: Add space after that ','.

2016-06-01 Thread Sandhya Bankar
Add space after that ','.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/musb/musbhsdma.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h
index f7b13fd2..46a2bb9 100644
--- a/drivers/usb/musb/musbhsdma.h
+++ b/drivers/usb/musb/musbhsdma.h
@@ -113,7 +113,7 @@ static inline void musb_write_hsdma_count(void __iomem 
*mbase,
u8 bchannel, u32 len)
 {
musb_writew(mbase,
-   MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW),len);
+   MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW), len);
musb_writew(mbase,
MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH),
(len >> 16));
-- 
1.8.3.4



[PATCH] usb: musb_host: Use sizeof(*qh)instead of sizeof *qh.

2016-06-01 Thread Sandhya Bankar
Use sizeof(*qh)instead of sizeof *qh.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/musb/musb_host.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 2f8ad7f..72121fe 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2228,7 +2228,7 @@ static int musb_urb_enqueue(
 * REVISIT consider a dedicated qh kmem_cache, so it's harder
 * for bugs in other kernel code to break this driver...
 */
-   qh = kzalloc(sizeof *qh, mem_flags);
+   qh = kzalloc(sizeof(*qh), mem_flags);
if (!qh) {
spin_lock_irqsave(&musb->lock, flags);
usb_hcd_unlink_urb_from_ep(hcd, urb);
-- 
1.8.3.4



[PATCH] usb: microtek: Use "foo *bar" instead of "foo * bar".

2016-06-01 Thread Sandhya Bankar
Use "foo *bar" instead of "foo * bar".

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/image/microtek.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h
index ccce318..7e32ae7 100644
--- a/drivers/usb/image/microtek.h
+++ b/drivers/usb/image/microtek.h
@@ -13,11 +13,11 @@ typedef void (*mts_scsi_cmnd_callback)(struct scsi_cmnd *);
 
 struct mts_transfer_context
 {
-   struct mts_desc* instance;
+   struct mts_desc *instance;
mts_scsi_cmnd_callback final_callback;
struct scsi_cmnd *srb;

-   void* data;
+   void *data;
unsigned data_length;
int data_pipe;
int fragment;
@@ -38,7 +38,7 @@ struct mts_desc {
u8 ep_response;
u8 ep_image;
 
-   struct Scsi_Host * host;
+   struct Scsi_Host *host;
 
struct urb *urb;
struct mts_transfer_context context;
-- 
1.8.3.4



[PATCH] usb: phy-omap-otg: Space required after that ','.

2016-05-31 Thread Sandhya Bankar
Space required after that ','.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/phy/phy-omap-otg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c
index c4bf2de..6f6d2a7 100644
--- a/drivers/usb/phy/phy-omap-otg.c
+++ b/drivers/usb/phy/phy-omap-otg.c
@@ -148,7 +148,7 @@ static int omap_otg_remove(struct platform_device *pdev)
struct otg_device *otg_dev = platform_get_drvdata(pdev);
struct extcon_dev *edev = otg_dev->extcon;
 
-   extcon_unregister_notifier(edev, EXTCON_USB_HOST,&otg_dev->id_nb);
+   extcon_unregister_notifier(edev, EXTCON_USB_HOST, &otg_dev->id_nb);
extcon_unregister_notifier(edev, EXTCON_USB, &otg_dev->vbus_nb);
 
return 0;
-- 
1.8.3.4



[PATCH] usb: cdc-acm: Space prohibited before close parenthesis ')'.

2016-05-31 Thread Sandhya Bankar
Space prohibited before close parenthesis ')'.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/class/cdc-acm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 94a14f5..def5a54 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -946,7 +946,7 @@ static int wait_serial_change(struct acm *acm, unsigned 
long arg)
DECLARE_WAITQUEUE(wait, current);
struct async_icount old, new;
 
-   if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD ))
+   if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD))
return -EINVAL;
do {
spin_lock_irq(&acm->read_lock);
-- 
1.8.3.4



[PATCH 3/3] usb: gr_udc: Remove unnecessary platform_set_drvdata().

2016-05-11 Thread Sandhya Bankar
Unnecessary [platform|pci]_set_drvdata() have been removed since the driver 
core clears the driver data to NULLafter device release or on probe failure. 
There is no need to manually clear the device driver data to NULL.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/gadget/udc/gr_udc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
index 39b7136..05f956c 100644
--- a/drivers/usb/gadget/udc/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -2117,7 +2117,6 @@ static int gr_remove(struct platform_device *pdev)
 
gr_dfs_delete(dev);
dma_pool_destroy(dev->desc_pool);
-   platform_set_drvdata(pdev, NULL);
 
gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req);
-- 
1.8.3.4



[PATCH 2/3] usb: dwc3-keystone: Remove unnecessary platform_set_drvdata().

2016-05-11 Thread Sandhya Bankar
Unnecessary [platform|pci]_set_drvdata() have been removed since the driver 
core clears the driver data to NULLafter device release or on probe failure. 
There is no need to manually clear the device driver data to NULL

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/dwc3/dwc3-keystone.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
index 7266470..089bb70 100644
--- a/drivers/usb/dwc3/dwc3-keystone.c
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -164,7 +164,6 @@ static int kdwc3_remove(struct platform_device *pdev)
kdwc3_disable_irqs(kdwc);
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
clk_disable_unprepare(kdwc->clk);
-   platform_set_drvdata(pdev, NULL);
 
return 0;
 }
-- 
1.8.3.4



[PATCH 1/3] usb: pci: Remove unnecessary pci_set_drvdata().

2016-05-11 Thread Sandhya Bankar
Unnecessary [platform|pci]_set_drvdata() have been removed since the driver 
core clears the driver data to NULLafter device release or on probe failure. 
There is no need to manually clear the
device driver data to NULL.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/dwc2/pci.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index ae41961..c76fade 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -69,7 +69,6 @@ static void dwc2_pci_remove(struct pci_dev *pci)
platform_device_unregister(glue->dwc2);
usb_phy_generic_unregister(glue->phy);
kfree(glue);
-   pci_set_drvdata(pci, NULL);
 }
 
 static int dwc2_pci_probe(struct pci_dev *pci,
-- 
1.8.3.4



[PATCH 0/3] Remove unnecessary pci_set_drvdata() and platform_set_drvdata().

2016-05-11 Thread Sandhya Bankar
Unnecessary [platform|pci]_set_drvdata() have been removed since the driver 
core clears the driver datato NULL after device release or on probe failure. 
There is no need to manually clear the device driver data to NULL.

Sandhya Bankar (3):
  usb: pci: Remove unnecessary pci_set_drvdata().
  usb: dwc3-keystone: Remove unnecessary platform_set_drvdata().
  usb: gr_udec: Remove unnecessary platform_set_drvdata().

 drivers/usb/dwc2/pci.c   | 1 -
 drivers/usb/dwc3/dwc3-keystone.c | 1 -
 drivers/usb/gadget/udc/gr_udc.c  | 1 -
 3 files changed, 3 deletions(-)

-- 
1.8.3.4



[PATCH] usb: wusbcore: Remove space before ',' and '(' .

2016-05-09 Thread Sandhya Bankar
Remove space before ',' and '(' . 
This patch is detected by checkpatch.pl

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/wusbcore/crypto.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c
index f7fc2371..33acd15 100644
--- a/drivers/usb/wusbcore/crypto.c
+++ b/drivers/usb/wusbcore/crypto.c
@@ -390,7 +390,7 @@ static int wusb_oob_mic_verify(void)
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f },
.MIC= { 0x75, 0x6a, 0x97, 0x51, 0x0c, 0x8c,
-   0x14, 0x7b } ,
+   0x14, 0x7b },
};
size_t hs_size;
 
@@ -480,7 +480,7 @@ static int wusb_key_derive_verify(void)
printk(KERN_ERR "E: keydvt in: key\n");
wusb_key_dump(stv_key_a1, sizeof(stv_key_a1));
printk(KERN_ERR "E: keydvt in: nonce\n");
-   wusb_key_dump( &stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1));
+   wusb_key_dump(&stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1));
printk(KERN_ERR "E: keydvt in: hnonce & dnonce\n");
wusb_key_dump(&stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1));
printk(KERN_ERR "E: keydvt out: KCK\n");
-- 
1.8.3.4



[PATCH] usb: wusbcore: Do not initialise statics to 0.

2016-05-09 Thread Sandhya Bankar
Do not initialise statics to 0.
This patch is found by checkpatch.pl script.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/wusbcore/crypto.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c
index 8ed8e34..f7fc2371 100644
--- a/drivers/usb/wusbcore/crypto.c
+++ b/drivers/usb/wusbcore/crypto.c
@@ -54,7 +54,7 @@
 #include 
 #include 
 
-static int debug_crypto_verify = 0;
+static int debug_crypto_verify;
 
 module_param(debug_crypto_verify, int, 0);
 MODULE_PARM_DESC(debug_crypto_verify, "verify the key generation algorithms");
-- 
1.8.3.4



[PATCH] usb: Use (foo *) instead of (foo*).

2016-05-04 Thread Sandhya Bankar
Use (foo *) instead of (foo*).

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/gadget/config.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index e6c0542..17a6077 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -93,7 +93,7 @@ int usb_gadget_config_buf(
*cp = *config;
 
/* then interface/endpoint/class/vendor/... */
-   len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
+   len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8 *)buf,
length - USB_DT_CONFIG_SIZE, desc);
if (len < 0)
return len;
-- 
1.8.3.4



[PATCH] usb: Remove unnecessary space before operator ','.

2016-05-04 Thread Sandhya Bankar
Remove unnecessary space before operator ','.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/phy/phy-twl6030-usb.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/phy/phy-twl6030-usb.c 
b/drivers/usb/phy/phy-twl6030-usb.c
index 014dbbd7..24e2b3c 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -155,13 +155,13 @@ static int twl6030_start_srp(struct phy_companion 
*comparator)
 static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
 {
/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
-   twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
+   twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_BACKUP_REG);
 
/* Program CFG_LDO_PD2 register and set VUSB bit */
-   twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
+   twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x1, TWL6030_CFG_LDO_PD2);
 
/* Program MISC2 register and set bit VUSB_IN_VBAT */
-   twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
+   twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2);
 
twl->usb3v3 = regulator_get(twl->dev, twl->regulator);
if (IS_ERR(twl->usb3v3))
@@ -301,10 +301,10 @@ static void otg_set_vbus_work(struct work_struct *data)
 */
 
if (twl->vbus_enable)
-   twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
+   twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x40,
CHARGERUSB_CTRL1);
else
-   twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
+   twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE, 0x00,
CHARGERUSB_CTRL1);
 }
 
-- 
1.8.3.4



[PATCH] usb: Remove unnecessary space before open square bracket.

2016-05-04 Thread Sandhya Bankar
Remove unnecessary space before open square bracket.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/isp1760/isp1760-if.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c
index 264be4d..9535b28 100644
--- a/drivers/usb/isp1760/isp1760-if.c
+++ b/drivers/usb/isp1760/isp1760-if.c
@@ -163,7 +163,7 @@ static void isp1761_pci_shutdown(struct pci_dev *dev)
printk(KERN_ERR "ips1761_pci_shutdown\n");
 }
 
-static const struct pci_device_id isp1760_plx [] = {
+static const struct pci_device_id isp1760_plx[] = {
{
.class  = PCI_CLASS_BRIDGE_OTHER << 8,
.class_mask = ~0,
-- 
1.8.3.4



[PATCH] usb: Remove unnecessary space before function pointer arguments.

2016-04-24 Thread Sandhya Bankar
Remove unnecessary space before function pointer arguments.

Signed-off-by: Sandhya Bankar 
---
 drivers/usb/atm/ueagle-atm.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 0186442..4333dc5 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -173,10 +173,10 @@ struct uea_softc {
const struct firmware *dsp_firm;
struct urb *urb_int;
 
-   void (*dispatch_cmv) (struct uea_softc *, struct intr_pkt *);
-   void (*schedule_load_page) (struct uea_softc *, struct intr_pkt *);
-   int (*stat) (struct uea_softc *);
-   int (*send_cmvs) (struct uea_softc *);
+   void (*dispatch_cmv)(struct uea_softc *, struct intr_pkt *);
+   void (*schedule_load_page)(struct uea_softc *, struct intr_pkt *);
+   int (*stat)(struct uea_softc *);
+   int (*send_cmvs)(struct uea_softc *);
 
/* keep in sync with eaglectl */
struct uea_stats {
-- 
1.8.3.4