[PATCH] type-safe min() in prism54
[pandora-kernel.git] / fs / fcntl.c
index bfecc62..dc4a700 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/file.h>
+#include <linux/capability.h>
 #include <linux/dnotify.h>
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
@@ -16,6 +17,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>
@@ -34,15 +36,15 @@ void fastcall set_close_on_exec(unsigned int fd, int flag)
        spin_unlock(&files->file_lock);
 }
 
-static inline int get_close_on_exec(unsigned int fd)
+static 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 +66,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 +97,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 +171,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);
@@ -200,8 +208,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
        struct inode * inode = filp->f_dentry->d_inode;
        int error = 0;
 
-       /* O_APPEND cannot be cleared if the file is marked as append-only */
-       if (!(arg & O_APPEND) && IS_APPEND(inode))
+       /*
+        * O_APPEND cannot be cleared if the file is marked as append-only
+        * and the file is open for write.
+        */
+       if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode))
                return -EPERM;
 
        /* O_NOATIME can only be set by the owner or superuser */
@@ -450,11 +461,11 @@ static void send_sigio_to_task(struct task_struct *p,
                        else
                                si.si_band = band_table[reason - POLL_IN];
                        si.si_fd    = fd;
-                       if (!send_group_sig_info(fown->signum, &si, p))
+                       if (!group_send_sig_info(fown->signum, &si, p))
                                break;
                /* fall-through: fall back on the old plain SIGIO signal */
                case 0:
-                       send_group_sig_info(SIGIO, SEND_SIG_PRIV, p);
+                       group_send_sig_info(SIGIO, SEND_SIG_PRIV, p);
        }
 }
 
@@ -488,7 +499,7 @@ static void send_sigurg_to_task(struct task_struct *p,
                                 struct fown_struct *fown)
 {
        if (sigio_perm(p, fown, SIGURG))
-               send_group_sig_info(SIGURG, SEND_SIG_PRIV, p);
+               group_send_sig_info(SIGURG, SEND_SIG_PRIV, p);
 }
 
 int send_sigurg(struct fown_struct *fown)