/*
- * 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
*
* 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.
*/
#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");
}
/*
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
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
__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);
}
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 {
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;
{
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
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;
* 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) {
}
/*
- * 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);
}
/*
*/
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));
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
void
xfs_finish_freeze(
- xfs_mount_t *mp)
+ xfs_mount_t *mp)
{
unsigned long s = mutex_spinlock(&mp->m_freeze_lock);
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);