summaryrefslogtreecommitdiffstats
path: root/fs/fscache
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2015-02-24 05:05:27 -0500
committerDavid Howells <dhowells@redhat.com>2015-04-02 09:28:53 -0400
commit30ceec6284129662efc3a1e7675b2bd857a046fe (patch)
tree98fba830445abbf24eb3fc969564fc20e29c04a8 /fs/fscache
parent3c3059841a9b99fa8dd8d878607deceec1e363e9 (diff)
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>
Diffstat (limited to 'fs/fscache')
-rw-r--r--fs/fscache/operation.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 68ead8482617..dec6defe3be3 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -120,6 +120,8 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
120int fscache_submit_exclusive_op(struct fscache_object *object, 120int fscache_submit_exclusive_op(struct fscache_object *object,
121 struct fscache_operation *op) 121 struct fscache_operation *op)
122{ 122{
123 const struct fscache_state *ostate;
124 unsigned long flags;
123 int ret; 125 int ret;
124 126
125 _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id); 127 _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
@@ -132,8 +134,19 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
132 ASSERTCMP(object->n_ops, >=, object->n_exclusive); 134 ASSERTCMP(object->n_ops, >=, object->n_exclusive);
133 ASSERT(list_empty(&op->pend_link)); 135 ASSERT(list_empty(&op->pend_link));
134 136
137 ostate = object->state;
138 smp_rmb();
139
135 op->state = FSCACHE_OP_ST_PENDING; 140 op->state = FSCACHE_OP_ST_PENDING;
136 if (fscache_object_is_active(object)) { 141 flags = READ_ONCE(object->flags);
142 if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {
143 fscache_stat(&fscache_n_op_rejected);
144 op->state = FSCACHE_OP_ST_CANCELLED;
145 ret = -ENOBUFS;
146 } else if (unlikely(fscache_cache_is_broken(object))) {
147 op->state = FSCACHE_OP_ST_CANCELLED;
148 ret = -EIO;
149 } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {
137 op->object = object; 150 op->object = object;
138 object->n_ops++; 151 object->n_ops++;
139 object->n_exclusive++; /* reads and writes must wait */ 152 object->n_exclusive++; /* reads and writes must wait */
@@ -155,7 +168,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
155 /* need to issue a new write op after this */ 168 /* need to issue a new write op after this */
156 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); 169 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
157 ret = 0; 170 ret = 0;
158 } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) { 171 } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
159 op->object = object; 172 op->object = object;
160 object->n_ops++; 173 object->n_ops++;
161 object->n_exclusive++; /* reads and writes must wait */ 174 object->n_exclusive++; /* reads and writes must wait */
@@ -164,11 +177,9 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
164 fscache_stat(&fscache_n_op_pend); 177 fscache_stat(&fscache_n_op_pend);
165 ret = 0; 178 ret = 0;
166 } else { 179 } else {
167 /* If we're in any other state, there must have been an I/O 180 fscache_report_unexpected_submission(object, op, ostate);
168 * error of some nature. 181 op->state = FSCACHE_OP_ST_CANCELLED;
169 */ 182 ret = -ENOBUFS;
170 ASSERT(test_bit(FSCACHE_IOERROR, &object->cache->flags));
171 ret = -EIO;
172 } 183 }
173 184
174 spin_unlock(&object->lock); 185 spin_unlock(&object->lock);
@@ -187,6 +198,7 @@ int fscache_submit_op(struct fscache_object *object,
187 struct fscache_operation *op) 198 struct fscache_operation *op)
188{ 199{
189 const struct fscache_state *ostate; 200 const struct fscache_state *ostate;
201 unsigned long flags;
190 int ret; 202 int ret;
191 203
192 _enter("{OBJ%x OP%x},{%u}", 204 _enter("{OBJ%x OP%x},{%u}",
@@ -204,7 +216,15 @@ int fscache_submit_op(struct fscache_object *object,
204 smp_rmb(); 216 smp_rmb();
205 217
206 op->state = FSCACHE_OP_ST_PENDING; 218 op->state = FSCACHE_OP_ST_PENDING;
207 if (fscache_object_is_active(object)) { 219 flags = READ_ONCE(object->flags);
220 if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {
221 fscache_stat(&fscache_n_op_rejected);
222 op->state = FSCACHE_OP_ST_CANCELLED;
223 ret = -ENOBUFS;
224 } else if (unlikely(fscache_cache_is_broken(object))) {
225 op->state = FSCACHE_OP_ST_CANCELLED;
226 ret = -EIO;
227 } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {
208 op->object = object; 228 op->object = object;
209 object->n_ops++; 229 object->n_ops++;
210 230
@@ -222,25 +242,18 @@ int fscache_submit_op(struct fscache_object *object,
222 fscache_run_op(object, op); 242 fscache_run_op(object, op);
223 } 243 }
224 ret = 0; 244 ret = 0;
225 } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) { 245 } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
226 op->object = object; 246 op->object = object;
227 object->n_ops++; 247 object->n_ops++;
228 atomic_inc(&op->usage); 248 atomic_inc(&op->usage);
229 list_add_tail(&op->pend_link, &object->pending_ops); 249 list_add_tail(&op->pend_link, &object->pending_ops);
230 fscache_stat(&fscache_n_op_pend); 250 fscache_stat(&fscache_n_op_pend);
231 ret = 0; 251 ret = 0;
232 } else if (fscache_object_is_dying(object)) { 252 } else {
233 fscache_stat(&fscache_n_op_rejected);
234 op->state = FSCACHE_OP_ST_CANCELLED;
235 ret = -ENOBUFS;
236 } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) {
237 fscache_report_unexpected_submission(object, op, ostate); 253 fscache_report_unexpected_submission(object, op, ostate);
238 ASSERT(!fscache_object_is_active(object)); 254 ASSERT(!fscache_object_is_active(object));
239 op->state = FSCACHE_OP_ST_CANCELLED; 255 op->state = FSCACHE_OP_ST_CANCELLED;
240 ret = -ENOBUFS; 256 ret = -ENOBUFS;
241 } else {
242 op->state = FSCACHE_OP_ST_CANCELLED;
243 ret = -ENOBUFS;
244 } 257 }
245 258
246 spin_unlock(&object->lock); 259 spin_unlock(&object->lock);