file: mostly eliminate spurious relocking in __range_close
[linux-2.6-block.git] / fs / file.c
index 7893ea161d77075ca0ab524d7c8021ab668c0978..7bb2cddbd82b9d3346bf7925c3120832a0a30620 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -693,29 +693,30 @@ static inline void __range_cloexec(struct files_struct *cur_fds,
        spin_unlock(&cur_fds->file_lock);
 }
 
-static inline void __range_close(struct files_struct *cur_fds, unsigned int fd,
+static inline void __range_close(struct files_struct *files, unsigned int fd,
                                 unsigned int max_fd)
 {
+       struct file *file;
        unsigned n;
 
-       rcu_read_lock();
-       n = last_fd(files_fdtable(cur_fds));
-       rcu_read_unlock();
+       spin_lock(&files->file_lock);
+       n = last_fd(files_fdtable(files));
        max_fd = min(max_fd, n);
 
-       while (fd <= max_fd) {
-               struct file *file;
-
-               spin_lock(&cur_fds->file_lock);
-               file = pick_file(cur_fds, fd++);
-               spin_unlock(&cur_fds->file_lock);
-
+       for (; fd <= max_fd; fd++) {
+               file = pick_file(files, fd);
                if (file) {
-                       /* found a valid file to close */
-                       filp_close(file, cur_fds);
+                       spin_unlock(&files->file_lock);
+                       filp_close(file, files);
                        cond_resched();
+                       spin_lock(&files->file_lock);
+               } else if (need_resched()) {
+                       spin_unlock(&files->file_lock);
+                       cond_resched();
+                       spin_lock(&files->file_lock);
                }
        }
+       spin_unlock(&files->file_lock);
 }
 
 /**