diff options
author | Pavel Shilovsky <piastry@etersoft.ru> | 2011-10-29 09:17:58 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-11-04 01:53:15 -0400 |
commit | 161ebf9fcca967e7396bb076af5ed18539497a3f (patch) | |
tree | 3e7496b6358740e5d2bdff78739393832dad5700 /fs | |
parent | 1a67a573b8d9f02211f36fbab50f6265dc49384a (diff) |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/file.c | 64 |
1 files changed, 32 insertions, 32 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c1f063cd1b0c..d9cc07fec99f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -672,7 +672,7 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock) | |||
672 | } | 672 | } |
673 | 673 | ||
674 | static bool | 674 | static bool |
675 | cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, | 675 | __cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, |
676 | __u64 length, __u8 type, __u16 netfid, | 676 | __u64 length, __u8 type, __u16 netfid, |
677 | struct cifsLockInfo **conf_lock) | 677 | struct cifsLockInfo **conf_lock) |
678 | { | 678 | { |
@@ -694,6 +694,14 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, | |||
694 | return false; | 694 | return false; |
695 | } | 695 | } |
696 | 696 | ||
697 | static bool | ||
698 | cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, | ||
699 | struct cifsLockInfo **conf_lock) | ||
700 | { | ||
701 | return __cifs_find_lock_conflict(cinode, lock->offset, lock->length, | ||
702 | lock->type, lock->netfid, conf_lock); | ||
703 | } | ||
704 | |||
697 | static int | 705 | static int |
698 | cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | 706 | cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, |
699 | __u8 type, __u16 netfid, struct file_lock *flock) | 707 | __u8 type, __u16 netfid, struct file_lock *flock) |
@@ -704,8 +712,8 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | |||
704 | 712 | ||
705 | mutex_lock(&cinode->lock_mutex); | 713 | mutex_lock(&cinode->lock_mutex); |
706 | 714 | ||
707 | exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid, | 715 | exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid, |
708 | &conf_lock); | 716 | &conf_lock); |
709 | if (exist) { | 717 | if (exist) { |
710 | flock->fl_start = conf_lock->offset; | 718 | flock->fl_start = conf_lock->offset; |
711 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; | 719 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; |
@@ -723,40 +731,27 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | |||
723 | return rc; | 731 | return rc; |
724 | } | 732 | } |
725 | 733 | ||
726 | static int | 734 | static void |
727 | cifs_lock_add(struct cifsInodeInfo *cinode, __u64 len, __u64 offset, | 735 | cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) |
728 | __u8 type, __u16 netfid) | ||
729 | { | 736 | { |
730 | struct cifsLockInfo *li; | ||
731 | |||
732 | li = cifs_lock_init(len, offset, type, netfid); | ||
733 | if (!li) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | mutex_lock(&cinode->lock_mutex); | 737 | mutex_lock(&cinode->lock_mutex); |
737 | list_add_tail(&li->llist, &cinode->llist); | 738 | list_add_tail(&lock->llist, &cinode->llist); |
738 | mutex_unlock(&cinode->lock_mutex); | 739 | mutex_unlock(&cinode->lock_mutex); |
739 | return 0; | ||
740 | } | 740 | } |
741 | 741 | ||
742 | static int | 742 | static int |
743 | cifs_lock_add_if(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | 743 | cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, |
744 | __u8 type, __u16 netfid, bool wait) | 744 | bool wait) |
745 | { | 745 | { |
746 | struct cifsLockInfo *lock, *conf_lock; | 746 | struct cifsLockInfo *conf_lock; |
747 | bool exist; | 747 | bool exist; |
748 | int rc = 0; | 748 | int rc = 0; |
749 | 749 | ||
750 | lock = cifs_lock_init(length, offset, type, netfid); | ||
751 | if (!lock) | ||
752 | return -ENOMEM; | ||
753 | |||
754 | try_again: | 750 | try_again: |
755 | exist = false; | 751 | exist = false; |
756 | mutex_lock(&cinode->lock_mutex); | 752 | mutex_lock(&cinode->lock_mutex); |
757 | 753 | ||
758 | exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid, | 754 | exist = cifs_find_lock_conflict(cinode, lock, &conf_lock); |
759 | &conf_lock); | ||
760 | if (!exist && cinode->can_cache_brlcks) { | 755 | if (!exist && cinode->can_cache_brlcks) { |
761 | list_add_tail(&lock->llist, &cinode->llist); | 756 | list_add_tail(&lock->llist, &cinode->llist); |
762 | mutex_unlock(&cinode->lock_mutex); | 757 | mutex_unlock(&cinode->lock_mutex); |
@@ -781,7 +776,6 @@ try_again: | |||
781 | } | 776 | } |
782 | } | 777 | } |
783 | 778 | ||
784 | kfree(lock); | ||
785 | mutex_unlock(&cinode->lock_mutex); | 779 | mutex_unlock(&cinode->lock_mutex); |
786 | return rc; | 780 | return rc; |
787 | } | 781 | } |
@@ -1254,20 +1248,26 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1254 | } | 1248 | } |
1255 | 1249 | ||
1256 | if (lock) { | 1250 | if (lock) { |
1257 | rc = cifs_lock_add_if(cinode, flock->fl_start, length, | 1251 | struct cifsLockInfo *lock; |
1258 | type, netfid, wait_flag); | 1252 | |
1253 | lock = cifs_lock_init(length, flock->fl_start, type, netfid); | ||
1254 | if (!lock) | ||
1255 | return -ENOMEM; | ||
1256 | |||
1257 | rc = cifs_lock_add_if(cinode, lock, wait_flag); | ||
1259 | if (rc < 0) | 1258 | if (rc < 0) |
1260 | return rc; | 1259 | kfree(lock); |
1261 | else if (!rc) | 1260 | if (rc <= 0) |
1262 | goto out; | 1261 | goto out; |
1263 | 1262 | ||
1264 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, | 1263 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, |
1265 | flock->fl_start, 0, 1, type, wait_flag, 0); | 1264 | flock->fl_start, 0, 1, type, wait_flag, 0); |
1266 | if (rc == 0) { | 1265 | if (rc) { |
1267 | /* For Windows locks we must store them. */ | 1266 | kfree(lock); |
1268 | rc = cifs_lock_add(cinode, length, flock->fl_start, | 1267 | goto out; |
1269 | type, netfid); | ||
1270 | } | 1268 | } |
1269 | |||
1270 | cifs_lock_add(cinode, lock); | ||
1271 | } else if (unlock) | 1271 | } else if (unlock) |
1272 | rc = cifs_unlock_range(cfile, flock, xid); | 1272 | rc = cifs_unlock_range(cfile, flock, xid); |
1273 | 1273 | ||