Skip to content

Commit 84ac0fd

Browse files
committed
cifs: do not depend on release_iface for maintaining iface_list
jira LE-4669 Rebuild_History Non-Buildable kernel-4.18.0-553.82.1.el8_10 commit-author Shyam Prasad N <sprasad@microsoft.com> commit 09eeb07 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> (cherry picked from commit 09eeb07) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent a71c716 commit 84ac0fd

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

fs/cifs/cifsglob.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,6 @@ release_iface(struct kref *ref)
927927
struct cifs_server_iface *iface = container_of(ref,
928928
struct cifs_server_iface,
929929
refcount);
930-
list_del_init(&iface->iface_head);
931930
kfree(iface);
932931
}
933932

fs/cifs/smb2ops.c

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

541541
/*
542-
* Go through iface_list and do kref_put to remove
543-
* any unused ifaces. ifaces in use will be removed
544-
* when the last user calls a kref_put on it
542+
* Go through iface_list and mark them as inactive
545543
*/
546544
list_for_each_entry_safe(iface, niface, &ses->iface_list,
547-
iface_head) {
545+
iface_head)
548546
iface->is_active = 0;
549-
kref_put(&iface->refcount, release_iface);
550-
ses->iface_count--;
551-
}
547+
552548
spin_unlock(&ses->iface_lock);
553549

554550
/*
@@ -623,10 +619,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
623619
iface_head) {
624620
ret = iface_cmp(iface, &tmp_iface);
625621
if (!ret) {
626-
/* just get a ref so that it doesn't get picked/freed */
627622
iface->is_active = 1;
628-
kref_get(&iface->refcount);
629-
ses->iface_count++;
630623
spin_unlock(&ses->iface_lock);
631624
goto next_iface;
632625
} else if (ret < 0) {
@@ -693,6 +686,20 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
693686
}
694687

695688
out:
689+
/*
690+
* Go through the list again and put the inactive entries
691+
*/
692+
spin_lock(&ses->iface_lock);
693+
list_for_each_entry_safe(iface, niface, &ses->iface_list,
694+
iface_head) {
695+
if (!iface->is_active) {
696+
list_del(&iface->iface_head);
697+
kref_put(&iface->refcount, release_iface);
698+
ses->iface_count--;
699+
}
700+
}
701+
spin_unlock(&ses->iface_lock);
702+
696703
return rc;
697704
}
698705

0 commit comments

Comments
 (0)