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        int                     fh_maxsize;     /* max size for fh_handle */
  30        struct dentry *         fh_dentry;      /* validated dentry */
  31        struct svc_export *     fh_export;      /* export pointer */
  32
  33        bool                    fh_locked;      /* inode locked by us */
  34        bool                    fh_want_write;  /* remount protection taken */
  35
  36#ifdef CONFIG_NFSD_V3
  37        bool                    fh_post_saved;  /* post-op attrs saved */
  38        bool                    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
 190static inline bool fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
 191{
 192        if (fh1->fh_size != fh2->fh_size)
 193                return false;
 194        if (memcmp(fh1->fh_base.fh_pad, fh2->fh_base.fh_pad, fh1->fh_size) != 0)
 195                return false;
 196        return true;
 197}
 198
 199static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
 200{
 201        if (fh1->fh_fsid_type != fh2->fh_fsid_type)
 202                return false;
 203        if (memcmp(fh1->fh_fsid, fh2->fh_fsid, key_len(fh1->fh_fsid_type)) != 0)
 204                return false;
 205        return true;
 206}
 207
 208#ifdef CONFIG_NFSD_V3
 209/*
 210 * The wcc data stored in current_fh should be cleared
 211 * between compound ops.
 212 */
 213static inline void
 214fh_clear_wcc(struct svc_fh *fhp)
 215{
 216        fhp->fh_post_saved = false;
 217        fhp->fh_pre_saved = false;
 218}
 219
 220/*
 221 * Fill in the pre_op attr for the wcc data
 222 */
 223static inline void
 224fill_pre_wcc(struct svc_fh *fhp)
 225{
 226        struct inode    *inode;
 227
 228        inode = d_inode(fhp->fh_dentry);
 229        if (!fhp->fh_pre_saved) {
 230                fhp->fh_pre_mtime = inode->i_mtime;
 231                fhp->fh_pre_ctime = inode->i_ctime;
 232                fhp->fh_pre_size  = inode->i_size;
 233                fhp->fh_pre_change = inode->i_version;
 234                fhp->fh_pre_saved = true;
 235        }
 236}
 237
 238extern void fill_post_wcc(struct svc_fh *);
 239#else
 240#define fh_clear_wcc(ignored)
 241#define fill_pre_wcc(ignored)
 242#define fill_post_wcc(notused)
 243#endif /* CONFIG_NFSD_V3 */
 244
 245
 246/*
 247 * Lock a file handle/inode
 248 * NOTE: both fh_lock and fh_unlock are done "by hand" in
 249 * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
 250 * so, any changes here should be reflected there.
 251 */
 252
 253static inline void
 254fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
 255{
 256        struct dentry   *dentry = fhp->fh_dentry;
 257        struct inode    *inode;
 258
 259        BUG_ON(!dentry);
 260
 261        if (fhp->fh_locked) {
 262                printk(KERN_WARNING "fh_lock: %pd2 already locked!\n",
 263                        dentry);
 264                return;
 265        }
 266
 267        inode = d_inode(dentry);
 268        mutex_lock_nested(&inode->i_mutex, subclass);
 269        fill_pre_wcc(fhp);
 270        fhp->fh_locked = true;
 271}
 272
 273static inline void
 274fh_lock(struct svc_fh *fhp)
 275{
 276        fh_lock_nested(fhp, I_MUTEX_NORMAL);
 277}
 278
 279/*
 280 * Unlock a file handle/inode
 281 */
 282static inline void
 283fh_unlock(struct svc_fh *fhp)
 284{
 285        if (fhp->fh_locked) {
 286                fill_post_wcc(fhp);
 287                mutex_unlock(&d_inode(fhp->fh_dentry)->i_mutex);
 288                fhp->fh_locked = false;
 289        }
 290}
 291
 292#endif /* _LINUX_NFSD_NFSFH_H */
 293