~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/fscache/operation.c

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.72 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* FS-Cache worker operation management routines
  2  *
  3  * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
  4  * Written by David Howells (dhowells@redhat.com)
  5  *
  6  * This program is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU General Public License
  8  * as published by the Free Software Foundation; either version
  9  * 2 of the License, or (at your option) any later version.
 10  *
 11  * See Documentation/filesystems/caching/operations.txt
 12  */
 13 
 14 #define FSCACHE_DEBUG_LEVEL OPERATION
 15 #include <linux/module.h>
 16 #include <linux/seq_file.h>
 17 #include <linux/slab.h>
 18 #include "internal.h"
 19 
 20 atomic_t fscache_op_debug_id;
 21 EXPORT_SYMBOL(fscache_op_debug_id);
 22 
 23 static void fscache_operation_dummy_cancel(struct fscache_operation *op)
 24 {
 25 }
 26 
 27 /**
 28  * fscache_operation_init - Do basic initialisation of an operation
 29  * @op: The operation to initialise
 30  * @release: The release function to assign
 31  *
 32  * Do basic initialisation of an operation.  The caller must still set flags,
 33  * object and processor if needed.
 34  */
 35 void fscache_operation_init(struct fscache_operation *op,
 36                             fscache_operation_processor_t processor,
 37                             fscache_operation_cancel_t cancel,
 38                             fscache_operation_release_t release)
 39 {
 40         INIT_WORK(&op->work, fscache_op_work_func);
 41         atomic_set(&op->usage, 1);
 42         op->state = FSCACHE_OP_ST_INITIALISED;
 43         op->debug_id = atomic_inc_return(&fscache_op_debug_id);
 44         op->processor = processor;
 45         op->cancel = cancel ?: fscache_operation_dummy_cancel;
 46         op->release = release;
 47         INIT_LIST_HEAD(&op->pend_link);
 48         fscache_stat(&fscache_n_op_initialised);
 49 }
 50 EXPORT_SYMBOL(fscache_operation_init);
 51 
 52 /**
 53  * fscache_enqueue_operation - Enqueue an operation for processing
 54  * @op: The operation to enqueue
 55  *
 56  * Enqueue an operation for processing by the FS-Cache thread pool.
 57  *
 58  * This will get its own ref on the object.
 59  */
 60 void fscache_enqueue_operation(struct fscache_operation *op)
 61 {
 62         _enter("{OBJ%x OP%x,%u}",
 63                op->object->debug_id, op->debug_id, atomic_read(&op->usage));
 64 
 65         ASSERT(list_empty(&op->pend_link));
 66         ASSERT(op->processor != NULL);
 67         ASSERT(fscache_object_is_available(op->object));
 68         ASSERTCMP(atomic_read(&op->usage), >, 0);
 69         ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
 70 
 71         fscache_stat(&fscache_n_op_enqueue);
 72         switch (op->flags & FSCACHE_OP_TYPE) {
 73         case FSCACHE_OP_ASYNC:
 74                 _debug("queue async");
 75                 atomic_inc(&op->usage);
 76                 if (!queue_work(fscache_op_wq, &op->work))
 77                         fscache_put_operation(op);
 78                 break;
 79         case FSCACHE_OP_MYTHREAD:
 80                 _debug("queue for caller's attention");
 81                 break;
 82         default:
 83                 pr_err("Unexpected op type %lx", op->flags);
 84                 BUG();
 85                 break;
 86         }
 87 }
 88 EXPORT_SYMBOL(fscache_enqueue_operation);
 89 
 90 /*
 91  * start an op running
 92  */
 93 static void fscache_run_op(struct fscache_object *object,
 94                            struct fscache_operation *op)
 95 {
 96         ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING);
 97 
 98         op->state = FSCACHE_OP_ST_IN_PROGRESS;
 99         object->n_in_progress++;
100         if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
101                 wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
102         if (op->processor)
103                 fscache_enqueue_operation(op);
104         fscache_stat(&fscache_n_op_run);
105 }
106 
107 /*
108  * report an unexpected submission
109  */
110 static void fscache_report_unexpected_submission(struct fscache_object *object,
111                                                  struct fscache_operation *op,
112                                                  const struct fscache_state *ostate)
113 {
114         static bool once_only;
115         struct fscache_operation *p;
116         unsigned n;
117 
118         if (once_only)
119                 return;
120         once_only = true;
121 
122         kdebug("unexpected submission OP%x [OBJ%x %s]",
123                op->debug_id, object->debug_id, object->state->name);
124         kdebug("objstate=%s [%s]", object->state->name, ostate->name);
125         kdebug("objflags=%lx", object->flags);
126         kdebug("objevent=%lx [%lx]", object->events, object->event_mask);
127         kdebug("ops=%u inp=%u exc=%u",
128                object->n_ops, object->n_in_progress, object->n_exclusive);
129 
130         if (!list_empty(&object->pending_ops)) {
131                 n = 0;
132                 list_for_each_entry(p, &object->pending_ops, pend_link) {
133                         ASSERTCMP(p->object, ==, object);
134                         kdebug("%p %p", op->processor, op->release);
135                         n++;
136                 }
137 
138                 kdebug("n=%u", n);
139         }
140 
141         dump_stack();
142 }
143 
144 /*
145  * submit an exclusive operation for an object
146  * - other ops are excluded from running simultaneously with this one
147  * - this gets any extra refs it needs on an op
148  */
149 int fscache_submit_exclusive_op(struct fscache_object *object,
150                                 struct fscache_operation *op)
151 {
152         const struct fscache_state *ostate;
153         unsigned long flags;
154         int ret;
155 
156         _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
157 
158         ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
159         ASSERTCMP(atomic_read(&op->usage), >, 0);
160 
161         spin_lock(&object->lock);
162         ASSERTCMP(object->n_ops, >=, object->n_in_progress);
163         ASSERTCMP(object->n_ops, >=, object->n_exclusive);
164         ASSERT(list_empty(&op->pend_link));
165 
166         ostate = object->state;
167         smp_rmb();
168 
169         op->state = FSCACHE_OP_ST_PENDING;
170         flags = READ_ONCE(object->flags);
171         if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {
172                 fscache_stat(&fscache_n_op_rejected);
173                 op->cancel(op);
174                 op->state = FSCACHE_OP_ST_CANCELLED;
175                 ret = -ENOBUFS;
176         } else if (unlikely(fscache_cache_is_broken(object))) {
177                 op->cancel(op);
178                 op->state = FSCACHE_OP_ST_CANCELLED;
179                 ret = -EIO;
180         } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {
181                 op->object = object;
182                 object->n_ops++;
183                 object->n_exclusive++;  /* reads and writes must wait */
184 
185                 if (object->n_in_progress > 0) {
186                         atomic_inc(&op->usage);
187                         list_add_tail(&op->pend_link, &object->pending_ops);
188                         fscache_stat(&fscache_n_op_pend);
189                 } else if (!list_empty(&object->pending_ops)) {
190                         atomic_inc(&op->usage);
191                         list_add_tail(&op->pend_link, &object->pending_ops);
192                         fscache_stat(&fscache_n_op_pend);
193                         fscache_start_operations(object);
194                 } else {
195                         ASSERTCMP(object->n_in_progress, ==, 0);
196                         fscache_run_op(object, op);
197                 }
198 
199                 /* need to issue a new write op after this */
200                 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
201                 ret = 0;
202         } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
203                 op->object = object;
204                 object->n_ops++;
205                 object->n_exclusive++;  /* reads and writes must wait */
206                 atomic_inc(&op->usage);
207                 list_add_tail(&op->pend_link, &object->pending_ops);
208                 fscache_stat(&fscache_n_op_pend);
209                 ret = 0;
210         } else if (flags & BIT(FSCACHE_OBJECT_KILLED_BY_CACHE)) {
211                 op->cancel(op);
212                 op->state = FSCACHE_OP_ST_CANCELLED;
213                 ret = -ENOBUFS;
214         } else {
215                 fscache_report_unexpected_submission(object, op, ostate);
216                 op->cancel(op);
217                 op->state = FSCACHE_OP_ST_CANCELLED;
218                 ret = -ENOBUFS;
219         }
220 
221         spin_unlock(&object->lock);
222         return ret;
223 }
224 
225 /*
226  * submit an operation for an object
227  * - objects may be submitted only in the following states:
228  *   - during object creation (write ops may be submitted)
229  *   - whilst the object is active
230  *   - after an I/O error incurred in one of the two above states (op rejected)
231  * - this gets any extra refs it needs on an op
232  */
233 int fscache_submit_op(struct fscache_object *object,
234                       struct fscache_operation *op)
235 {
236         const struct fscache_state *ostate;
237         unsigned long flags;
238         int ret;
239 
240         _enter("{OBJ%x OP%x},{%u}",
241                object->debug_id, op->debug_id, atomic_read(&op->usage));
242 
243         ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
244         ASSERTCMP(atomic_read(&op->usage), >, 0);
245 
246         spin_lock(&object->lock);
247         ASSERTCMP(object->n_ops, >=, object->n_in_progress);
248         ASSERTCMP(object->n_ops, >=, object->n_exclusive);
249         ASSERT(list_empty(&op->pend_link));
250 
251         ostate = object->state;
252         smp_rmb();
253 
254         op->state = FSCACHE_OP_ST_PENDING;
255         flags = READ_ONCE(object->flags);
256         if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {
257                 fscache_stat(&fscache_n_op_rejected);
258                 op->cancel(op);
259                 op->state = FSCACHE_OP_ST_CANCELLED;
260                 ret = -ENOBUFS;
261         } else if (unlikely(fscache_cache_is_broken(object))) {
262                 op->cancel(op);
263                 op->state = FSCACHE_OP_ST_CANCELLED;
264                 ret = -EIO;
265         } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {
266                 op->object = object;
267                 object->n_ops++;
268 
269                 if (object->n_exclusive > 0) {
270                         atomic_inc(&op->usage);
271                         list_add_tail(&op->pend_link, &object->pending_ops);
272                         fscache_stat(&fscache_n_op_pend);
273                 } else if (!list_empty(&object->pending_ops)) {
274                         atomic_inc(&op->usage);
275                         list_add_tail(&op->pend_link, &object->pending_ops);
276                         fscache_stat(&fscache_n_op_pend);
277                         fscache_start_operations(object);
278                 } else {
279                         ASSERTCMP(object->n_exclusive, ==, 0);
280                         fscache_run_op(object, op);
281                 }
282                 ret = 0;
283         } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
284                 op->object = object;
285                 object->n_ops++;
286                 atomic_inc(&op->usage);
287                 list_add_tail(&op->pend_link, &object->pending_ops);
288                 fscache_stat(&fscache_n_op_pend);
289                 ret = 0;
290         } else if (flags & BIT(FSCACHE_OBJECT_KILLED_BY_CACHE)) {
291                 op->cancel(op);
292                 op->state = FSCACHE_OP_ST_CANCELLED;
293                 ret = -ENOBUFS;
294         } else {
295                 fscache_report_unexpected_submission(object, op, ostate);
296                 ASSERT(!fscache_object_is_active(object));
297                 op->cancel(op);
298                 op->state = FSCACHE_OP_ST_CANCELLED;
299                 ret = -ENOBUFS;
300         }
301 
302         spin_unlock(&object->lock);
303         return ret;
304 }
305 
306 /*
307  * queue an object for withdrawal on error, aborting all following asynchronous
308  * operations
309  */
310 void fscache_abort_object(struct fscache_object *object)
311 {
312         _enter("{OBJ%x}", object->debug_id);
313 
314         fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR);
315 }
316 
317 /*
318  * Jump start the operation processing on an object.  The caller must hold
319  * object->lock.
320  */
321 void fscache_start_operations(struct fscache_object *object)
322 {
323         struct fscache_operation *op;
324         bool stop = false;
325 
326         while (!list_empty(&object->pending_ops) && !stop) {
327                 op = list_entry(object->pending_ops.next,
328                                 struct fscache_operation, pend_link);
329 
330                 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) {
331                         if (object->n_in_progress > 0)
332                                 break;
333                         stop = true;
334                 }
335                 list_del_init(&op->pend_link);
336                 fscache_run_op(object, op);
337 
338                 /* the pending queue was holding a ref on the object */
339                 fscache_put_operation(op);
340         }
341 
342         ASSERTCMP(object->n_in_progress, <=, object->n_ops);
343 
344         _debug("woke %d ops on OBJ%x",
345                object->n_in_progress, object->debug_id);
346 }
347 
348 /*
349  * cancel an operation that's pending on an object
350  */
351 int fscache_cancel_op(struct fscache_operation *op,
352                       bool cancel_in_progress_op)
353 {
354         struct fscache_object *object = op->object;
355         bool put = false;
356         int ret;
357 
358         _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id);
359 
360         ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING);
361         ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED);
362         ASSERTCMP(atomic_read(&op->usage), >, 0);
363 
364         spin_lock(&object->lock);
365 
366         ret = -EBUSY;
367         if (op->state == FSCACHE_OP_ST_PENDING) {
368                 ASSERT(!list_empty(&op->pend_link));
369                 list_del_init(&op->pend_link);
370                 put = true;
371 
372                 fscache_stat(&fscache_n_op_cancelled);
373                 op->cancel(op);
374                 op->state = FSCACHE_OP_ST_CANCELLED;
375                 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
376                         object->n_exclusive--;
377                 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
378                         wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
379                 ret = 0;
380         } else if (op->state == FSCACHE_OP_ST_IN_PROGRESS && cancel_in_progress_op) {
381                 ASSERTCMP(object->n_in_progress, >, 0);
382                 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
383                         object->n_exclusive--;
384                 object->n_in_progress--;
385                 if (object->n_in_progress == 0)
386                         fscache_start_operations(object);
387 
388                 fscache_stat(&fscache_n_op_cancelled);
389                 op->cancel(op);
390                 op->state = FSCACHE_OP_ST_CANCELLED;
391                 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
392                         object->n_exclusive--;
393                 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
394                         wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
395                 ret = 0;
396         }
397 
398         if (put)
399                 fscache_put_operation(op);
400         spin_unlock(&object->lock);
401         _leave(" = %d", ret);
402         return ret;
403 }
404 
405 /*
406  * Cancel all pending operations on an object
407  */
408 void fscache_cancel_all_ops(struct fscache_object *object)
409 {
410         struct fscache_operation *op;
411 
412         _enter("OBJ%x", object->debug_id);
413 
414         spin_lock(&object->lock);
415 
416         while (!list_empty(&object->pending_ops)) {
417                 op = list_entry(object->pending_ops.next,
418                                 struct fscache_operation, pend_link);
419                 fscache_stat(&fscache_n_op_cancelled);
420                 list_del_init(&op->pend_link);
421 
422                 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING);
423                 op->cancel(op);
424                 op->state = FSCACHE_OP_ST_CANCELLED;
425 
426                 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
427                         object->n_exclusive--;
428                 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
429                         wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
430                 fscache_put_operation(op);
431                 cond_resched_lock(&object->lock);
432         }
433 
434         spin_unlock(&object->lock);
435         _leave("");
436 }
437 
438 /*
439  * Record the completion or cancellation of an in-progress operation.
440  */
441 void fscache_op_complete(struct fscache_operation *op, bool cancelled)
442 {
443         struct fscache_object *object = op->object;
444 
445         _enter("OBJ%x", object->debug_id);
446 
447         ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
448         ASSERTCMP(object->n_in_progress, >, 0);
449         ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags),
450                     object->n_exclusive, >, 0);
451         ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags),
452                     object->n_in_progress, ==, 1);
453 
454         spin_lock(&object->lock);
455 
456         if (!cancelled) {
457                 op->state = FSCACHE_OP_ST_COMPLETE;
458         } else {
459                 op->cancel(op);
460                 op->state = FSCACHE_OP_ST_CANCELLED;
461         }
462 
463         if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
464                 object->n_exclusive--;
465         object->n_in_progress--;
466         if (object->n_in_progress == 0)
467                 fscache_start_operations(object);
468 
469         spin_unlock(&object->lock);
470         _leave("");
471 }
472 EXPORT_SYMBOL(fscache_op_complete);
473 
474 /*
475  * release an operation
476  * - queues pending ops if this is the last in-progress op
477  */
478 void fscache_put_operation(struct fscache_operation *op)
479 {
480         struct fscache_object *object;
481         struct fscache_cache *cache;
482 
483         _enter("{OBJ%x OP%x,%d}",
484                op->object->debug_id, op->debug_id, atomic_read(&op->usage));
485 
486         ASSERTCMP(atomic_read(&op->usage), >, 0);
487 
488         if (!atomic_dec_and_test(&op->usage))
489                 return;
490 
491         _debug("PUT OP");
492         ASSERTIFCMP(op->state != FSCACHE_OP_ST_INITIALISED &&
493                     op->state != FSCACHE_OP_ST_COMPLETE,
494                     op->state, ==, FSCACHE_OP_ST_CANCELLED);
495 
496         fscache_stat(&fscache_n_op_release);
497 
498         if (op->release) {
499                 op->release(op);
500                 op->release = NULL;
501         }
502         op->state = FSCACHE_OP_ST_DEAD;
503 
504         object = op->object;
505         if (likely(object)) {
506                 if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))
507                         atomic_dec(&object->n_reads);
508                 if (test_bit(FSCACHE_OP_UNUSE_COOKIE, &op->flags))
509                         fscache_unuse_cookie(object);
510 
511                 /* now... we may get called with the object spinlock held, so we
512                  * complete the cleanup here only if we can immediately acquire the
513                  * lock, and defer it otherwise */
514                 if (!spin_trylock(&object->lock)) {
515                         _debug("defer put");
516                         fscache_stat(&fscache_n_op_deferred_release);
517 
518                         cache = object->cache;
519                         spin_lock(&cache->op_gc_list_lock);
520                         list_add_tail(&op->pend_link, &cache->op_gc_list);
521                         spin_unlock(&cache->op_gc_list_lock);
522                         schedule_work(&cache->op_gc);
523                         _leave(" [defer]");
524                         return;
525                 }
526 
527                 ASSERTCMP(object->n_ops, >, 0);
528                 object->n_ops--;
529                 if (object->n_ops == 0)
530                         fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);
531 
532                 spin_unlock(&object->lock);
533         }
534 
535         kfree(op);
536         _leave(" [done]");
537 }
538 EXPORT_SYMBOL(fscache_put_operation);
539 
540 /*
541  * garbage collect operations that have had their release deferred
542  */
543 void fscache_operation_gc(struct work_struct *work)
544 {
545         struct fscache_operation *op;
546         struct fscache_object *object;
547         struct fscache_cache *cache =
548                 container_of(work, struct fscache_cache, op_gc);
549         int count = 0;
550 
551         _enter("");
552 
553         do {
554                 spin_lock(&cache->op_gc_list_lock);
555                 if (list_empty(&cache->op_gc_list)) {
556                         spin_unlock(&cache->op_gc_list_lock);
557                         break;
558                 }
559 
560                 op = list_entry(cache->op_gc_list.next,
561                                 struct fscache_operation, pend_link);
562                 list_del(&op->pend_link);
563                 spin_unlock(&cache->op_gc_list_lock);
564 
565                 object = op->object;
566                 spin_lock(&object->lock);
567 
568                 _debug("GC DEFERRED REL OBJ%x OP%x",
569                        object->debug_id, op->debug_id);
570                 fscache_stat(&fscache_n_op_gc);
571 
572                 ASSERTCMP(atomic_read(&op->usage), ==, 0);
573                 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD);
574 
575                 ASSERTCMP(object->n_ops, >, 0);
576                 object->n_ops--;
577                 if (object->n_ops == 0)
578                         fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);
579 
580                 spin_unlock(&object->lock);
581                 kfree(op);
582 
583         } while (count++ < 20);
584 
585         if (!list_empty(&cache->op_gc_list))
586                 schedule_work(&cache->op_gc);
587 
588         _leave("");
589 }
590 
591 /*
592  * execute an operation using fs_op_wq to provide processing context -
593  * the caller holds a ref to this object, so we don't need to hold one
594  */
595 void fscache_op_work_func(struct work_struct *work)
596 {
597         struct fscache_operation *op =
598                 container_of(work, struct fscache_operation, work);
599         unsigned long start;
600 
601         _enter("{OBJ%x OP%x,%d}",
602                op->object->debug_id, op->debug_id, atomic_read(&op->usage));
603 
604         ASSERT(op->processor != NULL);
605         start = jiffies;
606         op->processor(op);
607         fscache_hist(fscache_ops_histogram, start);
608         fscache_put_operation(op);
609 
610         _leave("");
611 }
612 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp