]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/fcntl.c
NFSv4: State recovery cleanup
[linux-2.6-omap-h63xx.git] / fs / fcntl.c
index bfecc623808358013379e400ccb4117bfbc8a57e..863b46e0d78a6594371a744358104faae657c307 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/security.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
+#include <linux/rcupdate.h>
 
 #include <asm/poll.h>
 #include <asm/siginfo.h>
@@ -39,10 +40,10 @@ static inline int get_close_on_exec(unsigned int fd)
        struct files_struct *files = current->files;
        struct fdtable *fdt;
        int res;
-       spin_lock(&files->file_lock);
+       rcu_read_lock();
        fdt = files_fdtable(files);
        res = FD_ISSET(fd, fdt->close_on_exec);
-       spin_unlock(&files->file_lock);
+       rcu_read_unlock();
        return res;
 }
 
@@ -64,8 +65,8 @@ static int locate_fd(struct files_struct *files,
        if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
                goto out;
 
-       fdt = files_fdtable(files);
 repeat:
+       fdt = files_fdtable(files);
        /*
         * Someone might have closed fd's in the range
         * orig_start..fdt->next_fd
@@ -95,9 +96,15 @@ repeat:
        if (error)
                goto repeat;
 
+       /*
+        * We reacquired files_lock, so we are safe as long as
+        * we reacquire the fdtable pointer and use it while holding
+        * the lock, no one can free it during that time.
+        */
+       fdt = files_fdtable(files);
        if (start <= fdt->next_fd)
                fdt->next_fd = newfd + 1;
-       
+
        error = newfd;
        
 out:
@@ -163,7 +170,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
        if (!tofree && FD_ISSET(newfd, fdt->open_fds))
                goto out_fput;
 
-       fdt->fd[newfd] = file;
+       rcu_assign_pointer(fdt->fd[newfd], file);
        FD_SET(newfd, fdt->open_fds);
        FD_CLR(newfd, fdt->close_on_exec);
        spin_unlock(&files->file_lock);