Skip to content

Commit 860b69a

Browse files
rohiths-msftsmfrench
authored andcommitted
Fix kernel oops when CONFIG_DEBUG_ATOMIC_SLEEP is enabled.
Removed oplock_break_received flag which was added to achieve synchronization between oplock handler and open handler by earlier commit. It is not needed because there is an existing lock open_file_lock to achieve the same. find_readable_file takes open_file_lock and then traverses the openFileList. Similarly, cifs_oplock_break while closing the deferred handle (i.e cifsFileInfo_put) takes open_file_lock and then sends close to the server. Added comments for better readability. Signed-off-by: Rohith Surabattula <rohiths@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent e83aa35 commit 860b69a

4 files changed

Lines changed: 23 additions & 18 deletions

File tree

fs/cifs/cifsfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct workqueue_struct *cifsiod_wq;
133133
struct workqueue_struct *decrypt_wq;
134134
struct workqueue_struct *fileinfo_put_wq;
135135
struct workqueue_struct *cifsoplockd_wq;
136-
struct workqueue_struct *deferredclose_wq;
136+
struct workqueue_struct *deferredclose_wq;
137137
__u32 cifs_lock_secret;
138138

139139
/*

fs/cifs/cifsglob.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,7 @@ struct cifsFileInfo {
12571257
struct work_struct oplock_break; /* work for oplock breaks */
12581258
struct work_struct put; /* work for the final part of _put */
12591259
struct delayed_work deferred;
1260-
bool oplock_break_received; /* Flag to indicate oplock break */
1261-
bool deferred_scheduled;
1260+
bool deferred_close_scheduled; /* Flag to indicate close is scheduled */
12621261
};
12631262

12641263
struct cifs_io_parms {

fs/cifs/file.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
323323
cfile->dentry = dget(dentry);
324324
cfile->f_flags = file->f_flags;
325325
cfile->invalidHandle = false;
326-
cfile->oplock_break_received = false;
327-
cfile->deferred_scheduled = false;
326+
cfile->deferred_close_scheduled = false;
328327
cfile->tlink = cifs_get_tlink(tlink);
329328
INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
330329
INIT_WORK(&cfile->put, cifsFileInfo_put_work);
@@ -574,21 +573,18 @@ int cifs_open(struct inode *inode, struct file *file)
574573
file->f_op = &cifs_file_direct_ops;
575574
}
576575

577-
spin_lock(&CIFS_I(inode)->deferred_lock);
578576
/* Get the cached handle as SMB2 close is deferred */
579577
rc = cifs_get_readable_path(tcon, full_path, &cfile);
580578
if (rc == 0) {
581579
if (file->f_flags == cfile->f_flags) {
582580
file->private_data = cfile;
581+
spin_lock(&CIFS_I(inode)->deferred_lock);
583582
cifs_del_deferred_close(cfile);
584583
spin_unlock(&CIFS_I(inode)->deferred_lock);
585584
goto out;
586585
} else {
587-
spin_unlock(&CIFS_I(inode)->deferred_lock);
588586
_cifsFileInfo_put(cfile, true, false);
589587
}
590-
} else {
591-
spin_unlock(&CIFS_I(inode)->deferred_lock);
592588
}
593589

594590
if (server->oplocks)
@@ -878,12 +874,12 @@ void smb2_deferred_work_close(struct work_struct *work)
878874
struct cifsFileInfo, deferred.work);
879875

880876
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
881-
if (!cfile->deferred_scheduled) {
877+
if (!cfile->deferred_close_scheduled) {
882878
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
883879
return;
884880
}
885881
cifs_del_deferred_close(cfile);
886-
cfile->deferred_scheduled = false;
882+
cfile->deferred_close_scheduled = false;
887883
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
888884
_cifsFileInfo_put(cfile, true, false);
889885
}
@@ -905,14 +901,15 @@ int cifs_close(struct inode *inode, struct file *file)
905901
inode->i_ctime = inode->i_mtime = current_time(inode);
906902
spin_lock(&cinode->deferred_lock);
907903
cifs_add_deferred_close(cfile, dclose);
908-
if (cfile->deferred_scheduled) {
904+
if (cfile->deferred_close_scheduled &&
905+
delayed_work_pending(&cfile->deferred)) {
909906
mod_delayed_work(deferredclose_wq,
910907
&cfile->deferred, cifs_sb->ctx->acregmax);
911908
} else {
912909
/* Deferred close for files */
913910
queue_delayed_work(deferredclose_wq,
914911
&cfile->deferred, cifs_sb->ctx->acregmax);
915-
cfile->deferred_scheduled = true;
912+
cfile->deferred_close_scheduled = true;
916913
spin_unlock(&cinode->deferred_lock);
917914
return 0;
918915
}
@@ -2020,8 +2017,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
20202017
if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
20212018
continue;
20222019
if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
2023-
if ((!open_file->invalidHandle) &&
2024-
(!open_file->oplock_break_received)) {
2020+
if ((!open_file->invalidHandle)) {
20252021
/* found a good file */
20262022
/* lock it so it will not be closed on us */
20272023
cifsFileInfo_get(open_file);
@@ -4874,13 +4870,14 @@ void cifs_oplock_break(struct work_struct *work)
48744870
}
48754871
/*
48764872
* When oplock break is received and there are no active
4877-
* file handles but cached, then set the flag oplock_break_received.
4873+
* file handles but cached, then schedule deferred close immediately.
48784874
* So, new open will not use cached handle.
48794875
*/
48804876
spin_lock(&CIFS_I(inode)->deferred_lock);
48814877
is_deferred = cifs_is_deferred_close(cfile, &dclose);
4882-
if (is_deferred && cfile->deferred_scheduled) {
4883-
cfile->oplock_break_received = true;
4878+
if (is_deferred &&
4879+
cfile->deferred_close_scheduled &&
4880+
delayed_work_pending(&cfile->deferred)) {
48844881
mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
48854882
}
48864883
spin_unlock(&CIFS_I(inode)->deferred_lock);

fs/cifs/misc.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,9 @@ cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
672672
spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
673673
}
674674

675+
/*
676+
* Critical section which runs after acquiring deferred_lock.
677+
*/
675678
bool
676679
cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **pdclose)
677680
{
@@ -688,6 +691,9 @@ cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **
688691
return false;
689692
}
690693

694+
/*
695+
* Critical section which runs after acquiring deferred_lock.
696+
*/
691697
void
692698
cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *dclose)
693699
{
@@ -707,6 +713,9 @@ cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *
707713
list_add_tail(&dclose->dlist, &CIFS_I(d_inode(cfile->dentry))->deferred_closes);
708714
}
709715

716+
/*
717+
* Critical section which runs after acquiring deferred_lock.
718+
*/
710719
void
711720
cifs_del_deferred_close(struct cifsFileInfo *cfile)
712721
{

0 commit comments

Comments
 (0)