dect
/
linux-2.6
Archived
13
0
Fork 0

xfs: cleanup uuid handling

The uuid table handling should not be part of a semi-generic uuid library
but in the XFS code using it, so move those bits to xfs_mount.c and
refactor the whole glob to make it a proper abstraction.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Felix Blyakher <felixb@sgi.com>
This commit is contained in:
Christoph Hellwig 2009-03-30 10:21:31 +02:00 committed by Christoph Hellwig
parent 1a5902c5d2
commit 27174203f5
3 changed files with 83 additions and 116 deletions

View File

@ -17,10 +17,6 @@
*/
#include <xfs.h>
static DEFINE_MUTEX(uuid_monitor);
static int uuid_table_size;
static uuid_t *uuid_table;
/* IRIX interpretation of an uuid_t */
typedef struct {
__be32 uu_timelow;
@ -46,12 +42,6 @@ uuid_getnodeuniq(uuid_t *uuid, int fsid [2])
fsid[1] = be32_to_cpu(uup->uu_timelow);
}
void
uuid_create_nil(uuid_t *uuid)
{
memset(uuid, 0, sizeof(*uuid));
}
int
uuid_is_nil(uuid_t *uuid)
{
@ -71,64 +61,3 @@ uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
{
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
* brain-dead, some applications depend on this 64-bit value remaining
* persistent. Specifically, DMI vendors store the value as a persistent
* filehandle.
*/
__uint64_t
uuid_hash64(uuid_t *uuid)
{
__uint64_t *sp = (__uint64_t *)uuid;
return sp[0] + sp[1];
}
int
uuid_table_insert(uuid_t *uuid)
{
int i, hole;
mutex_lock(&uuid_monitor);
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 (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_table[hole] = *uuid;
mutex_unlock(&uuid_monitor);
return 1;
}
void
uuid_table_remove(uuid_t *uuid)
{
int i;
mutex_lock(&uuid_monitor);
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;
}
ASSERT(i < uuid_table_size);
mutex_unlock(&uuid_monitor);
}

View File

@ -22,12 +22,8 @@ typedef struct {
unsigned char __u_bits[16];
} uuid_t;
extern void uuid_create_nil(uuid_t *uuid);
extern int uuid_is_nil(uuid_t *uuid);
extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
extern __uint64_t uuid_hash64(uuid_t *uuid);
extern int uuid_table_insert(uuid_t *uuid);
extern void uuid_table_remove(uuid_t *uuid);
#endif /* __XFS_SUPPORT_UUID_H__ */

View File

@ -45,7 +45,6 @@
#include "xfs_fsops.h"
#include "xfs_utils.h"
STATIC int xfs_uuid_mount(xfs_mount_t *);
STATIC void xfs_unmountfs_wait(xfs_mount_t *);
@ -121,6 +120,84 @@ static const struct {
{ sizeof(xfs_sb_t), 0 }
};
static DEFINE_MUTEX(xfs_uuid_table_mutex);
static int xfs_uuid_table_size;
static uuid_t *xfs_uuid_table;
/*
* 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(
struct xfs_mount *mp)
{
uuid_t *uuid = &mp->m_sb.sb_uuid;
int hole, i;
if (mp->m_flags & XFS_MOUNT_NOUUID)
return 0;
if (uuid_is_nil(uuid)) {
cmn_err(CE_WARN,
"XFS: Filesystem %s has nil UUID - can't mount",
mp->m_fsname);
return XFS_ERROR(EINVAL);
}
mutex_lock(&xfs_uuid_table_mutex);
for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) {
if (uuid_is_nil(&xfs_uuid_table[i])) {
hole = i;
continue;
}
if (uuid_equal(uuid, &xfs_uuid_table[i]))
goto out_duplicate;
}
if (hole < 0) {
xfs_uuid_table = kmem_realloc(xfs_uuid_table,
(xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table),
xfs_uuid_table_size * sizeof(*xfs_uuid_table),
KM_SLEEP);
hole = xfs_uuid_table_size++;
}
xfs_uuid_table[hole] = *uuid;
mutex_unlock(&xfs_uuid_table_mutex);
return 0;
out_duplicate:
mutex_unlock(&xfs_uuid_table_mutex);
cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount",
mp->m_fsname);
return XFS_ERROR(EINVAL);
}
STATIC void
xfs_uuid_unmount(
struct xfs_mount *mp)
{
uuid_t *uuid = &mp->m_sb.sb_uuid;
int i;
if (mp->m_flags & XFS_MOUNT_NOUUID)
return;
mutex_lock(&xfs_uuid_table_mutex);
for (i = 0; i < xfs_uuid_table_size; i++) {
if (uuid_is_nil(&xfs_uuid_table[i]))
continue;
if (!uuid_equal(uuid, &xfs_uuid_table[i]))
continue;
memset(&xfs_uuid_table[i], 0, sizeof(uuid_t));
break;
}
ASSERT(i < xfs_uuid_table_size);
mutex_unlock(&xfs_uuid_table_mutex);
}
/*
* Free up the resources associated with a mount structure. Assume that
* the structure was initially zeroed, so we can tell which fields got
@ -962,18 +1039,9 @@ xfs_mountfs(
mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
/*
* XFS uses the uuid from the superblock as the unique
* identifier for fsid. We can not use the uuid from the volume
* since a single partition filesystem is identical to a single
* partition volume/filesystem.
*/
if (!(mp->m_flags & XFS_MOUNT_NOUUID)) {
if (xfs_uuid_mount(mp)) {
error = XFS_ERROR(EINVAL);
goto out;
}
}
error = xfs_uuid_mount(mp);
if (error)
goto out;
/*
* Set the minimum read and write sizes
@ -1192,8 +1260,7 @@ xfs_mountfs(
out_free_perag:
xfs_free_perag(mp);
out_remove_uuid:
if (!(mp->m_flags & XFS_MOUNT_NOUUID))
uuid_table_remove(&mp->m_sb.sb_uuid);
xfs_uuid_unmount(mp);
out:
return error;
}
@ -1276,9 +1343,7 @@ xfs_unmountfs(
xfs_unmountfs_wait(mp); /* wait for async bufs */
xfs_log_unmount_write(mp);
xfs_log_unmount(mp);
if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
uuid_table_remove(&mp->m_sb.sb_uuid);
xfs_uuid_unmount(mp);
#if defined(DEBUG)
xfs_errortag_clearall(mp, 0);
@ -1779,29 +1844,6 @@ xfs_freesb(
mp->m_sb_bp = NULL;
}
/*
* 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)
{
if (uuid_is_nil(&mp->m_sb.sb_uuid)) {
cmn_err(CE_WARN,
"XFS: Filesystem %s has nil UUID - can't mount",
mp->m_fsname);
return -1;
}
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;
}
return 0;
}
/*
* Used to log changes to the superblock unit and width fields which could
* be altered by the mount options, as well as any potential sb_features2