Skip to content

Commit

Permalink
smb3: fix unusable share after force unmount failure
Browse files Browse the repository at this point in the history
If user does forced unmount ("umount -f") while files are still open
on the share (as was seen in a Kubernetes example running on SMB3.1.1
mount) then we were marking the share as "TID_EXITING" in umount_begin()
which caused all subsequent operations (except write) to fail ... but
unfortunately when umount_begin() is called we do not know yet that
there are open files or active references on the share that would prevent
unmount from succeeding.  Kubernetes had example when they were doing
umount -f when files were open which caused the share to become
unusable until the files were closed (and the umount retried).

Fix this so that TID_EXITING is not set until we are about to send
the tree disconnect (not at the beginning of forced umounts in
umount_begin) so that if "umount -f" fails (due to open files or
references) the mount is still usable.

Cc: stable@vger.kernel.org
Reviewed-by: Shyam Prasad N <sprasad@microsoft.com>
Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
  • Loading branch information
Steve French committed Mar 24, 2023
1 parent be4fde7 commit 491eafc
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 13 deletions.
9 changes: 6 additions & 3 deletions fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,13 +731,16 @@ static void cifs_umount_begin(struct super_block *sb)
spin_lock(&tcon->tc_lock);
if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
/* we have other mounts to same share or we have
already tried to force umount this and woken up
already tried to umount this and woken up
all waiting network requests, nothing to do */
spin_unlock(&tcon->tc_lock);
spin_unlock(&cifs_tcp_ses_lock);
return;
} else if (tcon->tc_count == 1)
tcon->status = TID_EXITING;
}
/*
* can not set tcon->status to TID_EXITING yet since we don't know if umount -f will
* fail later (e.g. due to open files). TID_EXITING will be set just before tdis req sent
*/
spin_unlock(&tcon->tc_lock);
spin_unlock(&cifs_tcp_ses_lock);

Expand Down
6 changes: 2 additions & 4 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,11 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)

/*
* only tree disconnect, open, and write, (and ulogoff which does not
* have tcon) are allowed as we start force umount
* have tcon) are allowed as we start umount
*/
spin_lock(&tcon->tc_lock);
if (tcon->status == TID_EXITING) {
if (smb_command != SMB_COM_WRITE_ANDX &&
smb_command != SMB_COM_OPEN_ANDX &&
smb_command != SMB_COM_TREE_DISCONNECT) {
if (smb_command != SMB_COM_TREE_DISCONNECT) {
spin_unlock(&tcon->tc_lock);
cifs_dbg(FYI, "can not send cmd %d while umounting\n",
smb_command);
Expand Down
1 change: 1 addition & 0 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -2324,6 +2324,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
WARN_ON(tcon->tc_count < 0);

list_del_init(&tcon->tcon_list);
tcon->status = TID_EXITING;
spin_unlock(&tcon->tc_lock);
spin_unlock(&cifs_tcp_ses_lock);

Expand Down
8 changes: 2 additions & 6 deletions fs/cifs/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,9 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
spin_lock(&tcon->tc_lock);
if (tcon->status == TID_EXITING) {
/*
* only tree disconnect, open, and write,
* (and ulogoff which does not have tcon)
* are allowed as we start force umount.
* only tree disconnect allowed when disconnecting ...
*/
if ((smb2_command != SMB2_WRITE) &&
(smb2_command != SMB2_CREATE) &&
(smb2_command != SMB2_TREE_DISCONNECT)) {
if (smb2_command != SMB2_TREE_DISCONNECT) {
spin_unlock(&tcon->tc_lock);
cifs_dbg(FYI, "can not send cmd %d while umounting\n",
smb2_command);
Expand Down

0 comments on commit 491eafc

Please sign in to comment.