Skip to content

Commit bcd7351

Browse files
committed
Merge tag 'fscache-20130702' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull FS-Cache updates from David Howells: "This contains a number of fixes for various FS-Cache issues plus some cleanups. The commits are, in order: 1) Provide a system wait_on_atomic_t() and wake_up_atomic_t() sharing the bit-wait table (enhancement for #8). 2) Don't put spin_lock() in a while-condition as spin_lock() may have a do {} while(0) wrapper (cleanup). 3) Symbolically name i_mutex lock classes rather than using numbers in CacheFiles (cleanup). 4) Don't sleep in page release if __GFP_FS is not set (deadlock vs ext4). 5) Uninline fscache_object_init() (cleanup for #7). 6) Wrap checks on object state (cleanup for #7). 7) Simplify the object state machine by separating work states from wait states. 8) Simplify cookie retention by objects (NULL pointer deref fix). 9) Remove unused list_to_page() macro (cleanup). 10) Make the remaining-pages counter in the retrieval op atomic (assertion failure fix). 11) Don't use spin_is_locked() in assertions (assertion failure fix)" * tag 'fscache-20130702' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: FS-Cache: Don't use spin_is_locked() in assertions FS-Cache: The retrieval remaining-pages counter needs to be atomic_t cachefiles: remove unused macro list_to_page() FS-Cache: Simplify cookie retention for fscache_objects, fixing oops FS-Cache: Fix object state machine to have separate work and wait states FS-Cache: Wrap checks on object state FS-Cache: Uninline fscache_object_init() FS-Cache: Don't sleep in page release if __GFP_FS is not set CacheFiles: name i_mutex lock class explicitly fs/fscache: remove spin_lock() from the condition in while() Add wait_on_atomic_t() and wake_up_atomic_t()
2 parents 6072a93 + dcfae32 commit bcd7351

File tree

16 files changed

+956
-822
lines changed

16 files changed

+956
-822
lines changed

fs/cachefiles/interface.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include <linux/mount.h>
1414
#include "internal.h"
1515

16-
#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
17-
1816
struct cachefiles_lookup_data {
1917
struct cachefiles_xattr *auxdata; /* auxiliary data */
2018
char *key; /* key path */
@@ -212,20 +210,29 @@ static void cachefiles_update_object(struct fscache_object *_object)
212210
object = container_of(_object, struct cachefiles_object, fscache);
213211
cache = container_of(object->fscache.cache, struct cachefiles_cache,
214212
cache);
213+
214+
if (!fscache_use_cookie(_object)) {
215+
_leave(" [relinq]");
216+
return;
217+
}
218+
215219
cookie = object->fscache.cookie;
216220

217221
if (!cookie->def->get_aux) {
222+
fscache_unuse_cookie(_object);
218223
_leave(" [no aux]");
219224
return;
220225
}
221226

222227
auxdata = kmalloc(2 + 512 + 3, cachefiles_gfp);
223228
if (!auxdata) {
229+
fscache_unuse_cookie(_object);
224230
_leave(" [nomem]");
225231
return;
226232
}
227233

228234
auxlen = cookie->def->get_aux(cookie->netfs_data, auxdata->data, 511);
235+
fscache_unuse_cookie(_object);
229236
ASSERTCMP(auxlen, <, 511);
230237

231238
auxdata->len = auxlen + 1;
@@ -263,7 +270,7 @@ static void cachefiles_drop_object(struct fscache_object *_object)
263270
#endif
264271

265272
/* delete retired objects */
266-
if (object->fscache.state == FSCACHE_OBJECT_RECYCLING &&
273+
if (test_bit(FSCACHE_COOKIE_RETIRED, &object->fscache.cookie->flags) &&
267274
_object != cache->cache.fsdef
268275
) {
269276
_debug("- retire object OBJ%x", object->fscache.debug_id);

fs/cachefiles/namei.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
3838
printk(KERN_ERR "%sobject: OBJ%x\n",
3939
prefix, object->fscache.debug_id);
4040
printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
41-
prefix, fscache_object_states[object->fscache.state],
41+
prefix, object->fscache.state->name,
4242
object->fscache.flags, work_busy(&object->fscache.work),
4343
object->fscache.events, object->fscache.event_mask);
4444
printk(KERN_ERR "%sops=%u inp=%u exc=%u\n",
@@ -127,10 +127,10 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
127127
found_dentry:
128128
kdebug("preemptive burial: OBJ%x [%s] %p",
129129
object->fscache.debug_id,
130-
fscache_object_states[object->fscache.state],
130+
object->fscache.state->name,
131131
dentry);
132132

133-
if (object->fscache.state < FSCACHE_OBJECT_DYING) {
133+
if (fscache_object_is_live(&object->fscache)) {
134134
printk(KERN_ERR "\n");
135135
printk(KERN_ERR "CacheFiles: Error:"
136136
" Can't preemptively bury live object\n");
@@ -192,7 +192,7 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
192192
/* an old object from a previous incarnation is hogging the slot - we
193193
* need to wait for it to be destroyed */
194194
wait_for_old_object:
195-
if (xobject->fscache.state < FSCACHE_OBJECT_DYING) {
195+
if (fscache_object_is_live(&object->fscache)) {
196196
printk(KERN_ERR "\n");
197197
printk(KERN_ERR "CacheFiles: Error:"
198198
" Unexpected object collision\n");
@@ -836,7 +836,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
836836
// dir->d_name.len, dir->d_name.len, dir->d_name.name, filename);
837837

838838
/* look up the victim */
839-
mutex_lock_nested(&dir->d_inode->i_mutex, 1);
839+
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
840840

841841
start = jiffies;
842842
victim = lookup_one_len(filename, dir, strlen(filename));

fs/cachefiles/xattr.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,12 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object,
109109
struct dentry *dentry = object->dentry;
110110
int ret;
111111

112-
ASSERT(object->fscache.cookie);
113112
ASSERT(dentry);
114113

115114
_enter("%p,#%d", object, auxdata->len);
116115

117116
/* attempt to install the cache metadata directly */
118-
_debug("SET %s #%u", object->fscache.cookie->def->name, auxdata->len);
117+
_debug("SET #%u", auxdata->len);
119118

120119
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
121120
&auxdata->type, auxdata->len,
@@ -138,13 +137,12 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
138137
struct dentry *dentry = object->dentry;
139138
int ret;
140139

141-
ASSERT(object->fscache.cookie);
142140
ASSERT(dentry);
143141

144142
_enter("%p,#%d", object, auxdata->len);
145143

146144
/* attempt to install the cache metadata directly */
147-
_debug("SET %s #%u", object->fscache.cookie->def->name, auxdata->len);
145+
_debug("SET #%u", auxdata->len);
148146

149147
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
150148
&auxdata->type, auxdata->len,

fs/fscache/cache.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ struct fscache_cache *fscache_select_cache_for_object(
115115
struct fscache_object, cookie_link);
116116

117117
cache = object->cache;
118-
if (object->state >= FSCACHE_OBJECT_DYING ||
118+
if (fscache_object_is_dying(object) ||
119119
test_bit(FSCACHE_IOERROR, &cache->flags))
120120
cache = NULL;
121121

@@ -224,8 +224,10 @@ int fscache_add_cache(struct fscache_cache *cache,
224224
BUG_ON(!ifsdef);
225225

226226
cache->flags = 0;
227-
ifsdef->event_mask = ULONG_MAX & ~(1 << FSCACHE_OBJECT_EV_CLEARED);
228-
ifsdef->state = FSCACHE_OBJECT_ACTIVE;
227+
ifsdef->event_mask =
228+
((1 << NR_FSCACHE_OBJECT_EVENTS) - 1) &
229+
~(1 << FSCACHE_OBJECT_EV_CLEARED);
230+
__set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &ifsdef->flags);
229231

230232
if (!tagname)
231233
tagname = cache->identifier;
@@ -330,25 +332,25 @@ static void fscache_withdraw_all_objects(struct fscache_cache *cache,
330332
{
331333
struct fscache_object *object;
332334

333-
spin_lock(&cache->object_list_lock);
334-
335335
while (!list_empty(&cache->object_list)) {
336-
object = list_entry(cache->object_list.next,
337-
struct fscache_object, cache_link);
338-
list_move_tail(&object->cache_link, dying_objects);
336+
spin_lock(&cache->object_list_lock);
339337

340-
_debug("withdraw %p", object->cookie);
338+
if (!list_empty(&cache->object_list)) {
339+
object = list_entry(cache->object_list.next,
340+
struct fscache_object, cache_link);
341+
list_move_tail(&object->cache_link, dying_objects);
341342

342-
spin_lock(&object->lock);
343-
spin_unlock(&cache->object_list_lock);
344-
fscache_raise_event(object, FSCACHE_OBJECT_EV_WITHDRAW);
345-
spin_unlock(&object->lock);
343+
_debug("withdraw %p", object->cookie);
344+
345+
/* This must be done under object_list_lock to prevent
346+
* a race with fscache_drop_object().
347+
*/
348+
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
349+
}
346350

351+
spin_unlock(&cache->object_list_lock);
347352
cond_resched();
348-
spin_lock(&cache->object_list_lock);
349353
}
350-
351-
spin_unlock(&cache->object_list_lock);
352354
}
353355

354356
/**

fs/fscache/cookie.c

Lines changed: 32 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ struct fscache_cookie *__fscache_acquire_cookie(
9595
atomic_set(&cookie->usage, 1);
9696
atomic_set(&cookie->n_children, 0);
9797

98+
/* We keep the active count elevated until relinquishment to prevent an
99+
* attempt to wake up every time the object operations queue quiesces.
100+
*/
101+
atomic_set(&cookie->n_active, 1);
102+
98103
atomic_inc(&parent->usage);
99104
atomic_inc(&parent->n_children);
100105

@@ -177,7 +182,6 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)
177182

178183
cookie->flags =
179184
(1 << FSCACHE_COOKIE_LOOKING_UP) |
180-
(1 << FSCACHE_COOKIE_CREATING) |
181185
(1 << FSCACHE_COOKIE_NO_DATA_YET);
182186

183187
/* ask the cache to allocate objects for this cookie and its parent
@@ -205,7 +209,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)
205209

206210
/* initiate the process of looking up all the objects in the chain
207211
* (done by fscache_initialise_object()) */
208-
fscache_enqueue_object(object);
212+
fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD);
209213

210214
spin_unlock(&cookie->lock);
211215

@@ -285,7 +289,7 @@ static int fscache_alloc_object(struct fscache_cache *cache,
285289

286290
object_already_extant:
287291
ret = -ENOBUFS;
288-
if (object->state >= FSCACHE_OBJECT_DYING) {
292+
if (fscache_object_is_dead(object)) {
289293
spin_unlock(&cookie->lock);
290294
goto error;
291295
}
@@ -321,7 +325,7 @@ static int fscache_attach_object(struct fscache_cookie *cookie,
321325
ret = -EEXIST;
322326
hlist_for_each_entry(p, &cookie->backing_objects, cookie_link) {
323327
if (p->cache == object->cache) {
324-
if (p->state >= FSCACHE_OBJECT_DYING)
328+
if (fscache_object_is_dying(p))
325329
ret = -ENOBUFS;
326330
goto cant_attach_object;
327331
}
@@ -332,7 +336,7 @@ static int fscache_attach_object(struct fscache_cookie *cookie,
332336
hlist_for_each_entry(p, &cookie->parent->backing_objects,
333337
cookie_link) {
334338
if (p->cache == object->cache) {
335-
if (p->state >= FSCACHE_OBJECT_DYING) {
339+
if (fscache_object_is_dying(p)) {
336340
ret = -ENOBUFS;
337341
spin_unlock(&cookie->parent->lock);
338342
goto cant_attach_object;
@@ -400,7 +404,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie)
400404
object = hlist_entry(cookie->backing_objects.first,
401405
struct fscache_object,
402406
cookie_link);
403-
if (object->state < FSCACHE_OBJECT_DYING)
407+
if (fscache_object_is_live(object))
404408
fscache_raise_event(
405409
object, FSCACHE_OBJECT_EV_INVALIDATE);
406410
}
@@ -467,9 +471,7 @@ EXPORT_SYMBOL(__fscache_update_cookie);
467471
*/
468472
void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
469473
{
470-
struct fscache_cache *cache;
471474
struct fscache_object *object;
472-
unsigned long event;
473475

474476
fscache_stat(&fscache_n_relinquishes);
475477
if (retire)
@@ -481,79 +483,48 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
481483
return;
482484
}
483485

484-
_enter("%p{%s,%p},%d",
485-
cookie, cookie->def->name, cookie->netfs_data, retire);
486+
_enter("%p{%s,%p,%d},%d",
487+
cookie, cookie->def->name, cookie->netfs_data,
488+
atomic_read(&cookie->n_active), retire);
489+
490+
ASSERTCMP(atomic_read(&cookie->n_active), >, 0);
486491

487492
if (atomic_read(&cookie->n_children) != 0) {
488493
printk(KERN_ERR "FS-Cache: Cookie '%s' still has children\n",
489494
cookie->def->name);
490495
BUG();
491496
}
492497

493-
/* wait for the cookie to finish being instantiated (or to fail) */
494-
if (test_bit(FSCACHE_COOKIE_CREATING, &cookie->flags)) {
495-
fscache_stat(&fscache_n_relinquishes_waitcrt);
496-
wait_on_bit(&cookie->flags, FSCACHE_COOKIE_CREATING,
497-
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
498-
}
499-
500-
event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;
498+
/* No further netfs-accessing operations on this cookie permitted */
499+
set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags);
500+
if (retire)
501+
set_bit(FSCACHE_COOKIE_RETIRED, &cookie->flags);
501502

502-
try_again:
503503
spin_lock(&cookie->lock);
504-
505-
/* break links with all the active objects */
506-
while (!hlist_empty(&cookie->backing_objects)) {
507-
int n_reads;
508-
object = hlist_entry(cookie->backing_objects.first,
509-
struct fscache_object,
510-
cookie_link);
511-
512-
_debug("RELEASE OBJ%x", object->debug_id);
513-
514-
set_bit(FSCACHE_COOKIE_WAITING_ON_READS, &cookie->flags);
515-
n_reads = atomic_read(&object->n_reads);
516-
if (n_reads) {
517-
int n_ops = object->n_ops;
518-
int n_in_progress = object->n_in_progress;
519-
spin_unlock(&cookie->lock);
520-
printk(KERN_ERR "FS-Cache:"
521-
" Cookie '%s' still has %d outstanding reads (%d,%d)\n",
522-
cookie->def->name,
523-
n_reads, n_ops, n_in_progress);
524-
wait_on_bit(&cookie->flags, FSCACHE_COOKIE_WAITING_ON_READS,
525-
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
526-
printk("Wait finished\n");
527-
goto try_again;
528-
}
529-
530-
/* detach each cache object from the object cookie */
531-
spin_lock(&object->lock);
532-
hlist_del_init(&object->cookie_link);
533-
534-
cache = object->cache;
535-
object->cookie = NULL;
536-
fscache_raise_event(object, event);
537-
spin_unlock(&object->lock);
538-
539-
if (atomic_dec_and_test(&cookie->usage))
540-
/* the cookie refcount shouldn't be reduced to 0 yet */
541-
BUG();
504+
hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
505+
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
542506
}
507+
spin_unlock(&cookie->lock);
543508

544-
/* detach pointers back to the netfs */
509+
/* Wait for cessation of activity requiring access to the netfs (when
510+
* n_active reaches 0).
511+
*/
512+
if (!atomic_dec_and_test(&cookie->n_active))
513+
wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
514+
TASK_UNINTERRUPTIBLE);
515+
516+
/* Clear pointers back to the netfs */
545517
cookie->netfs_data = NULL;
546518
cookie->def = NULL;
547-
548-
spin_unlock(&cookie->lock);
519+
BUG_ON(cookie->stores.rnode);
549520

550521
if (cookie->parent) {
551522
ASSERTCMP(atomic_read(&cookie->parent->usage), >, 0);
552523
ASSERTCMP(atomic_read(&cookie->parent->n_children), >, 0);
553524
atomic_dec(&cookie->parent->n_children);
554525
}
555526

556-
/* finally dispose of the cookie */
527+
/* Dispose of the netfs's link to the cookie */
557528
ASSERTCMP(atomic_read(&cookie->usage), >, 0);
558529
fscache_cookie_put(cookie);
559530

fs/fscache/fsdef.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ static struct fscache_cookie_def fscache_fsdef_index_def = {
5555

5656
struct fscache_cookie fscache_fsdef_index = {
5757
.usage = ATOMIC_INIT(1),
58+
.n_active = ATOMIC_INIT(1),
5859
.lock = __SPIN_LOCK_UNLOCKED(fscache_fsdef_index.lock),
5960
.backing_objects = HLIST_HEAD_INIT,
6061
.def = &fscache_fsdef_index_def,

0 commit comments

Comments
 (0)