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