hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/autofs/expire.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
34 * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
45 * Copyright 2001-2006 Ian Kent <raven@themaw.net>
5
- *
6
- * This file is part of the Linux kernel and is made available under
7
- * the terms of the GNU General Public License, version 2, or at your
8
- * option, any later version, incorporated herein by reference.
96 */
107
118 #include "autofs_i.h"
....@@ -73,6 +70,27 @@
7370 return status;
7471 }
7572
73
+/* p->d_lock held */
74
+static struct dentry *positive_after(struct dentry *p, struct dentry *child)
75
+{
76
+ if (child)
77
+ child = list_next_entry(child, d_child);
78
+ else
79
+ child = list_first_entry(&p->d_subdirs, struct dentry, d_child);
80
+
81
+ list_for_each_entry_from(child, &p->d_subdirs, d_child) {
82
+ spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
83
+ if (simple_positive(child)) {
84
+ dget_dlock(child);
85
+ spin_unlock(&child->d_lock);
86
+ return child;
87
+ }
88
+ spin_unlock(&child->d_lock);
89
+ }
90
+
91
+ return NULL;
92
+}
93
+
7694 /*
7795 * Calculate and dget next entry in the subdirs list under root.
7896 */
....@@ -80,43 +98,14 @@
8098 struct dentry *root)
8199 {
82100 struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
83
- struct list_head *next;
84101 struct dentry *q;
85102
86103 spin_lock(&sbi->lookup_lock);
87104 spin_lock(&root->d_lock);
88
-
89
- if (prev)
90
- next = prev->d_child.next;
91
- else {
92
- prev = dget_dlock(root);
93
- next = prev->d_subdirs.next;
94
- }
95
-
96
-cont:
97
- if (next == &root->d_subdirs) {
98
- spin_unlock(&root->d_lock);
99
- spin_unlock(&sbi->lookup_lock);
100
- dput(prev);
101
- return NULL;
102
- }
103
-
104
- q = list_entry(next, struct dentry, d_child);
105
-
106
- spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
107
- /* Already gone or negative dentry (under construction) - try next */
108
- if (!d_count(q) || !simple_positive(q)) {
109
- spin_unlock(&q->d_lock);
110
- next = q->d_child.next;
111
- goto cont;
112
- }
113
- dget_dlock(q);
114
- spin_unlock(&q->d_lock);
105
+ q = positive_after(root, prev);
115106 spin_unlock(&root->d_lock);
116107 spin_unlock(&sbi->lookup_lock);
117
-
118108 dput(prev);
119
-
120109 return q;
121110 }
122111
....@@ -127,59 +116,28 @@
127116 struct dentry *root)
128117 {
129118 struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
130
- struct list_head *next;
131
- struct dentry *p, *ret;
119
+ struct dentry *p = prev, *ret = NULL, *d = NULL;
132120
133121 if (prev == NULL)
134122 return dget(root);
135123
136124 spin_lock(&sbi->lookup_lock);
137
-relock:
138
- p = prev;
139125 spin_lock(&p->d_lock);
140
-again:
141
- next = p->d_subdirs.next;
142
- if (next == &p->d_subdirs) {
143
- while (1) {
144
- struct dentry *parent;
126
+ while (1) {
127
+ struct dentry *parent;
145128
146
- if (p == root) {
147
- spin_unlock(&p->d_lock);
148
- spin_unlock(&sbi->lookup_lock);
149
- dput(prev);
150
- return NULL;
151
- }
152
-
153
- parent = p->d_parent;
154
- if (!spin_trylock(&parent->d_lock)) {
155
- spin_unlock(&p->d_lock);
156
- cpu_relax();
157
- goto relock;
158
- }
159
- spin_unlock(&p->d_lock);
160
- next = p->d_child.next;
161
- p = parent;
162
- if (next != &parent->d_subdirs)
163
- break;
164
- }
165
- }
166
- ret = list_entry(next, struct dentry, d_child);
167
-
168
- spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
169
- /* Negative dentry - try next */
170
- if (!simple_positive(ret)) {
129
+ ret = positive_after(p, d);
130
+ if (ret || p == root)
131
+ break;
132
+ parent = p->d_parent;
171133 spin_unlock(&p->d_lock);
172
- lock_set_subclass(&ret->d_lock.dep_map, 0, _RET_IP_);
173
- p = ret;
174
- goto again;
134
+ spin_lock(&parent->d_lock);
135
+ d = p;
136
+ p = parent;
175137 }
176
- dget_dlock(ret);
177
- spin_unlock(&ret->d_lock);
178138 spin_unlock(&p->d_lock);
179139 spin_unlock(&sbi->lookup_lock);
180
-
181140 dput(prev);
182
-
183141 return ret;
184142 }
185143
....@@ -253,7 +211,7 @@
253211 }
254212 } else {
255213 struct autofs_info *ino = autofs_dentry_ino(p);
256
- unsigned int ino_count = atomic_read(&ino->count);
214
+ unsigned int ino_count = READ_ONCE(ino->count);
257215
258216 /* allow for dget above and top is already dgot */
259217 if (p == top)
....@@ -421,7 +379,7 @@
421379 /* Not a forced expire? */
422380 if (!(how & AUTOFS_EXP_FORCED)) {
423381 /* ref-walk currently on this dentry? */
424
- ino_count = atomic_read(&ino->count) + 1;
382
+ ino_count = READ_ONCE(ino->count) + 1;
425383 if (d_count(dentry) > ino_count)
426384 return NULL;
427385 }
....@@ -438,7 +396,7 @@
438396 /* Not a forced expire? */
439397 if (!(how & AUTOFS_EXP_FORCED)) {
440398 /* ref-walk currently on this dentry? */
441
- ino_count = atomic_read(&ino->count) + 1;
399
+ ino_count = READ_ONCE(ino->count) + 1;
442400 if (d_count(dentry) > ino_count)
443401 return NULL;
444402 }