diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 48b29d24c9f4..7e36ae34e947 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -183,6 +183,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, | |||
183 | int create_options = CREATE_NOT_DIR; | 183 | int create_options = CREATE_NOT_DIR; |
184 | FILE_ALL_INFO *buf; | 184 | FILE_ALL_INFO *buf; |
185 | struct TCP_Server_Info *server = tcon->ses->server; | 185 | struct TCP_Server_Info *server = tcon->ses->server; |
186 | struct cifs_open_parms oparms; | ||
186 | 187 | ||
187 | if (!server->ops->open) | 188 | if (!server->ops->open) |
188 | return -ENOSYS; | 189 | return -ENOSYS; |
@@ -224,9 +225,16 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, | |||
224 | if (backup_cred(cifs_sb)) | 225 | if (backup_cred(cifs_sb)) |
225 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 226 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
226 | 227 | ||
227 | rc = server->ops->open(xid, tcon, full_path, disposition, | 228 | oparms.tcon = tcon; |
228 | desired_access, create_options, fid, oplock, buf, | 229 | oparms.cifs_sb = cifs_sb; |
229 | cifs_sb); | 230 | oparms.desired_access = desired_access; |
231 | oparms.create_options = create_options; | ||
232 | oparms.disposition = disposition; | ||
233 | oparms.path = full_path; | ||
234 | oparms.fid = fid; | ||
235 | oparms.reconnect = false; | ||
236 | |||
237 | rc = server->ops->open(xid, &oparms, oplock, buf); | ||
230 | 238 | ||
231 | if (rc) | 239 | if (rc) |
232 | goto out; | 240 | goto out; |
@@ -553,11 +561,10 @@ cifs_relock_file(struct cifsFileInfo *cfile) | |||
553 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 561 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
554 | int rc = 0; | 562 | int rc = 0; |
555 | 563 | ||
556 | /* we are going to update can_cache_brlcks here - need a write access */ | 564 | down_read(&cinode->lock_sem); |
557 | down_write(&cinode->lock_sem); | ||
558 | if (cinode->can_cache_brlcks) { | 565 | if (cinode->can_cache_brlcks) { |
559 | /* can cache locks - no need to push them */ | 566 | /* can cache locks - no need to relock */ |
560 | up_write(&cinode->lock_sem); | 567 | up_read(&cinode->lock_sem); |
561 | return rc; | 568 | return rc; |
562 | } | 569 | } |
563 | 570 | ||
@@ -568,7 +575,7 @@ cifs_relock_file(struct cifsFileInfo *cfile) | |||
568 | else | 575 | else |
569 | rc = tcon->ses->server->ops->push_mand_locks(cfile); | 576 | rc = tcon->ses->server->ops->push_mand_locks(cfile); |
570 | 577 | ||
571 | up_write(&cinode->lock_sem); | 578 | up_read(&cinode->lock_sem); |
572 | return rc; | 579 | return rc; |
573 | } | 580 | } |
574 | 581 | ||
@@ -587,7 +594,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | |||
587 | int desired_access; | 594 | int desired_access; |
588 | int disposition = FILE_OPEN; | 595 | int disposition = FILE_OPEN; |
589 | int create_options = CREATE_NOT_DIR; | 596 | int create_options = CREATE_NOT_DIR; |
590 | struct cifs_fid fid; | 597 | struct cifs_open_parms oparms; |
591 | 598 | ||
592 | xid = get_xid(); | 599 | xid = get_xid(); |
593 | mutex_lock(&cfile->fh_mutex); | 600 | mutex_lock(&cfile->fh_mutex); |
@@ -637,9 +644,10 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | |||
637 | 644 | ||
638 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, | 645 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, |
639 | cifs_sb->mnt_file_mode /* ignored */, | 646 | cifs_sb->mnt_file_mode /* ignored */, |
640 | oflags, &oplock, &fid.netfid, xid); | 647 | oflags, &oplock, &cfile->fid.netfid, xid); |
641 | if (rc == 0) { | 648 | if (rc == 0) { |
642 | cifs_dbg(FYI, "posix reopen succeeded\n"); | 649 | cifs_dbg(FYI, "posix reopen succeeded\n"); |
650 | oparms.reconnect = true; | ||
643 | goto reopen_success; | 651 | goto reopen_success; |
644 | } | 652 | } |
645 | /* | 653 | /* |
@@ -654,7 +662,16 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | |||
654 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 662 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
655 | 663 | ||
656 | if (server->ops->get_lease_key) | 664 | if (server->ops->get_lease_key) |
657 | server->ops->get_lease_key(inode, &fid); | 665 | server->ops->get_lease_key(inode, &cfile->fid); |
666 | |||
667 | oparms.tcon = tcon; | ||
668 | oparms.cifs_sb = cifs_sb; | ||
669 | oparms.desired_access = desired_access; | ||
670 | oparms.create_options = create_options; | ||
671 | oparms.disposition = disposition; | ||
672 | oparms.path = full_path; | ||
673 | oparms.fid = &cfile->fid; | ||
674 | oparms.reconnect = true; | ||
658 | 675 | ||
659 | /* | 676 | /* |
660 | * Can not refresh inode by passing in file_info buf to be returned by | 677 | * Can not refresh inode by passing in file_info buf to be returned by |
@@ -663,9 +680,14 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | |||
663 | * version of file size can be stale. If we knew for sure that inode was | 680 | * version of file size can be stale. If we knew for sure that inode was |
664 | * not dirty locally we could do this. | 681 | * not dirty locally we could do this. |
665 | */ | 682 | */ |
666 | rc = server->ops->open(xid, tcon, full_path, disposition, | 683 | rc = server->ops->open(xid, &oparms, &oplock, NULL); |
667 | desired_access, create_options, &fid, &oplock, | 684 | if (rc == -ENOENT && oparms.reconnect == false) { |
668 | NULL, cifs_sb); | 685 | /* durable handle timeout is expired - open the file again */ |
686 | rc = server->ops->open(xid, &oparms, &oplock, NULL); | ||
687 | /* indicate that we need to relock the file */ | ||
688 | oparms.reconnect = true; | ||
689 | } | ||
690 | |||
669 | if (rc) { | 691 | if (rc) { |
670 | mutex_unlock(&cfile->fh_mutex); | 692 | mutex_unlock(&cfile->fh_mutex); |
671 | cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc); | 693 | cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc); |
@@ -696,8 +718,9 @@ reopen_success: | |||
696 | * to the server to get the new inode info. | 718 | * to the server to get the new inode info. |
697 | */ | 719 | */ |
698 | 720 | ||
699 | server->ops->set_fid(cfile, &fid, oplock); | 721 | server->ops->set_fid(cfile, &cfile->fid, oplock); |
700 | cifs_relock_file(cfile); | 722 | if (oparms.reconnect) |
723 | cifs_relock_file(cfile); | ||
701 | 724 | ||
702 | reopen_error_exit: | 725 | reopen_error_exit: |
703 | kfree(full_path); | 726 | kfree(full_path); |
@@ -999,7 +1022,7 @@ try_again: | |||
999 | rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); | 1022 | rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); |
1000 | if (!rc) | 1023 | if (!rc) |
1001 | goto try_again; | 1024 | goto try_again; |
1002 | locks_delete_block(flock); | 1025 | posix_unblock_lock(flock); |
1003 | } | 1026 | } |
1004 | return rc; | 1027 | return rc; |
1005 | } | 1028 | } |
@@ -1092,6 +1115,7 @@ struct lock_to_push { | |||
1092 | static int | 1115 | static int |
1093 | cifs_push_posix_locks(struct cifsFileInfo *cfile) | 1116 | cifs_push_posix_locks(struct cifsFileInfo *cfile) |
1094 | { | 1117 | { |
1118 | struct inode *inode = cfile->dentry->d_inode; | ||
1095 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 1119 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
1096 | struct file_lock *flock, **before; | 1120 | struct file_lock *flock, **before; |
1097 | unsigned int count = 0, i = 0; | 1121 | unsigned int count = 0, i = 0; |
@@ -1102,12 +1126,12 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1102 | 1126 | ||
1103 | xid = get_xid(); | 1127 | xid = get_xid(); |
1104 | 1128 | ||
1105 | lock_flocks(); | 1129 | spin_lock(&inode->i_lock); |
1106 | cifs_for_each_lock(cfile->dentry->d_inode, before) { | 1130 | cifs_for_each_lock(inode, before) { |
1107 | if ((*before)->fl_flags & FL_POSIX) | 1131 | if ((*before)->fl_flags & FL_POSIX) |
1108 | count++; | 1132 | count++; |
1109 | } | 1133 | } |
1110 | unlock_flocks(); | 1134 | spin_unlock(&inode->i_lock); |
1111 | 1135 | ||
1112 | INIT_LIST_HEAD(&locks_to_send); | 1136 | INIT_LIST_HEAD(&locks_to_send); |
1113 | 1137 | ||
@@ -1126,8 +1150,8 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1126 | } | 1150 | } |
1127 | 1151 | ||
1128 | el = locks_to_send.next; | 1152 | el = locks_to_send.next; |
1129 | lock_flocks(); | 1153 | spin_lock(&inode->i_lock); |
1130 | cifs_for_each_lock(cfile->dentry->d_inode, before) { | 1154 | cifs_for_each_lock(inode, before) { |
1131 | flock = *before; | 1155 | flock = *before; |
1132 | if ((flock->fl_flags & FL_POSIX) == 0) | 1156 | if ((flock->fl_flags & FL_POSIX) == 0) |
1133 | continue; | 1157 | continue; |
@@ -1152,7 +1176,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1152 | lck->offset = flock->fl_start; | 1176 | lck->offset = flock->fl_start; |
1153 | el = el->next; | 1177 | el = el->next; |
1154 | } | 1178 | } |
1155 | unlock_flocks(); | 1179 | spin_unlock(&inode->i_lock); |
1156 | 1180 | ||
1157 | list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { | 1181 | list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { |
1158 | int stored_rc; | 1182 | int stored_rc; |
@@ -3546,11 +3570,12 @@ static int cifs_release_page(struct page *page, gfp_t gfp) | |||
3546 | return cifs_fscache_release_page(page, gfp); | 3570 | return cifs_fscache_release_page(page, gfp); |
3547 | } | 3571 | } |
3548 | 3572 | ||
3549 | static void cifs_invalidate_page(struct page *page, unsigned long offset) | 3573 | static void cifs_invalidate_page(struct page *page, unsigned int offset, |
3574 | unsigned int length) | ||
3550 | { | 3575 | { |
3551 | struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host); | 3576 | struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host); |
3552 | 3577 | ||
3553 | if (offset == 0) | 3578 | if (offset == 0 && length == PAGE_CACHE_SIZE) |
3554 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); | 3579 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); |
3555 | } | 3580 | } |
3556 | 3581 | ||