Commit b94ca00e authored by Nathan Scott's avatar Nathan Scott

[XFS] UUID cleanup - remove unused functions, create a decent table abstraction

and make the mount code simpler in the process.

SGI Modid: 2.5.x-xfs:slinx:144596a
parent f78a06f5
......@@ -959,6 +959,7 @@ init_xfs_fs( void )
vn_init();
xfs_init();
uuid_init();
vfs_initdmapi();
vfs_initquota();
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
......@@ -11,7 +11,7 @@
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
......@@ -31,58 +31,22 @@
*/
#include <linux/types.h>
#include <linux/random.h>
#include <linux/time.h>
#ifdef __sparc__
#include <asm/idprom.h>
#else
#include <linux/netdevice.h>
#endif
#include <xfs_types.h>
#include <xfs_arch.h>
#include "time.h"
#include "move.h"
#include "uuid.h"
#include "kmem.h"
#include "debug.h"
#include "mutex.h"
#ifndef CONFIG_NET
#define dev_get_by_name(x) (NULL)
#define dev_put(x) do { } while (0)
#endif
/* NODE_SIZE is the number of bytes used for the node identifier portion. */
#define NODE_SIZE 6
/*
* Total size must be 128 bits. N.B. definition of uuid_t in uuid.h!
*/
typedef struct {
u_int32_t uu_timelow; /* time "low" */
u_int16_t uu_timemid; /* time "mid" */
u_int16_t uu_timehi; /* time "hi" and version */
u_int16_t uu_clockseq; /* "reserved" and clock sequence */
u_int16_t uu_node[NODE_SIZE / 2]; /* ethernet hardware address */
} uu_t;
/*
* The Time Base Correction is the amount to add on to a UNIX-based
* time value (i.e. seconds since 1 Jan. 1970) to convert it to the
* time base for UUIDs (15 Oct. 1582).
*/
#define UUID_TBC 0x01B21DD2138140LL
static mutex_t uuid_monitor;
static int uuid_table_size;
static uuid_t *uuid_table;
static short uuid_eaddr[NODE_SIZE / 2]; /* ethernet address */
static __int64_t uuid_time; /* last time basis used */
static u_int16_t uuid_clockseq; /* boot-time randomizer */
DECLARE_MUTEX(uuid_lock);
/*
* uuid_init - called from out of init_tbl[]
*/
void
uuid_init(void)
{
mutex_init(&uuid_monitor, MUTEX_DEFAULT, "uuid_monitor");
}
/*
......@@ -94,7 +58,7 @@ uuid_init(void)
void
uuid_getnodeuniq(uuid_t *uuid, int fsid [2])
{
char *uu=(char*)uuid;
char *uu = (char *)uuid;
/* on IRIX, this function assumes big-endian fields within
* the uuid, so we use INT_GET to get the same result on
......@@ -119,24 +83,24 @@ uuid_is_nil(uuid_t *uuid)
char *cp = (char *)uuid;
if (uuid == NULL)
return B_TRUE;
return 0;
/* implied check of version number here... */
for (i = 0; i < sizeof *uuid; i++)
if (*cp++) return B_FALSE; /* not nil */
return B_TRUE; /* is nil */
if (*cp++) return 0; /* not nil */
return 1; /* is nil */
}
int
uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
{
return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? B_FALSE : B_TRUE;
return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1;
}
/*
* Given a 128-bit uuid, return a 64-bit value by adding the top and bottom
* 64-bit words. NOTE: This function can not be changed EVER. Although
* 64-bit words. NOTE: This function can not be changed EVER. Although
* brain-dead, some applications depend on this 64-bit value remaining
* persistent. Specifically, DMI vendors store the value as a persistent
* persistent. Specifically, DMI vendors store the value as a persistent
* filehandle.
*/
__uint64_t
......@@ -145,94 +109,50 @@ uuid_hash64(uuid_t *uuid)
__uint64_t *sp = (__uint64_t *)uuid;
return sp[0] + sp[1];
} /* uuid_hash64 */
static void
get_eaddr(char *junk)
{
#ifdef __sparc__
memcpy(uuid_eaddr, idprom->id_ethaddr, 6);
#else
struct net_device *dev;
dev = dev_get_by_name("eth0");
if (!dev || !dev->addr_len) {
get_random_bytes(uuid_eaddr, sizeof(uuid_eaddr));
} else {
memcpy(uuid_eaddr, dev->dev_addr,
dev->addr_len<sizeof(uuid_eaddr)?
dev->addr_len:sizeof(uuid_eaddr));
dev_put(dev);
}
#endif
}
/*
* uuid_create - kernel version, does the actual work
*/
void
uuid_create(uuid_t *uuid)
int
uuid_table_insert(uuid_t *uuid)
{
int i;
uu_t *uu = (uu_t *)uuid;
static int uuid_have_eaddr = 0; /* ethernet addr inited? */
static int uuid_is_init = 0; /* time/clockseq inited? */
down(&uuid_lock);
if (!uuid_is_init) {
timespec_t ts;
nanotime(&ts);
/*
* The clock sequence must be initialized randomly.
*/
uuid_clockseq = ((unsigned long)jiffies & 0xfff) | 0x8000;
/*
* Initialize the uuid time, it's in 100 nanosecond
* units since a time base in 1582.
*/
uuid_time = ts.tv_sec * 10000000LL +
ts.tv_nsec / 100LL +
UUID_TBC;
uuid_is_init = 1;
int i, hole;
mutex_lock(&uuid_monitor, PVFS);
for (i = 0, hole = -1; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i])) {
hole = i;
continue;
}
if (uuid_equal(uuid, &uuid_table[i])) {
mutex_unlock(&uuid_monitor);
return 0;
}
}
if (!uuid_have_eaddr) {
uuid_have_eaddr = 1;
get_eaddr((char *)uuid_eaddr);
if (hole < 0) {
uuid_table = kmem_realloc(uuid_table,
(uuid_table_size + 1) * sizeof(*uuid_table),
uuid_table_size * sizeof(*uuid_table),
KM_SLEEP);
hole = uuid_table_size++;
}
uuid_time++;
uu->uu_timelow = (u_int32_t)(uuid_time & 0x00000000ffffffffLL);
uu->uu_timemid = (u_int16_t)((uuid_time >> 32) & 0x0000ffff);
uu->uu_timehi = (u_int16_t)((uuid_time >> 48) & 0x00000fff) | 0x1000;
up(&uuid_lock);
uu->uu_clockseq = uuid_clockseq;
for (i = 0; i < (NODE_SIZE / 2); i++)
uu->uu_node [i] = uuid_eaddr [i];
uuid_table[hole] = *uuid;
mutex_unlock(&uuid_monitor);
return 1;
}
int
uuid_compare(uuid_t *uuid1, uuid_t *uuid2)
void
uuid_table_remove(uuid_t *uuid)
{
int i;
char *cp1 = (char *) uuid1;
char *cp2 = (char *) uuid2;
if (uuid1 == NULL) {
if (uuid2 == NULL) {
return 0; /* equal because both are nil */
} else {
return -1; /* uuid1 nil, so precedes uuid2 */
}
} else if (uuid2 == NULL) {
return 1;
}
/* implied check of version number here... */
for (i = 0; i < sizeof(uuid_t); i++) {
if (*cp1 < *cp2)
return -1;
if (*cp1++ > *cp2++)
return 1;
mutex_lock(&uuid_monitor, PVFS);
for (i = 0; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i]))
continue;
if (!uuid_equal(uuid, &uuid_table[i]))
continue;
uuid_create_nil(&uuid_table[i]);
break;
}
return 0; /* they're equal */
ASSERT(i < uuid_table_size);
mutex_unlock(&uuid_monitor);
}
......@@ -36,10 +36,13 @@ typedef struct {
unsigned char __u_bits[16];
} uuid_t;
void uuid_init(void);
void uuid_create_nil(uuid_t *uuid);
int uuid_is_nil(uuid_t *uuid);
int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
__uint64_t uuid_hash64(uuid_t *uuid);
int uuid_table_insert(uuid_t *uuid);
void uuid_table_remove(uuid_t *uuid);
#endif /* __XFS_SUPPORT_UUID_H__ */
......@@ -36,10 +36,6 @@ STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
STATIC int xfs_uuid_mount(xfs_mount_t *);
STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
mutex_t xfs_uuidtabmon; /* monitor for uuidtab */
STATIC int xfs_uuidtab_size;
STATIC uuid_t *xfs_uuidtab;
void xfs_xlatesb(void *, xfs_sb_t *, int, xfs_arch_t, __int64_t);
static struct {
......@@ -1169,7 +1165,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
void
xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
{
xfs_buf_t *bp;
xfs_buf_t *bp;
int first;
int last;
xfs_mount_t *mp;
......@@ -1217,7 +1213,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
{
int scounter; /* short counter for 32 bit fields */
long long lcounter; /* long counter for 64 bit fields */
long long res_used, rem;
long long res_used, rem;
/*
* With the in-core superblock spin lock held, switch
......@@ -1400,7 +1396,7 @@ xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd)
int
xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
{
unsigned long s;
unsigned long s;
int status=0;
xfs_mod_sb_t *msbp;
......@@ -1457,10 +1453,12 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
* If it can't then we'll return NULL.
*/
xfs_buf_t *
xfs_getsb(xfs_mount_t *mp,
int flags)
xfs_getsb(
xfs_mount_t *mp,
int flags)
{
xfs_buf_t *bp;
ASSERT(mp->m_sb_bp != NULL);
bp = mp->m_sb_bp;
if (flags & XFS_BUF_TRYLOCK) {
......@@ -1495,67 +1493,36 @@ xfs_freesb(
}
/*
* See if the uuid is unique among mounted xfs filesystems.
* Mount fails if UUID is nil or a FS with the same UUID is already
* mounted
* See if the UUID is unique among mounted XFS filesystems.
* Mount fails if UUID is nil or a FS with the same UUID is already mounted.
*/
STATIC int
xfs_uuid_mount(xfs_mount_t *mp)
xfs_uuid_mount(
xfs_mount_t *mp)
{
int hole;
int i;
if (uuid_is_nil(&mp->m_sb.sb_uuid)) {
cmn_err(CE_WARN, "XFS: Filesystem %s has nil UUID - can't mount",
cmn_err(CE_WARN,
"XFS: Filesystem %s has nil UUID - can't mount",
mp->m_fsname);
return -1;
}
mutex_lock(&xfs_uuidtabmon, PVFS);
for (i = 0, hole = -1; i < xfs_uuidtab_size; i++) {
if (uuid_is_nil(&xfs_uuidtab[i])) {
hole = i;
continue;
}
if (uuid_equal(&mp->m_sb.sb_uuid, &xfs_uuidtab[i])) {
cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount",
mp->m_fsname);
mutex_unlock(&xfs_uuidtabmon);
return -1;
}
}
if (hole < 0) {
xfs_uuidtab = kmem_realloc(xfs_uuidtab,
(xfs_uuidtab_size + 1) * sizeof(*xfs_uuidtab),
xfs_uuidtab_size * sizeof(*xfs_uuidtab),
KM_SLEEP);
hole = xfs_uuidtab_size++;
if (!uuid_table_insert(&mp->m_sb.sb_uuid)) {
cmn_err(CE_WARN,
"XFS: Filesystem %s has duplicate UUID - can't mount",
mp->m_fsname);
return -1;
}
xfs_uuidtab[hole] = mp->m_sb.sb_uuid;
mutex_unlock(&xfs_uuidtabmon);
return 0;
}
/*
* Remove filesystem from the uuid table.
* Remove filesystem from the UUID table.
*/
STATIC void
xfs_uuid_unmount(xfs_mount_t *mp)
xfs_uuid_unmount(
xfs_mount_t *mp)
{
int i;
mutex_lock(&xfs_uuidtabmon, PVFS);
for (i = 0; i < xfs_uuidtab_size; i++) {
if (uuid_is_nil(&xfs_uuidtab[i]))
continue;
if (!uuid_equal(&mp->m_sb.sb_uuid, &xfs_uuidtab[i]))
continue;
uuid_create_nil(&xfs_uuidtab[i]);
break;
}
ASSERT(i < xfs_uuidtab_size);
mutex_unlock(&xfs_uuidtabmon);
uuid_table_remove(&mp->m_sb.sb_uuid);
}
/*
......@@ -1564,10 +1531,10 @@ xfs_uuid_unmount(xfs_mount_t *mp)
*/
STATIC void
xfs_mount_log_sbunit(
xfs_mount_t *mp,
__int64_t fields)
xfs_mount_t *mp,
__int64_t fields)
{
xfs_trans_t *tp;
xfs_trans_t *tp;
ASSERT(fields & (XFS_SB_UNIT|XFS_SB_WIDTH|XFS_SB_UUID));
......@@ -1578,7 +1545,7 @@ xfs_mount_log_sbunit(
return;
}
xfs_mod_sb(tp, fields);
(void)xfs_trans_commit(tp, 0, NULL);
xfs_trans_commit(tp, 0, NULL);
}
/* Functions to lock access out of the filesystem for forced
......@@ -1603,7 +1570,7 @@ xfs_start_freeze(
void
xfs_finish_freeze(
xfs_mount_t *mp)
xfs_mount_t *mp)
{
unsigned long s = mutex_spinlock(&mp->m_freeze_lock);
......@@ -1617,11 +1584,11 @@ xfs_finish_freeze(
void
xfs_check_frozen(
xfs_mount_t *mp,
bhv_desc_t *bdp,
int level)
xfs_mount_t *mp,
bhv_desc_t *bdp,
int level)
{
SPLDECL(s);
unsigned long s;
if (mp->m_frozen) {
s = mutex_spinlock(&mp->m_freeze_lock);
......
......@@ -65,7 +65,6 @@ xfs_init(void)
#ifdef XFS_DABUF_DEBUG
spinlock_init(&xfs_dabuf_global_lock, "xfsda");
#endif
mutex_init(&xfs_uuidtabmon, MUTEX_DEFAULT, "xfs_uuidtab");
/*
* Initialize all of the zone allocators we use.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment