diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 99819676425ae701929ec705ecb2841263d9621a..9ace837dd4a05b8260b7c71444f92f9a181a383a 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -46,6 +46,12 @@ Details : The ldiskfs mballoc3 code was using a __u16 to store the group number, but with 8TB+ filesystems there are more than 65536 groups, causing an oops. +Severity : normal +Bugzilla : 15576 +Description: Resolve device initialization race +Details : Prevent proc handler from accessing devices added to the + obd_devs array but yet be intialized. + Severity : enhancement Bugzilla : 15308 Description: Update to SLES10 SP2 kernel-2.6.16.60-0.23. diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index 0834dbfa679ee0953a8c254966223bd0d9b6d672..f82c9babee932469537dd7da92d2892813d8b122 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -86,7 +86,7 @@ static void obd_device_free(struct obd_device *obd) "%08x != %08x\n", obd, obd->obd_magic, OBD_DEVICE_MAGIC); if (obd->obd_namespace != NULL) { CERROR("obd %p: namespace %p was not properly cleaned up " - "(obd_force=%d)!\n", + "(obd_force=%d)!\n", obd, obd->obd_namespace, obd->obd_force); LBUG(); } @@ -118,7 +118,7 @@ struct obd_type *class_get_type(const char *name) #ifdef CONFIG_KMOD if (!type) { const char *modname = name; - if (strcmp(modname, LUSTRE_MDT_NAME) == 0) + if (strcmp(modname, LUSTRE_MDT_NAME) == 0) modname = LUSTRE_MDS_NAME; if (!request_module(modname)) { CDEBUG(D_INFO, "Loaded module '%s'\n", modname); @@ -218,7 +218,7 @@ int class_unregister_type(const char *name) RETURN(-EBUSY); } - if (type->typ_procroot) + if (type->typ_procroot) lprocfs_remove(&type->typ_procroot); spin_lock(&obd_types_lock); @@ -231,6 +231,17 @@ int class_unregister_type(const char *name) RETURN(0); } /* class_unregister_type */ +/** + * Create a new obd device. + * + * Find an empty slot in ::obd_devs[], create a new obd device in it. + * + * \param typename [in] obd device type string. + * \param name [in] obd device name. + * + * \retval NULL if create fails, otherwise return the obd device + * pointer created. + */ struct obd_device *class_newdev(const char *type_name, const char *name) { struct obd_device *result = NULL; @@ -239,7 +250,7 @@ struct obd_device *class_newdev(const char *type_name, const char *name) int i; int new_obd_minor = 0; - if (strlen(name) > MAX_OBD_NAME) { + if (strlen(name) >= MAX_OBD_NAME) { CERROR("name/uuid must be < %u bytes long\n", MAX_OBD_NAME); RETURN(ERR_PTR(-EINVAL)); } @@ -251,7 +262,7 @@ struct obd_device *class_newdev(const char *type_name, const char *name) } newdev = obd_device_alloc(); - if (newdev == NULL) { + if (newdev == NULL) { class_put_type(type); RETURN(ERR_PTR(-ENOMEM)); } @@ -281,18 +292,19 @@ struct obd_device *class_newdev(const char *type_name, const char *name) result->obd_minor = i; new_obd_minor = i; result->obd_type = type; - memcpy(result->obd_name, name, strlen(name)); + strncpy(result->obd_name, name, + sizeof(result->obd_name) - 1); obd_devs[i] = result; } } spin_unlock(&obd_dev_lock); - + if (result == NULL && i >= class_devno_max()) { CERROR("all %u OBD devices used, increase MAX_OBD_DEVICES\n", class_devno_max()); result = ERR_PTR(-EOVERFLOW); } - + if (IS_ERR(result)) { obd_device_free(newdev); class_put_type(type); @@ -385,15 +397,22 @@ struct obd_device *class_uuid2obd(struct obd_uuid *uuid) return class_num2obd(dev); } +/** + * Get obd device from ::obd_devs[] + * + * \param num [in] array index + * + * \retval NULL if ::obd_devs[\a num] does not contains an obd device + * otherwise return the obd device there. + */ struct obd_device *class_num2obd(int num) { struct obd_device *obd = NULL; if (num < class_devno_max()) { obd = obd_devs[num]; - if (obd == NULL) { + if (obd == NULL) return NULL; - } LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "%p obd_magic %08x != %08x\n", @@ -537,7 +556,7 @@ int obd_init_caches(void) LASSERT(obd_device_cachep == NULL); obd_device_cachep = cfs_mem_cache_create("ll_obd_dev_cache", - sizeof(struct obd_device), + sizeof(struct obd_device), 0, 0); if (!obd_device_cachep) GOTO(out, -ENOMEM); @@ -631,7 +650,7 @@ void __class_export_put(struct obd_export *exp) CDEBUG(D_IOCTL, "final put %p/%s\n", exp, exp->exp_client_uuid.uuid); - + spin_lock(&obd_zombie_impexp_lock); list_add(&exp->exp_obd_chain, &obd_zombie_exports); spin_unlock(&obd_zombie_impexp_lock); @@ -698,7 +717,7 @@ struct obd_export *class_new_export(struct obd_device *obd, obd_init_export(export); if (!obd_uuid_equals(cluuid, &obd->obd_uuid)) { - rc = lustre_hash_additem_unique(obd->obd_uuid_hash_body, cluuid, + rc = lustre_hash_additem_unique(obd->obd_uuid_hash_body, cluuid, &export->exp_uuid_hash); if (rc != 0) { CWARN("%s: denying duplicate export for %s\n", @@ -729,7 +748,7 @@ void class_unlink_export(struct obd_export *exp) spin_lock(&exp->exp_obd->obd_dev_lock); /* delete an uuid-export hashitem from hashtables */ if (!hlist_unhashed(&exp->exp_uuid_hash)) { - lustre_hash_delitem(exp->exp_obd->obd_uuid_hash_body, + lustre_hash_delitem(exp->exp_obd->obd_uuid_hash_body, &exp->exp_client_uuid, &exp->exp_uuid_hash); } list_del_init(&exp->exp_obd_chain); @@ -772,7 +791,7 @@ void class_import_put(struct obd_import *import) if (atomic_dec_and_test(&import->imp_refcount)) { CDEBUG(D_INFO, "final put import %p\n", import); - + spin_lock(&obd_zombie_impexp_lock); list_add(&import->imp_zombie_chain, &obd_zombie_imports); spin_unlock(&obd_zombie_impexp_lock); @@ -787,7 +806,7 @@ EXPORT_SYMBOL(class_import_put); void class_import_destroy(struct obd_import *import) { ENTRY; - + CDEBUG(D_IOCTL, "destroying import %p\n", import); LASSERT(atomic_read(&import->imp_refcount) == 0); @@ -1223,7 +1242,7 @@ char *obd_export_nid2str(struct obd_export *exp) { if (exp->exp_connection != NULL) return libcfs_nid2str(exp->exp_connection->c_peer.nid); - + return "(no nid)"; } EXPORT_SYMBOL(obd_export_nid2str); @@ -1246,7 +1265,7 @@ int obd_export_evict_by_nid(struct obd_device *obd, char *nid) "nid %s found, wanted nid %s, requested nid %s\n", obd_export_nid2str(doomed_exp), libcfs_nid2str(nid_key), nid); - + exports_evicted++; CDEBUG(D_HA, "%s: evict NID '%s' (%s) #%d at adminstrative request\n", obd->obd_name, nid, doomed_exp->exp_client_uuid.uuid, @@ -1274,7 +1293,7 @@ int obd_export_evict_by_uuid(struct obd_device *obd, char *uuid) return exports_evicted; } - doomed_exp = lustre_hash_get_object_by_key(obd->obd_uuid_hash_body, + doomed_exp = lustre_hash_get_object_by_key(obd->obd_uuid_hash_body, &doomed); if (doomed_exp == NULL) { diff --git a/lustre/obdclass/linux/linux-module.c b/lustre/obdclass/linux/linux-module.c index 57ccf93ca922d57fa479c136794121fdf27b28db..c71184218efc6ca3196725f4e35eecf89f9d262a 100644 --- a/lustre/obdclass/linux/linux-module.c +++ b/lustre/obdclass/linux/linux-module.c @@ -99,7 +99,7 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) ENTRY; err = copy_from_user(&hdr, (void *)arg, sizeof(hdr)); - if ( err ) + if ( err ) RETURN(err); if (hdr.ioc_version != OBD_IOCTL_VERSION) { @@ -167,8 +167,8 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) int obd_ioctl_popdata(void *arg, void *data, int len) { - int err; - + int err; + err = copy_to_user(arg, data, len); if (err) err = -EFAULT; @@ -262,6 +262,21 @@ int obd_proc_read_pinger(char *page, char **start, off_t off, int count, ); } +/** + * Check all obd devices health + * + * \param page + * \param start + * \param off + * \param count + * \param eof + * \param data + * proc read function parameters, please refer to kernel + * code fs/proc/generic.c proc_file_read() + * \param data [in] unused + * + * \retval number of characters printed + */ static int obd_proc_read_health(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -276,7 +291,7 @@ static int obd_proc_read_health(char *page, char **start, off_t off, struct obd_device *obd; obd = class_num2obd(i); - if (obd == NULL) + if (obd == NULL || !obd->obd_attached || !obd->obd_set_up) continue; LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); @@ -330,7 +345,7 @@ static void obd_device_list_seq_stop(struct seq_file *p, void *v) } static void *obd_device_list_seq_next(struct seq_file *p, void *v, loff_t *pos) -{ +{ ++*pos; if (*pos >= class_devno_max()) return NULL; @@ -427,7 +442,7 @@ int class_procfs_init(void) int class_procfs_clean(void) { ENTRY; - if (proc_lustre_root) + if (proc_lustre_root) lprocfs_remove(&proc_lustre_root); RETURN(0); } diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index 302e45ad466ca7a5f2283335966de9d80f4e8238..1b4de2c80877f7453d8a01ffcfdc9c40c6bf1b28 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -198,7 +198,7 @@ int server_put_mount(char *name, struct vfsmount *mnt) /* This might be the last one, can't deref after this */ unlock_mntput(mnt); - + down(&lustre_mount_info_lock); lmi = server_find_mount(name); up(&lustre_mount_info_lock); @@ -394,7 +394,7 @@ int lustre_process_log(struct super_block *sb, char *logname, "communication errors between this node and " "the MGS, a bad configuration, or other " "errors. See the syslog for more " - "information.\n", mgc->obd_name, logname, + "information.\n", mgc->obd_name, logname, rc); /* class_obd_list(); */ @@ -505,7 +505,7 @@ static int server_start_mgs(struct super_block *sb) if (rc) LCONSOLE_ERROR_MSG(0x15e, "Failed to start MGS '%s' (%d). Is " - "the 'mgs' module loaded?\n", + "the 'mgs' module loaded?\n", LUSTRE_MGS_OBDNAME, rc); RETURN(rc); @@ -534,7 +534,12 @@ static int server_stop_mgs(struct super_block *sb) DECLARE_MUTEX(mgc_start_lock); -/* Set up a mgcobd to process startup logs */ +/** Set up a mgc obd to process startup logs + * + * \param sb [in] super block of the mgc obd + * + * \retval 0 success, otherwise error code + */ static int lustre_start_mgc(struct super_block *sb) { struct lustre_handle mgc_conn = {0, }; @@ -591,7 +596,7 @@ static int lustre_start_mgc(struct super_block *sb) mutex_down(&mgc_start_lock); obd = class_name2obd(mgcname); - if (obd) { + if (obd && !obd->obd_stopping) { /* Re-using an existing MGC */ atomic_inc(&obd->u.cli.cl_mgc_refcount); @@ -772,7 +777,7 @@ static int lustre_stop_mgc(struct super_block *sb) GOTO(out, rc = -EBUSY); } - /* The MGC has no recoverable data in any case. + /* The MGC has no recoverable data in any case. * force shotdown set in umount_begin */ obd->obd_no_recov = 1; @@ -1086,7 +1091,7 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt) if (rc == -EINVAL) { LCONSOLE_ERROR_MSG(0x160, "The MGS is refusing to allow this " "server (%s) to start. Please see messages " - "on the MGS node.\n", + "on the MGS node.\n", lsi->lsi_ldd->ldd_svname); GOTO(out_mgc, rc); } @@ -1371,7 +1376,7 @@ static void server_put_super(struct super_block *sb) CDEBUG(D_MOUNT, "server put_super %s\n", tmpname); /* Stop the target */ - if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOSVC) && + if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOSVC) && (IS_MDT(lsi->lsi_ldd) || IS_OST(lsi->lsi_ldd))) { struct lustre_profile *lprof = NULL; @@ -1591,7 +1596,7 @@ static int server_fill_super(struct super_block *sb) if (class_name2obd(lsi->lsi_ldd->ldd_svname)) { LCONSOLE_ERROR_MSG(0x161, "The target named %s is already " "running. Double-mount may have compromised " - "the disk journal.\n", + "the disk journal.\n", lsi->lsi_ldd->ldd_svname); unlock_mntput(mnt); lustre_put_lsi(sb);