aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/caching/fscache.txt2
-rw-r--r--fs/fscache/internal.h3
-rw-r--r--fs/fscache/operation.c82
-rw-r--r--fs/fscache/page.c55
-rw-r--r--fs/fscache/stats.c12
5 files changed, 115 insertions, 39 deletions
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt
index b6c32c080ab1..0a77868f4977 100644
--- a/Documentation/filesystems/caching/fscache.txt
+++ b/Documentation/filesystems/caching/fscache.txt
@@ -250,6 +250,7 @@ proc files.
250 ok=N Number of successful alloc reqs 250 ok=N Number of successful alloc reqs
251 wt=N Number of alloc reqs that waited on lookup completion 251 wt=N Number of alloc reqs that waited on lookup completion
252 nbf=N Number of alloc reqs rejected -ENOBUFS 252 nbf=N Number of alloc reqs rejected -ENOBUFS
253 int=N Number of alloc reqs aborted -ERESTARTSYS
253 ops=N Number of alloc reqs submitted 254 ops=N Number of alloc reqs submitted
254 owt=N Number of alloc reqs waited for CPU time 255 owt=N Number of alloc reqs waited for CPU time
255 Retrvls n=N Number of retrieval (read) requests seen 256 Retrvls n=N Number of retrieval (read) requests seen
@@ -271,6 +272,7 @@ proc files.
271 Ops pend=N Number of times async ops added to pending queues 272 Ops pend=N Number of times async ops added to pending queues
272 run=N Number of times async ops given CPU time 273 run=N Number of times async ops given CPU time
273 enq=N Number of times async ops queued for processing 274 enq=N Number of times async ops queued for processing
275 can=N Number of async ops cancelled
274 dfr=N Number of async ops queued for deferred release 276 dfr=N Number of async ops queued for deferred release
275 rel=N Number of async ops released 277 rel=N Number of async ops released
276 gc=N Number of deferred-release async ops garbage collected 278 gc=N Number of deferred-release async ops garbage collected
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index b85cc8906818..50324ad2b194 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -112,6 +112,7 @@ extern int fscache_submit_exclusive_op(struct fscache_object *,
112 struct fscache_operation *); 112 struct fscache_operation *);
113extern int fscache_submit_op(struct fscache_object *, 113extern int fscache_submit_op(struct fscache_object *,
114 struct fscache_operation *); 114 struct fscache_operation *);
115extern int fscache_cancel_op(struct fscache_operation *);
115extern void fscache_abort_object(struct fscache_object *); 116extern void fscache_abort_object(struct fscache_object *);
116extern void fscache_start_operations(struct fscache_object *); 117extern void fscache_start_operations(struct fscache_object *);
117extern void fscache_operation_gc(struct work_struct *); 118extern void fscache_operation_gc(struct work_struct *);
@@ -140,6 +141,7 @@ extern atomic_t fscache_n_op_enqueue;
140extern atomic_t fscache_n_op_deferred_release; 141extern atomic_t fscache_n_op_deferred_release;
141extern atomic_t fscache_n_op_release; 142extern atomic_t fscache_n_op_release;
142extern atomic_t fscache_n_op_gc; 143extern atomic_t fscache_n_op_gc;
144extern atomic_t fscache_n_op_cancelled;
143 145
144extern atomic_t fscache_n_attr_changed; 146extern atomic_t fscache_n_attr_changed;
145extern atomic_t fscache_n_attr_changed_ok; 147extern atomic_t fscache_n_attr_changed_ok;
@@ -151,6 +153,7 @@ extern atomic_t fscache_n_allocs;
151extern atomic_t fscache_n_allocs_ok; 153extern atomic_t fscache_n_allocs_ok;
152extern atomic_t fscache_n_allocs_wait; 154extern atomic_t fscache_n_allocs_wait;
153extern atomic_t fscache_n_allocs_nobufs; 155extern atomic_t fscache_n_allocs_nobufs;
156extern atomic_t fscache_n_allocs_intr;
154extern atomic_t fscache_n_alloc_ops; 157extern atomic_t fscache_n_alloc_ops;
155extern atomic_t fscache_n_alloc_op_waits; 158extern atomic_t fscache_n_alloc_op_waits;
156 159
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 09e43b6e822f..296492efb81b 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -34,32 +34,31 @@ void fscache_enqueue_operation(struct fscache_operation *op)
34 34
35 fscache_set_op_state(op, "EnQ"); 35 fscache_set_op_state(op, "EnQ");
36 36
37 ASSERT(list_empty(&op->pend_link));
37 ASSERT(op->processor != NULL); 38 ASSERT(op->processor != NULL);
38 ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE); 39 ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE);
39 ASSERTCMP(atomic_read(&op->usage), >, 0); 40 ASSERTCMP(atomic_read(&op->usage), >, 0);
40 41
41 if (list_empty(&op->pend_link)) { 42 fscache_stat(&fscache_n_op_enqueue);
42 switch (op->flags & FSCACHE_OP_TYPE) { 43 switch (op->flags & FSCACHE_OP_TYPE) {
43 case FSCACHE_OP_FAST: 44 case FSCACHE_OP_FAST:
44 _debug("queue fast"); 45 _debug("queue fast");
45 atomic_inc(&op->usage); 46 atomic_inc(&op->usage);
46 if (!schedule_work(&op->fast_work)) 47 if (!schedule_work(&op->fast_work))
47 fscache_put_operation(op); 48 fscache_put_operation(op);
48 break; 49 break;
49 case FSCACHE_OP_SLOW: 50 case FSCACHE_OP_SLOW:
50 _debug("queue slow"); 51 _debug("queue slow");
51 slow_work_enqueue(&op->slow_work); 52 slow_work_enqueue(&op->slow_work);
52 break; 53 break;
53 case FSCACHE_OP_MYTHREAD: 54 case FSCACHE_OP_MYTHREAD:
54 _debug("queue for caller's attention"); 55 _debug("queue for caller's attention");
55 break; 56 break;
56 default: 57 default:
57 printk(KERN_ERR "FS-Cache: Unexpected op type %lx", 58 printk(KERN_ERR "FS-Cache: Unexpected op type %lx",
58 op->flags); 59 op->flags);
59 BUG(); 60 BUG();
60 break; 61 break;
61 }
62 fscache_stat(&fscache_n_op_enqueue);
63 } 62 }
64} 63}
65EXPORT_SYMBOL(fscache_enqueue_operation); 64EXPORT_SYMBOL(fscache_enqueue_operation);
@@ -97,6 +96,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
97 spin_lock(&object->lock); 96 spin_lock(&object->lock);
98 ASSERTCMP(object->n_ops, >=, object->n_in_progress); 97 ASSERTCMP(object->n_ops, >=, object->n_in_progress);
99 ASSERTCMP(object->n_ops, >=, object->n_exclusive); 98 ASSERTCMP(object->n_ops, >=, object->n_exclusive);
99 ASSERT(list_empty(&op->pend_link));
100 100
101 ret = -ENOBUFS; 101 ret = -ENOBUFS;
102 if (fscache_object_is_active(object)) { 102 if (fscache_object_is_active(object)) {
@@ -202,6 +202,7 @@ int fscache_submit_op(struct fscache_object *object,
202 spin_lock(&object->lock); 202 spin_lock(&object->lock);
203 ASSERTCMP(object->n_ops, >=, object->n_in_progress); 203 ASSERTCMP(object->n_ops, >=, object->n_in_progress);
204 ASSERTCMP(object->n_ops, >=, object->n_exclusive); 204 ASSERTCMP(object->n_ops, >=, object->n_exclusive);
205 ASSERT(list_empty(&op->pend_link));
205 206
206 ostate = object->state; 207 ostate = object->state;
207 smp_rmb(); 208 smp_rmb();
@@ -273,12 +274,7 @@ void fscache_start_operations(struct fscache_object *object)
273 stop = true; 274 stop = true;
274 } 275 }
275 list_del_init(&op->pend_link); 276 list_del_init(&op->pend_link);
276 object->n_in_progress++; 277 fscache_run_op(object, op);
277
278 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
279 wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
280 if (op->processor)
281 fscache_enqueue_operation(op);
282 278
283 /* the pending queue was holding a ref on the object */ 279 /* the pending queue was holding a ref on the object */
284 fscache_put_operation(op); 280 fscache_put_operation(op);
@@ -291,6 +287,36 @@ void fscache_start_operations(struct fscache_object *object)
291} 287}
292 288
293/* 289/*
290 * cancel an operation that's pending on an object
291 */
292int fscache_cancel_op(struct fscache_operation *op)
293{
294 struct fscache_object *object = op->object;
295 int ret;
296
297 _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id);
298
299 spin_lock(&object->lock);
300
301 ret = -EBUSY;
302 if (!list_empty(&op->pend_link)) {
303 fscache_stat(&fscache_n_op_cancelled);
304 list_del_init(&op->pend_link);
305 object->n_ops--;
306 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
307 object->n_exclusive--;
308 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
309 wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
310 fscache_put_operation(op);
311 ret = 0;
312 }
313
314 spin_unlock(&object->lock);
315 _leave(" = %d", ret);
316 return ret;
317}
318
319/*
294 * release an operation 320 * release an operation
295 * - queues pending ops if this is the last in-progress op 321 * - queues pending ops if this is the last in-progress op
296 */ 322 */
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 250dfd34c07b..e6f2e61133a1 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -295,8 +295,20 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
295 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { 295 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) {
296 _debug(">>> WT"); 296 _debug(">>> WT");
297 fscache_stat(&fscache_n_retrieval_op_waits); 297 fscache_stat(&fscache_n_retrieval_op_waits);
298 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, 298 if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
299 fscache_wait_bit, TASK_UNINTERRUPTIBLE); 299 fscache_wait_bit_interruptible,
300 TASK_INTERRUPTIBLE) < 0) {
301 ret = fscache_cancel_op(&op->op);
302 if (ret == 0) {
303 ret = -ERESTARTSYS;
304 goto error;
305 }
306
307 /* it's been removed from the pending queue by another
308 * party, so we should get to run shortly */
309 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
310 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
311 }
300 _debug("<<< GO"); 312 _debug("<<< GO");
301 } 313 }
302 314
@@ -313,6 +325,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
313 fscache_stat_d(&fscache_n_cop_read_or_alloc_page); 325 fscache_stat_d(&fscache_n_cop_read_or_alloc_page);
314 } 326 }
315 327
328error:
316 if (ret == -ENOMEM) 329 if (ret == -ENOMEM)
317 fscache_stat(&fscache_n_retrievals_nomem); 330 fscache_stat(&fscache_n_retrievals_nomem);
318 else if (ret == -ERESTARTSYS) 331 else if (ret == -ERESTARTSYS)
@@ -412,8 +425,20 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
412 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { 425 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) {
413 _debug(">>> WT"); 426 _debug(">>> WT");
414 fscache_stat(&fscache_n_retrieval_op_waits); 427 fscache_stat(&fscache_n_retrieval_op_waits);
415 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, 428 if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
416 fscache_wait_bit, TASK_UNINTERRUPTIBLE); 429 fscache_wait_bit_interruptible,
430 TASK_INTERRUPTIBLE) < 0) {
431 ret = fscache_cancel_op(&op->op);
432 if (ret == 0) {
433 ret = -ERESTARTSYS;
434 goto error;
435 }
436
437 /* it's been removed from the pending queue by another
438 * party, so we should get to run shortly */
439 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
440 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
441 }
417 _debug("<<< GO"); 442 _debug("<<< GO");
418 } 443 }
419 444
@@ -430,6 +455,7 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
430 fscache_stat_d(&fscache_n_cop_read_or_alloc_pages); 455 fscache_stat_d(&fscache_n_cop_read_or_alloc_pages);
431 } 456 }
432 457
458error:
433 if (ret == -ENOMEM) 459 if (ret == -ENOMEM)
434 fscache_stat(&fscache_n_retrievals_nomem); 460 fscache_stat(&fscache_n_retrievals_nomem);
435 else if (ret == -ERESTARTSYS) 461 else if (ret == -ERESTARTSYS)
@@ -505,8 +531,20 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
505 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { 531 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) {
506 _debug(">>> WT"); 532 _debug(">>> WT");
507 fscache_stat(&fscache_n_alloc_op_waits); 533 fscache_stat(&fscache_n_alloc_op_waits);
508 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, 534 if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
509 fscache_wait_bit, TASK_UNINTERRUPTIBLE); 535 fscache_wait_bit_interruptible,
536 TASK_INTERRUPTIBLE) < 0) {
537 ret = fscache_cancel_op(&op->op);
538 if (ret == 0) {
539 ret = -ERESTARTSYS;
540 goto error;
541 }
542
543 /* it's been removed from the pending queue by another
544 * party, so we should get to run shortly */
545 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
546 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
547 }
510 _debug("<<< GO"); 548 _debug("<<< GO");
511 } 549 }
512 550
@@ -515,7 +553,10 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
515 ret = object->cache->ops->allocate_page(op, page, gfp); 553 ret = object->cache->ops->allocate_page(op, page, gfp);
516 fscache_stat_d(&fscache_n_cop_allocate_page); 554 fscache_stat_d(&fscache_n_cop_allocate_page);
517 555
518 if (ret < 0) 556error:
557 if (ret == -ERESTARTSYS)
558 fscache_stat(&fscache_n_allocs_intr);
559 else if (ret < 0)
519 fscache_stat(&fscache_n_allocs_nobufs); 560 fscache_stat(&fscache_n_allocs_nobufs);
520 else 561 else
521 fscache_stat(&fscache_n_allocs_ok); 562 fscache_stat(&fscache_n_allocs_ok);
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c
index 20233fb44bfd..4c07439d1307 100644
--- a/fs/fscache/stats.c
+++ b/fs/fscache/stats.c
@@ -25,6 +25,7 @@ atomic_t fscache_n_op_requeue;
25atomic_t fscache_n_op_deferred_release; 25atomic_t fscache_n_op_deferred_release;
26atomic_t fscache_n_op_release; 26atomic_t fscache_n_op_release;
27atomic_t fscache_n_op_gc; 27atomic_t fscache_n_op_gc;
28atomic_t fscache_n_op_cancelled;
28 29
29atomic_t fscache_n_attr_changed; 30atomic_t fscache_n_attr_changed;
30atomic_t fscache_n_attr_changed_ok; 31atomic_t fscache_n_attr_changed_ok;
@@ -36,6 +37,7 @@ atomic_t fscache_n_allocs;
36atomic_t fscache_n_allocs_ok; 37atomic_t fscache_n_allocs_ok;
37atomic_t fscache_n_allocs_wait; 38atomic_t fscache_n_allocs_wait;
38atomic_t fscache_n_allocs_nobufs; 39atomic_t fscache_n_allocs_nobufs;
40atomic_t fscache_n_allocs_intr;
39atomic_t fscache_n_alloc_ops; 41atomic_t fscache_n_alloc_ops;
40atomic_t fscache_n_alloc_op_waits; 42atomic_t fscache_n_alloc_op_waits;
41 43
@@ -169,11 +171,12 @@ static int fscache_stats_show(struct seq_file *m, void *v)
169 atomic_read(&fscache_n_attr_changed_nomem), 171 atomic_read(&fscache_n_attr_changed_nomem),
170 atomic_read(&fscache_n_attr_changed_calls)); 172 atomic_read(&fscache_n_attr_changed_calls));
171 173
172 seq_printf(m, "Allocs : n=%u ok=%u wt=%u nbf=%u\n", 174 seq_printf(m, "Allocs : n=%u ok=%u wt=%u nbf=%u int=%u\n",
173 atomic_read(&fscache_n_allocs), 175 atomic_read(&fscache_n_allocs),
174 atomic_read(&fscache_n_allocs_ok), 176 atomic_read(&fscache_n_allocs_ok),
175 atomic_read(&fscache_n_allocs_wait), 177 atomic_read(&fscache_n_allocs_wait),
176 atomic_read(&fscache_n_allocs_nobufs)); 178 atomic_read(&fscache_n_allocs_nobufs),
179 atomic_read(&fscache_n_allocs_intr));
177 seq_printf(m, "Allocs : ops=%u owt=%u\n", 180 seq_printf(m, "Allocs : ops=%u owt=%u\n",
178 atomic_read(&fscache_n_alloc_ops), 181 atomic_read(&fscache_n_alloc_ops),
179 atomic_read(&fscache_n_alloc_op_waits)); 182 atomic_read(&fscache_n_alloc_op_waits));
@@ -201,10 +204,11 @@ static int fscache_stats_show(struct seq_file *m, void *v)
201 atomic_read(&fscache_n_store_ops), 204 atomic_read(&fscache_n_store_ops),
202 atomic_read(&fscache_n_store_calls)); 205 atomic_read(&fscache_n_store_calls));
203 206
204 seq_printf(m, "Ops : pend=%u run=%u enq=%u\n", 207 seq_printf(m, "Ops : pend=%u run=%u enq=%u can=%u\n",
205 atomic_read(&fscache_n_op_pend), 208 atomic_read(&fscache_n_op_pend),
206 atomic_read(&fscache_n_op_run), 209 atomic_read(&fscache_n_op_run),
207 atomic_read(&fscache_n_op_enqueue)); 210 atomic_read(&fscache_n_op_enqueue),
211 atomic_read(&fscache_n_op_cancelled));
208 seq_printf(m, "Ops : dfr=%u rel=%u gc=%u\n", 212 seq_printf(m, "Ops : dfr=%u rel=%u gc=%u\n",
209 atomic_read(&fscache_n_op_deferred_release), 213 atomic_read(&fscache_n_op_deferred_release),
210 atomic_read(&fscache_n_op_release), 214 atomic_read(&fscache_n_op_release),