linux/drivers/staging/lustre/lustre/llite/llite_nfs.c
<<
>>
Prefs
   1/*
   2 * GPL HEADER START
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 only,
   8 * as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License version 2 for more details (a copy is included
  14 * in the LICENSE file that accompanied this code).
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * version 2 along with this program; If not, see
  18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
  19 *
  20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  21 * CA 95054 USA or visit www.sun.com if you need additional information or
  22 * have any questions.
  23 *
  24 * GPL HEADER END
  25 */
  26/*
  27 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  28 * Use is subject to license terms.
  29 *
  30 * Copyright (c) 2011, 2012, Intel Corporation.
  31 */
  32/*
  33 * This file is part of Lustre, http://www.lustre.org/
  34 * Lustre is a trademark of Sun Microsystems, Inc.
  35 *
  36 * lustre/lustre/llite/llite_nfs.c
  37 *
  38 * NFS export of Lustre Light File System
  39 *
  40 * Author: Yury Umanets <umka@clusterfs.com>
  41 * Author: Huang Hua <huanghua@clusterfs.com>
  42 */
  43
  44#define DEBUG_SUBSYSTEM S_LLITE
  45#include "../include/lustre_lite.h"
  46#include "llite_internal.h"
  47#include <linux/exportfs.h>
  48
  49__u32 get_uuid2int(const char *name, int len)
  50{
  51        __u32 key0 = 0x12a3fe2d, key1 = 0x37abe8f9;
  52        while (len--) {
  53                __u32 key = key1 + (key0 ^ (*name++ * 7152373));
  54
  55                if (key & 0x80000000)
  56                        key -= 0x7fffffff;
  57                key1 = key0;
  58                key0 = key;
  59        }
  60        return (key0 << 1);
  61}
  62
  63void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid)
  64{
  65        __u64 key = 0, key0 = 0x12a3fe2d, key1 = 0x37abe8f9;
  66
  67        while (len--) {
  68                key = key1 + (key0 ^ (*name++ * 7152373));
  69                if (key & 0x8000000000000000ULL)
  70                        key -= 0x7fffffffffffffffULL;
  71                key1 = key0;
  72                key0 = key;
  73        }
  74
  75        fsid->val[0] = key;
  76        fsid->val[1] = key >> 32;
  77}
  78
  79static int ll_nfs_test_inode(struct inode *inode, void *opaque)
  80{
  81        return lu_fid_eq(&ll_i2info(inode)->lli_fid,
  82                         (struct lu_fid *)opaque);
  83}
  84
  85struct inode *search_inode_for_lustre(struct super_block *sb,
  86                                      const struct lu_fid *fid)
  87{
  88        struct ll_sb_info     *sbi = ll_s2sbi(sb);
  89        struct ptlrpc_request *req = NULL;
  90        struct inode      *inode = NULL;
  91        int                eadatalen = 0;
  92        unsigned long         hash = cl_fid_build_ino(fid,
  93                                                      ll_need_32bit_api(sbi));
  94        struct  md_op_data    *op_data;
  95        int                rc;
  96
  97        CDEBUG(D_INFO, "searching inode for:(%lu,"DFID")\n", hash, PFID(fid));
  98
  99        inode = ilookup5(sb, hash, ll_nfs_test_inode, (void *)fid);
 100        if (inode)
 101                return inode;
 102
 103        rc = ll_get_default_mdsize(sbi, &eadatalen);
 104        if (rc)
 105                return ERR_PTR(rc);
 106
 107        /* Because inode is NULL, ll_prep_md_op_data can not
 108         * be used here. So we allocate op_data ourselves */
 109        op_data = kzalloc(sizeof(*op_data), GFP_NOFS);
 110        if (!op_data)
 111                return ERR_PTR(-ENOMEM);
 112
 113        op_data->op_fid1 = *fid;
 114        op_data->op_mode = eadatalen;
 115        op_data->op_valid = OBD_MD_FLEASIZE;
 116
 117        /* mds_fid2dentry ignores f_type */
 118        rc = md_getattr(sbi->ll_md_exp, op_data, &req);
 119        OBD_FREE_PTR(op_data);
 120        if (rc) {
 121                CERROR("can't get object attrs, fid "DFID", rc %d\n",
 122                       PFID(fid), rc);
 123                return ERR_PTR(rc);
 124        }
 125        rc = ll_prep_inode(&inode, req, sb, NULL);
 126        ptlrpc_req_finished(req);
 127        if (rc)
 128                return ERR_PTR(rc);
 129
 130        return inode;
 131}
 132
 133struct lustre_nfs_fid {
 134        struct lu_fid   lnf_child;
 135        struct lu_fid   lnf_parent;
 136};
 137
 138static struct dentry *
 139ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *parent)
 140{
 141        struct inode  *inode;
 142        struct dentry *result;
 143
 144        CDEBUG(D_INFO, "Get dentry for fid: "DFID"\n", PFID(fid));
 145        if (!fid_is_sane(fid))
 146                return ERR_PTR(-ESTALE);
 147
 148        inode = search_inode_for_lustre(sb, fid);
 149        if (IS_ERR(inode))
 150                return ERR_CAST(inode);
 151
 152        if (is_bad_inode(inode)) {
 153                /* we didn't find the right inode.. */
 154                iput(inode);
 155                return ERR_PTR(-ESTALE);
 156        }
 157
 158        /**
 159         * It is an anonymous dentry without OST objects created yet.
 160         * We have to find the parent to tell MDS how to init lov objects.
 161         */
 162        if (S_ISREG(inode->i_mode) && !ll_i2info(inode)->lli_has_smd &&
 163            parent != NULL) {
 164                struct ll_inode_info *lli = ll_i2info(inode);
 165
 166                spin_lock(&lli->lli_lock);
 167                lli->lli_pfid = *parent;
 168                spin_unlock(&lli->lli_lock);
 169        }
 170
 171        result = d_obtain_alias(inode);
 172        if (IS_ERR(result)) {
 173                iput(inode);
 174                return result;
 175        }
 176
 177        return result;
 178}
 179
 180#define LUSTRE_NFS_FID    0x97
 181
 182/**
 183 * \a connectable - is nfsd will connect himself or this should be done
 184 *                at lustre
 185 *
 186 * The return value is file handle type:
 187 * 1 -- contains child file handle;
 188 * 2 -- contains child file handle and parent file handle;
 189 * 255 -- error.
 190 */
 191static int ll_encode_fh(struct inode *inode, __u32 *fh, int *plen,
 192                        struct inode *parent)
 193{
 194        struct lustre_nfs_fid *nfs_fid = (void *)fh;
 195
 196        CDEBUG(D_INFO, "encoding for (%lu,"DFID") maxlen=%d minlen=%d\n",
 197              inode->i_ino, PFID(ll_inode2fid(inode)), *plen,
 198              (int)sizeof(struct lustre_nfs_fid));
 199
 200        if (*plen < sizeof(struct lustre_nfs_fid) / 4)
 201                return 255;
 202
 203        nfs_fid->lnf_child = *ll_inode2fid(inode);
 204        nfs_fid->lnf_parent = *ll_inode2fid(parent);
 205        *plen = sizeof(struct lustre_nfs_fid) / 4;
 206
 207        return LUSTRE_NFS_FID;
 208}
 209
 210static int ll_nfs_get_name_filldir(struct dir_context *ctx, const char *name,
 211                                   int namelen, loff_t hash, u64 ino,
 212                                   unsigned type)
 213{
 214        /* It is hack to access lde_fid for comparison with lgd_fid.
 215         * So the input 'name' must be part of the 'lu_dirent'. */
 216        struct lu_dirent *lde = container_of0(name, struct lu_dirent, lde_name);
 217        struct ll_getname_data *lgd =
 218                container_of(ctx, struct ll_getname_data, ctx);
 219        struct lu_fid fid;
 220
 221        fid_le_to_cpu(&fid, &lde->lde_fid);
 222        if (lu_fid_eq(&fid, &lgd->lgd_fid)) {
 223                memcpy(lgd->lgd_name, name, namelen);
 224                lgd->lgd_name[namelen] = 0;
 225                lgd->lgd_found = 1;
 226        }
 227        return lgd->lgd_found;
 228}
 229
 230static int ll_get_name(struct dentry *dentry, char *name,
 231                       struct dentry *child)
 232{
 233        struct inode *dir = dentry->d_inode;
 234        int rc;
 235        struct ll_getname_data lgd = {
 236                .lgd_name = name,
 237                .lgd_fid = ll_i2info(child->d_inode)->lli_fid,
 238                .ctx.actor = ll_nfs_get_name_filldir,
 239        };
 240
 241        if (!dir || !S_ISDIR(dir->i_mode)) {
 242                rc = -ENOTDIR;
 243                goto out;
 244        }
 245
 246        if (!dir->i_fop) {
 247                rc = -EINVAL;
 248                goto out;
 249        }
 250
 251        mutex_lock(&dir->i_mutex);
 252        rc = ll_dir_read(dir, &lgd.ctx);
 253        mutex_unlock(&dir->i_mutex);
 254        if (!rc && !lgd.lgd_found)
 255                rc = -ENOENT;
 256out:
 257        return rc;
 258}
 259
 260static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid,
 261                                      int fh_len, int fh_type)
 262{
 263        struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
 264
 265        if (fh_type != LUSTRE_NFS_FID)
 266                return ERR_PTR(-EPROTO);
 267
 268        return ll_iget_for_nfs(sb, &nfs_fid->lnf_child, &nfs_fid->lnf_parent);
 269}
 270
 271static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid,
 272                                      int fh_len, int fh_type)
 273{
 274        struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
 275
 276        if (fh_type != LUSTRE_NFS_FID)
 277                return ERR_PTR(-EPROTO);
 278
 279        return ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL);
 280}
 281
 282static struct dentry *ll_get_parent(struct dentry *dchild)
 283{
 284        struct ptlrpc_request *req = NULL;
 285        struct inode      *dir = dchild->d_inode;
 286        struct ll_sb_info     *sbi;
 287        struct dentry    *result = NULL;
 288        struct mdt_body       *body;
 289        static char        dotdot[] = "..";
 290        struct md_op_data     *op_data;
 291        int                rc;
 292        int                   lmmsize;
 293
 294        LASSERT(dir && S_ISDIR(dir->i_mode));
 295
 296        sbi = ll_s2sbi(dir->i_sb);
 297
 298        CDEBUG(D_INFO, "getting parent for (%lu,"DFID")\n",
 299                        dir->i_ino, PFID(ll_inode2fid(dir)));
 300
 301        rc = ll_get_default_mdsize(sbi, &lmmsize);
 302        if (rc != 0)
 303                return ERR_PTR(rc);
 304
 305        op_data = ll_prep_md_op_data(NULL, dir, NULL, dotdot,
 306                                     strlen(dotdot), lmmsize,
 307                                     LUSTRE_OPC_ANY, NULL);
 308        if (IS_ERR(op_data))
 309                return (void *)op_data;
 310
 311        rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
 312        ll_finish_md_op_data(op_data);
 313        if (rc) {
 314                CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
 315                return ERR_PTR(rc);
 316        }
 317        body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 318        LASSERT(body->valid & OBD_MD_FLID);
 319
 320        CDEBUG(D_INFO, "parent for "DFID" is "DFID"\n",
 321                PFID(ll_inode2fid(dir)), PFID(&body->fid1));
 322
 323        result = ll_iget_for_nfs(dir->i_sb, &body->fid1, NULL);
 324
 325        ptlrpc_req_finished(req);
 326        return result;
 327}
 328
 329struct export_operations lustre_export_operations = {
 330       .get_parent = ll_get_parent,
 331       .encode_fh  = ll_encode_fh,
 332       .get_name   = ll_get_name,
 333        .fh_to_dentry = ll_fh_to_dentry,
 334        .fh_to_parent = ll_fh_to_parent,
 335};
 336