diff options
author | Pavel Shilovsky <piastry@etersoft.ru> | 2012-02-24 07:41:06 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2012-05-16 21:13:35 -0400 |
commit | fbd35acadd728eac5d94f360c7cd8cbe12a0379f (patch) | |
tree | 3db901833cee1e177aae17cb35e5d57fa998a27a /fs/cifs/file.c | |
parent | 121b046af54437b084aa0e4be967ae5aed7528b5 (diff) |
CIFS: Move locks to cifsFileInfo structure
CIFS brlock cache can be used by several file handles if we have a
write-caching lease on the file that is supported by SMB2 protocol.
Prepate the code to handle this situation correctly by sorting brlocks
by a fid to easily push them in portions when lease break comes.
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 89 |
1 files changed, 49 insertions, 40 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 4b5fe398cbf6..fc45cd97e14f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -264,6 +264,7 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, | |||
264 | pCifsFile->tlink = cifs_get_tlink(tlink); | 264 | pCifsFile->tlink = cifs_get_tlink(tlink); |
265 | mutex_init(&pCifsFile->fh_mutex); | 265 | mutex_init(&pCifsFile->fh_mutex); |
266 | INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); | 266 | INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); |
267 | INIT_LIST_HEAD(&pCifsFile->llist); | ||
267 | 268 | ||
268 | spin_lock(&cifs_file_list_lock); | 269 | spin_lock(&cifs_file_list_lock); |
269 | list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); | 270 | list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); |
@@ -334,9 +335,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
334 | * is closed anyway. | 335 | * is closed anyway. |
335 | */ | 336 | */ |
336 | mutex_lock(&cifsi->lock_mutex); | 337 | mutex_lock(&cifsi->lock_mutex); |
337 | list_for_each_entry_safe(li, tmp, &cifsi->llist, llist) { | 338 | list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) { |
338 | if (li->netfid != cifs_file->netfid) | ||
339 | continue; | ||
340 | list_del(&li->llist); | 339 | list_del(&li->llist); |
341 | cifs_del_lock_waiters(li); | 340 | cifs_del_lock_waiters(li); |
342 | kfree(li); | 341 | kfree(li); |
@@ -645,7 +644,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
645 | } | 644 | } |
646 | 645 | ||
647 | static struct cifsLockInfo * | 646 | static struct cifsLockInfo * |
648 | cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) | 647 | cifs_lock_init(__u64 offset, __u64 length, __u8 type) |
649 | { | 648 | { |
650 | struct cifsLockInfo *lock = | 649 | struct cifsLockInfo *lock = |
651 | kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); | 650 | kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); |
@@ -654,7 +653,6 @@ cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) | |||
654 | lock->offset = offset; | 653 | lock->offset = offset; |
655 | lock->length = length; | 654 | lock->length = length; |
656 | lock->type = type; | 655 | lock->type = type; |
657 | lock->netfid = netfid; | ||
658 | lock->pid = current->tgid; | 656 | lock->pid = current->tgid; |
659 | INIT_LIST_HEAD(&lock->blist); | 657 | INIT_LIST_HEAD(&lock->blist); |
660 | init_waitqueue_head(&lock->block_q); | 658 | init_waitqueue_head(&lock->block_q); |
@@ -672,19 +670,19 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock) | |||
672 | } | 670 | } |
673 | 671 | ||
674 | static bool | 672 | static bool |
675 | __cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, | 673 | cifs_find_fid_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, |
676 | __u64 length, __u8 type, __u16 netfid, | 674 | __u64 length, __u8 type, __u16 netfid, |
677 | struct cifsLockInfo **conf_lock) | 675 | struct cifsLockInfo **conf_lock) |
678 | { | 676 | { |
679 | struct cifsLockInfo *li, *tmp; | 677 | struct cifsLockInfo *li; |
680 | 678 | ||
681 | list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { | 679 | list_for_each_entry(li, &cfile->llist, llist) { |
682 | if (offset + length <= li->offset || | 680 | if (offset + length <= li->offset || |
683 | offset >= li->offset + li->length) | 681 | offset >= li->offset + li->length) |
684 | continue; | 682 | continue; |
685 | else if ((type & LOCKING_ANDX_SHARED_LOCK) && | 683 | else if ((type & LOCKING_ANDX_SHARED_LOCK) && |
686 | ((netfid == li->netfid && current->tgid == li->pid) || | 684 | ((netfid == cfile->netfid && current->tgid == li->pid) |
687 | type == li->type)) | 685 | || type == li->type)) |
688 | continue; | 686 | continue; |
689 | else { | 687 | else { |
690 | *conf_lock = li; | 688 | *conf_lock = li; |
@@ -695,11 +693,23 @@ __cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, | |||
695 | } | 693 | } |
696 | 694 | ||
697 | static bool | 695 | static bool |
698 | cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, | 696 | cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, |
697 | __u64 length, __u8 type, __u16 netfid, | ||
699 | struct cifsLockInfo **conf_lock) | 698 | struct cifsLockInfo **conf_lock) |
700 | { | 699 | { |
701 | return __cifs_find_lock_conflict(cinode, lock->offset, lock->length, | 700 | bool rc = false; |
702 | lock->type, lock->netfid, conf_lock); | 701 | struct cifsFileInfo *fid, *tmp; |
702 | |||
703 | spin_lock(&cifs_file_list_lock); | ||
704 | list_for_each_entry_safe(fid, tmp, &cinode->openFileList, flist) { | ||
705 | rc = cifs_find_fid_lock_conflict(fid, offset, length, type, | ||
706 | netfid, conf_lock); | ||
707 | if (rc) | ||
708 | break; | ||
709 | } | ||
710 | spin_unlock(&cifs_file_list_lock); | ||
711 | |||
712 | return rc; | ||
703 | } | 713 | } |
704 | 714 | ||
705 | /* | 715 | /* |
@@ -710,17 +720,18 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, | |||
710 | * the server or 1 otherwise. | 720 | * the server or 1 otherwise. |
711 | */ | 721 | */ |
712 | static int | 722 | static int |
713 | cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | 723 | cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, |
714 | __u8 type, __u16 netfid, struct file_lock *flock) | 724 | __u8 type, struct file_lock *flock) |
715 | { | 725 | { |
716 | int rc = 0; | 726 | int rc = 0; |
717 | struct cifsLockInfo *conf_lock; | 727 | struct cifsLockInfo *conf_lock; |
728 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | ||
718 | bool exist; | 729 | bool exist; |
719 | 730 | ||
720 | mutex_lock(&cinode->lock_mutex); | 731 | mutex_lock(&cinode->lock_mutex); |
721 | 732 | ||
722 | exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid, | 733 | exist = cifs_find_lock_conflict(cinode, offset, length, type, |
723 | &conf_lock); | 734 | cfile->netfid, &conf_lock); |
724 | if (exist) { | 735 | if (exist) { |
725 | flock->fl_start = conf_lock->offset; | 736 | flock->fl_start = conf_lock->offset; |
726 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; | 737 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; |
@@ -739,10 +750,11 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | |||
739 | } | 750 | } |
740 | 751 | ||
741 | static void | 752 | static void |
742 | cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) | 753 | cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) |
743 | { | 754 | { |
755 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | ||
744 | mutex_lock(&cinode->lock_mutex); | 756 | mutex_lock(&cinode->lock_mutex); |
745 | list_add_tail(&lock->llist, &cinode->llist); | 757 | list_add_tail(&lock->llist, &cfile->llist); |
746 | mutex_unlock(&cinode->lock_mutex); | 758 | mutex_unlock(&cinode->lock_mutex); |
747 | } | 759 | } |
748 | 760 | ||
@@ -753,10 +765,11 @@ cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) | |||
753 | * 3) -EACCESS, if there is a lock that prevents us and wait is false. | 765 | * 3) -EACCESS, if there is a lock that prevents us and wait is false. |
754 | */ | 766 | */ |
755 | static int | 767 | static int |
756 | cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, | 768 | cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, |
757 | bool wait) | 769 | bool wait) |
758 | { | 770 | { |
759 | struct cifsLockInfo *conf_lock; | 771 | struct cifsLockInfo *conf_lock; |
772 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | ||
760 | bool exist; | 773 | bool exist; |
761 | int rc = 0; | 774 | int rc = 0; |
762 | 775 | ||
@@ -764,9 +777,10 @@ try_again: | |||
764 | exist = false; | 777 | exist = false; |
765 | mutex_lock(&cinode->lock_mutex); | 778 | mutex_lock(&cinode->lock_mutex); |
766 | 779 | ||
767 | exist = cifs_find_lock_conflict(cinode, lock, &conf_lock); | 780 | exist = cifs_find_lock_conflict(cinode, lock->offset, lock->length, |
781 | lock->type, cfile->netfid, &conf_lock); | ||
768 | if (!exist && cinode->can_cache_brlcks) { | 782 | if (!exist && cinode->can_cache_brlcks) { |
769 | list_add_tail(&lock->llist, &cinode->llist); | 783 | list_add_tail(&lock->llist, &cfile->llist); |
770 | mutex_unlock(&cinode->lock_mutex); | 784 | mutex_unlock(&cinode->lock_mutex); |
771 | return rc; | 785 | return rc; |
772 | } | 786 | } |
@@ -888,7 +902,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
888 | for (i = 0; i < 2; i++) { | 902 | for (i = 0; i < 2; i++) { |
889 | cur = buf; | 903 | cur = buf; |
890 | num = 0; | 904 | num = 0; |
891 | list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { | 905 | list_for_each_entry_safe(li, tmp, &cfile->llist, llist) { |
892 | if (li->type != types[i]) | 906 | if (li->type != types[i]) |
893 | continue; | 907 | continue; |
894 | cur->Pid = cpu_to_le16(li->pid); | 908 | cur->Pid = cpu_to_le16(li->pid); |
@@ -1104,7 +1118,6 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1104 | __u64 length = 1 + flock->fl_end - flock->fl_start; | 1118 | __u64 length = 1 + flock->fl_end - flock->fl_start; |
1105 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; | 1119 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; |
1106 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 1120 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
1107 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | ||
1108 | __u16 netfid = cfile->netfid; | 1121 | __u16 netfid = cfile->netfid; |
1109 | 1122 | ||
1110 | if (posix_lck) { | 1123 | if (posix_lck) { |
@@ -1124,8 +1137,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1124 | return rc; | 1137 | return rc; |
1125 | } | 1138 | } |
1126 | 1139 | ||
1127 | rc = cifs_lock_test(cinode, flock->fl_start, length, type, netfid, | 1140 | rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock); |
1128 | flock); | ||
1129 | if (!rc) | 1141 | if (!rc) |
1130 | return rc; | 1142 | return rc; |
1131 | 1143 | ||
@@ -1212,15 +1224,13 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) | |||
1212 | for (i = 0; i < 2; i++) { | 1224 | for (i = 0; i < 2; i++) { |
1213 | cur = buf; | 1225 | cur = buf; |
1214 | num = 0; | 1226 | num = 0; |
1215 | list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { | 1227 | list_for_each_entry_safe(li, tmp, &cfile->llist, llist) { |
1216 | if (flock->fl_start > li->offset || | 1228 | if (flock->fl_start > li->offset || |
1217 | (flock->fl_start + length) < | 1229 | (flock->fl_start + length) < |
1218 | (li->offset + li->length)) | 1230 | (li->offset + li->length)) |
1219 | continue; | 1231 | continue; |
1220 | if (current->tgid != li->pid) | 1232 | if (current->tgid != li->pid) |
1221 | continue; | 1233 | continue; |
1222 | if (cfile->netfid != li->netfid) | ||
1223 | continue; | ||
1224 | if (types[i] != li->type) | 1234 | if (types[i] != li->type) |
1225 | continue; | 1235 | continue; |
1226 | if (!cinode->can_cache_brlcks) { | 1236 | if (!cinode->can_cache_brlcks) { |
@@ -1233,7 +1243,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) | |||
1233 | cpu_to_le32((u32)(li->offset>>32)); | 1243 | cpu_to_le32((u32)(li->offset>>32)); |
1234 | /* | 1244 | /* |
1235 | * We need to save a lock here to let us add | 1245 | * We need to save a lock here to let us add |
1236 | * it again to the inode list if the unlock | 1246 | * it again to the file's list if the unlock |
1237 | * range request fails on the server. | 1247 | * range request fails on the server. |
1238 | */ | 1248 | */ |
1239 | list_move(&li->llist, &tmp_llist); | 1249 | list_move(&li->llist, &tmp_llist); |
@@ -1247,10 +1257,10 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) | |||
1247 | * We failed on the unlock range | 1257 | * We failed on the unlock range |
1248 | * request - add all locks from | 1258 | * request - add all locks from |
1249 | * the tmp list to the head of | 1259 | * the tmp list to the head of |
1250 | * the inode list. | 1260 | * the file's list. |
1251 | */ | 1261 | */ |
1252 | cifs_move_llist(&tmp_llist, | 1262 | cifs_move_llist(&tmp_llist, |
1253 | &cinode->llist); | 1263 | &cfile->llist); |
1254 | rc = stored_rc; | 1264 | rc = stored_rc; |
1255 | } else | 1265 | } else |
1256 | /* | 1266 | /* |
@@ -1265,7 +1275,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) | |||
1265 | } else { | 1275 | } else { |
1266 | /* | 1276 | /* |
1267 | * We can cache brlock requests - simply remove | 1277 | * We can cache brlock requests - simply remove |
1268 | * a lock from the inode list. | 1278 | * a lock from the file's list. |
1269 | */ | 1279 | */ |
1270 | list_del(&li->llist); | 1280 | list_del(&li->llist); |
1271 | cifs_del_lock_waiters(li); | 1281 | cifs_del_lock_waiters(li); |
@@ -1276,7 +1286,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) | |||
1276 | stored_rc = cifs_lockv(xid, tcon, cfile->netfid, | 1286 | stored_rc = cifs_lockv(xid, tcon, cfile->netfid, |
1277 | types[i], num, 0, buf); | 1287 | types[i], num, 0, buf); |
1278 | if (stored_rc) { | 1288 | if (stored_rc) { |
1279 | cifs_move_llist(&tmp_llist, &cinode->llist); | 1289 | cifs_move_llist(&tmp_llist, &cfile->llist); |
1280 | rc = stored_rc; | 1290 | rc = stored_rc; |
1281 | } else | 1291 | } else |
1282 | cifs_free_llist(&tmp_llist); | 1292 | cifs_free_llist(&tmp_llist); |
@@ -1296,7 +1306,6 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1296 | __u64 length = 1 + flock->fl_end - flock->fl_start; | 1306 | __u64 length = 1 + flock->fl_end - flock->fl_start; |
1297 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; | 1307 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; |
1298 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 1308 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
1299 | struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); | ||
1300 | __u16 netfid = cfile->netfid; | 1309 | __u16 netfid = cfile->netfid; |
1301 | 1310 | ||
1302 | if (posix_lck) { | 1311 | if (posix_lck) { |
@@ -1323,11 +1332,11 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1323 | if (lock) { | 1332 | if (lock) { |
1324 | struct cifsLockInfo *lock; | 1333 | struct cifsLockInfo *lock; |
1325 | 1334 | ||
1326 | lock = cifs_lock_init(flock->fl_start, length, type, netfid); | 1335 | lock = cifs_lock_init(flock->fl_start, length, type); |
1327 | if (!lock) | 1336 | if (!lock) |
1328 | return -ENOMEM; | 1337 | return -ENOMEM; |
1329 | 1338 | ||
1330 | rc = cifs_lock_add_if(cinode, lock, wait_flag); | 1339 | rc = cifs_lock_add_if(cfile, lock, wait_flag); |
1331 | if (rc < 0) | 1340 | if (rc < 0) |
1332 | kfree(lock); | 1341 | kfree(lock); |
1333 | if (rc <= 0) | 1342 | if (rc <= 0) |
@@ -1340,7 +1349,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1340 | goto out; | 1349 | goto out; |
1341 | } | 1350 | } |
1342 | 1351 | ||
1343 | cifs_lock_add(cinode, lock); | 1352 | cifs_lock_add(cfile, lock); |
1344 | } else if (unlock) | 1353 | } else if (unlock) |
1345 | rc = cifs_unlock_range(cfile, flock, xid); | 1354 | rc = cifs_unlock_range(cfile, flock, xid); |
1346 | 1355 | ||