diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/file.c | 105 |
1 files changed, 50 insertions, 55 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c1f063cd1b0c..cf0b1539b321 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -645,20 +645,20 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
645 | } | 645 | } |
646 | 646 | ||
647 | static struct cifsLockInfo * | 647 | static struct cifsLockInfo * |
648 | cifs_lock_init(__u64 len, __u64 offset, __u8 type, __u16 netfid) | 648 | cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) |
649 | { | 649 | { |
650 | struct cifsLockInfo *li = | 650 | struct cifsLockInfo *lock = |
651 | kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); | 651 | kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); |
652 | if (!li) | 652 | if (!lock) |
653 | return li; | 653 | return lock; |
654 | li->netfid = netfid; | 654 | lock->offset = offset; |
655 | li->offset = offset; | 655 | lock->length = length; |
656 | li->length = len; | 656 | lock->type = type; |
657 | li->type = type; | 657 | lock->netfid = netfid; |
658 | li->pid = current->tgid; | 658 | lock->pid = current->tgid; |
659 | INIT_LIST_HEAD(&li->blist); | 659 | INIT_LIST_HEAD(&lock->blist); |
660 | init_waitqueue_head(&li->block_q); | 660 | init_waitqueue_head(&lock->block_q); |
661 | return li; | 661 | return lock; |
662 | } | 662 | } |
663 | 663 | ||
664 | static void | 664 | static void |
@@ -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); |
@@ -775,13 +770,10 @@ try_again: | |||
775 | (lock->blist.next == &lock->blist)); | 770 | (lock->blist.next == &lock->blist)); |
776 | if (!rc) | 771 | if (!rc) |
777 | goto try_again; | 772 | goto try_again; |
778 | else { | 773 | mutex_lock(&cinode->lock_mutex); |
779 | mutex_lock(&cinode->lock_mutex); | 774 | list_del_init(&lock->blist); |
780 | list_del_init(&lock->blist); | ||
781 | } | ||
782 | } | 775 | } |
783 | 776 | ||
784 | kfree(lock); | ||
785 | mutex_unlock(&cinode->lock_mutex); | 777 | mutex_unlock(&cinode->lock_mutex); |
786 | return rc; | 778 | return rc; |
787 | } | 779 | } |
@@ -933,7 +925,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
933 | else | 925 | else |
934 | type = CIFS_WRLCK; | 926 | type = CIFS_WRLCK; |
935 | 927 | ||
936 | lck = cifs_lock_init(length, flock->fl_start, type, | 928 | lck = cifs_lock_init(flock->fl_start, length, type, |
937 | cfile->netfid); | 929 | cfile->netfid); |
938 | if (!lck) { | 930 | if (!lck) { |
939 | rc = -ENOMEM; | 931 | rc = -ENOMEM; |
@@ -1070,14 +1062,12 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1070 | if (rc != 0) | 1062 | if (rc != 0) |
1071 | cERROR(1, "Error unlocking previously locked " | 1063 | cERROR(1, "Error unlocking previously locked " |
1072 | "range %d during test of lock", rc); | 1064 | "range %d during test of lock", rc); |
1073 | rc = 0; | 1065 | return 0; |
1074 | return rc; | ||
1075 | } | 1066 | } |
1076 | 1067 | ||
1077 | if (type & LOCKING_ANDX_SHARED_LOCK) { | 1068 | if (type & LOCKING_ANDX_SHARED_LOCK) { |
1078 | flock->fl_type = F_WRLCK; | 1069 | flock->fl_type = F_WRLCK; |
1079 | rc = 0; | 1070 | return 0; |
1080 | return rc; | ||
1081 | } | 1071 | } |
1082 | 1072 | ||
1083 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, | 1073 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, |
@@ -1095,8 +1085,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1095 | } else | 1085 | } else |
1096 | flock->fl_type = F_WRLCK; | 1086 | flock->fl_type = F_WRLCK; |
1097 | 1087 | ||
1098 | rc = 0; | 1088 | return 0; |
1099 | return rc; | ||
1100 | } | 1089 | } |
1101 | 1090 | ||
1102 | static void | 1091 | static void |
@@ -1254,20 +1243,26 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1254 | } | 1243 | } |
1255 | 1244 | ||
1256 | if (lock) { | 1245 | if (lock) { |
1257 | rc = cifs_lock_add_if(cinode, flock->fl_start, length, | 1246 | struct cifsLockInfo *lock; |
1258 | type, netfid, wait_flag); | 1247 | |
1248 | lock = cifs_lock_init(flock->fl_start, length, type, netfid); | ||
1249 | if (!lock) | ||
1250 | return -ENOMEM; | ||
1251 | |||
1252 | rc = cifs_lock_add_if(cinode, lock, wait_flag); | ||
1259 | if (rc < 0) | 1253 | if (rc < 0) |
1260 | return rc; | 1254 | kfree(lock); |
1261 | else if (!rc) | 1255 | if (rc <= 0) |
1262 | goto out; | 1256 | goto out; |
1263 | 1257 | ||
1264 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, | 1258 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, |
1265 | flock->fl_start, 0, 1, type, wait_flag, 0); | 1259 | flock->fl_start, 0, 1, type, wait_flag, 0); |
1266 | if (rc == 0) { | 1260 | if (rc) { |
1267 | /* For Windows locks we must store them. */ | 1261 | kfree(lock); |
1268 | rc = cifs_lock_add(cinode, length, flock->fl_start, | 1262 | goto out; |
1269 | type, netfid); | ||
1270 | } | 1263 | } |
1264 | |||
1265 | cifs_lock_add(cinode, lock); | ||
1271 | } else if (unlock) | 1266 | } else if (unlock) |
1272 | rc = cifs_unlock_range(cfile, flock, xid); | 1267 | rc = cifs_unlock_range(cfile, flock, xid); |
1273 | 1268 | ||