ext4: avoid hangs in ext4_da_should_update_i_disksize()
[linux-2.6.git] / fs / locks.c
index 8729347..703f545 100644 (file)
@@ -145,7 +145,6 @@ static DEFINE_SPINLOCK(file_lock_lock);
 
 /*
  * Protects the two list heads above, plus the inode->i_flock list
- * FIXME: should use a spinlock, once lockd and ceph are ready.
  */
 void lock_flocks(void)
 {
@@ -161,10 +160,22 @@ EXPORT_SYMBOL_GPL(unlock_flocks);
 
 static struct kmem_cache *filelock_cache __read_mostly;
 
+static void locks_init_lock_heads(struct file_lock *fl)
+{
+       INIT_LIST_HEAD(&fl->fl_link);
+       INIT_LIST_HEAD(&fl->fl_block);
+       init_waitqueue_head(&fl->fl_wait);
+}
+
 /* Allocate an empty lock structure. */
 struct file_lock *locks_alloc_lock(void)
 {
-       return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
+       struct file_lock *fl = kmem_cache_zalloc(filelock_cache, GFP_KERNEL);
+
+       if (fl)
+               locks_init_lock_heads(fl);
+
+       return fl;
 }
 EXPORT_SYMBOL_GPL(locks_alloc_lock);
 
@@ -176,8 +187,8 @@ void locks_release_private(struct file_lock *fl)
                fl->fl_ops = NULL;
        }
        if (fl->fl_lmops) {
-               if (fl->fl_lmops->fl_release_private)
-                       fl->fl_lmops->fl_release_private(fl);
+               if (fl->fl_lmops->lm_release_private)
+                       fl->fl_lmops->lm_release_private(fl);
                fl->fl_lmops = NULL;
        }
 
@@ -198,35 +209,12 @@ EXPORT_SYMBOL(locks_free_lock);
 
 void locks_init_lock(struct file_lock *fl)
 {
-       INIT_LIST_HEAD(&fl->fl_link);
-       INIT_LIST_HEAD(&fl->fl_block);
-       init_waitqueue_head(&fl->fl_wait);
-       fl->fl_next = NULL;
-       fl->fl_fasync = NULL;
-       fl->fl_owner = NULL;
-       fl->fl_pid = 0;
-       fl->fl_nspid = NULL;
-       fl->fl_file = NULL;
-       fl->fl_flags = 0;
-       fl->fl_type = 0;
-       fl->fl_start = fl->fl_end = 0;
-       fl->fl_ops = NULL;
-       fl->fl_lmops = NULL;
+       memset(fl, 0, sizeof(struct file_lock));
+       locks_init_lock_heads(fl);
 }
 
 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)
-{
-       struct file_lock *lock = (struct file_lock *) foo;
-
-       locks_init_lock(lock);
-}
-
 static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
 {
        if (fl->fl_ops) {
@@ -415,17 +403,7 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
        fl->fl_ops = NULL;
        fl->fl_lmops = NULL;
 
-       switch (l->l_type) {
-       case F_RDLCK:
-       case F_WRLCK:
-       case F_UNLCK:
-               fl->fl_type = l->l_type;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return (0);
+       return assign_type(fl, l->l_type);
 }
 #endif
 
@@ -444,16 +422,10 @@ static void lease_release_private_callback(struct file_lock *fl)
        fl->fl_file->f_owner.signum = 0;
 }
 
-static int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
-{
-       return fl->fl_file == try->fl_file;
-}
-
 static const struct lock_manager_operations lease_manager_ops = {
-       .fl_break = lease_break_callback,
-       .fl_release_private = lease_release_private_callback,
-       .fl_mylease = lease_mylease_callback,
-       .fl_change = lease_modify,
+       .lm_break = lease_break_callback,
+       .lm_release_private = lease_release_private_callback,
+       .lm_change = lease_modify,
 };
 
 /*
@@ -506,9 +478,9 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
  */
 static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 {
-       if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner)
+       if (fl1->fl_lmops && fl1->fl_lmops->lm_compare_owner)
                return fl2->fl_lmops == fl1->fl_lmops &&
-                       fl1->fl_lmops->fl_compare_owner(fl1, fl2);
+                       fl1->fl_lmops->lm_compare_owner(fl1, fl2);
        return fl1->fl_owner == fl2->fl_owner;
 }
 
@@ -558,8 +530,8 @@ static void locks_wake_up_blocks(struct file_lock *blocker)
                waiter = list_first_entry(&blocker->fl_block,
                                struct file_lock, fl_block);
                __locks_delete_block(waiter);
-               if (waiter->fl_lmops && waiter->fl_lmops->fl_notify)
-                       waiter->fl_lmops->fl_notify(waiter);
+               if (waiter->fl_lmops && waiter->fl_lmops->lm_notify)
+                       waiter->fl_lmops->lm_notify(waiter);
                else
                        wake_up(&waiter->fl_wait);
        }
@@ -1246,7 +1218,7 @@ int __break_lease(struct inode *inode, unsigned int mode)
                        fl->fl_type = future;
                        fl->fl_break_time = break_time;
                        /* lease must have lmops break callback */
-                       fl->fl_lmops->fl_break(fl);
+                       fl->fl_lmops->lm_break(fl);
                }
        }
 
@@ -1356,7 +1328,7 @@ int fcntl_getlease(struct file *filp)
  *     @arg: type of lease to obtain
  *     @flp: input - file_lock to use, output - file_lock inserted
  *
- *     The (input) flp->fl_lmops->fl_break function is required
+ *     The (input) flp->fl_lmops->lm_break function is required
  *     by break_lease().
  *
  *     Called with file_lock_lock held.
@@ -1382,14 +1354,14 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 
        time_out_leases(inode);
 
-       BUG_ON(!(*flp)->fl_lmops->fl_break);
+       BUG_ON(!(*flp)->fl_lmops->lm_break);
 
        if (arg != F_UNLCK) {
                error = -EAGAIN;
                if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
                        goto out;
                if ((arg == F_WRLCK)
-                   && ((atomic_read(&dentry->d_count) > 1)
+                   && ((dentry->d_count > 1)
                        || (atomic_read(&inode->i_count) > 1)))
                        goto out;
        }
@@ -1405,7 +1377,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
        for (before = &inode->i_flock;
                        ((fl = *before) != NULL) && IS_LEASE(fl);
                        before = &fl->fl_next) {
-               if (lease->fl_lmops->fl_mylease(fl, lease))
+               if (fl->fl_file == filp)
                        my_before = before;
                else if (fl->fl_type == (F_INPROGRESS | F_UNLCK))
                        /*
@@ -1424,7 +1396,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
                goto out;
 
        if (my_before != NULL) {
-               error = lease->fl_lmops->fl_change(my_before, arg);
+               error = lease->fl_lmops->lm_change(my_before, arg);
                if (!error)
                        *flp = *my_before;
                goto out;
@@ -1460,7 +1432,7 @@ static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
  *     @lease: file_lock to use
  *
  *     Call this to establish a lease on the file.
- *     The (*lease)->fl_lmops->fl_break operation must be set; if not,
+ *     The (*lease)->fl_lmops->lm_break operation must be set; if not,
  *     break_lease will oops!
  *
  *     This will call the filesystem's setlease file method, if
@@ -1758,10 +1730,10 @@ out:
  * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
  * locks, the ->lock() interface may return asynchronously, before the lock has
  * been granted or denied by the underlying filesystem, if (and only if)
- * fl_grant is set. Callers expecting ->lock() to return asynchronously
+ * lm_grant is set. Callers expecting ->lock() to return asynchronously
  * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
  * the request is for a blocking lock. When ->lock() does return asynchronously,
- * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock
+ * it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock
  * request completes.
  * If the request is for non-blocking lock the file system should return
  * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
@@ -1771,7 +1743,7 @@ out:
  * grants a lock so the VFS can find out which locks are locally held and do
  * the correct lock cleanup when required.
  * The underlying filesystem must not drop the kernel lock or call
- * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED
+ * ->lm_grant() before returning to the caller with a FILE_LOCK_DEFERRED
  * return code.
  */
 int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
@@ -2340,8 +2312,8 @@ EXPORT_SYMBOL(lock_may_write);
 static int __init filelock_init(void)
 {
        filelock_cache = kmem_cache_create("file_lock_cache",
-                       sizeof(struct file_lock), 0, SLAB_PANIC,
-                       init_once);
+                       sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
+
        return 0;
 }