diff options
author | Pavel Shilovsky <pshilovsky@etersoft.ru> | 2012-09-19 09:22:44 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 22:46:33 -0400 |
commit | 1b4b55a1d9404f51aacf1ff19887eb911484057d (patch) | |
tree | e2909277cc8db445c1d839c4859449a32cbfc08a /fs/cifs | |
parent | b140799a11adb6023d5f96712874c37b71dab290 (diff) |
CIFS: Turn lock mutex into rw semaphore
and allow several processes to walk through the lock list and read
can_cache_brlcks value if they are not going to modify them.
Signed-off-by: Pavel Shilovsky <pshilovsky@etersoft.ru>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 60 | ||||
-rw-r--r-- | fs/cifs/smb2file.c | 15 |
4 files changed, 41 insertions, 38 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e958d9438505..4cd68c77ce39 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -937,7 +937,7 @@ cifs_init_once(void *inode) | |||
937 | struct cifsInodeInfo *cifsi = inode; | 937 | struct cifsInodeInfo *cifsi = inode; |
938 | 938 | ||
939 | inode_init_once(&cifsi->vfs_inode); | 939 | inode_init_once(&cifsi->vfs_inode); |
940 | mutex_init(&cifsi->lock_mutex); | 940 | init_rwsem(&cifsi->lock_sem); |
941 | } | 941 | } |
942 | 942 | ||
943 | static int | 943 | static int |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index d3c72713fec4..e2492e1cdb85 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -1000,7 +1000,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); | |||
1000 | struct cifsInodeInfo { | 1000 | struct cifsInodeInfo { |
1001 | bool can_cache_brlcks; | 1001 | bool can_cache_brlcks; |
1002 | struct list_head llist; /* locks helb by this inode */ | 1002 | struct list_head llist; /* locks helb by this inode */ |
1003 | struct mutex lock_mutex; /* protect the fields above */ | 1003 | struct rw_semaphore lock_sem; /* protect the fields above */ |
1004 | /* BB add in lists for dirty pages i.e. write caching info for oplock */ | 1004 | /* BB add in lists for dirty pages i.e. write caching info for oplock */ |
1005 | struct list_head openFileList; | 1005 | struct list_head openFileList; |
1006 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ | 1006 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e2a8e4456275..1adff75dfffc 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -260,9 +260,9 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, | |||
260 | INIT_LIST_HEAD(&fdlocks->locks); | 260 | INIT_LIST_HEAD(&fdlocks->locks); |
261 | fdlocks->cfile = cfile; | 261 | fdlocks->cfile = cfile; |
262 | cfile->llist = fdlocks; | 262 | cfile->llist = fdlocks; |
263 | mutex_lock(&cinode->lock_mutex); | 263 | down_write(&cinode->lock_sem); |
264 | list_add(&fdlocks->llist, &cinode->llist); | 264 | list_add(&fdlocks->llist, &cinode->llist); |
265 | mutex_unlock(&cinode->lock_mutex); | 265 | up_write(&cinode->lock_sem); |
266 | 266 | ||
267 | cfile->count = 1; | 267 | cfile->count = 1; |
268 | cfile->pid = current->tgid; | 268 | cfile->pid = current->tgid; |
@@ -351,7 +351,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
351 | * Delete any outstanding lock records. We'll lose them when the file | 351 | * Delete any outstanding lock records. We'll lose them when the file |
352 | * is closed anyway. | 352 | * is closed anyway. |
353 | */ | 353 | */ |
354 | mutex_lock(&cifsi->lock_mutex); | 354 | down_write(&cifsi->lock_sem); |
355 | list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) { | 355 | list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) { |
356 | list_del(&li->llist); | 356 | list_del(&li->llist); |
357 | cifs_del_lock_waiters(li); | 357 | cifs_del_lock_waiters(li); |
@@ -359,7 +359,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
359 | } | 359 | } |
360 | list_del(&cifs_file->llist->llist); | 360 | list_del(&cifs_file->llist->llist); |
361 | kfree(cifs_file->llist); | 361 | kfree(cifs_file->llist); |
362 | mutex_unlock(&cifsi->lock_mutex); | 362 | up_write(&cifsi->lock_sem); |
363 | 363 | ||
364 | cifs_put_tlink(cifs_file->tlink); | 364 | cifs_put_tlink(cifs_file->tlink); |
365 | dput(cifs_file->dentry); | 365 | dput(cifs_file->dentry); |
@@ -762,7 +762,7 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, | |||
762 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 762 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
763 | bool exist; | 763 | bool exist; |
764 | 764 | ||
765 | mutex_lock(&cinode->lock_mutex); | 765 | down_read(&cinode->lock_sem); |
766 | 766 | ||
767 | exist = cifs_find_lock_conflict(cfile, offset, length, type, | 767 | exist = cifs_find_lock_conflict(cfile, offset, length, type, |
768 | &conf_lock); | 768 | &conf_lock); |
@@ -779,7 +779,7 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, | |||
779 | else | 779 | else |
780 | flock->fl_type = F_UNLCK; | 780 | flock->fl_type = F_UNLCK; |
781 | 781 | ||
782 | mutex_unlock(&cinode->lock_mutex); | 782 | up_read(&cinode->lock_sem); |
783 | return rc; | 783 | return rc; |
784 | } | 784 | } |
785 | 785 | ||
@@ -787,9 +787,9 @@ static void | |||
787 | cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) | 787 | cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) |
788 | { | 788 | { |
789 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | 789 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); |
790 | mutex_lock(&cinode->lock_mutex); | 790 | down_write(&cinode->lock_sem); |
791 | list_add_tail(&lock->llist, &cfile->llist->locks); | 791 | list_add_tail(&lock->llist, &cfile->llist->locks); |
792 | mutex_unlock(&cinode->lock_mutex); | 792 | up_write(&cinode->lock_sem); |
793 | } | 793 | } |
794 | 794 | ||
795 | /* | 795 | /* |
@@ -809,13 +809,13 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, | |||
809 | 809 | ||
810 | try_again: | 810 | try_again: |
811 | exist = false; | 811 | exist = false; |
812 | mutex_lock(&cinode->lock_mutex); | 812 | down_write(&cinode->lock_sem); |
813 | 813 | ||
814 | exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, | 814 | exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, |
815 | lock->type, &conf_lock); | 815 | lock->type, &conf_lock); |
816 | if (!exist && cinode->can_cache_brlcks) { | 816 | if (!exist && cinode->can_cache_brlcks) { |
817 | list_add_tail(&lock->llist, &cfile->llist->locks); | 817 | list_add_tail(&lock->llist, &cfile->llist->locks); |
818 | mutex_unlock(&cinode->lock_mutex); | 818 | up_write(&cinode->lock_sem); |
819 | return rc; | 819 | return rc; |
820 | } | 820 | } |
821 | 821 | ||
@@ -825,17 +825,17 @@ try_again: | |||
825 | rc = -EACCES; | 825 | rc = -EACCES; |
826 | else { | 826 | else { |
827 | list_add_tail(&lock->blist, &conf_lock->blist); | 827 | list_add_tail(&lock->blist, &conf_lock->blist); |
828 | mutex_unlock(&cinode->lock_mutex); | 828 | up_write(&cinode->lock_sem); |
829 | rc = wait_event_interruptible(lock->block_q, | 829 | rc = wait_event_interruptible(lock->block_q, |
830 | (lock->blist.prev == &lock->blist) && | 830 | (lock->blist.prev == &lock->blist) && |
831 | (lock->blist.next == &lock->blist)); | 831 | (lock->blist.next == &lock->blist)); |
832 | if (!rc) | 832 | if (!rc) |
833 | goto try_again; | 833 | goto try_again; |
834 | mutex_lock(&cinode->lock_mutex); | 834 | down_write(&cinode->lock_sem); |
835 | list_del_init(&lock->blist); | 835 | list_del_init(&lock->blist); |
836 | } | 836 | } |
837 | 837 | ||
838 | mutex_unlock(&cinode->lock_mutex); | 838 | up_write(&cinode->lock_sem); |
839 | return rc; | 839 | return rc; |
840 | } | 840 | } |
841 | 841 | ||
@@ -856,7 +856,7 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) | |||
856 | if ((flock->fl_flags & FL_POSIX) == 0) | 856 | if ((flock->fl_flags & FL_POSIX) == 0) |
857 | return 1; | 857 | return 1; |
858 | 858 | ||
859 | mutex_lock(&cinode->lock_mutex); | 859 | down_read(&cinode->lock_sem); |
860 | posix_test_lock(file, flock); | 860 | posix_test_lock(file, flock); |
861 | 861 | ||
862 | if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) { | 862 | if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) { |
@@ -864,7 +864,7 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) | |||
864 | rc = 1; | 864 | rc = 1; |
865 | } | 865 | } |
866 | 866 | ||
867 | mutex_unlock(&cinode->lock_mutex); | 867 | up_read(&cinode->lock_sem); |
868 | return rc; | 868 | return rc; |
869 | } | 869 | } |
870 | 870 | ||
@@ -884,14 +884,14 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) | |||
884 | return rc; | 884 | return rc; |
885 | 885 | ||
886 | try_again: | 886 | try_again: |
887 | mutex_lock(&cinode->lock_mutex); | 887 | down_write(&cinode->lock_sem); |
888 | if (!cinode->can_cache_brlcks) { | 888 | if (!cinode->can_cache_brlcks) { |
889 | mutex_unlock(&cinode->lock_mutex); | 889 | up_write(&cinode->lock_sem); |
890 | return rc; | 890 | return rc; |
891 | } | 891 | } |
892 | 892 | ||
893 | rc = posix_lock_file(file, flock, NULL); | 893 | rc = posix_lock_file(file, flock, NULL); |
894 | mutex_unlock(&cinode->lock_mutex); | 894 | up_write(&cinode->lock_sem); |
895 | if (rc == FILE_LOCK_DEFERRED) { | 895 | if (rc == FILE_LOCK_DEFERRED) { |
896 | rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); | 896 | rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); |
897 | if (!rc) | 897 | if (!rc) |
@@ -918,9 +918,10 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
918 | xid = get_xid(); | 918 | xid = get_xid(); |
919 | tcon = tlink_tcon(cfile->tlink); | 919 | tcon = tlink_tcon(cfile->tlink); |
920 | 920 | ||
921 | mutex_lock(&cinode->lock_mutex); | 921 | /* we are going to update can_cache_brlcks here - need a write access */ |
922 | down_write(&cinode->lock_sem); | ||
922 | if (!cinode->can_cache_brlcks) { | 923 | if (!cinode->can_cache_brlcks) { |
923 | mutex_unlock(&cinode->lock_mutex); | 924 | up_write(&cinode->lock_sem); |
924 | free_xid(xid); | 925 | free_xid(xid); |
925 | return rc; | 926 | return rc; |
926 | } | 927 | } |
@@ -931,7 +932,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
931 | */ | 932 | */ |
932 | max_buf = tcon->ses->server->maxBuf; | 933 | max_buf = tcon->ses->server->maxBuf; |
933 | if (!max_buf) { | 934 | if (!max_buf) { |
934 | mutex_unlock(&cinode->lock_mutex); | 935 | up_write(&cinode->lock_sem); |
935 | free_xid(xid); | 936 | free_xid(xid); |
936 | return -EINVAL; | 937 | return -EINVAL; |
937 | } | 938 | } |
@@ -940,7 +941,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
940 | sizeof(LOCKING_ANDX_RANGE); | 941 | sizeof(LOCKING_ANDX_RANGE); |
941 | buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); | 942 | buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); |
942 | if (!buf) { | 943 | if (!buf) { |
943 | mutex_unlock(&cinode->lock_mutex); | 944 | up_write(&cinode->lock_sem); |
944 | free_xid(xid); | 945 | free_xid(xid); |
945 | return -ENOMEM; | 946 | return -ENOMEM; |
946 | } | 947 | } |
@@ -978,7 +979,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
978 | } | 979 | } |
979 | 980 | ||
980 | cinode->can_cache_brlcks = false; | 981 | cinode->can_cache_brlcks = false; |
981 | mutex_unlock(&cinode->lock_mutex); | 982 | up_write(&cinode->lock_sem); |
982 | 983 | ||
983 | kfree(buf); | 984 | kfree(buf); |
984 | free_xid(xid); | 985 | free_xid(xid); |
@@ -1013,9 +1014,10 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1013 | 1014 | ||
1014 | xid = get_xid(); | 1015 | xid = get_xid(); |
1015 | 1016 | ||
1016 | mutex_lock(&cinode->lock_mutex); | 1017 | /* we are going to update can_cache_brlcks here - need a write access */ |
1018 | down_write(&cinode->lock_sem); | ||
1017 | if (!cinode->can_cache_brlcks) { | 1019 | if (!cinode->can_cache_brlcks) { |
1018 | mutex_unlock(&cinode->lock_mutex); | 1020 | up_write(&cinode->lock_sem); |
1019 | free_xid(xid); | 1021 | free_xid(xid); |
1020 | return rc; | 1022 | return rc; |
1021 | } | 1023 | } |
@@ -1031,7 +1033,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1031 | 1033 | ||
1032 | /* | 1034 | /* |
1033 | * Allocating count locks is enough because no FL_POSIX locks can be | 1035 | * Allocating count locks is enough because no FL_POSIX locks can be |
1034 | * added to the list while we are holding cinode->lock_mutex that | 1036 | * added to the list while we are holding cinode->lock_sem that |
1035 | * protects locking operations of this inode. | 1037 | * protects locking operations of this inode. |
1036 | */ | 1038 | */ |
1037 | for (; i < count; i++) { | 1039 | for (; i < count; i++) { |
@@ -1086,7 +1088,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1086 | 1088 | ||
1087 | out: | 1089 | out: |
1088 | cinode->can_cache_brlcks = false; | 1090 | cinode->can_cache_brlcks = false; |
1089 | mutex_unlock(&cinode->lock_mutex); | 1091 | up_write(&cinode->lock_sem); |
1090 | 1092 | ||
1091 | free_xid(xid); | 1093 | free_xid(xid); |
1092 | return rc; | 1094 | return rc; |
@@ -1278,7 +1280,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
1278 | if (!buf) | 1280 | if (!buf) |
1279 | return -ENOMEM; | 1281 | return -ENOMEM; |
1280 | 1282 | ||
1281 | mutex_lock(&cinode->lock_mutex); | 1283 | down_write(&cinode->lock_sem); |
1282 | for (i = 0; i < 2; i++) { | 1284 | for (i = 0; i < 2; i++) { |
1283 | cur = buf; | 1285 | cur = buf; |
1284 | num = 0; | 1286 | num = 0; |
@@ -1348,7 +1350,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
1348 | } | 1350 | } |
1349 | } | 1351 | } |
1350 | 1352 | ||
1351 | mutex_unlock(&cinode->lock_mutex); | 1353 | up_write(&cinode->lock_sem); |
1352 | kfree(buf); | 1354 | kfree(buf); |
1353 | return rc; | 1355 | return rc; |
1354 | } | 1356 | } |
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 181e13d9f9db..0ddd617ffa1a 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c | |||
@@ -135,7 +135,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
135 | 135 | ||
136 | cur = buf; | 136 | cur = buf; |
137 | 137 | ||
138 | mutex_lock(&cinode->lock_mutex); | 138 | down_write(&cinode->lock_sem); |
139 | list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { | 139 | list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { |
140 | if (flock->fl_start > li->offset || | 140 | if (flock->fl_start > li->offset || |
141 | (flock->fl_start + length) < | 141 | (flock->fl_start + length) < |
@@ -196,7 +196,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
196 | } else | 196 | } else |
197 | cifs_free_llist(&tmp_llist); | 197 | cifs_free_llist(&tmp_llist); |
198 | } | 198 | } |
199 | mutex_unlock(&cinode->lock_mutex); | 199 | up_write(&cinode->lock_sem); |
200 | 200 | ||
201 | kfree(buf); | 201 | kfree(buf); |
202 | return rc; | 202 | return rc; |
@@ -253,9 +253,10 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
253 | struct cifs_fid_locks *fdlocks; | 253 | struct cifs_fid_locks *fdlocks; |
254 | 254 | ||
255 | xid = get_xid(); | 255 | xid = get_xid(); |
256 | mutex_lock(&cinode->lock_mutex); | 256 | /* we are going to update can_cache_brlcks here - need a write access */ |
257 | down_write(&cinode->lock_sem); | ||
257 | if (!cinode->can_cache_brlcks) { | 258 | if (!cinode->can_cache_brlcks) { |
258 | mutex_unlock(&cinode->lock_mutex); | 259 | up_write(&cinode->lock_sem); |
259 | free_xid(xid); | 260 | free_xid(xid); |
260 | return rc; | 261 | return rc; |
261 | } | 262 | } |
@@ -266,7 +267,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
266 | */ | 267 | */ |
267 | max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf; | 268 | max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf; |
268 | if (!max_buf) { | 269 | if (!max_buf) { |
269 | mutex_unlock(&cinode->lock_mutex); | 270 | up_write(&cinode->lock_sem); |
270 | free_xid(xid); | 271 | free_xid(xid); |
271 | return -EINVAL; | 272 | return -EINVAL; |
272 | } | 273 | } |
@@ -274,7 +275,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
274 | max_num = max_buf / sizeof(struct smb2_lock_element); | 275 | max_num = max_buf / sizeof(struct smb2_lock_element); |
275 | buf = kzalloc(max_num * sizeof(struct smb2_lock_element), GFP_KERNEL); | 276 | buf = kzalloc(max_num * sizeof(struct smb2_lock_element), GFP_KERNEL); |
276 | if (!buf) { | 277 | if (!buf) { |
277 | mutex_unlock(&cinode->lock_mutex); | 278 | up_write(&cinode->lock_sem); |
278 | free_xid(xid); | 279 | free_xid(xid); |
279 | return -ENOMEM; | 280 | return -ENOMEM; |
280 | } | 281 | } |
@@ -288,7 +289,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
288 | cinode->can_cache_brlcks = false; | 289 | cinode->can_cache_brlcks = false; |
289 | kfree(buf); | 290 | kfree(buf); |
290 | 291 | ||
291 | mutex_unlock(&cinode->lock_mutex); | 292 | up_write(&cinode->lock_sem); |
292 | free_xid(xid); | 293 | free_xid(xid); |
293 | return rc; | 294 | return rc; |
294 | } | 295 | } |