summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnzo Matsumiya <ematsumiya@suse.de>2025-04-04 11:40:09 -0300
committerEnzo Matsumiya <ematsumiya@suse.de>2025-04-04 11:40:09 -0300
commitd3fef38b24a36c51d0774fd9b87da4393dd16cc2 (patch)
tree3ede57359d342547943d69acb6fd82588727913b
parent19688fc9e24f4c9be2a6841b37065dead642180f (diff)
downloadlinux-d3fef38b24a36c51d0774fd9b87da4393dd16cc2.tar.gz
linux-d3fef38b24a36c51d0774fd9b87da4393dd16cc2.tar.bz2
linux-d3fef38b24a36c51d0774fd9b87da4393dd16cc2.zip
smb: client: cdir no leasebreaks
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
-rw-r--r--fs/smb/client/cached_dir.c320
-rw-r--r--fs/smb/client/cached_dir.h14
-rw-r--r--fs/smb/client/readdir.c8
-rw-r--r--fs/smb/client/smb2inode.c2
-rw-r--r--fs/smb/client/smb2ops.c26
5 files changed, 85 insertions, 285 deletions
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index ddc8e7bd1fd8..a6ca99d62bc8 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -18,134 +18,8 @@
#define CDIR_FIND_LEASEKEY 0x4
#define CDIR_FIND_PTR 0x8
-
-static struct cached_lease_break *check_lease_break(struct cached_dirs *cdirs, u8 *lease_key)
-{
- struct cached_lease_break *lb;
-
- if (!cdirs || !lease_key)
- return NULL;
-
- write_seqlock(&cdirs->seq);
- list_for_each_entry(lb, &cdirs->lease_breaks, head) {
- if (!memcmp(lb->lease_key, lease_key, 16)) {
- atomic_inc(&lb->recvs);
- write_sequnlock(&cdirs->seq);
-
- return lb;
- }
- }
- write_sequnlock(&cdirs->seq);
-
- return NULL;
-}
-
-static void recv_lease_break(struct cached_dirs *cdirs, u8 *lease_key)
-{
- struct cached_lease_break *lb;
-
- if (!cdirs || !lease_key)
- return;
-
- if (check_lease_break(cdirs, lease_key))
- return;
-
- lb = kzalloc(sizeof(*lb), GFP_ATOMIC);
- if (!lb)
- return;
-
- lb->lease_key = kmemdup(lease_key, 16, GFP_ATOMIC);
- if (!lb->lease_key) {
- kfree(lb);
- return;
- }
-
- INIT_LIST_HEAD(&lb->head);
- atomic_set(&lb->recvs, 1);
- atomic_set(&lb->acks, 0);
- lb->time = jiffies;
-
- write_seqlock(&cdirs->seq);
- list_add_tail(&lb->head, &cdirs->lease_breaks);
- write_sequnlock(&cdirs->seq);
-
- pr_err("received leasebreak: %*ph\n", 16, lease_key);
-}
-
-static void ack_lease_break(struct cached_lease_break *lb)
-{
- if (!lb)
- return;
-
- atomic_inc(&lb->acks);
-}
-
-static bool drop_lease_break(struct cached_lease_break *lb, bool teardown)
-{
- if (!lb)
- return true;
-
- if (teardown || (atomic_read(&lb->acks) > atomic_read(&lb->recvs)) ||
- time_is_before_jiffies(lb->time + dir_cache_timeout * HZ)) {
- list_del(&lb->head);
- kfree(lb->lease_key);
- kfree(lb);
- return true;
- }
-
- return false;
-}
-
-static void cleanup_lease_breaks(struct cached_dirs *cdirs, bool teardown)
-{
- struct cached_lease_break *lb, *q;
-
- write_seqlock(&cdirs->seq);
- list_for_each_entry_safe(lb, q, &cdirs->lease_breaks, head)
- drop_lease_break(lb, teardown);
- write_sequnlock(&cdirs->seq);
-}
-
static bool cdir_match_key(struct cached_dir *cdir, const void *key, int mode);
-static void __dump_cdir(struct cached_dir *cdir, const char *caller)
-{
-//#if 0
-// pr_err("%s: cdir=%p, path='%s'\n", caller, cdir, cdir->path);
-//#else
-// pr_err("%s: cdir=%p:\n", caller, cdir);
-// pr_err("\t\tpath=%s\n", cdir->path);
-// pr_err("\t\tdentry=%pd\n", cdir->dentry);
-// if (cdir->lease_key)
-// pr_err("\t\tleasekey=%*ph\n", 16, cdir->lease_key);
-// else
-// pr_err("\t\tinvalid!\n");
-// pr_err("\t\texpired=%s\n", str_yes_no(cdir_is_expired(cdir)));
-// pr_err("\t\tuses=%u\n", kref_read(&cdir->ref));
-// pr_err("\t\tpfid=0x%llx\n", cdir->pfid);
-// pr_err("\t\tvfid=0x%llx\n", cdir->vfid);
-//#endif
-// pr_err("\t\t--------\n");
-}
-
-static void dump_cdir(struct cached_dir *cdir, const char *caller)
-{
- struct cached_dir copy = {};
- int seq = 0;
-
- if (!cdir)
- return;
-
- do {
- read_seqbegin_or_lock(&cdir->seq, &seq);
-
- copy = *cdir;
- __dump_cdir(cdir, caller);
- } while (need_seqretry(&cdir->seq, seq));
-
- done_seqretry(&cdir->seq, seq);
-}
-
/*
* Utils
*/
@@ -281,25 +155,6 @@ static inline bool cdir_in_use(struct cached_dir *cdir, void __maybe_unused *arg
return (kref_read(&cdir->ref) > 1);
}
-static bool cdir_got_lease_break(struct cached_dir *cdir, void *arg)
-{
- struct cached_lease_break *lb;
- struct cached_dirs *cdirs = (struct cached_dirs *)arg;
-
- if (!cdir || !cdirs)
- return true;
-
- if (!cdir_has_lease(cdir, NULL))
- return true;
-
- lb = check_lease_break(cdirs, cdir->lease_key);
- if (!lb)
- return false;
-
- ack_lease_break(lb);
- return true;
-}
-
static inline bool cdir_check(struct cached_dir *cdir, void *arg,
bool (*fn)(struct cached_dir *cdir, void *arg))
{
@@ -323,7 +178,6 @@ static inline bool cdir_check(struct cached_dir *cdir, void *arg,
#define cdir_check_lease(cdir) cdir_check(cdir, NULL, cdir_has_lease)
#define cdir_check_valid(cdir) cdir_check(cdir, NULL, cdir_is_valid)
#define cdir_check_use(cdir) cdir_check(cdir, NULL, cdir_in_use)
-#define cdir_check_lease_break(cdir, arg) cdir_check(cdir, arg, cdir_got_lease_break)
/*
* Mark a cdir as invalid (i.e. no lease anymore).
@@ -435,11 +289,20 @@ static int cdir_match_check(struct cached_dir *cdir, const void *key, int mode)
read_seqbegin_or_lock(&cdir->seq, &seq);
- if (cdir_match_key(cdir, key, mode))
- ret = 0;
+ if (cdir_match_key(cdir, key, mode)) {
+ if (kref_get_unless_zero(&cdir->ref)) {
+ if (cdir_is_valid(cdir, NULL))
+ ret = 0;
+ else
+ ret = -EINVAL;
+ }
+ }
- if (need_seqretry(&cdir->seq, seq))
+ if (need_seqretry(&cdir->seq, seq)) {
+ if (!ret)
+ kref_put(&cdir->ref, cdir_invalidate_put);
ret = -ECHILD;
+ }
done_seqretry(&cdir->seq, seq);
@@ -476,20 +339,10 @@ static struct cached_dir *cdir_find_entry(struct cached_dirs *cdirs, const void
}
} while (need_seqretry(&cdirs->seq, seq) && ret != -ECHILD);
-#if 0
- if (ret == -ECHILD)
- goto out;
-
- ret = 0;
-#endif
done_seqretry(&cdirs->seq, seq);
- if (!ret) {
- if (cdir_check_valid(cdir))
- return cdir;
-
- ret = -EINVAL;
- }
+ if (!ret)
+ return cdir;
return ERR_PTR(ret);
}
@@ -569,8 +422,13 @@ static void cdir_find_drop(struct cached_dirs *cdirs, const void *key, int mode)
if (IS_ERR(cdir))
return;
- if (cdir_check_lease_break(cdir, cdirs))
- return;
+#if 0
+ if (cdir_is_open(cdir, NULL)) {
+ (void) SMB2_close(get_xid(), cdirs->tcon, cdir->pfid, cdir->vfid);
+ cdir->pfid = COMPOUND_FID;
+ cdir->vfid = COMPOUND_FID;
+ }
+#endif
/*
* Put our ref.
@@ -593,22 +451,6 @@ static void cdir_find_drop(struct cached_dirs *cdirs, const void *key, int mode)
}
}
-#if 0
- //pr_err("%s: dropping now cdir=%p\n", __func__, cdir);
- write_seqlock(&cdir->seq);
- // leave it on the list??
- //cdir_del_entry(cdir, &copy);
- copy.dentry = READ_ONCE(cdir->dentry);
- cdir_free(cdir);
- write_sequnlock(&cdir->seq);
-
- // leave it on the list?
- //kfree(cdir);
-
- if (copy.dentry)
- dput(copy.dentry);
-#endif
-
mod_delayed_work(cfid_put_wq, &cdirs->cleanup_work, 0);
}
@@ -621,23 +463,13 @@ static bool cdir_cleanup_sync(struct cached_dirs *cdirs, bool teardown)
if (WARN_ON(!copy))
return list_empty(&cdirs->list);
- cleanup_lease_breaks(cdirs, teardown);
-
write_seqlock(&cdirs->seq);
list_for_each_entry_safe(cdir, q, &cdirs->list, head) {
- if (!teardown && cdir_check_valid(cdir)) {
- dump_cdir(cdir, "skipping valid cleanup");
+ if (!teardown && cdir_check_valid(cdir))
continue;
- }
write_seqlock(&cdir->seq);
if (cdir_invalidate_unlocked(cdir) || teardown) {
- if (teardown)
- __dump_cdir(cdir, "tearing down");
- else
- __dump_cdir(cdir, "cleaning up");
-
- //cdir_del_entry(cdir, &copy[i++]);
list_del(&cdir->head);
copy[i].dentry = READ_ONCE(cdir->dentry);
copy[i].pfid = READ_ONCE(cdir->pfid);
@@ -655,19 +487,14 @@ static bool cdir_cleanup_sync(struct cached_dirs *cdirs, bool teardown)
continue;
}
write_sequnlock(&cdir->seq);
-
- dump_cdir(cdir, "skipping invalid cleanup");
}
write_sequnlock(&cdirs->seq);
while (--i >= 0) {
- if (copy[i].dentry) {
- //pr_err("%s: cleaning up[%d]: put dentry='%pd'\n", __func__, i, copy[i].dentry);
+ if (copy[i].dentry)
dput(copy[i].dentry);
- }
if (cdir_is_open(&copy[i], NULL)) {
- //pr_err("%s: cleaning up[%d]: remote close=0x%llx\n", __func__, i, copy[i].pfid);
SMB2_close(get_xid(), cdirs->tcon, copy[i].pfid, copy[i].vfid);
atomic_dec(&cdirs->tcon->num_remote_opens);
}
@@ -870,20 +697,8 @@ struct cached_dir *cached_dir_get_path(struct cached_dirs *cdirs, const char *pa
{
struct cached_dir *cdir = cdir_find_entry(cdirs, cdir_root_path(path), CDIR_FIND_PATH);
- if (IS_ERR(cdir))
- return NULL;
-
- if (cdir_check_lease_break(cdir, cdirs)) {
- cdir_invalidate(cdir);
- return NULL;
- }
-
- if (kref_get_unless_zero(&cdir->ref)) {
- if (cdir_check_valid(cdir))
- return cdir;
-
- cdir_put(cdir);
- }
+ if (!IS_ERR(cdir))
+ return cdir;
return NULL;
}
@@ -901,8 +716,11 @@ struct cached_dir *cached_dir_open(struct cached_dirs *cdirs, const char *path,
/* Try to find a cached entry by @path. */
cdir = cached_dir_get_path(cdirs, cdir_root_path(path));
- if (cdir)
- return cdir;
+ if (cdir) {
+ if (!IS_ERR(cdir))
+ return cdir;
+ cdir = NULL;
+ }
/* Check if we can actually cache a new entry. */
if (atomic_read(&cdirs->count) >= 16) {
@@ -922,28 +740,11 @@ struct cached_dir *cached_dir_open(struct cached_dirs *cdirs, const char *path,
*/
if (IS_ERR(cdir)) {
cifs_dbg(VFS, "%s: remote open failed, err=%ld\n", __func__, PTR_ERR(cdir));
- return NULL;
- }
-
- /*
- * Cache a new entry only if we're sure there are no duplicates.
- *
- * We want to know if a concurrent thread successfully cached the same path as us, so
- * check if there was a lease break for us.
- */
- if (cdir_check_lease_break(cdir, cdirs)) {
- dput(cdir->dentry);
- cdir_free(cdir);
- kfree(cdir);
- cdir = NULL;
+ return ERR_CAST(cdir);
}
- /*
- * Regardless if there was a leasebreak for our @path, we still check (preventively) if
- * that same path wasn't added before us.
- */
check = cached_dir_get_path(cdirs, cdir_root_path(path));
- if (check && !IS_ERR(check)) {
+ if (check) {
pr_err("%s: race in open path=%s\n", __func__, cdir_root_path(path));
// cdir != NULL means no leasebreak for this path, but also means some other bug?
@@ -953,7 +754,9 @@ struct cached_dir *cached_dir_open(struct cached_dirs *cdirs, const char *path,
kfree(cdir);
}
- return check;
+ if (!IS_ERR(check))
+ return check;
+ check = NULL;
}
// got a leasebreak but nobody cached it yet? should retry...
@@ -976,13 +779,6 @@ void cached_dir_close(struct cached_dirs *cdirs, struct cached_dir *cdir)
if (!cdir)
return;
- //dump_cdir(cdir, "closing");
-
- if (!cdir_check_valid(cdir)) {
- pr_err("%s: closing cdir no longer valid, should reopen? path='%s', dentry='%pd', leasekey=%*ph\n",
- __func__, cdir->path, cdir->dentry, 16, cdir->lease_key);
- }
-
if (cdir_put(cdir)) {
mod_delayed_work(cfid_put_wq, &cdirs->cleanup_work, 0);
return;
@@ -994,6 +790,7 @@ void cached_dir_close(struct cached_dirs *cdirs, struct cached_dir *cdir)
void cached_dir_drop(struct cached_dirs *cdirs, const char *path)
{
pr_err("%s: cached dir drop (path=%s)\n", __func__, cdir_root_path(path));
+
cdir_find_drop(cdirs, cdir_root_path(path), CDIR_FIND_PATH);
}
@@ -1002,7 +799,6 @@ void cached_dir_lease_break(struct cached_dirs *cdirs, u8 *lease_key)
{
pr_err("%s: cached dir lease break (key=%*ph)\n", __func__, 16, lease_key);
- recv_lease_break(cdirs, lease_key);
cdir_find_drop(cdirs, lease_key, CDIR_FIND_LEASEKEY);
}
@@ -1019,6 +815,9 @@ bool cached_dir_check_expired_path(struct cached_dirs *cdirs, const char *path)
/* cached_dir_get_path() already checks for valid + non-expired, nothing else to do here */
cdir = cached_dir_get_path(cdirs, path);
if (cdir) {
+ if (IS_ERR(cdir))
+ return true;
+
if (cdir_put(cdir))
return true;
return false;
@@ -1040,26 +839,25 @@ bool cached_dir_check_expired_dentry(struct cached_dirs *cdirs, struct dentry *d
cdir = cdir_find_entry(cdirs, dentry, CDIR_FIND_DENTRY);
pr_err("%s: cdir=%p (err=%ld) for dentry='%pd', expired=%s\n", cdirs->tcon->tree_name, cdir, !cdir ? 0 : (IS_ERR(cdir) ? PTR_ERR(cdir) : 0), dentry,
(cdir && !IS_ERR(cdir)) ? str_yes_no(cdir_check_expired(cdir, (void *)time)) : "yes");
- if (!cdir || IS_ERR(cdir))
+
+ if (IS_ERR(cdir))
return true;
- if (cdir) {
- if (kref_get_unless_zero(&cdir->ref)) {
- bool older = cdir_check_expired(cdir, (void *)time);
-
- //pr_err("%s: cdir=%p, dentry=%pd, older=%s (cdir=%u, time=%u)\n", __func__,
- // cdir, dentry, str_yes_no(older), jiffies_to_msecs(jiffies - cdir->time), jiffies_to_msecs(jiffies - time));
- if (cdir_put(cdir)) {
- pr_err("%s: (last ref) cdir=%p, dentry=%pd, older=%s (cdir=%u, time=%u)\n", __func__,
- cdir, dentry, str_yes_no(older), jiffies_to_msecs(jiffies - cdir->time), jiffies_to_msecs(jiffies - time));
- return true;
- }
-
- if (older)
- pr_err("%s: (ref) cdir=%p, dentry=%pd, older=true (cdir=%u, time=%u)\n", __func__,
- cdir, dentry, jiffies_to_msecs(jiffies - cdir->time), jiffies_to_msecs(jiffies - time));
- return older;
+ if (kref_get_unless_zero(&cdir->ref)) {
+ bool older = cdir_check_expired(cdir, (void *)time);
+
+ //pr_err("%s: cdir=%p, dentry=%pd, older=%s (cdir=%u, time=%u)\n", __func__,
+ // cdir, dentry, str_yes_no(older), jiffies_to_msecs(jiffies - cdir->time), jiffies_to_msecs(jiffies - time));
+ if (cdir_put(cdir)) {
+ pr_err("%s: (last ref) cdir=%p, dentry=%pd, older=%s (cdir=%u, time=%u)\n", __func__,
+ cdir, dentry, str_yes_no(older), jiffies_to_msecs(jiffies - cdir->time), jiffies_to_msecs(jiffies - time));
+ return true;
}
+
+ if (older)
+ pr_err("%s: (ref) cdir=%p, dentry=%pd, older=true (cdir=%u, time=%u)\n", __func__,
+ cdir, dentry, jiffies_to_msecs(jiffies - cdir->time), jiffies_to_msecs(jiffies - time));
+ return older;
}
pr_err("%s: no cdir for dentry=%pd (%p, positive=%s), time=%lu\n", __func__, dentry, dentry, str_yes_no(d_really_is_positive(dentry)), time);
@@ -1083,7 +881,6 @@ void cached_dir_init(struct cifs_tcon *tcon)
tcon->tc_count++;
INIT_LIST_HEAD(&tcon->cdirs->list);
- INIT_LIST_HEAD(&tcon->cdirs->lease_breaks);
INIT_DELAYED_WORK(&tcon->cdirs->cleanup_work, cdir_cleanup);
seqlock_init(&tcon->cdirs->seq);
atomic_set(&tcon->cdirs->count, 0);
@@ -1160,7 +957,6 @@ void cached_dir_destroy(struct cifs_sb_info *cifs_sb)
void cached_dir_cleanup(struct cifs_tcon *tcon, bool free)
{
- struct cached_lease_break *lb, *q;
struct cached_dirs *cdirs;
struct cached_dir *cdir;
@@ -1184,12 +980,6 @@ void cached_dir_cleanup(struct cifs_tcon *tcon, bool free)
WRITE_ONCE(cdir->vfid, COMPOUND_FID);
write_sequnlock(&cdir->seq);
}
-
- list_for_each_entry_safe(lb, q, &cdirs->lease_breaks, head) {
- list_del(&lb->head);
- kfree(lb->lease_key);
- kfree(lb);
- }
write_sequnlock(&cdirs->seq);
(void) cdir_cleanup_sync(cdirs, true);
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index 8753df164171..4e5c9b86fc49 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -48,17 +48,8 @@ struct cached_dir {
struct smb2_file_all_info *info;
};
-struct cached_lease_break {
- struct list_head head;
- u8 *lease_key;
- atomic_t recvs;
- atomic_t acks;
- unsigned long time;
-};
-
struct cached_dirs {
struct list_head list;
- struct list_head lease_breaks;
seqlock_t seq;
/* tcon backreference */
@@ -71,11 +62,6 @@ struct cached_dirs {
struct cached_dir *cached_dir_get_path(struct cached_dirs *cdirs, const char *path);
struct cached_dir *cached_dir_open(struct cached_dirs *cdirs, const char *path,
struct cifs_sb_info *cifs_sb);
-#if 0
-int cached_dir_add(struct cached_dirs *cdirs, const char *path, struct dentry *dentry,
- struct cifs_sb_info *cifs_sb, struct cifs_fid *fid,
- struct smb2_file_all_info *info);
-#endif
void cached_dir_close(struct cached_dirs *cdirs, struct cached_dir *cdir);
void cached_dir_drop(struct cached_dirs *cdirs, const char *path);
void cached_dir_lease_break(struct cached_dirs *cdirs, u8 *lease_key);
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
index 1311caa93fee..07aa3cb0c4a6 100644
--- a/fs/smb/client/readdir.c
+++ b/fs/smb/client/readdir.c
@@ -963,6 +963,10 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
if (!cdir) {
pr_err("%s: (1) cdir not found for path='%s' (unexpected because remote open)\n", __func__, full_path);
goto cache_not_found;
+ } else if (IS_ERR(cdir)) {
+ rc = PTR_ERR(cdir);
+ cdir = NULL;
+ goto rddir2_exit;
}
if (!cached_dir_emit_entries(cdir, ctx, file))
@@ -1017,6 +1021,10 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
if (!cdir) {
pr_err("%s: (2) cdir not found for path='%s' (unexpected because remote open)\n", __func__, full_path);
goto rddir2_exit;
+ } else if (IS_ERR(cdir)) {
+ rc = PTR_ERR(cdir);
+ cdir = NULL;
+ goto rddir2_exit;
}
if (!current_entry) {
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 8ab20e56c97e..1b5602cadfcf 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -938,6 +938,8 @@ int smb2_query_path_info(const unsigned int xid,
if (!cdir) {
pr_err("%s: cache dir not found for path='\'\n", __func__);
goto no_cache;
+ } else if (IS_ERR(cdir)) {
+ return PTR_ERR(cdir);
}
/* If it is a root and its handle is cached then use it */
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 5a336ebfa533..094beadb89e3 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -852,6 +852,9 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
cdir = cached_dir_open(tcon->cdirs, "", cifs_sb);
if (cdir) {
+ if (IS_ERR(cdir))
+ return;
+
fid.persistent_fid = cdir->pfid;
fid.volatile_fid = cdir->vfid;
memcpy(fid.lease_key, cdir->lease_key, SMB2_LEASE_KEY_SIZE);
@@ -930,22 +933,28 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_open_parms oparms;
struct kvec err_iov = {};
struct cifs_fid fid;
+ struct cached_dir *cdir;
bool islink;
int rc, rc2;
+#if 0
if (!cached_dir_check_expired_path(tcon->cdirs, full_path))
return 0;
+#endif
-#if 0 // lookup + open (leasebreak?)
cdir = cached_dir_open(tcon->cdirs, full_path, cifs_sb);
if (cdir) {
- bool expired = cached_dir_is_expired(cdir);
+ bool expired;
+
+ if (IS_ERR(cdir))
+ return PTR_ERR(cdir);
+
+ expired = cached_dir_is_expired(cdir);
cached_dir_close(tcon->cdirs, cdir);
if (!expired)
return 0;
}
-#endif
pr_err("%s: cached dir for path='%s' not found or expired, remote opening...\n",
__func__, *full_path ? full_path : "\\");
@@ -2716,10 +2725,15 @@ replay_again:
*/
if (!strcmp(path, "")) {
cdir = cached_dir_open(tcon->cdirs, path, cifs_sb);
- if (!cdir)
+ if (!cdir) {
pr_err("%s: cache dir not found for path='\\' (unexpected because of remote open)\n", __func__);
- else
+ } else if (IS_ERR(cdir)) {
+ rc = PTR_ERR(cdir);
+ kfree(vars);
+ goto out_free_path;
+ } else {
using_cdir = true;
+ }
}
rqst[0].rq_iov = vars->open_iov;
@@ -2812,7 +2826,7 @@ replay_again:
SMB2_close_free(&rqst[2]);
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
- cached_dir_close(tcon->cdirs, cdir);
+ cached_dir_close(tcon->cdirs, cdir);
if (!cdir && using_cdir) {
pr_err("%s: was using cdir, it's gone now, retrying...\n", __func__);
rc = -EAGAIN;