linux/fs/nfsd/nfsfh.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
   3 *
   4 * This file describes the layout of the file handles as passed
   5 * over the wire.
   6 */
   7#ifndef _LINUX_NFSD_NFSFH_H
   8#define _LINUX_NFSD_NFSFH_H
   9
  10#include <linux/sunrpc/svc.h>
  11#include <uapi/linux/nfsd/nfsfh.h>
  12
  13static inline __u32 ino_t_to_u32(ino_t ino)
  14{
  15        return (__u32) ino;
  16}
  17
  18static inline ino_t u32_to_ino_t(__u32 uino)
  19{
  20        return (ino_t) uino;
  21}
  22
  23/*
  24 * This is the internal representation of an NFS handle used in knfsd.
  25 * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
  26 */
  27typedef struct svc_fh {
  28        struct knfsd_fh         fh_handle;      /* FH data */
  29        struct dentry *         fh_dentry;      /* validated dentry */
  30        struct svc_export *     fh_export;      /* export pointer */
  31        int                     fh_maxsize;     /* max size for fh_handle */
  32
  33        unsigned char           fh_locked;      /* inode locked by us */
  34        unsigned char           fh_want_write;  /* remount protection taken */
  35
  36#ifdef CONFIG_NFSD_V3
  37        unsigned char           fh_post_saved;  /* post-op attrs saved */
  38        unsigned char           fh_pre_saved;   /* pre-op attrs saved */
  39
  40        /* Pre-op attributes saved during fh_lock */
  41        __u64                   fh_pre_size;    /* size before operation */
  42        struct timespec         fh_pre_mtime;   /* mtime before oper */
  43        struct timespec         fh_pre_ctime;   /* ctime before oper */
  44        /*
  45         * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
  46         *  to find out if it is valid.
  47         */
  48        u64                     fh_pre_change;
  49
  50        /* Post-op attributes saved in fh_unlock */
  51        struct kstat            fh_post_attr;   /* full attrs after operation */
  52        u64                     fh_post_change; /* nfsv4 change; see above */
  53#endif /* CONFIG_NFSD_V3 */
  54
  55} svc_fh;
  56
  57enum nfsd_fsid {
  58        FSID_DEV = 0,
  59        FSID_NUM,
  60        FSID_MAJOR_MINOR,
  61        FSID_ENCODE_DEV,
  62        FSID_UUID4_INUM,
  63        FSID_UUID8,
  64        FSID_UUID16,
  65        FSID_UUID16_INUM,
  66};
  67
  68enum fsid_source {
  69        FSIDSOURCE_DEV,
  70        FSIDSOURCE_FSID,
  71        FSIDSOURCE_UUID,
  72};
  73extern enum fsid_source fsid_source(struct svc_fh *fhp);
  74
  75
  76/*
  77 * This might look a little large to "inline" but in all calls except
  78 * one, 'vers' is constant so moste of the function disappears.
  79 *
  80 * In some cases the values are considered to be host endian and in
  81 * others, net endian. fsidv is always considered to be u32 as the
  82 * callers don't know which it will be. So we must use __force to keep
  83 * sparse from complaining. Since these values are opaque to the
  84 * client, that shouldn't be a problem.
  85 */
  86static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
  87                           u32 fsid, unsigned char *uuid)
  88{
  89        u32 *up;
  90        switch(vers) {
  91        case FSID_DEV:
  92                fsidv[0] = (__force __u32)htonl((MAJOR(dev)<<16) |
  93                                 MINOR(dev));
  94                fsidv[1] = ino_t_to_u32(ino);
  95                break;
  96        case FSID_NUM:
  97                fsidv[0] = fsid;
  98                break;
  99        case FSID_MAJOR_MINOR:
 100                fsidv[0] = (__force __u32)htonl(MAJOR(dev));
 101                fsidv[1] = (__force __u32)htonl(MINOR(dev));
 102                fsidv[2] = ino_t_to_u32(ino);
 103                break;
 104
 105        case FSID_ENCODE_DEV:
 106                fsidv[0] = new_encode_dev(dev);
 107                fsidv[1] = ino_t_to_u32(ino);
 108                break;
 109
 110        case FSID_UUID4_INUM:
 111                /* 4 byte fsid and inode number */
 112                up = (u32*)uuid;
 113                fsidv[0] = ino_t_to_u32(ino);
 114                fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
 115                break;
 116
 117        case FSID_UUID8:
 118                /* 8 byte fsid  */
 119                up = (u32*)uuid;
 120                fsidv[0] = up[0] ^ up[2];
 121                fsidv[1] = up[1] ^ up[3];
 122                break;
 123
 124        case FSID_UUID16:
 125                /* 16 byte fsid - NFSv3+ only */
 126                memcpy(fsidv, uuid, 16);
 127                break;
 128
 129        case FSID_UUID16_INUM:
 130                /* 8 byte inode and 16 byte fsid */
 131                *(u64*)fsidv = (u64)ino;
 132                memcpy(fsidv+2, uuid, 16);
 133                break;
 134        default: BUG();
 135        }
 136}
 137
 138static inline int key_len(int type)
 139{
 140        switch(type) {
 141        case FSID_DEV:          return 8;
 142        case FSID_NUM:          return 4;
 143        case FSID_MAJOR_MINOR:  return 12;
 144        case FSID_ENCODE_DEV:   return 8;
 145        case FSID_UUID4_INUM:   return 8;
 146        case FSID_UUID8:        return 8;
 147        case FSID_UUID16:       return 16;
 148        case FSID_UUID16_INUM:  return 24;
 149        default: return 0;
 150        }
 151}
 152
 153/*
 154 * Shorthand for dprintk()'s
 155 */
 156extern char * SVCFH_fmt(struct svc_fh *fhp);
 157
 158/*
 159 * Function prototypes
 160 */
 161__be32  fh_verify(struct svc_rqst *, struct svc_fh *, umode_t, int);
 162__be32  fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
 163__be32  fh_update(struct svc_fh *);
 164void    fh_put(struct svc_fh *);
 165
 166static __inline__ struct svc_fh *
 167fh_copy(struct svc_fh *dst, struct svc_fh *src)
 168{
 169        WARN_ON(src->fh_dentry || src->fh_locked);
 170                        
 171        *dst = *src;
 172        return dst;
 173}
 174
 175static inline void
 176fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
 177{
 178        dst->fh_size = src->fh_size;
 179        memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
 180}
 181
 182static __inline__ struct svc_fh *
 183fh_init(struct svc_fh *fhp, int maxsize)
 184{
 185        memset(fhp, 0, sizeof(*fhp));
 186        fhp->fh_maxsize = maxsize;
 187        return fhp;
 188}
 189
 190#ifdef CONFIG_NFSD_V3
 191/*
 192 * The wcc data stored in current_fh should be cleared
 193 * between compound ops.
 194 */
 195static inline void
 196fh_clear_wcc(struct svc_fh *fhp)
 197{
 198        fhp->fh_post_saved = 0;
 199        fhp->fh_pre_saved = 0;
 200}
 201
 202/*
 203 * Fill in the pre_op attr for the wcc data
 204 */
 205static inline void
 206fill_pre_wcc(struct svc_fh *fhp)
 207{
 208        struct inode    *inode;
 209
 210        inode = fhp->fh_dentry->d_inode;
 211        if (!fhp->fh_pre_saved) {
 212                fhp->fh_pre_mtime = inode->i_mtime;
 213                fhp->fh_pre_ctime = inode->i_ctime;
 214                fhp->fh_pre_size  = inode->i_size;
 215                fhp->fh_pre_change = inode->i_version;
 216                fhp->fh_pre_saved = 1;
 217        }
 218}
 219
 220extern void fill_post_wcc(struct svc_fh *);
 221#else
 222#define fh_clear_wcc(ignored)
 223#define fill_pre_wcc(ignored)
 224#define fill_post_wcc(notused)
 225#endif /* CONFIG_NFSD_V3 */
 226
 227
 228/*
 229 * Lock a file handle/inode
 230 * NOTE: both fh_lock and fh_unlock are done "by hand" in
 231 * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
 232 * so, any changes here should be reflected there.
 233 */
 234
 235static inline void
 236fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
 237{
 238        struct dentry   *dentry = fhp->fh_dentry;
 239        struct inode    *inode;
 240
 241        BUG_ON(!dentry);
 242
 243        if (fhp->fh_locked) {
 244                printk(KERN_WARNING "fh_lock: %pd2 already locked!\n",
 245                        dentry);
 246                return;
 247        }
 248
 249        inode = dentry->d_inode;
 250        mutex_lock_nested(&inode->i_mutex, subclass);
 251        fill_pre_wcc(fhp);
 252        fhp->fh_locked = 1;
 253}
 254
 255static inline void
 256fh_lock(struct svc_fh *fhp)
 257{
 258        fh_lock_nested(fhp, I_MUTEX_NORMAL);
 259}
 260
 261/*
 262 * Unlock a file handle/inode
 263 */
 264static inline void
 265fh_unlock(struct svc_fh *fhp)
 266{
 267        if (fhp->fh_locked) {
 268                fill_post_wcc(fhp);
 269                mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
 270                fhp->fh_locked = 0;
 271        }
 272}
 273
 274#endif /* _LINUX_NFSD_NFSFH_H */
 275