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 160 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 212 213 214 215 216 217 218 219 220 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
|
/*
* 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-1999 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 new "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 {
__u32 fb_dcookie; /* dentry cookie */
__u32 fb_ino; /* our inode number */
__u32 fb_dirino; /* dir inode number */
__u32 fb_dev; /* our device */
__u32 fb_xdev;
__u32 fb_xino;
__u32 fb_generation;
};
#define NFS_FH_PADDING (NFS_FHSIZE - sizeof(struct nfs_fhbase))
struct knfs_fh {
struct nfs_fhbase fh_base;
__u8 fh_cookie[NFS_FH_PADDING];
};
#define fh_dcookie fh_base.fb_dcookie
#define fh_ino fh_base.fb_ino
#define fh_dirino fh_base.fb_dirino
#define fh_dev fh_base.fb_dev
#define fh_xdev fh_base.fb_xdev
#define fh_xino fh_base.fb_xino
#define fh_generation fh_base.fb_generation
#ifdef __KERNEL__
/*
* Conversion macros for the filehandle fields.
*/
extern inline __u32 kdev_t_to_u32(kdev_t dev)
{
return (__u32) dev;
}
extern inline kdev_t u32_to_kdev_t(__u32 udev)
{
return (kdev_t) udev;
}
extern inline __u32 ino_t_to_u32(ino_t ino)
{
return (__u32) ino;
}
extern 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 knfs_fh fh_handle; /* FH data */
struct dentry * fh_dentry; /* validated dentry */
struct svc_export * fh_export; /* export pointer */
#ifdef CONFIG_NFSD_V3
unsigned char fh_post_saved; /* post-op attrs saved */
unsigned char fh_pre_saved; /* pre-op attrs saved */
#endif /* CONFIG_NFSD_V3 */
unsigned char fh_locked; /* inode locked by us */
#ifdef CONFIG_NFSD_V3
/* Pre-op attributes saved during fh_lock */
__u64 fh_pre_size; /* size before operation */
time_t fh_pre_mtime; /* mtime before oper */
time_t 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 */
kdev_t fh_post_rdev; /* i_rdev */
time_t fh_post_atime; /* i_atime */
time_t fh_post_mtime; /* i_mtime */
time_t fh_post_ctime; /* i_ctime */
#endif /* CONFIG_NFSD_V3 */
} svc_fh;
/*
* Shorthand for dprintk()'s
*/
#define SVCFH_DENTRY(f) ((f)->fh_dentry)
#define SVCFH_INO(f) ((f)->fh_handle.fh_ino)
#define SVCFH_DEV(f) ((f)->fh_handle.fh_dev)
/*
* Function prototypes
*/
u32 fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
void fh_compose(struct svc_fh *, struct svc_export *, struct dentry *);
void fh_update(struct svc_fh *);
void fh_put(struct svc_fh *);
static __inline__ struct svc_fh *
fh_copy(struct svc_fh *dst, struct svc_fh *src)
{
if (src->fh_dentry || src->fh_locked) {
struct dentry *dentry = src->fh_dentry;
printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
}
*dst = *src;
return dst;
}
static __inline__ struct svc_fh *
fh_init(struct svc_fh *fhp)
{
memset(fhp, 0, sizeof(*fhp));
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;
}
fhp->fh_locked = 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;
fhp->fh_post_blksize = inode->i_blksize;
fhp->fh_post_blocks = inode->i_blocks;
fhp->fh_post_rdev = inode->i_rdev;
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;
fhp->fh_locked = 0;
}
#endif /* CONFIG_NFSD_V3 */
/*
* Lock a file handle/inode
*/
static inline void
fh_lock(struct svc_fh *fhp)
{
struct dentry *dentry = fhp->fh_dentry;
struct inode *inode;
dfprintk(FILEOP, "nfsd: fh_lock(%x/%ld) locked = %d\n",
SVCFH_DEV(fhp), (long)SVCFH_INO(fhp), fhp->fh_locked);
if (!fhp->fh_dentry) {
printk(KERN_ERR "fh_lock: fh not verified!\n");
return;
}
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;
down(&inode->i_sem);
#ifdef CONFIG_NFSD_V3
fill_pre_wcc(fhp);
#else
fhp->fh_locked = 1;
#endif /* CONFIG_NFSD_V3 */
}
/*
* Unlock a file handle/inode
*/
static inline void
fh_unlock(struct svc_fh *fhp)
{
if (!fhp->fh_dentry)
printk(KERN_ERR "fh_unlock: fh not verified!\n");
if (fhp->fh_locked) {
#ifdef CONFIG_NFSD_V3
fill_post_wcc(fhp);
up(&fhp->fh_dentry->d_inode->i_sem);
#else
struct dentry *dentry = fhp->fh_dentry;
struct inode *inode = dentry->d_inode;
fhp->fh_locked = 0;
up(&inode->i_sem);
#endif /* CONFIG_NFSD_V3 */
}
}
#endif /* __KERNEL__ */
#endif /* _LINUX_NFSD_FH_H */
|