diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/support/uuid.c | 71 | ||||
-rw-r--r-- | fs/xfs/support/uuid.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 124 |
3 files changed, 83 insertions, 116 deletions
diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c index 5830c040ea7e..b83f76b6d410 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/support/uuid.c | |||
@@ -17,10 +17,6 @@ | |||
17 | */ | 17 | */ |
18 | #include <xfs.h> | 18 | #include <xfs.h> |
19 | 19 | ||
20 | static DEFINE_MUTEX(uuid_monitor); | ||
21 | static int uuid_table_size; | ||
22 | static uuid_t *uuid_table; | ||
23 | |||
24 | /* IRIX interpretation of an uuid_t */ | 20 | /* IRIX interpretation of an uuid_t */ |
25 | typedef struct { | 21 | typedef struct { |
26 | __be32 uu_timelow; | 22 | __be32 uu_timelow; |
@@ -46,12 +42,6 @@ uuid_getnodeuniq(uuid_t *uuid, int fsid [2]) | |||
46 | fsid[1] = be32_to_cpu(uup->uu_timelow); | 42 | fsid[1] = be32_to_cpu(uup->uu_timelow); |
47 | } | 43 | } |
48 | 44 | ||
49 | void | ||
50 | uuid_create_nil(uuid_t *uuid) | ||
51 | { | ||
52 | memset(uuid, 0, sizeof(*uuid)); | ||
53 | } | ||
54 | |||
55 | int | 45 | int |
56 | uuid_is_nil(uuid_t *uuid) | 46 | uuid_is_nil(uuid_t *uuid) |
57 | { | 47 | { |
@@ -71,64 +61,3 @@ uuid_equal(uuid_t *uuid1, uuid_t *uuid2) | |||
71 | { | 61 | { |
72 | return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1; | 62 | return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1; |
73 | } | 63 | } |
74 | |||
75 | /* | ||
76 | * Given a 128-bit uuid, return a 64-bit value by adding the top and bottom | ||
77 | * 64-bit words. NOTE: This function can not be changed EVER. Although | ||
78 | * brain-dead, some applications depend on this 64-bit value remaining | ||
79 | * persistent. Specifically, DMI vendors store the value as a persistent | ||
80 | * filehandle. | ||
81 | */ | ||
82 | __uint64_t | ||
83 | uuid_hash64(uuid_t *uuid) | ||
84 | { | ||
85 | __uint64_t *sp = (__uint64_t *)uuid; | ||
86 | |||
87 | return sp[0] + sp[1]; | ||
88 | } | ||
89 | |||
90 | int | ||
91 | uuid_table_insert(uuid_t *uuid) | ||
92 | { | ||
93 | int i, hole; | ||
94 | |||
95 | mutex_lock(&uuid_monitor); | ||
96 | for (i = 0, hole = -1; i < uuid_table_size; i++) { | ||
97 | if (uuid_is_nil(&uuid_table[i])) { | ||
98 | hole = i; | ||
99 | continue; | ||
100 | } | ||
101 | if (uuid_equal(uuid, &uuid_table[i])) { | ||
102 | mutex_unlock(&uuid_monitor); | ||
103 | return 0; | ||
104 | } | ||
105 | } | ||
106 | if (hole < 0) { | ||
107 | uuid_table = kmem_realloc(uuid_table, | ||
108 | (uuid_table_size + 1) * sizeof(*uuid_table), | ||
109 | uuid_table_size * sizeof(*uuid_table), | ||
110 | KM_SLEEP); | ||
111 | hole = uuid_table_size++; | ||
112 | } | ||
113 | uuid_table[hole] = *uuid; | ||
114 | mutex_unlock(&uuid_monitor); | ||
115 | return 1; | ||
116 | } | ||
117 | |||
118 | void | ||
119 | uuid_table_remove(uuid_t *uuid) | ||
120 | { | ||
121 | int i; | ||
122 | |||
123 | mutex_lock(&uuid_monitor); | ||
124 | for (i = 0; i < uuid_table_size; i++) { | ||
125 | if (uuid_is_nil(&uuid_table[i])) | ||
126 | continue; | ||
127 | if (!uuid_equal(uuid, &uuid_table[i])) | ||
128 | continue; | ||
129 | uuid_create_nil(&uuid_table[i]); | ||
130 | break; | ||
131 | } | ||
132 | ASSERT(i < uuid_table_size); | ||
133 | mutex_unlock(&uuid_monitor); | ||
134 | } | ||
diff --git a/fs/xfs/support/uuid.h b/fs/xfs/support/uuid.h index cff5b607d445..4732d71262cc 100644 --- a/fs/xfs/support/uuid.h +++ b/fs/xfs/support/uuid.h | |||
@@ -22,12 +22,8 @@ typedef struct { | |||
22 | unsigned char __u_bits[16]; | 22 | unsigned char __u_bits[16]; |
23 | } uuid_t; | 23 | } uuid_t; |
24 | 24 | ||
25 | extern void uuid_create_nil(uuid_t *uuid); | ||
26 | extern int uuid_is_nil(uuid_t *uuid); | 25 | extern int uuid_is_nil(uuid_t *uuid); |
27 | extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2); | 26 | extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2); |
28 | extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]); | 27 | extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]); |
29 | extern __uint64_t uuid_hash64(uuid_t *uuid); | ||
30 | extern int uuid_table_insert(uuid_t *uuid); | ||
31 | extern void uuid_table_remove(uuid_t *uuid); | ||
32 | 28 | ||
33 | #endif /* __XFS_SUPPORT_UUID_H__ */ | 29 | #endif /* __XFS_SUPPORT_UUID_H__ */ |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 92fedfcc879a..b101990df027 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include "xfs_fsops.h" | 45 | #include "xfs_fsops.h" |
46 | #include "xfs_utils.h" | 46 | #include "xfs_utils.h" |
47 | 47 | ||
48 | STATIC int xfs_uuid_mount(xfs_mount_t *); | ||
49 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); | 48 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); |
50 | 49 | ||
51 | 50 | ||
@@ -121,6 +120,84 @@ static const struct { | |||
121 | { sizeof(xfs_sb_t), 0 } | 120 | { sizeof(xfs_sb_t), 0 } |
122 | }; | 121 | }; |
123 | 122 | ||
123 | static DEFINE_MUTEX(xfs_uuid_table_mutex); | ||
124 | static int xfs_uuid_table_size; | ||
125 | static uuid_t *xfs_uuid_table; | ||
126 | |||
127 | /* | ||
128 | * See if the UUID is unique among mounted XFS filesystems. | ||
129 | * Mount fails if UUID is nil or a FS with the same UUID is already mounted. | ||
130 | */ | ||
131 | STATIC int | ||
132 | xfs_uuid_mount( | ||
133 | struct xfs_mount *mp) | ||
134 | { | ||
135 | uuid_t *uuid = &mp->m_sb.sb_uuid; | ||
136 | int hole, i; | ||
137 | |||
138 | if (mp->m_flags & XFS_MOUNT_NOUUID) | ||
139 | return 0; | ||
140 | |||
141 | if (uuid_is_nil(uuid)) { | ||
142 | cmn_err(CE_WARN, | ||
143 | "XFS: Filesystem %s has nil UUID - can't mount", | ||
144 | mp->m_fsname); | ||
145 | return XFS_ERROR(EINVAL); | ||
146 | } | ||
147 | |||
148 | mutex_lock(&xfs_uuid_table_mutex); | ||
149 | for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) { | ||
150 | if (uuid_is_nil(&xfs_uuid_table[i])) { | ||
151 | hole = i; | ||
152 | continue; | ||
153 | } | ||
154 | if (uuid_equal(uuid, &xfs_uuid_table[i])) | ||
155 | goto out_duplicate; | ||
156 | } | ||
157 | |||
158 | if (hole < 0) { | ||
159 | xfs_uuid_table = kmem_realloc(xfs_uuid_table, | ||
160 | (xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table), | ||
161 | xfs_uuid_table_size * sizeof(*xfs_uuid_table), | ||
162 | KM_SLEEP); | ||
163 | hole = xfs_uuid_table_size++; | ||
164 | } | ||
165 | xfs_uuid_table[hole] = *uuid; | ||
166 | mutex_unlock(&xfs_uuid_table_mutex); | ||
167 | |||
168 | return 0; | ||
169 | |||
170 | out_duplicate: | ||
171 | mutex_unlock(&xfs_uuid_table_mutex); | ||
172 | cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount", | ||
173 | mp->m_fsname); | ||
174 | return XFS_ERROR(EINVAL); | ||
175 | } | ||
176 | |||
177 | STATIC void | ||
178 | xfs_uuid_unmount( | ||
179 | struct xfs_mount *mp) | ||
180 | { | ||
181 | uuid_t *uuid = &mp->m_sb.sb_uuid; | ||
182 | int i; | ||
183 | |||
184 | if (mp->m_flags & XFS_MOUNT_NOUUID) | ||
185 | return; | ||
186 | |||
187 | mutex_lock(&xfs_uuid_table_mutex); | ||
188 | for (i = 0; i < xfs_uuid_table_size; i++) { | ||
189 | if (uuid_is_nil(&xfs_uuid_table[i])) | ||
190 | continue; | ||
191 | if (!uuid_equal(uuid, &xfs_uuid_table[i])) | ||
192 | continue; | ||
193 | memset(&xfs_uuid_table[i], 0, sizeof(uuid_t)); | ||
194 | break; | ||
195 | } | ||
196 | ASSERT(i < xfs_uuid_table_size); | ||
197 | mutex_unlock(&xfs_uuid_table_mutex); | ||
198 | } | ||
199 | |||
200 | |||
124 | /* | 201 | /* |
125 | * Free up the resources associated with a mount structure. Assume that | 202 | * Free up the resources associated with a mount structure. Assume that |
126 | * the structure was initially zeroed, so we can tell which fields got | 203 | * the structure was initially zeroed, so we can tell which fields got |
@@ -962,18 +1039,9 @@ xfs_mountfs( | |||
962 | 1039 | ||
963 | mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); | 1040 | mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); |
964 | 1041 | ||
965 | /* | 1042 | error = xfs_uuid_mount(mp); |
966 | * XFS uses the uuid from the superblock as the unique | 1043 | if (error) |
967 | * identifier for fsid. We can not use the uuid from the volume | 1044 | goto out; |
968 | * since a single partition filesystem is identical to a single | ||
969 | * partition volume/filesystem. | ||
970 | */ | ||
971 | if (!(mp->m_flags & XFS_MOUNT_NOUUID)) { | ||
972 | if (xfs_uuid_mount(mp)) { | ||
973 | error = XFS_ERROR(EINVAL); | ||
974 | goto out; | ||
975 | } | ||
976 | } | ||
977 | 1045 | ||
978 | /* | 1046 | /* |
979 | * Set the minimum read and write sizes | 1047 | * Set the minimum read and write sizes |
@@ -1192,8 +1260,7 @@ xfs_mountfs( | |||
1192 | out_free_perag: | 1260 | out_free_perag: |
1193 | xfs_free_perag(mp); | 1261 | xfs_free_perag(mp); |
1194 | out_remove_uuid: | 1262 | out_remove_uuid: |
1195 | if (!(mp->m_flags & XFS_MOUNT_NOUUID)) | 1263 | xfs_uuid_unmount(mp); |
1196 | uuid_table_remove(&mp->m_sb.sb_uuid); | ||
1197 | out: | 1264 | out: |
1198 | return error; | 1265 | return error; |
1199 | } | 1266 | } |
@@ -1276,9 +1343,7 @@ xfs_unmountfs( | |||
1276 | xfs_unmountfs_wait(mp); /* wait for async bufs */ | 1343 | xfs_unmountfs_wait(mp); /* wait for async bufs */ |
1277 | xfs_log_unmount_write(mp); | 1344 | xfs_log_unmount_write(mp); |
1278 | xfs_log_unmount(mp); | 1345 | xfs_log_unmount(mp); |
1279 | 1346 | xfs_uuid_unmount(mp); | |
1280 | if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) | ||
1281 | uuid_table_remove(&mp->m_sb.sb_uuid); | ||
1282 | 1347 | ||
1283 | #if defined(DEBUG) | 1348 | #if defined(DEBUG) |
1284 | xfs_errortag_clearall(mp, 0); | 1349 | xfs_errortag_clearall(mp, 0); |
@@ -1780,29 +1845,6 @@ xfs_freesb( | |||
1780 | } | 1845 | } |
1781 | 1846 | ||
1782 | /* | 1847 | /* |
1783 | * See if the UUID is unique among mounted XFS filesystems. | ||
1784 | * Mount fails if UUID is nil or a FS with the same UUID is already mounted. | ||
1785 | */ | ||
1786 | STATIC int | ||
1787 | xfs_uuid_mount( | ||
1788 | xfs_mount_t *mp) | ||
1789 | { | ||
1790 | if (uuid_is_nil(&mp->m_sb.sb_uuid)) { | ||
1791 | cmn_err(CE_WARN, | ||
1792 | "XFS: Filesystem %s has nil UUID - can't mount", | ||
1793 | mp->m_fsname); | ||
1794 | return -1; | ||
1795 | } | ||
1796 | if (!uuid_table_insert(&mp->m_sb.sb_uuid)) { | ||
1797 | cmn_err(CE_WARN, | ||
1798 | "XFS: Filesystem %s has duplicate UUID - can't mount", | ||
1799 | mp->m_fsname); | ||
1800 | return -1; | ||
1801 | } | ||
1802 | return 0; | ||
1803 | } | ||
1804 | |||
1805 | /* | ||
1806 | * Used to log changes to the superblock unit and width fields which could | 1848 | * Used to log changes to the superblock unit and width fields which could |
1807 | * be altered by the mount options, as well as any potential sb_features2 | 1849 | * be altered by the mount options, as well as any potential sb_features2 |
1808 | * fixup. Only the first superblock is updated. | 1850 | * fixup. Only the first superblock is updated. |