Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2883aaea authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents e387dc12 e26bfebd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
		hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
			if (invalidate)
				set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
			clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
			fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
		}
	} else {
@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
		wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
				 TASK_UNINTERRUPTIBLE);

	/* Make sure any pending writes are cancelled. */
	if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
		fscache_invalidate_writes(cookie);

	/* Reset the cookie state if it wasn't relinquished */
	if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
		atomic_inc(&cookie->n_active);
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
	cookie->flags		= 1 << FSCACHE_COOKIE_ENABLED;

	spin_lock_init(&cookie->lock);
	spin_lock_init(&cookie->stores_lock);
	INIT_HLIST_HEAD(&cookie->backing_objects);

	/* check the netfs type is not already present */
+30 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object
static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);

#define __STATE_NAME(n) fscache_osm_##n
#define STATE(n) (&__STATE_NAME(n))
@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure);
static WORK_STATE(KILL_OBJECT,		"KILL", fscache_kill_object);
static WORK_STATE(KILL_DEPENDENTS,	"KDEP", fscache_kill_dependents);
static WORK_STATE(DROP_OBJECT,		"DROP", fscache_drop_object);
static WORK_STATE(OBJECT_DEAD,		"DEAD", (void*)2UL);
static WORK_STATE(OBJECT_DEAD,		"DEAD", fscache_object_dead);

static WAIT_STATE(WAIT_FOR_INIT,	"?INI",
		  TRANSIT_TO(INIT_OBJECT,	1 << FSCACHE_OBJECT_EV_NEW_CHILD));
@@ -229,6 +230,10 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object)
	event = -1;
	if (new_state == NO_TRANSIT) {
		_debug("{OBJ%x} %s notrans", object->debug_id, state->name);
		if (unlikely(state == STATE(OBJECT_DEAD))) {
			_leave(" [dead]");
			return;
		}
		fscache_enqueue_object(object);
		event_mask = object->oob_event_mask;
		goto unmask_events;
@@ -239,7 +244,7 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object)
	object->state = state = new_state;

	if (state->work) {
		if (unlikely(state->work == ((void *)2UL))) {
		if (unlikely(state == STATE(OBJECT_DEAD))) {
			_leave(" [dead]");
			return;
		}
@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
	fscache_mark_object_dead(object);
	object->oob_event_mask = 0;

	if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
		/* Reject any new read/write ops and abort any that are pending. */
		clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
		fscache_cancel_all_ops(object);
	}

	if (list_empty(&object->dependents) &&
	    object->n_ops == 0 &&
	    object->n_children == 0)
@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object,
	}
}
EXPORT_SYMBOL(fscache_object_mark_killed);

/*
 * The object is dead.  We can get here if an object gets queued by an event
 * that would lead to its death (such as EV_KILL) when the dispatcher is
 * already running (and so can be requeued) but hasn't yet cleared the event
 * mask.
 */
static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
						       int event)
{
	if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
			      &object->flags))
		return NO_TRANSIT;

	WARN(true, "FS-Cache object redispatched after death");
	return NO_TRANSIT;
}
+1 −0
Original line number Diff line number Diff line
@@ -360,6 +360,7 @@ struct fscache_object {
#define FSCACHE_OBJECT_IS_AVAILABLE	5	/* T if object has become active */
#define FSCACHE_OBJECT_RETIRED		6	/* T if object was retired on relinquishment */
#define FSCACHE_OBJECT_KILLED_BY_CACHE	7	/* T if object was killed by the cache */
#define FSCACHE_OBJECT_RUN_AFTER_DEAD	8	/* T if object has been dispatched after death */

	struct list_head	cache_link;	/* link in cache->object_list */
	struct hlist_node	cookie_link;	/* link in cookie->backing_objects */