root/fs/ocfs2/export.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ocfs2_get_dentry
  2. ocfs2_get_parent
  3. ocfs2_encode_fh
  4. ocfs2_fh_to_dentry
  5. ocfs2_fh_to_parent

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

/* [<][>][^][v][top][bottom][index][help] */