aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2012-02-24 07:41:06 -0500
committerSteve French <sfrench@us.ibm.com>2012-05-16 21:13:35 -0400
commitfbd35acadd728eac5d94f360c7cd8cbe12a0379f (patch)
tree3db901833cee1e177aae17cb35e5d57fa998a27a /fs/cifs/file.c
parent121b046af54437b084aa0e4be967ae5aed7528b5 (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.c89
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
647static struct cifsLockInfo * 646static struct cifsLockInfo *
648cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) 647cifs_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
674static bool 672static bool
675__cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, 673cifs_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
697static bool 695static bool
698cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, 696cifs_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 */
712static int 722static int
713cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, 723cifs_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
741static void 752static void
742cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) 753cifs_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 */
755static int 767static int
756cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, 768cifs_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