nfsfh.h 9.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
/*
 * include/linux/nfsd/nfsfh.h
 *
 * This file describes the layout of the file handles as passed
 * over the wire.
 *
 * Earlier versions of knfsd used to sign file handles using keyed MD5
 * or SHA. I've removed this code, because it doesn't give you more
 * security than blocking external access to port 2049 on your firewall.
 *
 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
 */

#ifndef _LINUX_NFSD_FH_H
#define _LINUX_NFSD_FH_H

#include <asm/types.h>
#ifdef __KERNEL__
# include <linux/types.h>
# include <linux/string.h>
# include <linux/fs.h>
#endif
#include <linux/nfsd/const.h>
#include <linux/nfsd/debug.h>

/*
 * This is the old "dentry style" Linux NFSv2 file handle.
 *
 * The xino and xdev fields are currently used to transport the
 * ino/dev of the exported inode.
 */
struct nfs_fhbase_old {
	__u32		fb_dcookie;	/* dentry cookie - always 0xfeebbaca */
	__u32		fb_ino;		/* our inode number */
	__u32		fb_dirino;	/* dir inode number, 0 for directories */
	__u32		fb_dev;		/* our device */
	__u32		fb_xdev;
	__u32		fb_xino;
	__u32		fb_generation;
};

/*
 * This is the new flexible, extensible style NFSv2/v3 file handle.
 * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
 *
 * The file handle is seens as a list of 4byte words.
 * The first word contains a version number (1) and four descriptor bytes
 * that tell how the remaining 3 variable length fields should be handled.
 * These three bytes are auth_type, fsid_type and fileid_type.
 *
 * All 4byte values are in host-byte-order.
 *
 * The auth_type field specifies how the filehandle can be authenticated
 * This might allow a file to be confirmed to be in a writable part of a
 * filetree without checking the path from it upto the root.
 * Current values:
 *     0  - No authentication.  fb_auth is 0 bytes long
 * Possible future values:
 *     1  - 4 bytes taken from MD5 hash of the remainer of the file handle
 *          prefixed by a secret and with the important export flags.
 *
 * The fsid_type identifies how the filesystem (or export point) is
 *    encoded.
 *  Current values:
 *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
 *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
 *              says we mustn't.  We must break it up and reassemble.
 *     1  - 4 byte user specified identifier
 *     2  - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
 *     3  - 4 byte device id, encoded for user-space, 4 byte inode number
 *
 * The fileid_type identified how the file within the filesystem is encoded.
 * This is (will be) passed to, and set by, the underlying filesystem if it supports
 * filehandle operations.  The filesystem must not use the value '0' or '0xff' and may
 * only use the values 1 and 2 as defined below:
 *  Current values:
 *    0   - The root, or export point, of the filesystem.  fb_fileid is 0 bytes.
 *    1   - 32bit inode number, 32 bit generation number.
 *    2   - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
 *
 */
struct nfs_fhbase_new {
	__u8		fb_version;	/* == 1, even => nfs_fhbase_old */
	__u8		fb_auth_type;
	__u8		fb_fsid_type;
	__u8		fb_fileid_type;
	__u32		fb_auth[1];
/*	__u32		fb_fsid[0]; floating */
/*	__u32		fb_fileid[0]; floating */
};

struct knfsd_fh {
	unsigned int	fh_size;	/* significant for NFSv3.
					 * Points to the current size while building
					 * a new file handle
					 */
	union {
		struct nfs_fhbase_old	fh_old;
		__u32			fh_pad[NFS4_FHSIZE/4];
		struct nfs_fhbase_new	fh_new;
	} fh_base;
};

#define ofh_dcookie		fh_base.fh_old.fb_dcookie
#define ofh_ino			fh_base.fh_old.fb_ino
#define ofh_dirino		fh_base.fh_old.fb_dirino
#define ofh_dev			fh_base.fh_old.fb_dev
#define ofh_xdev		fh_base.fh_old.fb_xdev
#define ofh_xino		fh_base.fh_old.fb_xino
#define ofh_generation		fh_base.fh_old.fb_generation

#define	fh_version		fh_base.fh_new.fb_version
#define	fh_fsid_type		fh_base.fh_new.fb_fsid_type
#define	fh_auth_type		fh_base.fh_new.fb_auth_type
#define	fh_fileid_type		fh_base.fh_new.fb_fileid_type
#define	fh_auth			fh_base.fh_new.fb_auth
#define	fh_fsid			fh_base.fh_new.fb_auth

#ifdef __KERNEL__

static inline __u32 ino_t_to_u32(ino_t ino)
{
	return (__u32) ino;
}

static inline ino_t u32_to_ino_t(__u32 uino)
{
	return (ino_t) uino;
}

/*
 * This is the internal representation of an NFS handle used in knfsd.
 * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
 */
typedef struct svc_fh {
	struct knfsd_fh		fh_handle;	/* FH data */
	struct dentry *		fh_dentry;	/* validated dentry */
	struct svc_export *	fh_export;	/* export pointer */
	int			fh_maxsize;	/* max size for fh_handle */

	unsigned char		fh_locked;	/* inode locked by us */

#ifdef CONFIG_NFSD_V3
	unsigned char		fh_post_saved;	/* post-op attrs saved */
	unsigned char		fh_pre_saved;	/* pre-op attrs saved */

	/* Pre-op attributes saved during fh_lock */
	__u64			fh_pre_size;	/* size before operation */
	struct timespec		fh_pre_mtime;	/* mtime before oper */
	struct timespec		fh_pre_ctime;	/* ctime before oper */

	/* Post-op attributes saved in fh_unlock */
	umode_t			fh_post_mode;	/* i_mode */
	nlink_t			fh_post_nlink;	/* i_nlink */
	uid_t			fh_post_uid;	/* i_uid */
	gid_t			fh_post_gid;	/* i_gid */
	__u64			fh_post_size;	/* i_size */
	unsigned long		fh_post_blocks; /* i_blocks */
	unsigned long		fh_post_blksize;/* i_blksize */
160
	__be32			fh_post_rdev[2];/* i_rdev */
L
Linus Torvalds 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
	struct timespec		fh_post_atime;	/* i_atime */
	struct timespec		fh_post_mtime;	/* i_mtime */
	struct timespec		fh_post_ctime;	/* i_ctime */
#endif /* CONFIG_NFSD_V3 */

} svc_fh;

static inline void mk_fsid_v0(u32 *fsidv, dev_t dev, ino_t ino)
{
	fsidv[0] = htonl((MAJOR(dev)<<16) |
			MINOR(dev));
	fsidv[1] = ino_t_to_u32(ino);
}

static inline void mk_fsid_v1(u32 *fsidv, u32 fsid)
{
	fsidv[0] = fsid;
}

static inline void mk_fsid_v2(u32 *fsidv, dev_t dev, ino_t ino)
{
	fsidv[0] = htonl(MAJOR(dev));
	fsidv[1] = htonl(MINOR(dev));
	fsidv[2] = ino_t_to_u32(ino);
}

static inline void mk_fsid_v3(u32 *fsidv, dev_t dev, ino_t ino)
{
	fsidv[0] = new_encode_dev(dev);
	fsidv[1] = ino_t_to_u32(ino);
}

static inline int key_len(int type)
{
	switch(type) {
	case 0: return 8;
	case 1: return 4;
	case 2: return 12;
	case 3: return 8;
	default: return 0;
	}
}

/*
 * Shorthand for dprintk()'s
 */
extern char * SVCFH_fmt(struct svc_fh *fhp);

/*
 * Function prototypes
 */
212 213 214
__be32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
__be32	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
__be32	fh_update(struct svc_fh *);
L
Linus Torvalds 已提交
215 216 217 218 219
void	fh_put(struct svc_fh *);

static __inline__ struct svc_fh *
fh_copy(struct svc_fh *dst, struct svc_fh *src)
{
220
	WARN_ON(src->fh_dentry || src->fh_locked);
L
Linus Torvalds 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
			
	*dst = *src;
	return dst;
}

static __inline__ struct svc_fh *
fh_init(struct svc_fh *fhp, int maxsize)
{
	memset(fhp, 0, sizeof(*fhp));
	fhp->fh_maxsize = maxsize;
	return fhp;
}

#ifdef CONFIG_NFSD_V3
/*
 * Fill in the pre_op attr for the wcc data
 */
static inline void
fill_pre_wcc(struct svc_fh *fhp)
{
	struct inode    *inode;

	inode = fhp->fh_dentry->d_inode;
	if (!fhp->fh_pre_saved) {
		fhp->fh_pre_mtime = inode->i_mtime;
		fhp->fh_pre_ctime = inode->i_ctime;
			fhp->fh_pre_size  = inode->i_size;
			fhp->fh_pre_saved = 1;
	}
}

/*
 * Fill in the post_op attr for the wcc data
 */
static inline void
fill_post_wcc(struct svc_fh *fhp)
{
	struct inode    *inode = fhp->fh_dentry->d_inode;

	if (fhp->fh_post_saved)
		printk("nfsd: inode locked twice during operation.\n");

	fhp->fh_post_mode       = inode->i_mode;
	fhp->fh_post_nlink      = inode->i_nlink;
	fhp->fh_post_uid	= inode->i_uid;
	fhp->fh_post_gid	= inode->i_gid;
	fhp->fh_post_size       = inode->i_size;
268 269
	fhp->fh_post_blksize    = BLOCK_SIZE;
	fhp->fh_post_blocks     = inode->i_blocks;
L
Linus Torvalds 已提交
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
	fhp->fh_post_rdev[0]    = htonl((u32)imajor(inode));
	fhp->fh_post_rdev[1]    = htonl((u32)iminor(inode));
	fhp->fh_post_atime      = inode->i_atime;
	fhp->fh_post_mtime      = inode->i_mtime;
	fhp->fh_post_ctime      = inode->i_ctime;
	fhp->fh_post_saved      = 1;
}
#else
#define	fill_pre_wcc(ignored)
#define fill_post_wcc(notused)
#endif /* CONFIG_NFSD_V3 */


/*
 * Lock a file handle/inode
 * NOTE: both fh_lock and fh_unlock are done "by hand" in
286
 * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
L
Linus Torvalds 已提交
287 288
 * so, any changes here should be reflected there.
 */
P
Peter Zijlstra 已提交
289

L
Linus Torvalds 已提交
290
static inline void
P
Peter Zijlstra 已提交
291
fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
L
Linus Torvalds 已提交
292 293 294 295 296 297 298
{
	struct dentry	*dentry = fhp->fh_dentry;
	struct inode	*inode;

	dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
			SVCFH_fmt(fhp), fhp->fh_locked);

299 300
	BUG_ON(!dentry);

L
Linus Torvalds 已提交
301 302 303 304 305 306 307
	if (fhp->fh_locked) {
		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
			dentry->d_parent->d_name.name, dentry->d_name.name);
		return;
	}

	inode = dentry->d_inode;
P
Peter Zijlstra 已提交
308
	mutex_lock_nested(&inode->i_mutex, subclass);
L
Linus Torvalds 已提交
309 310 311 312
	fill_pre_wcc(fhp);
	fhp->fh_locked = 1;
}

P
Peter Zijlstra 已提交
313 314 315 316 317 318
static inline void
fh_lock(struct svc_fh *fhp)
{
	fh_lock_nested(fhp, I_MUTEX_NORMAL);
}

L
Linus Torvalds 已提交
319 320 321 322 323 324
/*
 * Unlock a file handle/inode
 */
static inline void
fh_unlock(struct svc_fh *fhp)
{
325
	BUG_ON(!fhp->fh_dentry);
L
Linus Torvalds 已提交
326 327 328

	if (fhp->fh_locked) {
		fill_post_wcc(fhp);
329
		mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
L
Linus Torvalds 已提交
330 331 332 333 334 335 336
		fhp->fh_locked = 0;
	}
}
#endif /* __KERNEL__ */


#endif /* _LINUX_NFSD_FH_H */