|
@@ -312,9 +312,11 @@ void fscache_start_operations(struct fscache_object *object)
|
|
|
* cancel an operation that's pending on an object
|
|
|
*/
|
|
|
int fscache_cancel_op(struct fscache_operation *op,
|
|
|
- void (*do_cancel)(struct fscache_operation *))
|
|
|
+ void (*do_cancel)(struct fscache_operation *),
|
|
|
+ bool cancel_in_progress_op)
|
|
|
{
|
|
|
struct fscache_object *object = op->object;
|
|
|
+ bool put = false;
|
|
|
int ret;
|
|
|
|
|
|
_enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id);
|
|
@@ -328,8 +330,19 @@ int fscache_cancel_op(struct fscache_operation *op,
|
|
|
ret = -EBUSY;
|
|
|
if (op->state == FSCACHE_OP_ST_PENDING) {
|
|
|
ASSERT(!list_empty(&op->pend_link));
|
|
|
- fscache_stat(&fscache_n_op_cancelled);
|
|
|
list_del_init(&op->pend_link);
|
|
|
+ put = true;
|
|
|
+ fscache_stat(&fscache_n_op_cancelled);
|
|
|
+ if (do_cancel)
|
|
|
+ do_cancel(op);
|
|
|
+ op->state = FSCACHE_OP_ST_CANCELLED;
|
|
|
+ if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
|
|
|
+ object->n_exclusive--;
|
|
|
+ if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
|
|
|
+ wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
|
|
|
+ ret = 0;
|
|
|
+ } else if (op->state == FSCACHE_OP_ST_IN_PROGRESS && cancel_in_progress_op) {
|
|
|
+ fscache_stat(&fscache_n_op_cancelled);
|
|
|
if (do_cancel)
|
|
|
do_cancel(op);
|
|
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
|
@@ -337,10 +350,11 @@ int fscache_cancel_op(struct fscache_operation *op,
|
|
|
object->n_exclusive--;
|
|
|
if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
|
|
|
wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
|
|
|
- fscache_put_operation(op);
|
|
|
ret = 0;
|
|
|
}
|
|
|
|
|
|
+ if (put)
|
|
|
+ fscache_put_operation(op);
|
|
|
spin_unlock(&object->lock);
|
|
|
_leave(" = %d", ret);
|
|
|
return ret;
|