char *lp_profile;
char *lp_dt;
char *lp_md;
+ int lp_refs;
+ bool lp_list_deleted;
};
struct lustre_profile *class_get_profile(const char * prof);
void class_del_profile(const char *prof);
+void class_put_profile(struct lustre_profile *lprof);
void class_del_profiles(void);
+
#if LUSTRE_TRACKS_LOCK_EXP_REFS
void __class_export_add_lock_ref(struct obd_export *, struct ldlm_lock *);
sbi->ll_client_common_fill_super_succeeded = 1;
out_free:
- if (md)
- OBD_FREE(md, strlen(lprof->lp_md) + instlen + 2);
- if (dt)
- OBD_FREE(dt, strlen(lprof->lp_dt) + instlen + 2);
- if (err)
- ll_put_super(sb);
- else if (sbi->ll_flags & LL_SBI_VERBOSE)
- LCONSOLE_WARN("Mounted %s\n", profilenm);
+ if (md)
+ OBD_FREE(md, strlen(lprof->lp_md) + instlen + 2);
+ if (dt)
+ OBD_FREE(dt, strlen(lprof->lp_dt) + instlen + 2);
+ if (lprof != NULL)
+ class_put_profile(lprof);
+ if (err)
+ ll_put_super(sb);
+ else if (sbi->ll_flags & LL_SBI_VERBOSE)
+ LCONSOLE_WARN("Mounted %s\n", profilenm);
- OBD_FREE_PTR(cfg);
- RETURN(err);
+ OBD_FREE_PTR(cfg);
+ RETURN(err);
} /* ll_fill_super */
void ll_put_super(struct super_block *sb)
lcfg = lustre_cfg_new(LCFG_ATTACH, bufs);
if (lcfg == NULL)
- GOTO(free_bufs, rc = -ENOMEM);
+ GOTO(put_profile, rc = -ENOMEM);
rc = class_attach(lcfg);
if (rc)
class_detach(obd, lcfg);
lcfg_cleanup:
lustre_cfg_free(lcfg);
+put_profile:
+ class_put_profile(lprof);
free_bufs:
OBD_FREE_PTR(bufs);
cleanup_mem:
lcfg = lustre_cfg_new(LCFG_ATTACH, bufs);
if (lcfg == NULL)
- GOTO(cleanup_mem, rc = -ENOMEM);
+ GOTO(put_profile, rc = -ENOMEM);
rc = class_attach(lcfg);
if (rc)
class_detach(obd, lcfg);
lcfg_cleanup:
lustre_cfg_free(lcfg);
+put_profile:
+ class_put_profile(lprof);
cleanup_mem:
if (bufs)
OBD_FREE_PTR(bufs);
static int __init init_obdclass(void)
{
- int i, err;
+ int i, err;
spin_lock_init(&obd_stale_export_lock);
INIT_LIST_HEAD(&obd_stale_exports);
atomic_set(&obd_stale_export_num, 0);
- LCONSOLE_INFO("Lustre: Build Version: "BUILD_VERSION"\n");
+ LCONSOLE_INFO("Lustre: Build Version: "BUILD_VERSION"\n");
spin_lock_init(&obd_types_lock);
- obd_zombie_impexp_init();
+ obd_zombie_impexp_init();
#ifdef CONFIG_PROC_FS
- obd_memory = lprocfs_alloc_stats(OBD_STATS_NUM,
+ obd_memory = lprocfs_alloc_stats(OBD_STATS_NUM,
LPROCFS_STATS_FLAG_NONE |
LPROCFS_STATS_FLAG_IRQ_SAFE);
- if (obd_memory == NULL) {
- CERROR("kmalloc of 'obd_memory' failed\n");
- RETURN(-ENOMEM);
- }
+ if (obd_memory == NULL) {
+ CERROR("kmalloc of 'obd_memory' failed\n");
+ RETURN(-ENOMEM);
+ }
- lprocfs_counter_init(obd_memory, OBD_MEMORY_STAT,
- LPROCFS_CNTR_AVGMINMAX,
- "memused", "bytes");
+ lprocfs_counter_init(obd_memory, OBD_MEMORY_STAT,
+ LPROCFS_CNTR_AVGMINMAX,
+ "memused", "bytes");
#endif
- err = obd_init_checks();
- if (err == -EOVERFLOW)
- return err;
+ err = obd_init_checks();
+ if (err == -EOVERFLOW)
+ return err;
- class_init_uuidlist();
- err = class_handle_init();
- if (err)
- return err;
+ class_init_uuidlist();
+ err = class_handle_init();
+ if (err)
+ return err;
INIT_LIST_HEAD(&obd_types);
return err;
}
- /* This struct is already zeroed for us (static global) */
- for (i = 0; i < class_devno_max(); i++)
- obd_devs[i] = NULL;
+ /* This struct is already zeroed for us (static global) */
+ for (i = 0; i < class_devno_max(); i++)
+ obd_devs[i] = NULL;
- /* Default the dirty page cache cap to 1/2 of system memory.
- * For clients with less memory, a larger fraction is needed
- * for other purposes (mostly for BGL). */
+ /* Default the dirty page cache cap to 1/2 of system memory.
+ * For clients with less memory, a larger fraction is needed
+ * for other purposes (mostly for BGL). */
if (totalram_pages <= 512 << (20 - PAGE_CACHE_SHIFT))
obd_max_dirty_pages = totalram_pages / 4;
else
obd_max_dirty_pages = totalram_pages / 2;
- err = obd_init_caches();
- if (err)
- return err;
- err = class_procfs_init();
- if (err)
- return err;
+ err = obd_init_caches();
+ if (err)
+ return err;
+ err = class_procfs_init();
+ if (err)
+ return err;
err = lu_global_init();
if (err)
if (err)
return err;
- err = lustre_register_fs();
+ err = lustre_register_fs();
- return err;
+ return err;
}
void obd_update_maxusage(void)
static struct list_head lustre_profile_list =
LIST_HEAD_INIT(lustre_profile_list);
+static DEFINE_SPINLOCK(lustre_profile_list_lock);
struct lustre_profile *class_get_profile(const char * prof)
{
- struct lustre_profile *lprof;
+ struct lustre_profile *lprof;
- ENTRY;
+ ENTRY;
+ spin_lock(&lustre_profile_list_lock);
list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
- if (!strcmp(lprof->lp_profile, prof)) {
- RETURN(lprof);
- }
- }
- RETURN(NULL);
+ if (!strcmp(lprof->lp_profile, prof)) {
+ lprof->lp_refs++;
+ spin_unlock(&lustre_profile_list_lock);
+ RETURN(lprof);
+ }
+ }
+ spin_unlock(&lustre_profile_list_lock);
+ RETURN(NULL);
}
EXPORT_SYMBOL(class_get_profile);
memcpy(lprof->lp_md, mdc, mdclen);
}
+ spin_lock(&lustre_profile_list_lock);
+ lprof->lp_refs = 1;
+ lprof->lp_list_deleted = false;
+
list_add(&lprof->lp_list, &lustre_profile_list);
+ spin_unlock(&lustre_profile_list_lock);
RETURN(err);
out:
void class_del_profile(const char *prof)
{
- struct lustre_profile *lprof;
- ENTRY;
+ struct lustre_profile *lprof;
+ ENTRY;
- CDEBUG(D_CONFIG, "Del profile %s\n", prof);
+ CDEBUG(D_CONFIG, "Del profile %s\n", prof);
- lprof = class_get_profile(prof);
- if (lprof) {
+ lprof = class_get_profile(prof);
+ if (lprof) {
+ spin_lock(&lustre_profile_list_lock);
+ /* because get profile increments the ref counter */
+ lprof->lp_refs--;
list_del(&lprof->lp_list);
- OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
- OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
- if (lprof->lp_md)
- OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
- OBD_FREE(lprof, sizeof *lprof);
- }
- EXIT;
+ lprof->lp_list_deleted = true;
+ spin_unlock(&lustre_profile_list_lock);
+
+ class_put_profile(lprof);
+ }
+ EXIT;
}
EXPORT_SYMBOL(class_del_profile);
+void class_put_profile(struct lustre_profile *lprof)
+{
+ spin_lock(&lustre_profile_list_lock);
+ if ((--lprof->lp_refs) > 0) {
+ LASSERT(lprof->lp_refs > 0);
+ spin_unlock(&lustre_profile_list_lock);
+ return;
+ }
+ spin_unlock(&lustre_profile_list_lock);
+
+ /* confirm not a negative number */
+ LASSERT(lprof->lp_refs == 0);
+
+ /* At least one class_del_profile/profiles must be called
+ * on the target profile or lustre_profile_list will corrupt */
+ LASSERT(lprof->lp_list_deleted);
+ OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
+ OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
+ if (lprof->lp_md != NULL)
+ OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
+ OBD_FREE(lprof, sizeof(*lprof));
+}
+EXPORT_SYMBOL(class_put_profile);
+
/* COMPAT_146 */
void class_del_profiles(void)
{
- struct lustre_profile *lprof, *n;
- ENTRY;
+ struct lustre_profile *lprof, *n;
+ ENTRY;
+ spin_lock(&lustre_profile_list_lock);
list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
list_del(&lprof->lp_list);
- OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
- OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
- if (lprof->lp_md)
- OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
- OBD_FREE(lprof, sizeof *lprof);
- }
- EXIT;
+ lprof->lp_list_deleted = true;
+ spin_unlock(&lustre_profile_list_lock);
+
+ class_put_profile(lprof);
+
+ spin_lock(&lustre_profile_list_lock);
+ }
+ spin_unlock(&lustre_profile_list_lock);
+ EXIT;
}
EXPORT_SYMBOL(class_del_profiles);
If there are any setup/cleanup errors, save the lov
name for safety cleanup later. */
lprof = class_get_profile(lsi->lsi_svname);
- if (lprof && lprof->lp_dt) {
- OBD_ALLOC(extraname, strlen(lprof->lp_dt) + 1);
- strcpy(extraname, lprof->lp_dt);
+ if (lprof != NULL) {
+ if (lprof->lp_dt != NULL) {
+ OBD_ALLOC(extraname, strlen(lprof->lp_dt) + 1);
+ strncpy(extraname, lprof->lp_dt,
+ strlen(lprof->lp_dt) + 1);
+ }
+ class_put_profile(lprof);
}
obd = class_name2obd(lsi->lsi_svname);