Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2015, Primary Data, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Tao Peng <bergwolf@primarydata.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/dcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/exportfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/nfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/nfs_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "nfstrace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define NFSDBG_FACILITY		NFSDBG_VFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	FILEID_HIGH_OFF = 0,	/* inode fileid high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	FILEID_LOW_OFF,		/* inode fileid low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	FILE_I_TYPE_OFF,	/* inode type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	EMBED_FH_OFF		/* embeded server fh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static struct nfs_fh *nfs_exp_embedfh(__u32 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	return (struct nfs_fh *)(p + EMBED_FH_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * Let's break subtree checking for now... otherwise we'll have to embed parent fh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * but there might not be enough space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct nfs_fh *server_fh = NFS_FH(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct nfs_fh *clnt_fh = nfs_exp_embedfh(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	dprintk("%s: max fh len %d inode %p parent %p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		__func__, *max_len, inode, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	if (*max_len < len || IS_AUTOMOUNT(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		dprintk("%s: fh len %d too small, required %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			__func__, *max_len, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		*max_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		return FILEID_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	p[FILEID_HIGH_OFF] = NFS_FILEID(inode) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	p[FILEID_LOW_OFF] = NFS_FILEID(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	p[FILE_I_TYPE_OFF] = inode->i_mode & S_IFMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	p[len - 1] = 0; /* Padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	nfs_copy_fh(clnt_fh, server_fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	*max_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	dprintk("%s: result fh fileid %llu mode %u size %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		__func__, NFS_FILEID(inode), inode->i_mode, *max_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	return *max_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) static struct dentry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) nfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		 int fh_len, int fh_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	struct nfs4_label *label = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct nfs_fattr *fattr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	const struct nfs_rpc_ops *rpc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	u32 *p = fid->raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	/* NULL translates to ESTALE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (fh_len < len || fh_type != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	fattr = nfs_alloc_fattr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (fattr == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		dentry = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	fattr->fileid = ((u64)p[FILEID_HIGH_OFF] << 32) + p[FILEID_LOW_OFF];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	fattr->mode = p[FILE_I_TYPE_OFF];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	fattr->valid |= NFS_ATTR_FATTR_FILEID | NFS_ATTR_FATTR_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	dprintk("%s: fileid %llu mode %d\n", __func__, fattr->fileid, fattr->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	inode = nfs_ilookup(sb, fattr, server_fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		goto out_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	label = nfs4_label_alloc(NFS_SB(sb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (IS_ERR(label)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		dentry = ERR_CAST(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		goto out_free_fattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	rpc_ops = NFS_SB(sb)->nfs_client->rpc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		dprintk("%s: getattr failed %d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		trace_nfs_fh_to_dentry(sb, server_fh, fattr->fileid, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		dentry = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		goto out_free_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	inode = nfs_fhget(sb, server_fh, fattr, label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) out_found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	dentry = d_obtain_alias(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) out_free_label:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	nfs4_label_free(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) out_free_fattr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	nfs_free_fattr(fattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	return dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static struct dentry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) nfs_get_parent(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	struct inode *inode = d_inode(dentry), *pinode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	struct nfs_server *server = NFS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	struct nfs_fattr *fattr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	struct nfs4_label *label = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	struct dentry *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct nfs_rpc_ops const *ops = server->nfs_client->rpc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct nfs_fh fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (!ops->lookupp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		return ERR_PTR(-EACCES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	fattr = nfs_alloc_fattr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (fattr == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		parent = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	label = nfs4_label_alloc(server, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (IS_ERR(label)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		parent = ERR_CAST(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		goto out_free_fattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	ret = ops->lookupp(inode, &fh, fattr, label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		parent = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		goto out_free_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	pinode = nfs_fhget(sb, &fh, fattr, label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	parent = d_obtain_alias(pinode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) out_free_label:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	nfs4_label_free(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) out_free_fattr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	nfs_free_fattr(fattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	return parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) const struct export_operations nfs_export_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	.encode_fh = nfs_encode_fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	.fh_to_dentry = nfs_fh_to_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	.get_parent = nfs_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };