@@ -516,11 +516,10 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
}
spin_unlock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &entry, entry) {
list_del(&cfid->entry);
- cancel_work_sync(&cfid->lease_break);
/*
* Drop the ref-count from above, either the lease-ref (if there
* was one) or the extra one acquired.
*/
kref_put(&cfid->refcount, smb2_close_cached_fid);
@@ -594,10 +593,12 @@ static struct cached_fid *init_cached_dir(const char *path)
static void free_cached_dir(struct cached_fid *cfid)
{
struct cached_dirent *dirent, *q;
+ WARN_ON(work_pending(&cfid->lease_break));
+
dput(cfid->dentry);
cfid->dentry = NULL;
/*
* Delete all cached dirent names
@@ -640,15 +641,10 @@ static void cfids_laundromat_worker(struct work_struct *work)
}
spin_unlock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &entry, entry) {
list_del(&cfid->entry);
- /*
- * Cancel and wait for the work to finish in case we are racing
- * with it.
- */
- cancel_work_sync(&cfid->lease_break);
/*
* Drop the ref-count from above, either the lease-ref (if there
* was one) or the extra one acquired.
*/
kref_put(&cfid->refcount, smb2_close_cached_fid);
It isn't possible for cfids_laundromat_worker(), invalidate_all_cached_dirs(), and cached_dir_lease_break() to race with each other. Each holds the spinlock while walking the list of cfids, and removes entries from the list. cfids_laundromat_worker() and invalidate_all_cached_dirs() will never see a cfid that has pending work. Signed-off-by: Paul Aurich <paul@darkrain42.org> --- fs/smb/client/cached_dir.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)