···676676 as possible.677677678678679679+ (*) Indicate that a stale object was found and discarded:680680+681681+ void fscache_object_retrying_stale(struct fscache_object *object);682682+683683+ This is called to indicate that the lookup procedure found an object in684684+ the cache that the netfs decided was stale. The object has been685685+ discarded from the cache and the lookup will be performed again.686686+687687+688688+ (*) Indicate that the caching backend killed an object:689689+690690+ void fscache_object_mark_killed(struct fscache_object *object,691691+ enum fscache_why_object_killed why);692692+693693+ This is called to indicate that the cache backend preemptively killed an694694+ object. The why parameter should be set to indicate the reason:695695+696696+ FSCACHE_OBJECT_IS_STALE - the object was stale and needs discarding.697697+ FSCACHE_OBJECT_NO_SPACE - there was insufficient cache space698698+ FSCACHE_OBJECT_WAS_RETIRED - the object was retired when relinquished.699699+ FSCACHE_OBJECT_WAS_CULLED - the object was culled to make space.700700+701701+679702 (*) Get and release references on a retrieval record:680703681704 void fscache_get_retrieval(struct fscache_retrieval *op);
+6-1
Documentation/filesystems/caching/fscache.txt
···284284 enq=N Number of times async ops queued for processing285285 can=N Number of async ops cancelled286286 rej=N Number of async ops rejected due to object lookup/create failure287287+ ini=N Number of async ops initialised287288 dfr=N Number of async ops queued for deferred release288288- rel=N Number of async ops released289289+ rel=N Number of async ops released (should equal ini=N when idle)289290 gc=N Number of deferred-release async ops garbage collected290291 CacheOp alo=N Number of in-progress alloc_object() cache ops291292 luo=N Number of in-progress lookup_object() cache ops···304303 wrp=N Number of in-progress write_page() cache ops305304 ucp=N Number of in-progress uncache_page() cache ops306305 dsp=N Number of in-progress dissociate_pages() cache ops306306+ CacheEv nsp=N Number of object lookups/creations rejected due to lack of space307307+ stl=N Number of stale objects deleted308308+ rtr=N Number of objects retired when relinquished309309+ cul=N Number of objects culled307310308311309312 (*) /proc/fs/fscache/histogram
-1
fs/cachefiles/internal.h
···4343 loff_t i_size; /* object size */4444 unsigned long flags;4545#define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */4646-#define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */4746 atomic_t usage; /* object usage count */4847 uint8_t type; /* object type */4948 uint8_t new; /* T if object new */
+21-12
fs/cachefiles/namei.c
···9797 * call vfs_unlink(), vfs_rmdir() or vfs_rename()9898 */9999static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,100100- struct dentry *dentry)100100+ struct dentry *dentry,101101+ enum fscache_why_object_killed why)101102{102103 struct cachefiles_object *object;103104 struct rb_node *p;···133132 pr_err("\n");134133 pr_err("Error: Can't preemptively bury live object\n");135134 cachefiles_printk_object(object, NULL);136136- } else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {137137- pr_err("Error: Object already preemptively buried\n");135135+ } else {136136+ if (why != FSCACHE_OBJECT_IS_STALE)137137+ fscache_object_mark_killed(&object->fscache, why);138138 }139139140140 write_unlock(&cache->active_lock);···267265static int cachefiles_bury_object(struct cachefiles_cache *cache,268266 struct dentry *dir,269267 struct dentry *rep,270270- bool preemptive)268268+ bool preemptive,269269+ enum fscache_why_object_killed why)271270{272271 struct dentry *grave, *trap;273272 struct path path, path_to_graveyard;···292289 ret = vfs_unlink(d_inode(dir), rep, NULL);293290294291 if (preemptive)295295- cachefiles_mark_object_buried(cache, rep);292292+ cachefiles_mark_object_buried(cache, rep, why);296293 }297294298295 mutex_unlock(&d_inode(dir)->i_mutex);···397394 "Rename failed with error %d", ret);398395399396 if (preemptive)400400- cachefiles_mark_object_buried(cache, rep);397397+ cachefiles_mark_object_buried(cache, rep, why);401398 }402399403400 unlock_rename(cache->graveyard, dir);···425422426423 mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);427424428428- if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {425425+ if (test_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->fscache.flags)) {429426 /* object allocation for the same key preemptively deleted this430427 * object's file so that it could create its own file */431428 _debug("object preemptively buried");···436433 * may have been renamed */437434 if (dir == object->dentry->d_parent) {438435 ret = cachefiles_bury_object(cache, dir,439439- object->dentry, false);436436+ object->dentry, false,437437+ FSCACHE_OBJECT_WAS_RETIRED);440438 } else {441439 /* it got moved, presumably by cachefilesd culling it,442440 * so it's no longer in the key path and we can ignore···526522 if (d_is_negative(next)) {527523 ret = cachefiles_has_space(cache, 1, 0);528524 if (ret < 0)529529- goto create_error;525525+ goto no_space_error;530526531527 path.dentry = dir;532528 ret = security_path_mkdir(&path, next, 0);···555551 if (d_is_negative(next)) {556552 ret = cachefiles_has_space(cache, 1, 0);557553 if (ret < 0)558558- goto create_error;554554+ goto no_space_error;559555560556 path.dentry = dir;561557 ret = security_path_mknod(&path, next, S_IFREG, 0);···606602 * mutex) */607603 object->dentry = NULL;608604609609- ret = cachefiles_bury_object(cache, dir, next, true);605605+ ret = cachefiles_bury_object(cache, dir, next, true,606606+ FSCACHE_OBJECT_IS_STALE);610607 dput(next);611608 next = NULL;612609···615610 goto delete_error;616611617612 _debug("redo lookup");613613+ fscache_object_retrying_stale(&object->fscache);618614 goto lookup_again;619615 }620616 }···668662 _leave(" = 0 [%lu]", d_backing_inode(object->dentry)->i_ino);669663 return 0;670664665665+no_space_error:666666+ fscache_object_mark_killed(&object->fscache, FSCACHE_OBJECT_NO_SPACE);671667create_error:672668 _debug("create error %d", ret);673669 if (ret == -EIO)···935927 /* actually remove the victim (drops the dir mutex) */936928 _debug("bury");937929938938- ret = cachefiles_bury_object(cache, dir, victim, false);930930+ ret = cachefiles_bury_object(cache, dir, victim, false,931931+ FSCACHE_OBJECT_WAS_CULLED);939932 if (ret < 0)940933 goto error;941934
+4-4
fs/fscache/cookie.c
···327327328328object_already_extant:329329 ret = -ENOBUFS;330330- if (fscache_object_is_dead(object)) {330330+ if (fscache_object_is_dying(object) ||331331+ fscache_cache_is_broken(object)) {331332 spin_unlock(&cookie->lock);332333 goto error;333334 }···672671 if (!op)673672 return -ENOMEM;674673675675- fscache_operation_init(op, NULL, NULL);674674+ fscache_operation_init(op, NULL, NULL, NULL);676675 op->flags = FSCACHE_OP_MYTHREAD |677676 (1 << FSCACHE_OP_WAITING) |678677 (1 << FSCACHE_OP_UNUSE_COOKIE);···696695 /* the work queue now carries its own ref on the object */697696 spin_unlock(&cookie->lock);698697699699- ret = fscache_wait_for_operation_activation(object, op,700700- NULL, NULL, NULL);698698+ ret = fscache_wait_for_operation_activation(object, op, NULL, NULL);701699 if (ret == 0) {702700 /* ask the cache to honour the operation */703701 ret = object->cache->ops->check_consistency(op);
···328328EXPORT_SYMBOL(fscache_object_init);329329330330/*331331+ * Mark the object as no longer being live, making sure that we synchronise332332+ * against op submission.333333+ */334334+static inline void fscache_mark_object_dead(struct fscache_object *object)335335+{336336+ spin_lock(&object->lock);337337+ clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);338338+ spin_unlock(&object->lock);339339+}340340+341341+/*331342 * Abort object initialisation before we start it.332343 */333344static const struct fscache_state *fscache_abort_initialisation(struct fscache_object *object,···621610 object->cache->ops->lookup_complete(object);622611 fscache_stat_d(&fscache_n_cop_lookup_complete);623612613613+ set_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->flags);614614+624615 cookie = object->cookie;625616 set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);626617 if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))···642629 _enter("{OBJ%x,%d,%d},%d",643630 object->debug_id, object->n_ops, object->n_children, event);644631645645- clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);632632+ fscache_mark_object_dead(object);646633 object->oob_event_mask = 0;647634648635 if (list_empty(&object->dependents) &&···961948 if (!op)962949 goto nomem;963950964964- fscache_operation_init(op, object->cache->ops->invalidate_object, NULL);951951+ fscache_operation_init(op, object->cache->ops->invalidate_object,952952+ NULL, NULL);965953 op->flags = FSCACHE_OP_ASYNC |966954 (1 << FSCACHE_OP_EXCLUSIVE) |967955 (1 << FSCACHE_OP_UNUSE_COOKIE);···988974 return transit_to(UPDATE_OBJECT);989975990976nomem:991991- clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);977977+ fscache_mark_object_dead(object);992978 fscache_unuse_cookie(object);993979 _leave(" [ENOMEM]");994980 return transit_to(KILL_OBJECT);995981996982submit_op_failed:997997- clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);983983+ fscache_mark_object_dead(object);998984 spin_unlock(&cookie->lock);999985 fscache_unuse_cookie(object);1000986 kfree(op);···10301016 _leave("");10311017 return transit_to(WAIT_FOR_CMD);10321018}10191019+10201020+/**10211021+ * fscache_object_retrying_stale - Note retrying stale object10221022+ * @object: The object that will be retried10231023+ *10241024+ * Note that an object lookup found an on-disk object that was adjudged to be10251025+ * stale and has been deleted. The lookup will be retried.10261026+ */10271027+void fscache_object_retrying_stale(struct fscache_object *object)10281028+{10291029+ fscache_stat(&fscache_n_cache_no_space_reject);10301030+}10311031+EXPORT_SYMBOL(fscache_object_retrying_stale);10321032+10331033+/**10341034+ * fscache_object_mark_killed - Note that an object was killed10351035+ * @object: The object that was culled10361036+ * @why: The reason the object was killed.10371037+ *10381038+ * Note that an object was killed. Returns true if the object was10391039+ * already marked killed, false if it wasn't.10401040+ */10411041+void fscache_object_mark_killed(struct fscache_object *object,10421042+ enum fscache_why_object_killed why)10431043+{10441044+ if (test_and_set_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->flags)) {10451045+ pr_err("Error: Object already killed by cache [%s]\n",10461046+ object->cache->identifier);10471047+ return;10481048+ }10491049+10501050+ switch (why) {10511051+ case FSCACHE_OBJECT_NO_SPACE:10521052+ fscache_stat(&fscache_n_cache_no_space_reject);10531053+ break;10541054+ case FSCACHE_OBJECT_IS_STALE:10551055+ fscache_stat(&fscache_n_cache_stale_objects);10561056+ break;10571057+ case FSCACHE_OBJECT_WAS_RETIRED:10581058+ fscache_stat(&fscache_n_cache_retired_objects);10591059+ break;10601060+ case FSCACHE_OBJECT_WAS_CULLED:10611061+ fscache_stat(&fscache_n_cache_culled_objects);10621062+ break;10631063+ }10641064+}10651065+EXPORT_SYMBOL(fscache_object_mark_killed);
+187-105
fs/fscache/operation.c
···2020atomic_t fscache_op_debug_id;2121EXPORT_SYMBOL(fscache_op_debug_id);22222323+static void fscache_operation_dummy_cancel(struct fscache_operation *op)2424+{2525+}2626+2727+/**2828+ * fscache_operation_init - Do basic initialisation of an operation2929+ * @op: The operation to initialise3030+ * @release: The release function to assign3131+ *3232+ * Do basic initialisation of an operation. The caller must still set flags,3333+ * object and processor if needed.3434+ */3535+void fscache_operation_init(struct fscache_operation *op,3636+ fscache_operation_processor_t processor,3737+ fscache_operation_cancel_t cancel,3838+ fscache_operation_release_t release)3939+{4040+ INIT_WORK(&op->work, fscache_op_work_func);4141+ atomic_set(&op->usage, 1);4242+ op->state = FSCACHE_OP_ST_INITIALISED;4343+ op->debug_id = atomic_inc_return(&fscache_op_debug_id);4444+ op->processor = processor;4545+ op->cancel = cancel ?: fscache_operation_dummy_cancel;4646+ op->release = release;4747+ INIT_LIST_HEAD(&op->pend_link);4848+ fscache_stat(&fscache_n_op_initialised);4949+}5050+EXPORT_SYMBOL(fscache_operation_init);5151+2352/**2453 * fscache_enqueue_operation - Enqueue an operation for processing2554 * @op: The operation to enqueue···10576}1067710778/*108108- * submit an exclusive operation for an object109109- * - other ops are excluded from running simultaneously with this one110110- * - this gets any extra refs it needs on an op111111- */112112-int fscache_submit_exclusive_op(struct fscache_object *object,113113- struct fscache_operation *op)114114-{115115- int ret;116116-117117- _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);118118-119119- ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);120120- ASSERTCMP(atomic_read(&op->usage), >, 0);121121-122122- spin_lock(&object->lock);123123- ASSERTCMP(object->n_ops, >=, object->n_in_progress);124124- ASSERTCMP(object->n_ops, >=, object->n_exclusive);125125- ASSERT(list_empty(&op->pend_link));126126-127127- op->state = FSCACHE_OP_ST_PENDING;128128- if (fscache_object_is_active(object)) {129129- op->object = object;130130- object->n_ops++;131131- object->n_exclusive++; /* reads and writes must wait */132132-133133- if (object->n_in_progress > 0) {134134- atomic_inc(&op->usage);135135- list_add_tail(&op->pend_link, &object->pending_ops);136136- fscache_stat(&fscache_n_op_pend);137137- } else if (!list_empty(&object->pending_ops)) {138138- atomic_inc(&op->usage);139139- list_add_tail(&op->pend_link, &object->pending_ops);140140- fscache_stat(&fscache_n_op_pend);141141- fscache_start_operations(object);142142- } else {143143- ASSERTCMP(object->n_in_progress, ==, 0);144144- fscache_run_op(object, op);145145- }146146-147147- /* need to issue a new write op after this */148148- clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);149149- ret = 0;150150- } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {151151- op->object = object;152152- object->n_ops++;153153- object->n_exclusive++; /* reads and writes must wait */154154- atomic_inc(&op->usage);155155- list_add_tail(&op->pend_link, &object->pending_ops);156156- fscache_stat(&fscache_n_op_pend);157157- ret = 0;158158- } else {159159- /* If we're in any other state, there must have been an I/O160160- * error of some nature.161161- */162162- ASSERT(test_bit(FSCACHE_IOERROR, &object->cache->flags));163163- ret = -EIO;164164- }165165-166166- spin_unlock(&object->lock);167167- return ret;168168-}169169-170170-/*17179 * report an unexpected submission17280 */17381static void fscache_report_unexpected_submission(struct fscache_object *object,···142176}143177144178/*179179+ * submit an exclusive operation for an object180180+ * - other ops are excluded from running simultaneously with this one181181+ * - this gets any extra refs it needs on an op182182+ */183183+int fscache_submit_exclusive_op(struct fscache_object *object,184184+ struct fscache_operation *op)185185+{186186+ const struct fscache_state *ostate;187187+ unsigned long flags;188188+ int ret;189189+190190+ _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);191191+192192+ ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);193193+ ASSERTCMP(atomic_read(&op->usage), >, 0);194194+195195+ spin_lock(&object->lock);196196+ ASSERTCMP(object->n_ops, >=, object->n_in_progress);197197+ ASSERTCMP(object->n_ops, >=, object->n_exclusive);198198+ ASSERT(list_empty(&op->pend_link));199199+200200+ ostate = object->state;201201+ smp_rmb();202202+203203+ op->state = FSCACHE_OP_ST_PENDING;204204+ flags = READ_ONCE(object->flags);205205+ if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {206206+ fscache_stat(&fscache_n_op_rejected);207207+ op->cancel(op);208208+ op->state = FSCACHE_OP_ST_CANCELLED;209209+ ret = -ENOBUFS;210210+ } else if (unlikely(fscache_cache_is_broken(object))) {211211+ op->cancel(op);212212+ op->state = FSCACHE_OP_ST_CANCELLED;213213+ ret = -EIO;214214+ } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {215215+ op->object = object;216216+ object->n_ops++;217217+ object->n_exclusive++; /* reads and writes must wait */218218+219219+ if (object->n_in_progress > 0) {220220+ atomic_inc(&op->usage);221221+ list_add_tail(&op->pend_link, &object->pending_ops);222222+ fscache_stat(&fscache_n_op_pend);223223+ } else if (!list_empty(&object->pending_ops)) {224224+ atomic_inc(&op->usage);225225+ list_add_tail(&op->pend_link, &object->pending_ops);226226+ fscache_stat(&fscache_n_op_pend);227227+ fscache_start_operations(object);228228+ } else {229229+ ASSERTCMP(object->n_in_progress, ==, 0);230230+ fscache_run_op(object, op);231231+ }232232+233233+ /* need to issue a new write op after this */234234+ clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);235235+ ret = 0;236236+ } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {237237+ op->object = object;238238+ object->n_ops++;239239+ object->n_exclusive++; /* reads and writes must wait */240240+ atomic_inc(&op->usage);241241+ list_add_tail(&op->pend_link, &object->pending_ops);242242+ fscache_stat(&fscache_n_op_pend);243243+ ret = 0;244244+ } else if (flags & BIT(FSCACHE_OBJECT_KILLED_BY_CACHE)) {245245+ op->cancel(op);246246+ op->state = FSCACHE_OP_ST_CANCELLED;247247+ ret = -ENOBUFS;248248+ } else {249249+ fscache_report_unexpected_submission(object, op, ostate);250250+ op->cancel(op);251251+ op->state = FSCACHE_OP_ST_CANCELLED;252252+ ret = -ENOBUFS;253253+ }254254+255255+ spin_unlock(&object->lock);256256+ return ret;257257+}258258+259259+/*145260 * submit an operation for an object146261 * - objects may be submitted only in the following states:147262 * - during object creation (write ops may be submitted)···234187 struct fscache_operation *op)235188{236189 const struct fscache_state *ostate;190190+ unsigned long flags;237191 int ret;238192239193 _enter("{OBJ%x OP%x},{%u}",···252204 smp_rmb();253205254206 op->state = FSCACHE_OP_ST_PENDING;255255- if (fscache_object_is_active(object)) {207207+ flags = READ_ONCE(object->flags);208208+ if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) {209209+ fscache_stat(&fscache_n_op_rejected);210210+ op->cancel(op);211211+ op->state = FSCACHE_OP_ST_CANCELLED;212212+ ret = -ENOBUFS;213213+ } else if (unlikely(fscache_cache_is_broken(object))) {214214+ op->cancel(op);215215+ op->state = FSCACHE_OP_ST_CANCELLED;216216+ ret = -EIO;217217+ } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) {256218 op->object = object;257219 object->n_ops++;258220···280222 fscache_run_op(object, op);281223 }282224 ret = 0;283283- } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {225225+ } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {284226 op->object = object;285227 object->n_ops++;286228 atomic_inc(&op->usage);287229 list_add_tail(&op->pend_link, &object->pending_ops);288230 fscache_stat(&fscache_n_op_pend);289231 ret = 0;290290- } else if (fscache_object_is_dying(object)) {291291- fscache_stat(&fscache_n_op_rejected);292292- op->state = FSCACHE_OP_ST_CANCELLED;293293- ret = -ENOBUFS;294294- } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) {295295- fscache_report_unexpected_submission(object, op, ostate);296296- ASSERT(!fscache_object_is_active(object));232232+ } else if (flags & BIT(FSCACHE_OBJECT_KILLED_BY_CACHE)) {233233+ op->cancel(op);297234 op->state = FSCACHE_OP_ST_CANCELLED;298235 ret = -ENOBUFS;299236 } else {237237+ fscache_report_unexpected_submission(object, op, ostate);238238+ ASSERT(!fscache_object_is_active(object));239239+ op->cancel(op);300240 op->state = FSCACHE_OP_ST_CANCELLED;301241 ret = -ENOBUFS;302242 }···349293 * cancel an operation that's pending on an object350294 */351295int fscache_cancel_op(struct fscache_operation *op,352352- void (*do_cancel)(struct fscache_operation *))296296+ bool cancel_in_progress_op)353297{354298 struct fscache_object *object = op->object;299299+ bool put = false;355300 int ret;356301357302 _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id);···366309 ret = -EBUSY;367310 if (op->state == FSCACHE_OP_ST_PENDING) {368311 ASSERT(!list_empty(&op->pend_link));369369- fscache_stat(&fscache_n_op_cancelled);370312 list_del_init(&op->pend_link);371371- if (do_cancel)372372- do_cancel(op);313313+ put = true;314314+315315+ fscache_stat(&fscache_n_op_cancelled);316316+ op->cancel(op);373317 op->state = FSCACHE_OP_ST_CANCELLED;374318 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))375319 object->n_exclusive--;376320 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))377321 wake_up_bit(&op->flags, FSCACHE_OP_WAITING);378378- fscache_put_operation(op);322322+ ret = 0;323323+ } else if (op->state == FSCACHE_OP_ST_IN_PROGRESS && cancel_in_progress_op) {324324+ ASSERTCMP(object->n_in_progress, >, 0);325325+ if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))326326+ object->n_exclusive--;327327+ object->n_in_progress--;328328+ if (object->n_in_progress == 0)329329+ fscache_start_operations(object);330330+331331+ fscache_stat(&fscache_n_op_cancelled);332332+ op->cancel(op);333333+ op->state = FSCACHE_OP_ST_CANCELLED;334334+ if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))335335+ object->n_exclusive--;336336+ if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))337337+ wake_up_bit(&op->flags, FSCACHE_OP_WAITING);379338 ret = 0;380339 }381340341341+ if (put)342342+ fscache_put_operation(op);382343 spin_unlock(&object->lock);383344 _leave(" = %d", ret);384345 return ret;···420345 list_del_init(&op->pend_link);421346422347 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING);348348+ op->cancel(op);423349 op->state = FSCACHE_OP_ST_CANCELLED;424350425351 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))···453377454378 spin_lock(&object->lock);455379456456- op->state = cancelled ?457457- FSCACHE_OP_ST_CANCELLED : FSCACHE_OP_ST_COMPLETE;380380+ if (!cancelled) {381381+ op->state = FSCACHE_OP_ST_COMPLETE;382382+ } else {383383+ op->cancel(op);384384+ op->state = FSCACHE_OP_ST_CANCELLED;385385+ }458386459387 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))460388 object->n_exclusive--;···489409 return;490410491411 _debug("PUT OP");492492- ASSERTIFCMP(op->state != FSCACHE_OP_ST_COMPLETE,412412+ ASSERTIFCMP(op->state != FSCACHE_OP_ST_INITIALISED &&413413+ op->state != FSCACHE_OP_ST_COMPLETE,493414 op->state, ==, FSCACHE_OP_ST_CANCELLED);494494- op->state = FSCACHE_OP_ST_DEAD;495415496416 fscache_stat(&fscache_n_op_release);497417···499419 op->release(op);500420 op->release = NULL;501421 }422422+ op->state = FSCACHE_OP_ST_DEAD;502423503424 object = op->object;425425+ if (likely(object)) {426426+ if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))427427+ atomic_dec(&object->n_reads);428428+ if (test_bit(FSCACHE_OP_UNUSE_COOKIE, &op->flags))429429+ fscache_unuse_cookie(object);504430505505- if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))506506- atomic_dec(&object->n_reads);507507- if (test_bit(FSCACHE_OP_UNUSE_COOKIE, &op->flags))508508- fscache_unuse_cookie(object);431431+ /* now... we may get called with the object spinlock held, so we432432+ * complete the cleanup here only if we can immediately acquire the433433+ * lock, and defer it otherwise */434434+ if (!spin_trylock(&object->lock)) {435435+ _debug("defer put");436436+ fscache_stat(&fscache_n_op_deferred_release);509437510510- /* now... we may get called with the object spinlock held, so we511511- * complete the cleanup here only if we can immediately acquire the512512- * lock, and defer it otherwise */513513- if (!spin_trylock(&object->lock)) {514514- _debug("defer put");515515- fscache_stat(&fscache_n_op_deferred_release);438438+ cache = object->cache;439439+ spin_lock(&cache->op_gc_list_lock);440440+ list_add_tail(&op->pend_link, &cache->op_gc_list);441441+ spin_unlock(&cache->op_gc_list_lock);442442+ schedule_work(&cache->op_gc);443443+ _leave(" [defer]");444444+ return;445445+ }516446517517- cache = object->cache;518518- spin_lock(&cache->op_gc_list_lock);519519- list_add_tail(&op->pend_link, &cache->op_gc_list);520520- spin_unlock(&cache->op_gc_list_lock);521521- schedule_work(&cache->op_gc);522522- _leave(" [defer]");523523- return;447447+ ASSERTCMP(object->n_ops, >, 0);448448+ object->n_ops--;449449+ if (object->n_ops == 0)450450+ fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);451451+452452+ spin_unlock(&object->lock);524453 }525525-526526- ASSERTCMP(object->n_ops, >, 0);527527- object->n_ops--;528528- if (object->n_ops == 0)529529- fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);530530-531531- spin_unlock(&object->lock);532454533455 kfree(op);534456 _leave(" [done]");
+43-43
fs/fscache/page.c
···213213 return -ENOMEM;214214 }215215216216- fscache_operation_init(op, fscache_attr_changed_op, NULL);216216+ fscache_operation_init(op, fscache_attr_changed_op, NULL, NULL);217217 op->flags = FSCACHE_OP_ASYNC |218218 (1 << FSCACHE_OP_EXCLUSIVE) |219219 (1 << FSCACHE_OP_UNUSE_COOKIE);···239239 wake_cookie = __fscache_unuse_cookie(cookie);240240nobufs:241241 spin_unlock(&cookie->lock);242242- kfree(op);242242+ fscache_put_operation(op);243243 if (wake_cookie)244244 __fscache_wake_unused_cookie(cookie);245245 fscache_stat(&fscache_n_attr_changed_nobufs);···247247 return -ENOBUFS;248248}249249EXPORT_SYMBOL(__fscache_attr_changed);250250+251251+/*252252+ * Handle cancellation of a pending retrieval op253253+ */254254+static void fscache_do_cancel_retrieval(struct fscache_operation *_op)255255+{256256+ struct fscache_retrieval *op =257257+ container_of(_op, struct fscache_retrieval, op);258258+259259+ atomic_set(&op->n_pages, 0);260260+}250261251262/*252263 * release a retrieval op reference···269258270259 _enter("{OP%x}", op->op.debug_id);271260272272- ASSERTCMP(atomic_read(&op->n_pages), ==, 0);261261+ ASSERTIFCMP(op->op.state != FSCACHE_OP_ST_INITIALISED,262262+ atomic_read(&op->n_pages), ==, 0);273263274264 fscache_hist(fscache_retrieval_histogram, op->start_time);275265 if (op->context)276276- fscache_put_context(op->op.object->cookie, op->context);266266+ fscache_put_context(op->cookie, op->context);277267278268 _leave("");279269}···297285 return NULL;298286 }299287300300- fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op);288288+ fscache_operation_init(&op->op, NULL,289289+ fscache_do_cancel_retrieval,290290+ fscache_release_retrieval_op);301291 op->op.flags = FSCACHE_OP_MYTHREAD |302292 (1UL << FSCACHE_OP_WAITING) |303293 (1UL << FSCACHE_OP_UNUSE_COOKIE);294294+ op->cookie = cookie;304295 op->mapping = mapping;305296 op->end_io_func = end_io_func;306297 op->context = context;307298 op->start_time = jiffies;308299 INIT_LIST_HEAD(&op->to_do);300300+301301+ /* Pin the netfs read context in case we need to do the actual netfs302302+ * read because we've encountered a cache read failure.303303+ */304304+ if (context)305305+ fscache_get_context(op->cookie, context);309306 return op;310307}311308···351330}352331353332/*354354- * Handle cancellation of a pending retrieval op355355- */356356-static void fscache_do_cancel_retrieval(struct fscache_operation *_op)357357-{358358- struct fscache_retrieval *op =359359- container_of(_op, struct fscache_retrieval, op);360360-361361- atomic_set(&op->n_pages, 0);362362-}363363-364364-/*365333 * wait for an object to become active (or dead)366334 */367335int fscache_wait_for_operation_activation(struct fscache_object *object,368336 struct fscache_operation *op,369337 atomic_t *stat_op_waits,370370- atomic_t *stat_object_dead,371371- void (*do_cancel)(struct fscache_operation *))338338+ atomic_t *stat_object_dead)372339{373340 int ret;374341···368359 fscache_stat(stat_op_waits);369360 if (wait_on_bit(&op->flags, FSCACHE_OP_WAITING,370361 TASK_INTERRUPTIBLE) != 0) {371371- ret = fscache_cancel_op(op, do_cancel);362362+ ret = fscache_cancel_op(op, false);372363 if (ret == 0)373364 return -ERESTARTSYS;374365···386377 _leave(" = -ENOBUFS [cancelled]");387378 return -ENOBUFS;388379 }389389- if (unlikely(fscache_object_is_dead(object))) {390390- pr_err("%s() = -ENOBUFS [obj dead %d]\n", __func__, op->state);391391- fscache_cancel_op(op, do_cancel);380380+ if (unlikely(fscache_object_is_dying(object) ||381381+ fscache_cache_is_broken(object))) {382382+ enum fscache_operation_state state = op->state;383383+ fscache_cancel_op(op, true);392384 if (stat_object_dead)393385 fscache_stat(stat_object_dead);386386+ _leave(" = -ENOBUFS [obj dead %d]", state);394387 return -ENOBUFS;395388 }396389 return 0;···464453465454 fscache_stat(&fscache_n_retrieval_ops);466455467467- /* pin the netfs read context in case we need to do the actual netfs468468- * read because we've encountered a cache read failure */469469- fscache_get_context(object->cookie, op->context);470470-471456 /* we wait for the operation to become active, and then process it472457 * *here*, in this thread, and not in the thread pool */473458 ret = fscache_wait_for_operation_activation(474459 object, &op->op,475460 __fscache_stat(&fscache_n_retrieval_op_waits),476476- __fscache_stat(&fscache_n_retrievals_object_dead),477477- fscache_do_cancel_retrieval);461461+ __fscache_stat(&fscache_n_retrievals_object_dead));478462 if (ret < 0)479463 goto error;480464···509503 spin_unlock(&cookie->lock);510504 if (wake_cookie)511505 __fscache_wake_unused_cookie(cookie);512512- kfree(op);506506+ fscache_put_retrieval(op);513507nobufs:514508 fscache_stat(&fscache_n_retrievals_nobufs);515509 _leave(" = -ENOBUFS");···590584591585 fscache_stat(&fscache_n_retrieval_ops);592586593593- /* pin the netfs read context in case we need to do the actual netfs594594- * read because we've encountered a cache read failure */595595- fscache_get_context(object->cookie, op->context);596596-597587 /* we wait for the operation to become active, and then process it598588 * *here*, in this thread, and not in the thread pool */599589 ret = fscache_wait_for_operation_activation(600590 object, &op->op,601591 __fscache_stat(&fscache_n_retrieval_op_waits),602602- __fscache_stat(&fscache_n_retrievals_object_dead),603603- fscache_do_cancel_retrieval);592592+ __fscache_stat(&fscache_n_retrievals_object_dead));604593 if (ret < 0)605594 goto error;606595···633632 wake_cookie = __fscache_unuse_cookie(cookie);634633nobufs_unlock:635634 spin_unlock(&cookie->lock);636636- kfree(op);635635+ fscache_put_retrieval(op);637636 if (wake_cookie)638637 __fscache_wake_unused_cookie(cookie);639638nobufs:···701700 ret = fscache_wait_for_operation_activation(702701 object, &op->op,703702 __fscache_stat(&fscache_n_alloc_op_waits),704704- __fscache_stat(&fscache_n_allocs_object_dead),705705- fscache_do_cancel_retrieval);703703+ __fscache_stat(&fscache_n_allocs_object_dead));706704 if (ret < 0)707705 goto error;708706···726726 wake_cookie = __fscache_unuse_cookie(cookie);727727nobufs_unlock:728728 spin_unlock(&cookie->lock);729729- kfree(op);729729+ fscache_put_retrieval(op);730730 if (wake_cookie)731731 __fscache_wake_unused_cookie(cookie);732732nobufs:···944944 if (!op)945945 goto nomem;946946947947- fscache_operation_init(&op->op, fscache_write_op,947947+ fscache_operation_init(&op->op, fscache_write_op, NULL,948948 fscache_release_write_op);949949 op->op.flags = FSCACHE_OP_ASYNC |950950 (1 << FSCACHE_OP_WAITING) |···10161016 spin_unlock(&object->lock);10171017 spin_unlock(&cookie->lock);10181018 radix_tree_preload_end();10191019- kfree(op);10191019+ fscache_put_operation(&op->op);10201020 fscache_stat(&fscache_n_stores_ok);10211021 _leave(" = 0");10221022 return 0;···10361036nobufs:10371037 spin_unlock(&cookie->lock);10381038 radix_tree_preload_end();10391039- kfree(op);10391039+ fscache_put_operation(&op->op);10401040 if (wake_cookie)10411041 __fscache_wake_unused_cookie(cookie);10421042 fscache_stat(&fscache_n_stores_nobufs);···10441044 return -ENOBUFS;1045104510461046nomem_free:10471047- kfree(op);10471047+ fscache_put_operation(&op->op);10481048nomem:10491049 fscache_stat(&fscache_n_stores_oom);10501050 _leave(" = -ENOMEM");