linux/fs/ocfs2/export.c
<<
>>
Prefs
   1/* -*- mode: c; c-basic-offset: 8; -*-
   2 * vim: noexpandtab sw=8 ts=8 sts=0:
   3 *
   4 * export.c
   5 *
   6 * Functions to facilitate NFS exporting
   7 *
   8 * Copyright (C) 2002, 2005 Oracle.  All rights reserved.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public
  12 * License as published by the Free Software Foundation; either
  13 * version 2 of the License, or (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 * General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public
  21 * License along with this program; if not, write to the
  22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  23 * Boston, MA 021110-1307, USA.
  24 */
  25
  26#include <linux/fs.h>
  27#include <linux/types.h>
  28
  29#include <cluster/masklog.h>
  30
  31#include "ocfs2.h"
  32
  33#include "alloc.h"
  34#include "dir.h"
  35#include "dlmglue.h"
  36#include "dcache.h"
  37#include "export.h"
  38#include "inode.h"
  39
  40#include "buffer_head_io.h"
  41#include "suballoc.h"
  42#include "ocfs2_trace.h"
  43
  44struct ocfs2_inode_handle
  45{
  46        u64 ih_blkno;
  47        u32 ih_generation;
  48};
  49
  50static struct dentry *ocfs2_get_dentry(struct super_block *sb,
  51                struct ocfs2_inode_handle *handle)
  52{
  53        struct inode *inode;
  54        struct ocfs2_super *osb = OCFS2_SB(sb);
  55        u64 blkno = handle->ih_blkno;
  56        int status, set;
  57        struct dentry *result;
  58
  59        trace_ocfs2_get_dentry_begin(sb, handle, (unsigned long long)blkno);
  60
  61        if (blkno == 0) {
  62                result = ERR_PTR(-ESTALE);
  63                goto bail;
  64        }
  65
  66        inode = ocfs2_ilookup(sb, blkno);
  67        /*
  68         * If the inode exists in memory, we only need to check it's
  69         * generation number
  70         */
  71        if (inode)
  72                goto check_gen;
  73
  74        /*
  75         * This will synchronize us against ocfs2_delete_inode() on
  76         * all nodes
  77         */
  78        status = ocfs2_nfs_sync_lock(osb, 1);
  79        if (status < 0) {
  80                mlog(ML_ERROR, "getting nfs sync lock(EX) failed %d\n", status);
  81                goto check_err;
  82        }
  83
  84        status = ocfs2_test_inode_bit(osb, blkno, &set);
  85        trace_ocfs2_get_dentry_test_bit(status, set);
  86        if (status < 0) {
  87                if (status == -EINVAL) {
  88                        /*
  89                         * The blkno NFS gave us doesn't even show up
  90                         * as an inode, we return -ESTALE to be
  91                         * nice
  92                         */
  93                        status = -ESTALE;
  94                } else
  95                        mlog(ML_ERROR, "test inode bit failed %d\n", status);
  96                goto unlock_nfs_sync;
  97        }
  98
  99        /* If the inode allocator bit is clear, this inode must be stale */
 100        if (!set) {
 101                status = -ESTALE;
 102                goto unlock_nfs_sync;
 103        }
 104
 105        inode = ocfs2_iget(osb, blkno, 0, 0);
 106
 107unlock_nfs_sync:
 108        ocfs2_nfs_sync_unlock(osb, 1);
 109
 110check_err:
 111        if (status < 0) {
 112                if (status == -ESTALE) {
 113                        trace_ocfs2_get_dentry_stale((unsigned long long)blkno,
 114                                                     handle->ih_generation);
 115                }
 116                result = ERR_PTR(status);
 117                goto bail;
 118        }
 119
 120        if (IS_ERR(inode)) {
 121                mlog_errno(PTR_ERR(inode));
 122                result = (void *)inode;
 123                goto bail;
 124        }
 125
 126check_gen:
 127        if (handle->ih_generation != inode->i_generation) {
 128                iput(inode);
 129                trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
 130                                                  handle->ih_generation,
 131                                                  inode->i_generation);
 132                result = ERR_PTR(-ESTALE);
 133                goto bail;
 134        }
 135
 136        result = d_obtain_alias(inode);
 137        if (IS_ERR(result))
 138                mlog_errno(PTR_ERR(result));
 139
 140bail:
 141        trace_ocfs2_get_dentry_end(result);
 142        return result;
 143}
 144
 145static struct dentry *ocfs2_get_parent(struct dentry *child)
 146{
 147        int status;
 148        u64 blkno;
 149        struct dentry *parent;
 150        struct inode *dir = child->d_inode;
 151
 152        trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name,
 153                               (unsigned long long)OCFS2_I(dir)->ip_blkno);
 154
 155        status = ocfs2_inode_lock(dir, NULL, 0);
 156        if (status < 0) {
 157                if (status != -ENOENT)
 158                        mlog_errno(status);
 159                parent = ERR_PTR(status);
 160                goto bail;
 161        }
 162
 163        status = ocfs2_lookup_ino_from_name(dir, "..", 2, &blkno);
 164        if (status < 0) {
 165                parent = ERR_PTR(-ENOENT);
 166                goto bail_unlock;
 167        }
 168
 169        parent = d_obtain_alias(ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0));
 170
 171bail_unlock:
 172        ocfs2_inode_unlock(dir, 0);
 173
 174bail:
 175        trace_ocfs2_get_parent_end(parent);
 176
 177        return parent;
 178}
 179
 180static int ocfs2_encode_fh(struct inode *inode, u32 *fh_in, int *max_len,
 181                           struct inode *parent)
 182{
 183        int len = *max_len;
 184        int type = 1;
 185        u64 blkno;
 186        u32 generation;
 187        __le32 *fh = (__force __le32 *) fh_in;
 188
 189#ifdef TRACE_HOOKS_ARE_NOT_BRAINDEAD_IN_YOUR_OPINION
 190#error "You go ahead and fix that mess, then.  Somehow"
 191        trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len,
 192                                    dentry->d_name.name,
 193                                    fh, len, connectable);
 194#endif
 195
 196        if (parent && (len < 6)) {
 197                *max_len = 6;
 198                type = 255;
 199                goto bail;
 200        } else if (len < 3) {
 201                *max_len = 3;
 202                type = 255;
 203                goto bail;
 204        }
 205
 206        blkno = OCFS2_I(inode)->ip_blkno;
 207        generation = inode->i_generation;
 208
 209        trace_ocfs2_encode_fh_self((unsigned long long)blkno, generation);
 210
 211        len = 3;
 212        fh[0] = cpu_to_le32((u32)(blkno >> 32));
 213        fh[1] = cpu_to_le32((u32)(blkno & 0xffffffff));
 214        fh[2] = cpu_to_le32(generation);
 215
 216        if (parent) {
 217                blkno = OCFS2_I(parent)->ip_blkno;
 218                generation = parent->i_generation;
 219
 220                fh[3] = cpu_to_le32((u32)(blkno >> 32));
 221                fh[4] = cpu_to_le32((u32)(blkno & 0xffffffff));
 222                fh[5] = cpu_to_le32(generation);
 223
 224                len = 6;
 225                type = 2;
 226
 227                trace_ocfs2_encode_fh_parent((unsigned long long)blkno,
 228                                             generation);
 229        }
 230
 231        *max_len = len;
 232
 233bail:
 234        trace_ocfs2_encode_fh_type(type);
 235        return type;
 236}
 237
 238static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb,
 239                struct fid *fid, int fh_len, int fh_type)
 240{
 241        struct ocfs2_inode_handle handle;
 242
 243        if (fh_len < 3 || fh_type > 2)
 244                return NULL;
 245
 246        handle.ih_blkno = (u64)le32_to_cpu(fid->raw[0]) << 32;
 247        handle.ih_blkno |= (u64)le32_to_cpu(fid->raw[1]);
 248        handle.ih_generation = le32_to_cpu(fid->raw[2]);
 249        return ocfs2_get_dentry(sb, &handle);
 250}
 251
 252static struct dentry *ocfs2_fh_to_parent(struct super_block *sb,
 253                struct fid *fid, int fh_len, int fh_type)
 254{
 255        struct ocfs2_inode_handle parent;
 256
 257        if (fh_type != 2 || fh_len < 6)
 258                return NULL;
 259
 260        parent.ih_blkno = (u64)le32_to_cpu(fid->raw[3]) << 32;
 261        parent.ih_blkno |= (u64)le32_to_cpu(fid->raw[4]);
 262        parent.ih_generation = le32_to_cpu(fid->raw[5]);
 263        return ocfs2_get_dentry(sb, &parent);
 264}
 265
 266const struct export_operations ocfs2_export_ops = {
 267        .encode_fh      = ocfs2_encode_fh,
 268        .fh_to_dentry   = ocfs2_fh_to_dentry,
 269        .fh_to_parent   = ocfs2_fh_to_parent,
 270        .get_parent     = ocfs2_get_parent,
 271};
 272
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.