aboutsummaryrefslogtreecommitdiff
path: root/sys/fs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/smbfs/smbfs.h1
-rw-r--r--sys/fs/smbfs/smbfs_node.c5
-rw-r--r--sys/fs/smbfs/smbfs_vfsops.c15
3 files changed, 19 insertions, 2 deletions
diff --git a/sys/fs/smbfs/smbfs.h b/sys/fs/smbfs/smbfs.h
index b6f97bec7047..50487916826f 100644
--- a/sys/fs/smbfs/smbfs.h
+++ b/sys/fs/smbfs/smbfs.h
@@ -89,6 +89,7 @@ struct smbmount {
struct lock sm_hashlock;
LIST_HEAD(smbnode_hashhead, smbnode) *sm_hash;
u_long sm_hashlen;
+ int sm_didrele;
};
#define VFSTOSMBFS(mp) ((struct smbmount *)((mp)->mnt_data))
diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c
index 7f17967d43fe..0feadd0eec12 100644
--- a/sys/fs/smbfs/smbfs_node.c
+++ b/sys/fs/smbfs/smbfs_node.c
@@ -322,6 +322,11 @@ smbfs_reclaim(ap)
if (dvp->v_usecount >= 1) {
VI_UNLOCK(dvp);
vrele(dvp);
+ /*
+ * Indicate that we released something; see comment
+ * in smbfs_unmount().
+ */
+ smp->sm_didrele = 1;
} else {
VI_UNLOCK(dvp);
SMBERROR("BUG: negative use count for parent!\n");
diff --git a/sys/fs/smbfs/smbfs_vfsops.c b/sys/fs/smbfs/smbfs_vfsops.c
index 8dba8c84a525..db0bc8418a50 100644
--- a/sys/fs/smbfs/smbfs_vfsops.c
+++ b/sys/fs/smbfs/smbfs_vfsops.c
@@ -243,8 +243,19 @@ smbfs_unmount(struct mount *mp, int mntflags, struct thread *td)
flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- /* There is 1 extra root vnode reference from smbfs_mount(). */
- error = vflush(mp, 1, flags);
+ /*
+ * Keep trying to flush the vnode list for the mount while
+ * some are still busy and we are making progress towards
+ * making them not busy. This is needed because smbfs vnodes
+ * reference their parent directory but may appear after their
+ * parent in the list; one pass over the vnode list is not
+ * sufficient in this case.
+ */
+ do {
+ smp->sm_didrele = 0;
+ /* There is 1 extra root vnode reference from smbfs_mount(). */
+ error = vflush(mp, 1, flags);
+ } while (error == EBUSY && smp->sm_didrele != 0);
if (error)
return error;
smb_makescred(&scred, td, td->td_ucred);