linux/fs/gfs2/export.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
   3 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
   4 *
   5 * This copyrighted material is made available to anyone wishing to use,
   6 * modify, copy, or redistribute it subject to the terms and conditions
   7 * of the GNU General Public License version 2.
   8 */
   9
  10#include <linux/spinlock.h>
  11#include <linux/completion.h>
  12#include <linux/buffer_head.h>
  13#include <linux/exportfs.h>
  14#include <linux/gfs2_ondisk.h>
  15#include <linux/crc32.h>
  16
  17#include "gfs2.h"
  18#include "incore.h"
  19#include "dir.h"
  20#include "glock.h"
  21#include "glops.h"
  22#include "inode.h"
  23#include "super.h"
  24#include "rgrp.h"
  25#include "util.h"
  26
  27#define GFS2_SMALL_FH_SIZE 4
  28#define GFS2_LARGE_FH_SIZE 8
  29#define GFS2_OLD_FH_SIZE 10
  30
  31static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
  32                          int connectable)
  33{
  34        __be32 *fh = (__force __be32 *)p;
  35        struct inode *inode = dentry->d_inode;
  36        struct super_block *sb = inode->i_sb;
  37        struct gfs2_inode *ip = GFS2_I(inode);
  38
  39        if (connectable && (*len < GFS2_LARGE_FH_SIZE)) {
  40                *len = GFS2_LARGE_FH_SIZE;
  41                return 255;
  42        } else if (*len < GFS2_SMALL_FH_SIZE) {
  43                *len = GFS2_SMALL_FH_SIZE;
  44                return 255;
  45        }
  46
  47        fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
  48        fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
  49        fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
  50        fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
  51        *len = GFS2_SMALL_FH_SIZE;
  52
  53        if (!connectable || inode == sb->s_root->d_inode)
  54                return *len;
  55
  56        spin_lock(&dentry->d_lock);
  57        inode = dentry->d_parent->d_inode;
  58        ip = GFS2_I(inode);
  59        igrab(inode);
  60        spin_unlock(&dentry->d_lock);
  61
  62        fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
  63        fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
  64        fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
  65        fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
  66        *len = GFS2_LARGE_FH_SIZE;
  67
  68        iput(inode);
  69
  70        return *len;
  71}
  72
  73struct get_name_filldir {
  74        struct gfs2_inum_host inum;
  75        char *name;
  76};
  77
  78static int get_name_filldir(void *opaque, const char *name, int length,
  79                            loff_t offset, u64 inum, unsigned int type)
  80{
  81        struct get_name_filldir *gnfd = opaque;
  82
  83        if (inum != gnfd->inum.no_addr)
  84                return 0;
  85
  86        memcpy(gnfd->name, name, length);
  87        gnfd->name[length] = 0;
  88
  89        return 1;
  90}
  91
  92static int gfs2_get_name(struct dentry *parent, char *name,
  93                         struct dentry *child)
  94{
  95        struct inode *dir = parent->d_inode;
  96        struct inode *inode = child->d_inode;
  97        struct gfs2_inode *dip, *ip;
  98        struct get_name_filldir gnfd;
  99        struct gfs2_holder gh;
 100        u64 offset = 0;
 101        int error;
 102
 103        if (!dir)
 104                return -EINVAL;
 105
 106        if (!S_ISDIR(dir->i_mode) || !inode)
 107                return -EINVAL;
 108
 109        dip = GFS2_I(dir);
 110        ip = GFS2_I(inode);
 111
 112        *name = 0;
 113        gnfd.inum.no_addr = ip->i_no_addr;
 114        gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
 115        gnfd.name = name;
 116
 117        error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
 118        if (error)
 119                return error;
 120
 121        error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir);
 122
 123        gfs2_glock_dq_uninit(&gh);
 124
 125        if (!error && !*name)
 126                error = -ENOENT;
 127
 128        return error;
 129}
 130
 131static struct dentry *gfs2_get_parent(struct dentry *child)
 132{
 133        return d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
 134}
 135
 136static struct dentry *gfs2_get_dentry(struct super_block *sb,
 137                                      struct gfs2_inum_host *inum)
 138{
 139        struct gfs2_sbd *sdp = sb->s_fs_info;
 140        struct inode *inode;
 141
 142        inode = gfs2_ilookup(sb, inum->no_addr, 0);
 143        if (inode) {
 144                if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
 145                        iput(inode);
 146                        return ERR_PTR(-ESTALE);
 147                }
 148                goto out_inode;
 149        }
 150
 151        inode = gfs2_lookup_by_inum(sdp, inum->no_addr, &inum->no_formal_ino,
 152                                    GFS2_BLKST_DINODE);
 153        if (IS_ERR(inode))
 154                return ERR_CAST(inode);
 155
 156out_inode:
 157        return d_obtain_alias(inode);
 158}
 159
 160static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
 161                int fh_len, int fh_type)
 162{
 163        struct gfs2_inum_host this;
 164        __be32 *fh = (__force __be32 *)fid->raw;
 165
 166        switch (fh_type) {
 167        case GFS2_SMALL_FH_SIZE:
 168        case GFS2_LARGE_FH_SIZE:
 169        case GFS2_OLD_FH_SIZE:
 170                this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
 171                this.no_formal_ino |= be32_to_cpu(fh[1]);
 172                this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
 173                this.no_addr |= be32_to_cpu(fh[3]);
 174                return gfs2_get_dentry(sb, &this);
 175        default:
 176                return NULL;
 177        }
 178}
 179
 180static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
 181                int fh_len, int fh_type)
 182{
 183        struct gfs2_inum_host parent;
 184        __be32 *fh = (__force __be32 *)fid->raw;
 185
 186        switch (fh_type) {
 187        case GFS2_LARGE_FH_SIZE:
 188        case GFS2_OLD_FH_SIZE:
 189                parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
 190                parent.no_formal_ino |= be32_to_cpu(fh[5]);
 191                parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
 192                parent.no_addr |= be32_to_cpu(fh[7]);
 193                return gfs2_get_dentry(sb, &parent);
 194        default:
 195                return NULL;
 196        }
 197}
 198
 199const struct export_operations gfs2_export_ops = {
 200        .encode_fh = gfs2_encode_fh,
 201        .fh_to_dentry = gfs2_fh_to_dentry,
 202        .fh_to_parent = gfs2_fh_to_parent,
 203        .get_name = gfs2_get_name,
 204        .get_parent = gfs2_get_parent,
 205};
 206
 207