libata: hardreset on SERR_INTERNAL
[powerpc.git] / fs / locks.c
index 1ad29c9..52a8100 100644 (file)
@@ -142,12 +142,12 @@ int lease_break_time = 45;
 static LIST_HEAD(file_lock_list);
 static LIST_HEAD(blocked_list);
 
-static kmem_cache_t *filelock_cache __read_mostly;
+static struct kmem_cache *filelock_cache __read_mostly;
 
 /* Allocate an empty lock structure. */
 static struct file_lock *locks_alloc_lock(void)
 {
-       return kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
+       return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
 }
 
 static void locks_release_private(struct file_lock *fl)
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(locks_init_lock);
  * Initialises the fields of the file lock which are invariant for
  * free file_locks.
  */
-static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags)
 {
        struct file_lock *lock = (struct file_lock *) foo;
 
@@ -314,14 +314,14 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
        off_t start, end;
 
        switch (l->l_whence) {
-       case 0: /*SEEK_SET*/
+       case SEEK_SET:
                start = 0;
                break;
-       case 1: /*SEEK_CUR*/
+       case SEEK_CUR:
                start = filp->f_pos;
                break;
-       case 2: /*SEEK_END*/
-               start = i_size_read(filp->f_dentry->d_inode);
+       case SEEK_END:
+               start = i_size_read(filp->f_path.dentry->d_inode);
                break;
        default:
                return -EINVAL;
@@ -364,14 +364,14 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
        loff_t start;
 
        switch (l->l_whence) {
-       case 0: /*SEEK_SET*/
+       case SEEK_SET:
                start = 0;
                break;
-       case 1: /*SEEK_CUR*/
+       case SEEK_CUR:
                start = filp->f_pos;
                break;
-       case 2: /*SEEK_END*/
-               start = i_size_read(filp->f_dentry->d_inode);
+       case SEEK_END:
+               start = i_size_read(filp->f_path.dentry->d_inode);
                break;
        default:
                return -EINVAL;
@@ -672,7 +672,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl,
        struct file_lock *cfl;
 
        lock_kernel();
-       for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
+       for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
                if (!IS_POSIX(cfl))
                        continue;
                if (posix_locks_conflict(cfl, fl))
@@ -725,16 +725,22 @@ next_task:
 /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
  * at the head of the list, but that's secret knowledge known only to
  * flock_lock_file and posix_lock_file.
+ *
+ * Note that if called with an FL_EXISTS argument, the caller may determine
+ * whether or not a lock was successfully freed by testing the return
+ * value for -ENOENT.
  */
 static int flock_lock_file(struct file *filp, struct file_lock *request)
 {
        struct file_lock *new_fl = NULL;
        struct file_lock **before;
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode * inode = filp->f_path.dentry->d_inode;
        int error = 0;
        int found = 0;
 
        lock_kernel();
+       if (request->fl_flags & FL_ACCESS)
+               goto find_conflict;
        for_each_lock(inode, before) {
                struct file_lock *fl = *before;
                if (IS_POSIX(fl))
@@ -750,8 +756,11 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
                break;
        }
 
-       if (request->fl_type == F_UNLCK)
+       if (request->fl_type == F_UNLCK) {
+               if ((request->fl_flags & FL_EXISTS) && !found)
+                       error = -ENOENT;
                goto out;
+       }
 
        error = -ENOMEM;
        new_fl = locks_alloc_lock();
@@ -764,6 +773,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
        if (found)
                cond_resched();
 
+find_conflict:
        for_each_lock(inode, before) {
                struct file_lock *fl = *before;
                if (IS_POSIX(fl))
@@ -777,6 +787,8 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
                        locks_insert_block(fl, request);
                goto out;
        }
+       if (request->fl_flags & FL_ACCESS)
+               goto out;
        locks_copy_lock(new_fl, request);
        locks_insert_lock(&inode->i_flock, new_fl);
        new_fl = NULL;
@@ -948,8 +960,11 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
 
        error = 0;
        if (!added) {
-               if (request->fl_type == F_UNLCK)
+               if (request->fl_type == F_UNLCK) {
+                       if (request->fl_flags & FL_EXISTS)
+                               error = -ENOENT;
                        goto out;
+               }
 
                if (!new_fl) {
                        error = -ENOLCK;
@@ -996,10 +1011,14 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
  * Add a POSIX style lock to a file.
  * We merge adjacent & overlapping locks whenever possible.
  * POSIX locks are sorted by owner task, then by starting address
+ *
+ * Note that if called with an FL_EXISTS argument, the caller may determine
+ * whether or not a lock was successfully freed by testing the return
+ * value for -ENOENT.
  */
 int posix_lock_file(struct file *filp, struct file_lock *fl)
 {
-       return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL);
+       return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL);
 }
 EXPORT_SYMBOL(posix_lock_file);
 
@@ -1014,7 +1033,7 @@ EXPORT_SYMBOL(posix_lock_file);
 int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
                        struct file_lock *conflock)
 {
-       return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock);
+       return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock);
 }
 EXPORT_SYMBOL(posix_lock_file_conf);
 
@@ -1314,8 +1333,8 @@ int fcntl_getlease(struct file *filp)
        int type = F_UNLCK;
 
        lock_kernel();
-       time_out_leases(filp->f_dentry->d_inode);
-       for (fl = filp->f_dentry->d_inode->i_flock; fl && IS_LEASE(fl);
+       time_out_leases(filp->f_path.dentry->d_inode);
+       for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
                        fl = fl->fl_next) {
                if (fl->fl_file == filp) {
                        type = fl->fl_type & ~F_INPROGRESS;
@@ -1340,7 +1359,7 @@ int fcntl_getlease(struct file *filp)
 static int __setlease(struct file *filp, long arg, struct file_lock **flp)
 {
        struct file_lock *fl, **before, **my_before = NULL, *lease;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error, rdlease_count = 0, wrlease_count = 0;
 
@@ -1402,8 +1421,9 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
        if (!leases_enable)
                goto out;
 
-       error = lease_alloc(filp, arg, &fl);
-       if (error)
+       error = -ENOMEM;
+       fl = locks_alloc_lock();
+       if (fl == NULL)
                goto out;
 
        locks_copy_lock(fl, lease);
@@ -1411,6 +1431,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
        locks_insert_lock(before, fl);
 
        *flp = fl;
+       error = 0;
 out:
        return error;
 }
@@ -1427,7 +1448,7 @@ out:
 
 int setlease(struct file *filp, long arg, struct file_lock **lease)
 {
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error;
 
@@ -1461,7 +1482,7 @@ EXPORT_SYMBOL(setlease);
 int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
 {
        struct file_lock fl, *flp = &fl;
-       struct dentry *dentry = filp->f_dentry;
+       struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error;
 
@@ -1493,7 +1514,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
                goto out_unlock;
        }
 
-       error = f_setown(filp, current->pid, 0);
+       error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
 out_unlock:
        unlock_kernel();
        return error;
@@ -1671,7 +1692,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
        if (copy_from_user(&flock, l, sizeof(flock)))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
 
        /* Don't allow mandatory locks on files that may be memory mapped
         * and shared.
@@ -1814,7 +1835,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
        if (copy_from_user(&flock, l, sizeof(flock)))
                goto out;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
 
        /* Don't allow mandatory locks on files that may be memory mapped
         * and shared.
@@ -1901,7 +1922,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
         * posix_lock_file().  Another process could be setting a lock on this
         * file at the same time, but we wouldn't remove that lock anyway.
         */
-       if (!filp->f_dentry->d_inode->i_flock)
+       if (!filp->f_path.dentry->d_inode->i_flock)
                return;
 
        lock.fl_type = F_UNLCK;
@@ -1930,7 +1951,7 @@ EXPORT_SYMBOL(locks_remove_posix);
  */
 void locks_remove_flock(struct file *filp)
 {
-       struct inode * inode = filp->f_dentry->d_inode; 
+       struct inode * inode = filp->f_path.dentry->d_inode;
        struct file_lock *fl;
        struct file_lock **before;
 
@@ -1999,7 +2020,7 @@ static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
        struct inode *inode = NULL;
 
        if (fl->fl_file != NULL)
-               inode = fl->fl_file->f_dentry->d_inode;
+               inode = fl->fl_file->f_path.dentry->d_inode;
 
        out += sprintf(out, "%d:%s ", id, pfx);
        if (IS_POSIX(fl)) {