Skip to content

Commit 09eeb07

Browse files
sprasad-microsoftSteve French
authored andcommitted
cifs: do not depend on release_iface for maintaining iface_list
parse_server_interfaces should be in complete charge of maintaining the iface_list linked list. Today, iface entries are removed from the list only when the last refcount is dropped. i.e. in release_iface. However, this can result in undercounting of refcount if the server stops advertising interfaces (which Azure SMB server does). This change puts parse_server_interfaces in full charge of maintaining the iface_list. So if an empty list is returned by the server, the entries in the list will immediately be removed. This way, a following call to the same function will not find entries in the list. Fixes: aa45dad ("cifs: change iface_list from array to sorted linked list") Cc: stable@vger.kernel.org Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 7257bcf commit 09eeb07

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

fs/smb/client/cifsglob.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,6 @@ release_iface(struct kref *ref)
994994
struct cifs_server_iface *iface = container_of(ref,
995995
struct cifs_server_iface,
996996
refcount);
997-
list_del_init(&iface->iface_head);
998997
kfree(iface);
999998
}
1000999

fs/smb/client/smb2ops.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -595,16 +595,12 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
595595
}
596596

597597
/*
598-
* Go through iface_list and do kref_put to remove
599-
* any unused ifaces. ifaces in use will be removed
600-
* when the last user calls a kref_put on it
598+
* Go through iface_list and mark them as inactive
601599
*/
602600
list_for_each_entry_safe(iface, niface, &ses->iface_list,
603-
iface_head) {
601+
iface_head)
604602
iface->is_active = 0;
605-
kref_put(&iface->refcount, release_iface);
606-
ses->iface_count--;
607-
}
603+
608604
spin_unlock(&ses->iface_lock);
609605

610606
/*
@@ -678,10 +674,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
678674
iface_head) {
679675
ret = iface_cmp(iface, &tmp_iface);
680676
if (!ret) {
681-
/* just get a ref so that it doesn't get picked/freed */
682677
iface->is_active = 1;
683-
kref_get(&iface->refcount);
684-
ses->iface_count++;
685678
spin_unlock(&ses->iface_lock);
686679
goto next_iface;
687680
} else if (ret < 0) {
@@ -748,6 +741,20 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
748741
}
749742

750743
out:
744+
/*
745+
* Go through the list again and put the inactive entries
746+
*/
747+
spin_lock(&ses->iface_lock);
748+
list_for_each_entry_safe(iface, niface, &ses->iface_list,
749+
iface_head) {
750+
if (!iface->is_active) {
751+
list_del(&iface->iface_head);
752+
kref_put(&iface->refcount, release_iface);
753+
ses->iface_count--;
754+
}
755+
}
756+
spin_unlock(&ses->iface_lock);
757+
751758
return rc;
752759
}
753760

0 commit comments

Comments
 (0)