cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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};