Skip to content

Commit 11c8b3f

Browse files
Paulo AlcantaraSteve French
authored andcommitted
cifs: don't take exclusive lock for updating target hints
Avoid contention while updating dfs target hints. This should be perfectly fine to update them under shared locks. Signed-off-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 48d240b commit 11c8b3f

File tree

1 file changed

+20
-27
lines changed

1 file changed

+20
-27
lines changed

fs/cifs/dfs_cache.c

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ static int dfscache_proc_show(struct seq_file *m, void *v)
269269
list_for_each_entry(t, &ce->tlist, list) {
270270
seq_printf(m, " %s%s\n",
271271
t->name,
272-
ce->tgthint == t ? " (target hint)" : "");
272+
READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
273273
}
274274
}
275275
}
@@ -321,7 +321,7 @@ static inline void dump_tgts(const struct cache_entry *ce)
321321
cifs_dbg(FYI, "target list:\n");
322322
list_for_each_entry(t, &ce->tlist, list) {
323323
cifs_dbg(FYI, " %s%s\n", t->name,
324-
ce->tgthint == t ? " (target hint)" : "");
324+
READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
325325
}
326326
}
327327

@@ -427,7 +427,7 @@ static int cache_entry_hash(const void *data, int size, unsigned int *hash)
427427
/* Return target hint of a DFS cache entry */
428428
static inline char *get_tgt_name(const struct cache_entry *ce)
429429
{
430-
struct cache_dfs_tgt *t = ce->tgthint;
430+
struct cache_dfs_tgt *t = READ_ONCE(ce->tgthint);
431431

432432
return t ? t->name : ERR_PTR(-ENOENT);
433433
}
@@ -470,6 +470,7 @@ static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed)
470470
static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
471471
struct cache_entry *ce, const char *tgthint)
472472
{
473+
struct cache_dfs_tgt *target;
473474
int i;
474475

475476
ce->ttl = max_t(int, refs[0].ttl, CACHE_MIN_TTL);
@@ -496,8 +497,9 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
496497
ce->numtgts++;
497498
}
498499

499-
ce->tgthint = list_first_entry_or_null(&ce->tlist,
500-
struct cache_dfs_tgt, list);
500+
target = list_first_entry_or_null(&ce->tlist, struct cache_dfs_tgt,
501+
list);
502+
WRITE_ONCE(ce->tgthint, target);
501503

502504
return 0;
503505
}
@@ -712,14 +714,15 @@ void dfs_cache_destroy(void)
712714
static int update_cache_entry_locked(struct cache_entry *ce, const struct dfs_info3_param *refs,
713715
int numrefs)
714716
{
717+
struct cache_dfs_tgt *target;
718+
char *th = NULL;
715719
int rc;
716-
char *s, *th = NULL;
717720

718721
WARN_ON(!rwsem_is_locked(&htable_rw_lock));
719722

720-
if (ce->tgthint) {
721-
s = ce->tgthint->name;
722-
th = kstrdup(s, GFP_ATOMIC);
723+
target = READ_ONCE(ce->tgthint);
724+
if (target) {
725+
th = kstrdup(target->name, GFP_ATOMIC);
723726
if (!th)
724727
return -ENOMEM;
725728
}
@@ -896,7 +899,7 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
896899
}
897900
it->it_path_consumed = t->path_consumed;
898901

899-
if (ce->tgthint == t)
902+
if (READ_ONCE(ce->tgthint) == t)
900903
list_add(&it->it_list, head);
901904
else
902905
list_add_tail(&it->it_list, head);
@@ -1052,31 +1055,22 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
10521055
goto out_free_path;
10531056
}
10541057

1055-
up_read(&htable_rw_lock);
1056-
down_write(&htable_rw_lock);
1057-
1058-
ce = lookup_cache_entry(npath);
1059-
if (IS_ERR(ce)) {
1060-
rc = PTR_ERR(ce);
1061-
goto out_unlock;
1062-
}
1063-
1064-
t = ce->tgthint;
1058+
t = READ_ONCE(ce->tgthint);
10651059

10661060
if (likely(!strcasecmp(it->it_name, t->name)))
10671061
goto out_unlock;
10681062

10691063
list_for_each_entry(t, &ce->tlist, list) {
10701064
if (!strcasecmp(t->name, it->it_name)) {
1071-
ce->tgthint = t;
1065+
WRITE_ONCE(ce->tgthint, t);
10721066
cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
10731067
it->it_name);
10741068
break;
10751069
}
10761070
}
10771071

10781072
out_unlock:
1079-
up_write(&htable_rw_lock);
1073+
up_read(&htable_rw_lock);
10801074
out_free_path:
10811075
kfree(npath);
10821076
return rc;
@@ -1106,29 +1100,28 @@ void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt
11061100

11071101
cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
11081102

1109-
if (!down_write_trylock(&htable_rw_lock))
1110-
return;
1103+
down_read(&htable_rw_lock);
11111104

11121105
ce = lookup_cache_entry(path);
11131106
if (IS_ERR(ce))
11141107
goto out_unlock;
11151108

1116-
t = ce->tgthint;
1109+
t = READ_ONCE(ce->tgthint);
11171110

11181111
if (unlikely(!strcasecmp(it->it_name, t->name)))
11191112
goto out_unlock;
11201113

11211114
list_for_each_entry(t, &ce->tlist, list) {
11221115
if (!strcasecmp(t->name, it->it_name)) {
1123-
ce->tgthint = t;
1116+
WRITE_ONCE(ce->tgthint, t);
11241117
cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
11251118
it->it_name);
11261119
break;
11271120
}
11281121
}
11291122

11301123
out_unlock:
1131-
up_write(&htable_rw_lock);
1124+
up_read(&htable_rw_lock);
11321125
}
11331126

11341127
/**

0 commit comments

Comments
 (0)