From 1f372dff1da37e2b36ae9085368fa46896398598 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells@redhat.com>
Date: Thu, 13 Dec 2012 20:03:13 +0000
Subject: [PATCH] FS-Cache: Mark cancellation of in-progress operation

Mark as cancelled an operation that is in progress rather than pending at the
time it is cancelled, and call fscache_complete_op() to cancel an operation so
that blocked ops can be started.

Signed-off-by: David Howells <dhowells@redhat.com>
---
 fs/cachefiles/interface.c     |  2 +-
 fs/fscache/operation.c        |  7 ++++---
 fs/fscache/page.c             | 10 +++++-----
 include/linux/fscache-cache.h |  4 ++--
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 7a9d574b961c..746ce532e130 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -484,7 +484,7 @@ static void cachefiles_invalidate_object(struct fscache_operation *op)
 		}
 	}
 
-	fscache_op_complete(op);
+	fscache_op_complete(op, true);
 	_leave("");
 }
 
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 9e6b7d232bb1..36c59604130d 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -363,9 +363,9 @@ void fscache_cancel_all_ops(struct fscache_object *object)
 }
 
 /*
- * Record the completion of an in-progress operation.
+ * Record the completion or cancellation of an in-progress operation.
  */
-void fscache_op_complete(struct fscache_operation *op)
+void fscache_op_complete(struct fscache_operation *op, bool cancelled)
 {
 	struct fscache_object *object = op->object;
 
@@ -380,7 +380,8 @@ void fscache_op_complete(struct fscache_operation *op)
 
 	spin_lock(&object->lock);
 
-	op->state = FSCACHE_OP_ST_COMPLETE;
+	op->state = cancelled ?
+		FSCACHE_OP_ST_CANCELLED : FSCACHE_OP_ST_COMPLETE;
 
 	if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
 		object->n_exclusive--;
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index ef0218f5080d..8a92b9fabe83 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -171,7 +171,7 @@ static void fscache_attr_changed_op(struct fscache_operation *op)
 			fscache_abort_object(object);
 	}
 
-	fscache_op_complete(op);
+	fscache_op_complete(op, true);
 	_leave("");
 }
 
@@ -704,7 +704,7 @@ static void fscache_write_op(struct fscache_operation *_op)
 		 * exists, so we should just cancel this write operation.
 		 */
 		spin_unlock(&object->lock);
-		op->op.state = FSCACHE_OP_ST_CANCELLED;
+		fscache_op_complete(&op->op, false);
 		_leave(" [inactive]");
 		return;
 	}
@@ -717,7 +717,7 @@ static void fscache_write_op(struct fscache_operation *_op)
 		 * cancel this write operation.
 		 */
 		spin_unlock(&object->lock);
-		op->op.state = FSCACHE_OP_ST_CANCELLED;
+		fscache_op_complete(&op->op, false);
 		_leave(" [cancel] op{f=%lx s=%u} obj{s=%u f=%lx}",
 		       _op->flags, _op->state, object->state, object->flags);
 		return;
@@ -755,7 +755,7 @@ static void fscache_write_op(struct fscache_operation *_op)
 	fscache_end_page_write(object, page);
 	if (ret < 0) {
 		fscache_abort_object(object);
-		fscache_op_complete(&op->op);
+		fscache_op_complete(&op->op, true);
 	} else {
 		fscache_enqueue_operation(&op->op);
 	}
@@ -770,7 +770,7 @@ superseded:
 	spin_unlock(&cookie->stores_lock);
 	clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
 	spin_unlock(&object->lock);
-	fscache_op_complete(&op->op);
+	fscache_op_complete(&op->op, true);
 	_leave("");
 }
 
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 73e68c8d5df4..5dfa0aa216b6 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -116,7 +116,7 @@ extern atomic_t fscache_op_debug_id;
 extern void fscache_op_work_func(struct work_struct *work);
 
 extern void fscache_enqueue_operation(struct fscache_operation *);
-extern void fscache_op_complete(struct fscache_operation *);
+extern void fscache_op_complete(struct fscache_operation *, bool);
 extern void fscache_put_operation(struct fscache_operation *);
 
 /**
@@ -196,7 +196,7 @@ static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
 {
 	op->n_pages -= n_pages;
 	if (op->n_pages <= 0)
-		fscache_op_complete(&op->op);
+		fscache_op_complete(&op->op, true);
 }
 
 /**