CIFS: Simplify setlk error handling for mandatory locking

Now we allocate a lock structure at first, then we request to the server
and save the lock if server returned OK though void function - it prevents
the situation when we locked a file on the server and then return -ENOMEM
from setlk.

Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Acked-by: Jeff Layton <jlayton@samba.org>
Signed-off-by: Steve French <sfrench@us.ibm.com>
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index c1f063c..d9cc07f 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -672,7 +672,7 @@
 }
 
 static bool
-cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
+__cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
 			__u64 length, __u8 type, __u16 netfid,
 			struct cifsLockInfo **conf_lock)
 {
@@ -694,6 +694,14 @@
 	return false;
 }
 
+static bool
+cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock,
+			struct cifsLockInfo **conf_lock)
+{
+	return __cifs_find_lock_conflict(cinode, lock->offset, lock->length,
+					 lock->type, lock->netfid, conf_lock);
+}
+
 static int
 cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
 	       __u8 type, __u16 netfid, struct file_lock *flock)
@@ -704,8 +712,8 @@
 
 	mutex_lock(&cinode->lock_mutex);
 
-	exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
-					&conf_lock);
+	exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid,
+					  &conf_lock);
 	if (exist) {
 		flock->fl_start = conf_lock->offset;
 		flock->fl_end = conf_lock->offset + conf_lock->length - 1;
@@ -723,40 +731,27 @@
 	return rc;
 }
 
-static int
-cifs_lock_add(struct cifsInodeInfo *cinode, __u64 len, __u64 offset,
-	      __u8 type, __u16 netfid)
+static void
+cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock)
 {
-	struct cifsLockInfo *li;
-
-	li = cifs_lock_init(len, offset, type, netfid);
-	if (!li)
-		return -ENOMEM;
-
 	mutex_lock(&cinode->lock_mutex);
-	list_add_tail(&li->llist, &cinode->llist);
+	list_add_tail(&lock->llist, &cinode->llist);
 	mutex_unlock(&cinode->lock_mutex);
-	return 0;
 }
 
 static int
-cifs_lock_add_if(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
-		 __u8 type, __u16 netfid, bool wait)
+cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock,
+		 bool wait)
 {
-	struct cifsLockInfo *lock, *conf_lock;
+	struct cifsLockInfo *conf_lock;
 	bool exist;
 	int rc = 0;
 
-	lock = cifs_lock_init(length, offset, type, netfid);
-	if (!lock)
-		return -ENOMEM;
-
 try_again:
 	exist = false;
 	mutex_lock(&cinode->lock_mutex);
 
-	exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
-					&conf_lock);
+	exist = cifs_find_lock_conflict(cinode, lock, &conf_lock);
 	if (!exist && cinode->can_cache_brlcks) {
 		list_add_tail(&lock->llist, &cinode->llist);
 		mutex_unlock(&cinode->lock_mutex);
@@ -781,7 +776,6 @@
 		}
 	}
 
-	kfree(lock);
 	mutex_unlock(&cinode->lock_mutex);
 	return rc;
 }
@@ -1254,20 +1248,26 @@
 	}
 
 	if (lock) {
-		rc = cifs_lock_add_if(cinode, flock->fl_start, length,
-				      type, netfid, wait_flag);
+		struct cifsLockInfo *lock;
+
+		lock = cifs_lock_init(length, flock->fl_start, type, netfid);
+		if (!lock)
+			return -ENOMEM;
+
+		rc = cifs_lock_add_if(cinode, lock, wait_flag);
 		if (rc < 0)
-			return rc;
-		else if (!rc)
+			kfree(lock);
+		if (rc <= 0)
 			goto out;
 
 		rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
 				 flock->fl_start, 0, 1, type, wait_flag, 0);
-		if (rc == 0) {
-			/* For Windows locks we must store them. */
-			rc = cifs_lock_add(cinode, length, flock->fl_start,
-					   type, netfid);
+		if (rc) {
+			kfree(lock);
+			goto out;
 		}
+
+		cifs_lock_add(cinode, lock);
 	} else if (unlock)
 		rc = cifs_unlock_range(cfile, flock, xid);