mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
FS-Cache: When submitting an op, cancel it if the target object is dying
When submitting an operation, prefer to cancel the operation immediately rather than queuing it for later processing if the object is marked as dying (ie. the object state machine has reached the KILL_OBJECT state). Whilst we're at it, change the series of related test_bit() calls into a READ_ONCE() and bitwise-AND operators to reduce the number of load instructions (test_bit() has a volatile address). Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Steve Dickson <steved@redhat.com> Acked-by: Jeff Layton <jeff.layton@primarydata.com>
This commit is contained in:
parent
3c3059841a
commit
30ceec6284
@ -120,6 +120,8 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
|
|||||||
int fscache_submit_exclusive_op(struct fscache_object *object,
|
int fscache_submit_exclusive_op(struct fscache_object *object,
|
||||||
struct fscache_operation *op)
|
struct fscache_operation *op)
|
||||||
{
|
{
|
||||||
|
const struct fscache_state *ostate;
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
|
_enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
|
||||||
@ -132,8 +134,19 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
|
|||||||
ASSERTCMP(object->n_ops, >=, object->n_exclusive);
|
ASSERTCMP(object->n_ops, >=, object->n_exclusive);
|
||||||
ASSERT(list_empty(&op->pend_link));
|
ASSERT(list_empty(&op->pend_link));
|
||||||
|
|
||||||
|
ostate = object->state;
|
||||||
|
smp_rmb();
|
||||||
|
|
||||||
op->state = FSCACHE_OP_ST_PENDING;
|
op->state = FSCACHE_OP_ST_PENDING;
|
||||||
if (fscache_object_is_active(object)) {
|
flags = READ_ONCE(object->flags);
|
||||||
|
if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {
|
||||||
|
fscache_stat(&fscache_n_op_rejected);
|
||||||
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
||||||
|
ret = -ENOBUFS;
|
||||||
|
} else if (unlikely(fscache_cache_is_broken(object))) {
|
||||||
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
||||||
|
ret = -EIO;
|
||||||
|
} else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {
|
||||||
op->object = object;
|
op->object = object;
|
||||||
object->n_ops++;
|
object->n_ops++;
|
||||||
object->n_exclusive++; /* reads and writes must wait */
|
object->n_exclusive++; /* reads and writes must wait */
|
||||||
@ -155,7 +168,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
|
|||||||
/* need to issue a new write op after this */
|
/* need to issue a new write op after this */
|
||||||
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
|
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
|
} else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
|
||||||
op->object = object;
|
op->object = object;
|
||||||
object->n_ops++;
|
object->n_ops++;
|
||||||
object->n_exclusive++; /* reads and writes must wait */
|
object->n_exclusive++; /* reads and writes must wait */
|
||||||
@ -164,11 +177,9 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
|
|||||||
fscache_stat(&fscache_n_op_pend);
|
fscache_stat(&fscache_n_op_pend);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
/* If we're in any other state, there must have been an I/O
|
fscache_report_unexpected_submission(object, op, ostate);
|
||||||
* error of some nature.
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
||||||
*/
|
ret = -ENOBUFS;
|
||||||
ASSERT(test_bit(FSCACHE_IOERROR, &object->cache->flags));
|
|
||||||
ret = -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&object->lock);
|
spin_unlock(&object->lock);
|
||||||
@ -187,6 +198,7 @@ int fscache_submit_op(struct fscache_object *object,
|
|||||||
struct fscache_operation *op)
|
struct fscache_operation *op)
|
||||||
{
|
{
|
||||||
const struct fscache_state *ostate;
|
const struct fscache_state *ostate;
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_enter("{OBJ%x OP%x},{%u}",
|
_enter("{OBJ%x OP%x},{%u}",
|
||||||
@ -204,7 +216,15 @@ int fscache_submit_op(struct fscache_object *object,
|
|||||||
smp_rmb();
|
smp_rmb();
|
||||||
|
|
||||||
op->state = FSCACHE_OP_ST_PENDING;
|
op->state = FSCACHE_OP_ST_PENDING;
|
||||||
if (fscache_object_is_active(object)) {
|
flags = READ_ONCE(object->flags);
|
||||||
|
if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {
|
||||||
|
fscache_stat(&fscache_n_op_rejected);
|
||||||
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
||||||
|
ret = -ENOBUFS;
|
||||||
|
} else if (unlikely(fscache_cache_is_broken(object))) {
|
||||||
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
||||||
|
ret = -EIO;
|
||||||
|
} else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {
|
||||||
op->object = object;
|
op->object = object;
|
||||||
object->n_ops++;
|
object->n_ops++;
|
||||||
|
|
||||||
@ -222,25 +242,18 @@ int fscache_submit_op(struct fscache_object *object,
|
|||||||
fscache_run_op(object, op);
|
fscache_run_op(object, op);
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
|
} else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
|
||||||
op->object = object;
|
op->object = object;
|
||||||
object->n_ops++;
|
object->n_ops++;
|
||||||
atomic_inc(&op->usage);
|
atomic_inc(&op->usage);
|
||||||
list_add_tail(&op->pend_link, &object->pending_ops);
|
list_add_tail(&op->pend_link, &object->pending_ops);
|
||||||
fscache_stat(&fscache_n_op_pend);
|
fscache_stat(&fscache_n_op_pend);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (fscache_object_is_dying(object)) {
|
} else {
|
||||||
fscache_stat(&fscache_n_op_rejected);
|
|
||||||
op->state = FSCACHE_OP_ST_CANCELLED;
|
|
||||||
ret = -ENOBUFS;
|
|
||||||
} else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) {
|
|
||||||
fscache_report_unexpected_submission(object, op, ostate);
|
fscache_report_unexpected_submission(object, op, ostate);
|
||||||
ASSERT(!fscache_object_is_active(object));
|
ASSERT(!fscache_object_is_active(object));
|
||||||
op->state = FSCACHE_OP_ST_CANCELLED;
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
||||||
ret = -ENOBUFS;
|
ret = -ENOBUFS;
|
||||||
} else {
|
|
||||||
op->state = FSCACHE_OP_ST_CANCELLED;
|
|
||||||
ret = -ENOBUFS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&object->lock);
|
spin_unlock(&object->lock);
|
||||||
|
@ -411,17 +411,22 @@ static inline bool fscache_object_is_available(struct fscache_object *object)
|
|||||||
return test_bit(FSCACHE_OBJECT_IS_AVAILABLE, &object->flags);
|
return test_bit(FSCACHE_OBJECT_IS_AVAILABLE, &object->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool fscache_cache_is_broken(struct fscache_object *object)
|
||||||
|
{
|
||||||
|
return test_bit(FSCACHE_IOERROR, &object->cache->flags);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool fscache_object_is_active(struct fscache_object *object)
|
static inline bool fscache_object_is_active(struct fscache_object *object)
|
||||||
{
|
{
|
||||||
return fscache_object_is_available(object) &&
|
return fscache_object_is_available(object) &&
|
||||||
fscache_object_is_live(object) &&
|
fscache_object_is_live(object) &&
|
||||||
!test_bit(FSCACHE_IOERROR, &object->cache->flags);
|
!fscache_cache_is_broken(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool fscache_object_is_dead(struct fscache_object *object)
|
static inline bool fscache_object_is_dead(struct fscache_object *object)
|
||||||
{
|
{
|
||||||
return fscache_object_is_dying(object) &&
|
return fscache_object_is_dying(object) &&
|
||||||
test_bit(FSCACHE_IOERROR, &object->cache->flags);
|
fscache_cache_is_broken(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user