History

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull fscache fixes from Al Viro. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fscache: Fix dead object requeue fscache: Clear outstanding writes when disabling a cookie FS-Cache: Initialise stores_lock in netfs cookie

Linus Torvalds committed 9 years ago

Commit 2883aae2 parents e387dc1 e26bfeb4 files · +37 −2Browse files

Unified · Split

4 files
  1. fs/fscache/cookie.c +5 −0
  2. fs/fscache/netfs.c +1 −0
  3. fs/fscache/object.c +30 −2
  4. include/linux/fscache-cache.h +1 −0
fs/fscache/cookie.c+5−0
@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) · 541 unmodified lines
542542 hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
543543 if (invalidate)
544544 set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
545+ clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
545546 fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
546547 }
547548 } else {
@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) · 12 unmodified lines
560561 wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
561562 TASK_UNINTERRUPTIBLE);
562563
564+ /* Make sure any pending writes are cancelled. */
565+ if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
566+ fscache_invalidate_writes(cookie);
567+
563568 /* Reset the cookie state if it wasn't relinquished */
564569 if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
565570 atomic_inc(&cookie->n_active);
fs/fscache/netfs.c+1−0
@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) · 47 unmodified lines
4848 cookie->flags = 1 << FSCACHE_COOKIE_ENABLED;
4949
5050 spin_lock_init(&cookie->lock);
51+ spin_lock_init(&cookie->stores_lock);
5152 INIT_HLIST_HEAD(&cookie->backing_objects);
5253
5354 /* check the netfs type is not already present */
fs/fscache/object.c+30−2
@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object · 29 unmodified lines
3030 static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
3131 static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
3232 static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
33+static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);
3334
3435 #define __STATE_NAME(n) fscache_osm_##n
3536 #define STATE(n) (&__STATE_NAME(n))
@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure); · 55 unmodified lines
9192 static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object);
9293 static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents);
9394 static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object);
94−static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL);
95+static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead);
9596
9697 static WAIT_STATE(WAIT_FOR_INIT, "?INI",
9798 TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
@@ -229,6 +230,10 @@ execute_work_state: · 131 unmodified lines
229230 event = -1;
230231 if (new_state == NO_TRANSIT) {
231232 _debug("{OBJ%x} %s notrans", object->debug_id, state->name);
233+ if (unlikely(state == STATE(OBJECT_DEAD))) {
234+ _leave(" [dead]");
235+ return;
236+ }
232237 fscache_enqueue_object(object);
233238 event_mask = object->oob_event_mask;
234239 goto unmask_events;
@@ -239,7 +244,7 @@ execute_work_state: · 4 unmodified lines
239244 object->state = state = new_state;
240245
241246 if (state->work) {
242− if (unlikely(state->work == ((void *)2UL))) {
247+ if (unlikely(state == STATE(OBJECT_DEAD))) {
243248 _leave(" [dead]");
244249 return;
245250 }
@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob · 399 unmodified lines
645650 fscache_mark_object_dead(object);
646651 object->oob_event_mask = 0;
647652
653+ if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
654+ /* Reject any new read/write ops and abort any that are pending. */
655+ clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
656+ fscache_cancel_all_ops(object);
657+ }
658+
648659 if (list_empty(&object->dependents) &&
649660 object->n_ops == 0 &&
650661 object->n_children == 0)
@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object, · 426 unmodified lines
10771088 }
10781089 }
10791090 EXPORT_SYMBOL(fscache_object_mark_killed);
1091+
1092+/*
1093+ * The object is dead. We can get here if an object gets queued by an event
1094+ * that would lead to its death (such as EV_KILL) when the dispatcher is
1095+ * already running (and so can be requeued) but hasn't yet cleared the event
1096+ * mask.
1097+ */
1098+static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
1099+ int event)
1100+{
1101+ if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
1102+ &object->flags))
1103+ return NO_TRANSIT;
1104+
1105+ WARN(true, "FS-Cache object redispatched after death");
1106+ return NO_TRANSIT;
1107+}
include/linux/fscache-cache.h+1−0
@@ -360,6 +360,7 @@ struct fscache_object { · 359 unmodified lines
360360 #define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */
361361 #define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */
362362 #define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */
363+#define FSCACHE_OBJECT_RUN_AFTER_DEAD 8 /* T if object has been dispatched after death */
363364
364365 struct list_head cache_link; /* link in cache->object_list */
365366 struct hlist_node cookie_link; /* link in cookie->backing_objects */