Use gethostid in the Linux convention.

Disable the gethostid() override for Solaris behavior because Linux systems
implement the POSIX standard in a way that allows a negative result.

Mask the gethostid() result to the lower four bytes, like coreutils does in
/usr/bin/hostid, to prevent junk bits or sign-extension on systems that have an
eight byte long type. This can cause a spurious hostid mismatch that prevents
zpool import on 64-bit systems.
This commit is contained in:
Darik Horn 2011-04-25 10:18:07 -05:00
parent a1cc0b3290
commit 492b8e9e7b
3 changed files with 5 additions and 12 deletions

View File

@ -1533,7 +1533,9 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
&hostid) == 0) {
if ((unsigned long)hostid != gethostid()) {
unsigned long system_hostid = gethostid() & 0xffffffff;
if ((unsigned long)hostid != system_hostid) {
char *hostname;
uint64_t timestamp;
time_t t;

View File

@ -44,14 +44,4 @@
# define issetugid() (geteuid() == 0 || getegid() == 0)
#endif
#if !defined(__sun__) && !defined(__sun)
/* It seems Solaris only returns positive host ids */
static inline long fake_gethostid(void)
{
long id = gethostid();
return id >= 0 ? id : -id;
}
#define gethostid() fake_gethostid()
#endif
#endif /* _LIBSPL_UNISTD_H */

View File

@ -179,6 +179,7 @@ check_status(nvlist_t *config, boolean_t isimport)
uint64_t stateval;
uint64_t suspended;
uint64_t hostid = 0;
unsigned long system_hostid = gethostid() & 0xffffffff;
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
&version) == 0);
@ -202,7 +203,7 @@ check_status(nvlist_t *config, boolean_t isimport)
* Pool last accessed by another system.
*/
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
if (hostid != 0 && (unsigned long)hostid != gethostid() &&
if (hostid != 0 && (unsigned long)hostid != system_hostid &&
stateval == POOL_STATE_ACTIVE)
return (ZPOOL_STATUS_HOSTID_MISMATCH);