diff --git a/lustre/include/lu_object.h b/lustre/include/lu_object.h index ef3645dab14532982d45b4a05315b33dcf755064..cf83ef1913ba4b21087215b0b223ff9eafe0a29a 100644 --- a/lustre/include/lu_object.h +++ b/lustre/include/lu_object.h @@ -798,6 +798,11 @@ void lu_object_print(const struct lu_env *env, void *cookie, */ int lu_object_invariant(const struct lu_object *o); +/* + * Finalize and free devices in the device stack. + */ +void lu_stack_fini(const struct lu_env *env, struct lu_device *top); + /* * Returns 1 iff object @o exists on the stable storage, * returns -1 iff object @o is on remote server. diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 4b100bda19874f2a790604d40c51856ee0e8a526..61a23b2f6650a0608d513de976fd78cae238b3a5 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -3507,7 +3507,6 @@ err_mdt_svc: static void mdt_stack_fini(const struct lu_env *env, struct mdt_device *m, struct lu_device *top) { - struct lu_device *d = top, *n; struct obd_device *obd = m->mdt_md_dev.md_lu_dev.ld_obd; struct lustre_cfg_bufs *bufs; struct lustre_cfg *lcfg; @@ -3536,46 +3535,7 @@ static void mdt_stack_fini(const struct lu_env *env, top->ld_ops->ldo_process_config(env, top, lcfg); lustre_cfg_free(lcfg); - lu_site_purge(env, top->ld_site, ~0); - while (d != NULL) { - struct lu_device_type *ldt = d->ld_type; - - /* each fini() returns next device in stack of layers - * so we can avoid the recursion */ - n = ldt->ldt_ops->ldto_device_fini(env, d); - lu_device_put(d); - - /* switch to the next device in the layer */ - d = n; - } - - /* purge again. */ - lu_site_purge(env, top->ld_site, ~0); - - if (!list_empty(&top->ld_site->ls_lru) || top->ld_site->ls_total != 0) { - /* - * Uh-oh, objects still exist. - */ - static DECLARE_LU_CDEBUG_PRINT_INFO(cookie, D_ERROR); - - lu_site_print(env, top->ld_site, &cookie, lu_cdebug_printer); - } - - d = top; - while (d != NULL) { - struct obd_type *type; - struct lu_device_type *ldt = d->ld_type; - - /* each free() returns next device in stack of layers - * so we can avoid the recursion */ - n = ldt->ldt_ops->ldto_device_free(env, d); - type = ldt->ldt_obd_type; - type->typ_refcnt--; - class_put_type(type); - - /* switch to the next device in the layer */ - d = n; - } + lu_stack_fini(env, top); m->mdt_child = NULL; m->mdt_bottom = NULL; } diff --git a/lustre/obdclass/lu_object.c b/lustre/obdclass/lu_object.c index 4dfe1399ad0bcc19e5fe8c98fc8b956d9608f3d0..ee55b41788b5980b89792b0f85f42b0e81ce3747 100644 --- a/lustre/obdclass/lu_object.c +++ b/lustre/obdclass/lu_object.c @@ -783,6 +783,51 @@ struct lu_object *lu_object_locate(struct lu_object_header *h, } EXPORT_SYMBOL(lu_object_locate); + + +/* + * Finalize and free devices in the device stack. + * + * Finalize device stack by purging object cache, and calling + * lu_device_type_operations::ldto_device_fini() and + * lu_device_type_operations::ldto_device_free() on all devices in the stack. + */ +void lu_stack_fini(const struct lu_env *env, struct lu_device *top) +{ + struct lu_site *site = top->ld_site; + struct lu_device *scan; + struct lu_device *next; + + lu_site_purge(env, site, ~0); + for (scan = top; scan != NULL; scan = next) { + next = scan->ld_type->ldt_ops->ldto_device_fini(env, scan); + lu_device_put(scan); + } + + /* purge again. */ + lu_site_purge(env, site, ~0); + + if (!list_empty(&site->ls_lru) || site->ls_total != 0) { + /* + * Uh-oh, objects still exist. + */ + static DECLARE_LU_CDEBUG_PRINT_INFO(cookie, D_ERROR); + + lu_site_print(env, site, &cookie, lu_cdebug_printer); + } + + for (scan = top; scan != NULL; scan = next) { + const struct lu_device_type *ldt = scan->ld_type; + struct obd_type *type; + + next = ldt->ldt_ops->ldto_device_free(env, scan); + type = ldt->ldt_obd_type; + type->typ_refcnt--; + class_put_type(type); + } +} +EXPORT_SYMBOL(lu_stack_fini); + enum { /* * Maximal number of tld slots.