diff options
| author | NeilBrown <neilb@suse.de> | 2007-02-14 03:33:12 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-14 11:09:53 -0500 |
| commit | af6a4e280e3ff453653f39190b57b345ff0bec16 (patch) | |
| tree | 4895c90613737db7354f43431ed10a55dc0c98f0 /include/linux | |
| parent | 982aedfd091e6d9831216f8519f12242091be4fd (diff) | |
[PATCH] knfsd: add some new fsid types
Add support for using a filesystem UUID to identify and export point in the
filehandle.
For NFSv2, this UUID is xor-ed down to 4 or 8 bytes so that it doesn't take up
too much room. For NFSv3+, we use the full 16 bytes, and possibly also a
64bit inode number for exports beneath the root of a filesystem.
When generating an fsid to return in 'stat' information, use the UUID (hashed
down to size) if it is available and a small 'fsid' was not specifically
provided.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/nfsd/export.h | 7 | ||||
| -rw-r--r-- | include/linux/nfsd/nfsd.h | 12 | ||||
| -rw-r--r-- | include/linux/nfsd/nfsfh.h | 99 |
3 files changed, 80 insertions, 38 deletions
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 045e38cdbe64..9f62d6182d32 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h | |||
| @@ -74,19 +74,20 @@ struct svc_export { | |||
| 74 | uid_t ex_anon_uid; | 74 | uid_t ex_anon_uid; |
| 75 | gid_t ex_anon_gid; | 75 | gid_t ex_anon_gid; |
| 76 | int ex_fsid; | 76 | int ex_fsid; |
| 77 | unsigned char * ex_uuid; /* 16 byte fsid */ | ||
| 77 | struct nfsd4_fs_locations ex_fslocs; | 78 | struct nfsd4_fs_locations ex_fslocs; |
| 78 | }; | 79 | }; |
| 79 | 80 | ||
| 80 | /* an "export key" (expkey) maps a filehandlefragement to an | 81 | /* an "export key" (expkey) maps a filehandlefragement to an |
| 81 | * svc_export for a given client. There can be two per export, one | 82 | * svc_export for a given client. There can be several per export, |
| 82 | * for type 0 (dev/ino), one for type 1 (fsid) | 83 | * for the different fsid types. |
| 83 | */ | 84 | */ |
| 84 | struct svc_expkey { | 85 | struct svc_expkey { |
| 85 | struct cache_head h; | 86 | struct cache_head h; |
| 86 | 87 | ||
| 87 | struct auth_domain * ek_client; | 88 | struct auth_domain * ek_client; |
| 88 | int ek_fsidtype; | 89 | int ek_fsidtype; |
| 89 | u32 ek_fsid[3]; | 90 | u32 ek_fsid[6]; |
| 90 | 91 | ||
| 91 | struct vfsmount * ek_mnt; | 92 | struct vfsmount * ek_mnt; |
| 92 | struct dentry * ek_dentry; | 93 | struct dentry * ek_dentry; |
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 4b7c4b568f6d..72feac581aa3 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
| @@ -254,18 +254,6 @@ void nfsd_lockd_shutdown(void); | |||
| 254 | */ | 254 | */ |
| 255 | extern struct timeval nfssvc_boot; | 255 | extern struct timeval nfssvc_boot; |
| 256 | 256 | ||
| 257 | static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh) | ||
| 258 | { | ||
| 259 | if (fh->fh_export->ex_flags & NFSEXP_FSID) { | ||
| 260 | struct vfsmount *mnt = fh->fh_export->ex_mnt; | ||
| 261 | if (!old_valid_dev(mnt->mnt_sb->s_dev) || | ||
| 262 | (reffh->fh_version == 1 && reffh->fh_fsid_type == 1)) | ||
| 263 | return 1; | ||
| 264 | } | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | |||
| 269 | #ifdef CONFIG_NFSD_V4 | 257 | #ifdef CONFIG_NFSD_V4 |
| 270 | 258 | ||
| 271 | /* before processing a COMPOUND operation, we have to check that there | 259 | /* before processing a COMPOUND operation, we have to check that there |
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index d9c6c382165d..11e568ee0eeb 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h | |||
| @@ -165,38 +165,91 @@ typedef struct svc_fh { | |||
| 165 | 165 | ||
| 166 | } svc_fh; | 166 | } svc_fh; |
| 167 | 167 | ||
| 168 | static inline void mk_fsid_v0(u32 *fsidv, dev_t dev, ino_t ino) | 168 | enum nfsd_fsid { |
| 169 | { | 169 | FSID_DEV = 0, |
| 170 | fsidv[0] = htonl((MAJOR(dev)<<16) | | 170 | FSID_NUM, |
| 171 | MINOR(dev)); | 171 | FSID_MAJOR_MINOR, |
| 172 | fsidv[1] = ino_t_to_u32(ino); | 172 | FSID_ENCODE_DEV, |
| 173 | } | 173 | FSID_UUID4_INUM, |
| 174 | FSID_UUID8, | ||
| 175 | FSID_UUID16, | ||
| 176 | FSID_UUID16_INUM, | ||
| 177 | }; | ||
| 174 | 178 | ||
| 175 | static inline void mk_fsid_v1(u32 *fsidv, u32 fsid) | 179 | enum fsid_source { |
| 176 | { | 180 | FSIDSOURCE_DEV, |
| 177 | fsidv[0] = fsid; | 181 | FSIDSOURCE_FSID, |
| 178 | } | 182 | FSIDSOURCE_UUID, |
| 183 | }; | ||
| 184 | extern enum fsid_source fsid_source(struct svc_fh *fhp); | ||
| 179 | 185 | ||
| 180 | static inline void mk_fsid_v2(u32 *fsidv, dev_t dev, ino_t ino) | ||
| 181 | { | ||
| 182 | fsidv[0] = htonl(MAJOR(dev)); | ||
| 183 | fsidv[1] = htonl(MINOR(dev)); | ||
| 184 | fsidv[2] = ino_t_to_u32(ino); | ||
| 185 | } | ||
| 186 | 186 | ||
| 187 | static inline void mk_fsid_v3(u32 *fsidv, dev_t dev, ino_t ino) | 187 | /* This might look a little large to "inline" but in all calls except |
| 188 | * one, 'vers' is constant so moste of the function disappears. | ||
| 189 | */ | ||
| 190 | static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino, | ||
| 191 | u32 fsid, unsigned char *uuid) | ||
| 188 | { | 192 | { |
| 189 | fsidv[0] = new_encode_dev(dev); | 193 | u32 *up; |
| 190 | fsidv[1] = ino_t_to_u32(ino); | 194 | switch(vers) { |
| 195 | case FSID_DEV: | ||
| 196 | fsidv[0] = htonl((MAJOR(dev)<<16) | | ||
| 197 | MINOR(dev)); | ||
| 198 | fsidv[1] = ino_t_to_u32(ino); | ||
| 199 | break; | ||
| 200 | case FSID_NUM: | ||
| 201 | fsidv[0] = fsid; | ||
| 202 | break; | ||
| 203 | case FSID_MAJOR_MINOR: | ||
| 204 | fsidv[0] = htonl(MAJOR(dev)); | ||
| 205 | fsidv[1] = htonl(MINOR(dev)); | ||
| 206 | fsidv[2] = ino_t_to_u32(ino); | ||
| 207 | break; | ||
| 208 | |||
| 209 | case FSID_ENCODE_DEV: | ||
| 210 | fsidv[0] = new_encode_dev(dev); | ||
| 211 | fsidv[1] = ino_t_to_u32(ino); | ||
| 212 | break; | ||
| 213 | |||
| 214 | case FSID_UUID4_INUM: | ||
| 215 | /* 4 byte fsid and inode number */ | ||
| 216 | up = (u32*)uuid; | ||
| 217 | fsidv[0] = ino_t_to_u32(ino); | ||
| 218 | fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3]; | ||
| 219 | break; | ||
| 220 | |||
| 221 | case FSID_UUID8: | ||
| 222 | /* 8 byte fsid */ | ||
| 223 | up = (u32*)uuid; | ||
| 224 | fsidv[0] = up[0] ^ up[2]; | ||
| 225 | fsidv[1] = up[1] ^ up[3]; | ||
| 226 | break; | ||
| 227 | |||
| 228 | case FSID_UUID16: | ||
| 229 | /* 16 byte fsid - NFSv3+ only */ | ||
| 230 | memcpy(fsidv, uuid, 16); | ||
| 231 | break; | ||
| 232 | |||
| 233 | case FSID_UUID16_INUM: | ||
| 234 | /* 8 byte inode and 16 byte fsid */ | ||
| 235 | *(u64*)fsidv = (u64)ino; | ||
| 236 | memcpy(fsidv+2, uuid, 16); | ||
| 237 | break; | ||
| 238 | default: BUG(); | ||
| 239 | } | ||
| 191 | } | 240 | } |
| 192 | 241 | ||
| 193 | static inline int key_len(int type) | 242 | static inline int key_len(int type) |
| 194 | { | 243 | { |
| 195 | switch(type) { | 244 | switch(type) { |
| 196 | case 0: return 8; | 245 | case FSID_DEV: return 8; |
| 197 | case 1: return 4; | 246 | case FSID_NUM: return 4; |
| 198 | case 2: return 12; | 247 | case FSID_MAJOR_MINOR: return 12; |
| 199 | case 3: return 8; | 248 | case FSID_ENCODE_DEV: return 8; |
| 249 | case FSID_UUID4_INUM: return 8; | ||
| 250 | case FSID_UUID8: return 8; | ||
| 251 | case FSID_UUID16: return 16; | ||
| 252 | case FSID_UUID16_INUM: return 24; | ||
| 200 | default: return 0; | 253 | default: return 0; |
| 201 | } | 254 | } |
| 202 | } | 255 | } |
