VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
b4d0d230ccfb5 (Thomas Gleixner 2019-05-20 19:08:01 +0200   1) // SPDX-License-Identifier: GPL-2.0-or-later
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100   2) /* AFS dynamic root handling
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100   3)  *
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100   4)  * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100   5)  * Written by David Howells (dhowells@redhat.com)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100   6)  */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100   7) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100   8) #include <linux/fs.h>
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100   9) #include <linux/namei.h>
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100  10) #include <linux/dns_resolver.h>
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100  11) #include "internal.h"
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100  12) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  13) static atomic_t afs_autocell_ino;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  14) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  15) /*
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  16)  * iget5() comparator for inode created by autocell operations
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  17)  *
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  18)  * These pseudo inodes don't match anything.
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  19)  */
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  20) static int afs_iget5_pseudo_test(struct inode *inode, void *opaque)
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  21) {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  22) 	return 0;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  23) }
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  24) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  25) /*
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  26)  * iget5() inode initialiser
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  27)  */
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  28) static int afs_iget5_pseudo_set(struct inode *inode, void *opaque)
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  29) {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  30) 	struct afs_super_info *as = AFS_FS_S(inode->i_sb);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  31) 	struct afs_vnode *vnode = AFS_FS_I(inode);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  32) 	struct afs_fid *fid = opaque;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  33) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  34) 	vnode->volume		= as->volume;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  35) 	vnode->fid		= *fid;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  36) 	inode->i_ino		= fid->vnode;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  37) 	inode->i_generation	= fid->unique;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  38) 	return 0;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  39) }
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  40) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  41) /*
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  42)  * Create an inode for a dynamic root directory or an autocell dynamic
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  43)  * automount dir.
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  44)  */
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  45) struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  46) {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  47) 	struct afs_super_info *as = AFS_FS_S(sb);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  48) 	struct afs_vnode *vnode;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  49) 	struct inode *inode;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  50) 	struct afs_fid fid = {};
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  51) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  52) 	_enter("");
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  53) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  54) 	if (as->volume)
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  55) 		fid.vid = as->volume->vid;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  56) 	if (root) {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  57) 		fid.vnode = 1;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  58) 		fid.unique = 1;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  59) 	} else {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  60) 		fid.vnode = atomic_inc_return(&afs_autocell_ino);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  61) 		fid.unique = 0;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  62) 	}
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  63) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  64) 	inode = iget5_locked(sb, fid.vnode,
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  65) 			     afs_iget5_pseudo_test, afs_iget5_pseudo_set, &fid);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  66) 	if (!inode) {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  67) 		_leave(" = -ENOMEM");
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  68) 		return ERR_PTR(-ENOMEM);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  69) 	}
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  70) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  71) 	_debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  72) 	       inode, inode->i_ino, fid.vid, fid.vnode, fid.unique);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  73) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  74) 	vnode = AFS_FS_I(inode);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  75) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  76) 	/* there shouldn't be an existing inode */
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  77) 	BUG_ON(!(inode->i_state & I_NEW));
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  78) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  79) 	inode->i_size		= 0;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  80) 	inode->i_mode		= S_IFDIR | S_IRUGO | S_IXUGO;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  81) 	if (root) {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  82) 		inode->i_op	= &afs_dynroot_inode_operations;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  83) 		inode->i_fop	= &simple_dir_operations;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  84) 	} else {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  85) 		inode->i_op	= &afs_autocell_inode_operations;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  86) 	}
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  87) 	set_nlink(inode, 2);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  88) 	inode->i_uid		= GLOBAL_ROOT_UID;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  89) 	inode->i_gid		= GLOBAL_ROOT_GID;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  90) 	inode->i_ctime = inode->i_atime = inode->i_mtime = current_time(inode);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  91) 	inode->i_blocks		= 0;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  92) 	inode->i_generation	= 0;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  93) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  94) 	set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  95) 	if (!root) {
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  96) 		set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  97) 		inode->i_flags |= S_AUTOMOUNT;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  98) 	}
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100  99) 
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100 100) 	inode->i_flags |= S_NOATIME;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100 101) 	unlock_new_inode(inode);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100 102) 	_leave(" = %p", inode);
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100 103) 	return inode;
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100 104) }
e49c7b2f6de7f (David Howells   2020-04-10 20:51:51 +0100 105) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 106) /*
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 107)  * Probe to see if a cell may exist.  This prevents positive dentries from
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 108)  * being created unnecessarily.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 109)  */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 110) static int afs_probe_cell_name(struct dentry *dentry)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 111) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 112) 	struct afs_cell *cell;
a58946c158a04 (David Howells   2019-06-26 21:02:33 +0100 113) 	struct afs_net *net = afs_d2net(dentry);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 114) 	const char *name = dentry->d_name.name;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 115) 	size_t len = dentry->d_name.len;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 116) 	int ret;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 117) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 118) 	/* Names prefixed with a dot are R/W mounts. */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 119) 	if (name[0] == '.') {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 120) 		if (len == 1)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 121) 			return -EINVAL;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 122) 		name++;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 123) 		len--;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 124) 	}
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 125) 
dca54a7bbb8ca (David Howells   2020-10-13 20:51:59 +0100 126) 	cell = afs_find_cell(net, name, len, afs_cell_trace_use_probe);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 127) 	if (!IS_ERR(cell)) {
dca54a7bbb8ca (David Howells   2020-10-13 20:51:59 +0100 128) 		afs_unuse_cell(net, cell, afs_cell_trace_unuse_probe);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 129) 		return 0;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 130) 	}
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 131) 
a58946c158a04 (David Howells   2019-06-26 21:02:33 +0100 132) 	ret = dns_query(net->net, "afsdb", name, len, "srv=1",
a58946c158a04 (David Howells   2019-06-26 21:02:33 +0100 133) 			NULL, NULL, false);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 134) 	if (ret == -ENODATA)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 135) 		ret = -EDESTADDRREQ;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 136) 	return ret;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 137) }
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 138) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 139) /*
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 140)  * Try to auto mount the mountpoint with pseudo directory, if the autocell
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 141)  * operation is setted.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 142)  */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 143) struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 144) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 145) 	struct afs_vnode *vnode = AFS_FS_I(dir);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 146) 	struct inode *inode;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 147) 	int ret = -ENOENT;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 148) 
3b6492df4153b (David Howells   2018-10-20 00:57:57 +0100 149) 	_enter("%p{%pd}, {%llx:%llu}",
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 150) 	       dentry, dentry, vnode->fid.vid, vnode->fid.vnode);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 151) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 152) 	if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 153) 		goto out;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 154) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 155) 	ret = afs_probe_cell_name(dentry);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 156) 	if (ret < 0)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 157) 		goto out;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 158) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 159) 	inode = afs_iget_pseudo_dir(dir->i_sb, false);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 160) 	if (IS_ERR(inode)) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 161) 		ret = PTR_ERR(inode);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 162) 		goto out;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 163) 	}
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 164) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 165) 	_leave("= %p", inode);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 166) 	return inode;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 167) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 168) out:
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 169) 	_leave("= %d", ret);
1401a0fc2d479 (Al Viro         2018-06-24 10:45:44 -0400 170) 	return ret == -ENOENT ? NULL : ERR_PTR(ret);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 171) }
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 172) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 173) /*
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 174)  * Look up @cell in a dynroot directory.  This is a substitution for the
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 175)  * local cell name for the net namespace.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 176)  */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 177) static struct dentry *afs_lookup_atcell(struct dentry *dentry)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 178) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 179) 	struct afs_cell *cell;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 180) 	struct afs_net *net = afs_d2net(dentry);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 181) 	struct dentry *ret;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 182) 	char *name;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 183) 	int len;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 184) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 185) 	if (!net->ws_cell)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 186) 		return ERR_PTR(-ENOENT);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 187) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 188) 	ret = ERR_PTR(-ENOMEM);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 189) 	name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 190) 	if (!name)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 191) 		goto out_p;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 192) 
92e3cc91d8f51 (David Howells   2020-10-09 14:11:58 +0100 193) 	down_read(&net->cells_lock);
92e3cc91d8f51 (David Howells   2020-10-09 14:11:58 +0100 194) 	cell = net->ws_cell;
92e3cc91d8f51 (David Howells   2020-10-09 14:11:58 +0100 195) 	if (cell) {
92e3cc91d8f51 (David Howells   2020-10-09 14:11:58 +0100 196) 		len = cell->name_len;
92e3cc91d8f51 (David Howells   2020-10-09 14:11:58 +0100 197) 		memcpy(name, cell->name, len + 1);
92e3cc91d8f51 (David Howells   2020-10-09 14:11:58 +0100 198) 	}
92e3cc91d8f51 (David Howells   2020-10-09 14:11:58 +0100 199) 	up_read(&net->cells_lock);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 200) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 201) 	ret = ERR_PTR(-ENOENT);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 202) 	if (!cell)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 203) 		goto out_n;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 204) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 205) 	ret = lookup_one_len(name, dentry->d_parent, len);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 206) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 207) 	/* We don't want to d_add() the @cell dentry here as we don't want to
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 208) 	 * the cached dentry to hide changes to the local cell name.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 209) 	 */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 210) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 211) out_n:
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 212) 	kfree(name);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 213) out_p:
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 214) 	return ret;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 215) }
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 216) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 217) /*
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 218)  * Look up an entry in a dynroot directory.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 219)  */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 220) static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry,
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 221) 					 unsigned int flags)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 222) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 223) 	_enter("%pd", dentry);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 224) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 225) 	ASSERTCMP(d_inode(dentry), ==, NULL);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 226) 
1da4bd9f9d187 (David Howells   2019-12-11 08:56:04 +0000 227) 	if (flags & LOOKUP_CREATE)
1da4bd9f9d187 (David Howells   2019-12-11 08:56:04 +0000 228) 		return ERR_PTR(-EOPNOTSUPP);
1da4bd9f9d187 (David Howells   2019-12-11 08:56:04 +0000 229) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 230) 	if (dentry->d_name.len >= AFSNAMEMAX) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 231) 		_leave(" = -ENAMETOOLONG");
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 232) 		return ERR_PTR(-ENAMETOOLONG);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 233) 	}
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 234) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 235) 	if (dentry->d_name.len == 5 &&
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 236) 	    memcmp(dentry->d_name.name, "@cell", 5) == 0)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 237) 		return afs_lookup_atcell(dentry);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 238) 
1401a0fc2d479 (Al Viro         2018-06-24 10:45:44 -0400 239) 	return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 240) }
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 241) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 242) const struct inode_operations afs_dynroot_inode_operations = {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 243) 	.lookup		= afs_dynroot_lookup,
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 244) };
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 245) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 246) /*
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 247)  * Dirs in the dynamic root don't need revalidation.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 248)  */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 249) static int afs_dynroot_d_revalidate(struct dentry *dentry, unsigned int flags)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 250) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 251) 	return 1;
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 252) }
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 253) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 254) /*
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 255)  * Allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 256)  * sleep)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 257)  * - called from dput() when d_count is going to 0.
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 258)  * - return 1 to request dentry be unhashed, 0 otherwise
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 259)  */
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 260) static int afs_dynroot_d_delete(const struct dentry *dentry)
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 261) {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 262) 	return d_really_is_positive(dentry);
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 263) }
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 264) 
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 265) const struct dentry_operations afs_dynroot_dentry_operations = {
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 266) 	.d_revalidate	= afs_dynroot_d_revalidate,
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 267) 	.d_delete	= afs_dynroot_d_delete,
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 268) 	.d_release	= afs_d_release,
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 269) 	.d_automount	= afs_d_automount,
66c7e1d319a5b (David Howells   2018-04-06 14:17:25 +0100 270) };
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 271) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 272) /*
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 273)  * Create a manually added cell mount directory.
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 274)  * - The caller must hold net->proc_cells_lock
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 275)  */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 276) int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 277) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 278) 	struct super_block *sb = net->dynroot_sb;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 279) 	struct dentry *root, *subdir;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 280) 	int ret;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 281) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 282) 	if (!sb || atomic_read(&sb->s_active) == 0)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 283) 		return 0;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 284) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 285) 	/* Let the ->lookup op do the creation */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 286) 	root = sb->s_root;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 287) 	inode_lock(root->d_inode);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 288) 	subdir = lookup_one_len(cell->name, root, cell->name_len);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 289) 	if (IS_ERR(subdir)) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 290) 		ret = PTR_ERR(subdir);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 291) 		goto unlock;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 292) 	}
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 293) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 294) 	/* Note that we're retaining an extra ref on the dentry */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 295) 	subdir->d_fsdata = (void *)1UL;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 296) 	ret = 0;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 297) unlock:
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 298) 	inode_unlock(root->d_inode);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 299) 	return ret;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 300) }
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 301) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 302) /*
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 303)  * Remove a manually added cell mount directory.
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 304)  * - The caller must hold net->proc_cells_lock
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 305)  */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 306) void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 307) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 308) 	struct super_block *sb = net->dynroot_sb;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 309) 	struct dentry *root, *subdir;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 310) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 311) 	if (!sb || atomic_read(&sb->s_active) == 0)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 312) 		return;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 313) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 314) 	root = sb->s_root;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 315) 	inode_lock(root->d_inode);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 316) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 317) 	/* Don't want to trigger a lookup call, which will re-add the cell */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 318) 	subdir = try_lookup_one_len(cell->name, root, cell->name_len);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 319) 	if (IS_ERR_OR_NULL(subdir)) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 320) 		_debug("lookup %ld", PTR_ERR(subdir));
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 321) 		goto no_dentry;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 322) 	}
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 323) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 324) 	_debug("rmdir %pd %u", subdir, d_count(subdir));
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 325) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 326) 	if (subdir->d_fsdata) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 327) 		_debug("unpin %u", d_count(subdir));
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 328) 		subdir->d_fsdata = NULL;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 329) 		dput(subdir);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 330) 	}
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 331) 	dput(subdir);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 332) no_dentry:
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 333) 	inode_unlock(root->d_inode);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 334) 	_leave("");
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 335) }
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 336) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 337) /*
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 338)  * Populate a newly created dynamic root with cell names.
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 339)  */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 340) int afs_dynroot_populate(struct super_block *sb)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 341) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 342) 	struct afs_cell *cell;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 343) 	struct afs_net *net = afs_sb2net(sb);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 344) 	int ret;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 345) 
3b05e528cb9ef (David Howells   2019-05-09 09:17:08 +0100 346) 	mutex_lock(&net->proc_cells_lock);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 347) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 348) 	net->dynroot_sb = sb;
6b3944e42e2e5 (David Howells   2018-10-11 22:45:49 +0100 349) 	hlist_for_each_entry(cell, &net->proc_cells, proc_link) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 350) 		ret = afs_dynroot_mkdir(net, cell);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 351) 		if (ret < 0)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 352) 			goto error;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 353) 	}
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 354) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 355) 	ret = 0;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 356) out:
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 357) 	mutex_unlock(&net->proc_cells_lock);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 358) 	return ret;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 359) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 360) error:
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 361) 	net->dynroot_sb = NULL;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 362) 	goto out;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 363) }
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 364) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 365) /*
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 366)  * When a dynamic root that's in the process of being destroyed, depopulate it
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 367)  * of pinned directories.
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 368)  */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 369) void afs_dynroot_depopulate(struct super_block *sb)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 370) {
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 371) 	struct afs_net *net = afs_sb2net(sb);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 372) 	struct dentry *root = sb->s_root, *subdir, *tmp;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 373) 
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 374) 	/* Prevent more subdirs from being created */
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 375) 	mutex_lock(&net->proc_cells_lock);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 376) 	if (net->dynroot_sb == sb)
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 377) 		net->dynroot_sb = NULL;
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 378) 	mutex_unlock(&net->proc_cells_lock);
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 379) 
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 380) 	if (root) {
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 381) 		inode_lock(root->d_inode);
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 382) 
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 383) 		/* Remove all the pins for dirs created for manually added cells */
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 384) 		list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 385) 			if (subdir->d_fsdata) {
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 386) 				subdir->d_fsdata = NULL;
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 387) 				dput(subdir);
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 388) 			}
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 389) 		}
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 390) 
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 391) 		inode_unlock(root->d_inode);
5e0b17b026eb7 (David Howells   2020-08-21 10:15:12 +0100 392) 	}
0da0b7fd73e4f (David Howells   2018-06-15 15:19:22 +0100 393) }