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