VisionFive2 Linux kernel

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

More than 9999 Commits   35 Branches   59 Tags
b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100   1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   2) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   3)  *  linux/fs/affs/namei.c
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   4)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   5)  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   6)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   7)  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   8)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   9)  *  (C) 1991  Linus Torvalds - minix filesystem
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  10)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  11) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  12) #include "affs.h"
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800  13) #include <linux/exportfs.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  14) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  15) typedef int (*toupper_t)(int);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  16) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  17) /* Simple toupper() for DOS\1 */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  18) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  19) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  20) affs_toupper(int ch)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  21) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  22) 	return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  23) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  24) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  25) /* International toupper() for DOS\3 ("international") */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  26) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  27) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  28) affs_intl_toupper(int ch)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  29) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  30) 	return (ch >= 'a' && ch <= 'z') || (ch >= 0xE0
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  31) 		&& ch <= 0xFE && ch != 0xF7) ?
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  32) 		ch - ('a' - 'A') : ch;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  33) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  34) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  35) static inline toupper_t
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  36) affs_get_toupper(struct super_block *sb)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  37) {
79bda4d510f80 (Fabian Frederick   2015-04-16 12:48:24 -0700  38) 	return affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL) ?
79bda4d510f80 (Fabian Frederick   2015-04-16 12:48:24 -0700  39) 	       affs_intl_toupper : affs_toupper;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  40) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  41) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  42) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  43)  * Note: the dentry argument is the parent dentry.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  44)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  45) static inline int
8387ff2577eb9 (Linus Torvalds     2016-06-10 07:51:30 -0700  46) __affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr, toupper_t toupper, bool notruncate)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  47) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  48) 	const u8 *name = qstr->name;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  49) 	unsigned long hash;
eeb36f8e938d1 (Fabian Frederick   2015-02-17 13:46:20 -0800  50) 	int retval;
eeb36f8e938d1 (Fabian Frederick   2015-02-17 13:46:20 -0800  51) 	u32 len;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  52) 
eeb36f8e938d1 (Fabian Frederick   2015-02-17 13:46:20 -0800  53) 	retval = affs_check_name(qstr->name, qstr->len, notruncate);
eeb36f8e938d1 (Fabian Frederick   2015-02-17 13:46:20 -0800  54) 	if (retval)
eeb36f8e938d1 (Fabian Frederick   2015-02-17 13:46:20 -0800  55) 		return retval;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  56) 
8387ff2577eb9 (Linus Torvalds     2016-06-10 07:51:30 -0700  57) 	hash = init_name_hash(dentry);
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800  58) 	len = min(qstr->len, AFFSNAMEMAX);
eeb36f8e938d1 (Fabian Frederick   2015-02-17 13:46:20 -0800  59) 	for (; len > 0; name++, len--)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  60) 		hash = partial_name_hash(toupper(*name), hash);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  61) 	qstr->hash = end_name_hash(hash);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  62) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  63) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  64) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  65) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  66) static int
da53be12bbb4f (Linus Torvalds     2013-05-21 15:22:44 -0700  67) affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  68) {
8387ff2577eb9 (Linus Torvalds     2016-06-10 07:51:30 -0700  69) 	return __affs_hash_dentry(dentry, qstr, affs_toupper,
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  70) 				  affs_nofilenametruncate(dentry));
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  71) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  72) }
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  73) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  74) static int
da53be12bbb4f (Linus Torvalds     2013-05-21 15:22:44 -0700  75) affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  76) {
8387ff2577eb9 (Linus Torvalds     2016-06-10 07:51:30 -0700  77) 	return __affs_hash_dentry(dentry, qstr, affs_intl_toupper,
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  78) 				  affs_nofilenametruncate(dentry));
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  79) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  80) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  81) 
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  82) static inline int __affs_compare_dentry(unsigned int len,
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  83) 		const char *str, const struct qstr *name, toupper_t toupper,
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  84) 		bool notruncate)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  85) {
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  86) 	const u8 *aname = str;
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  87) 	const u8 *bname = name->name;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  88) 
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  89) 	/*
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  90) 	 * 'str' is the name of an already existing dentry, so the name
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  91) 	 * must be valid. 'name' must be validated first.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  92) 	 */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  93) 
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700  94) 	if (affs_check_name(name->name, name->len, notruncate))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  95) 		return 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  96) 
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  97) 	/*
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100  98) 	 * If the names are longer than the allowed 30 chars,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  99) 	 * the excess is ignored, so their length may differ.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 100) 	 */
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800 101) 	if (len >= AFFSNAMEMAX) {
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800 102) 		if (name->len < AFFSNAMEMAX)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 103) 			return 1;
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800 104) 		len = AFFSNAMEMAX;
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100 105) 	} else if (len != name->len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 106) 		return 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 107) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 108) 	for (; len > 0; len--)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 109) 		if (toupper(*aname++) != toupper(*bname++))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 110) 			return 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 111) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 112) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 113) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 114) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 115) static int
6fa67e7075593 (Al Viro            2016-07-31 16:37:25 -0400 116) affs_compare_dentry(const struct dentry *dentry,
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100 117) 		unsigned int len, const char *str, const struct qstr *name)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 118) {
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 119) 
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 120) 	return __affs_compare_dentry(len, str, name, affs_toupper,
e0b3f595d13b3 (Al Viro            2016-07-29 18:22:49 -0400 121) 				     affs_nofilenametruncate(dentry));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 122) }
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 123) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 124) static int
6fa67e7075593 (Al Viro            2016-07-31 16:37:25 -0400 125) affs_intl_compare_dentry(const struct dentry *dentry,
621e155a35919 (Nicholas Piggin    2011-01-07 17:49:27 +1100 126) 		unsigned int len, const char *str, const struct qstr *name)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 127) {
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 128) 	return __affs_compare_dentry(len, str, name, affs_intl_toupper,
e0b3f595d13b3 (Al Viro            2016-07-29 18:22:49 -0400 129) 				     affs_nofilenametruncate(dentry));
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 130) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 131) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 132) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 133) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 134)  * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 135)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 136) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 137) static inline int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 138) affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 139) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 140) 	const u8 *name = dentry->d_name.name;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 141) 	int len = dentry->d_name.len;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 142) 
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800 143) 	if (len >= AFFSNAMEMAX) {
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800 144) 		if (*name2 < AFFSNAMEMAX)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 145) 			return 0;
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800 146) 		len = AFFSNAMEMAX;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 147) 	} else if (len != *name2)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 148) 		return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 149) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 150) 	for (name2++; len > 0; len--)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 151) 		if (toupper(*name++) != toupper(*name2++))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 152) 			return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 153) 	return 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 154) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 155) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 156) int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 157) affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 158) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 159) 	toupper_t toupper = affs_get_toupper(sb);
eeb36f8e938d1 (Fabian Frederick   2015-02-17 13:46:20 -0800 160) 	u32 hash;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 161) 
f157853e407c0 (Fabian Frederick   2015-02-17 13:46:23 -0800 162) 	hash = len = min(len, AFFSNAMEMAX);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 163) 	for (; len > 0; len--)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 164) 		hash = (hash * 13 + toupper(*name++)) & 0x7ff;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 165) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 166) 	return hash % AFFS_SB(sb)->s_hashsize;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 167) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 168) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 169) static struct buffer_head *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 170) affs_find_entry(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 171) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 172) 	struct super_block *sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 173) 	struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 174) 	toupper_t toupper = affs_get_toupper(sb);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 175) 	u32 key;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 176) 
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 177) 	pr_debug("%s(\"%pd\")\n", __func__, dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 178) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 179) 	bh = affs_bread(sb, dir->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 180) 	if (!bh)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 181) 		return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 182) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 183) 	key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 184) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 185) 	for (;;) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 186) 		affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 187) 		if (key == 0)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 188) 			return NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 189) 		bh = affs_bread(sb, key);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 190) 		if (!bh)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 191) 			return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 192) 		if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 193) 			return bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 194) 		key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 195) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 196) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 197) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 198) struct dentry *
00cd8dd3bf95f (Al Viro            2012-06-10 17:13:09 -0400 199) affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 200) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 201) 	struct super_block *sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 202) 	struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 203) 	struct inode *inode = NULL;
87fbd639c02ec (Al Viro            2018-05-06 12:20:40 -0400 204) 	struct dentry *res;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 205) 
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 206) 	pr_debug("%s(\"%pd\")\n", __func__, dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 207) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 208) 	affs_lock_dir(dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 209) 	bh = affs_find_entry(dir, dentry);
30da870ce4a4e (Al Viro            2018-05-06 12:15:20 -0400 210) 	if (IS_ERR(bh)) {
30da870ce4a4e (Al Viro            2018-05-06 12:15:20 -0400 211) 		affs_unlock_dir(dir);
e231c2ee64eb1 (David Howells      2008-02-07 00:15:26 -0800 212) 		return ERR_CAST(bh);
30da870ce4a4e (Al Viro            2018-05-06 12:15:20 -0400 213) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 214) 	if (bh) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 215) 		u32 ino = bh->b_blocknr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 216) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 217) 		/* store the real header ino in d_fsdata for faster lookups */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 218) 		dentry->d_fsdata = (void *)(long)ino;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 219) 		switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 220) 		//link to dirs disabled
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 221) 		//case ST_LINKDIR:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 222) 		case ST_LINKFILE:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 223) 			ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 224) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 225) 		affs_brelse(bh);
210f855963ba5 (David Howells      2008-02-07 00:15:29 -0800 226) 		inode = affs_iget(sb, ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 227) 	}
87fbd639c02ec (Al Viro            2018-05-06 12:20:40 -0400 228) 	res = d_splice_alias(inode, dentry);
87fbd639c02ec (Al Viro            2018-05-06 12:20:40 -0400 229) 	if (!IS_ERR_OR_NULL(res))
87fbd639c02ec (Al Viro            2018-05-06 12:20:40 -0400 230) 		res->d_fsdata = dentry->d_fsdata;
30da870ce4a4e (Al Viro            2018-05-06 12:15:20 -0400 231) 	affs_unlock_dir(dir);
87fbd639c02ec (Al Viro            2018-05-06 12:20:40 -0400 232) 	return res;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 233) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 234) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 235) int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 236) affs_unlink(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 237) {
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800 238) 	pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino,
2b0143b5c986b (David Howells      2015-03-17 22:25:59 +0000 239) 		 d_inode(dentry)->i_ino, dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 240) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 241) 	return affs_remove_header(dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 242) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 243) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 244) int
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 245) affs_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 246) 	    struct dentry *dentry, umode_t mode, bool excl)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 247) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 248) 	struct super_block *sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 249) 	struct inode	*inode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 250) 	int		 error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 251) 
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 252) 	pr_debug("%s(%lu,\"%pd\",0%ho)\n",
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 253) 		 __func__, dir->i_ino, dentry, mode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 254) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 255) 	inode = affs_new_inode(dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 256) 	if (!inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 257) 		return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 258) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 259) 	inode->i_mode = mode;
c1618208511f0 (Fabian Frederick   2017-02-27 14:27:54 -0800 260) 	affs_mode_to_prot(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 261) 	mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 262) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 263) 	inode->i_op = &affs_file_inode_operations;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 264) 	inode->i_fop = &affs_file_operations;
79bda4d510f80 (Fabian Frederick   2015-04-16 12:48:24 -0700 265) 	inode->i_mapping->a_ops = affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS) ?
a0016ff2867ad (Fabian Frederick   2015-04-16 12:48:15 -0700 266) 				  &affs_aops_ofs : &affs_aops;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 267) 	error = affs_add_entry(dir, inode, dentry, ST_FILE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 268) 	if (error) {
6d6b77f163c7e (Miklos Szeredi     2011-10-28 14:13:28 +0200 269) 		clear_nlink(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 270) 		iput(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 271) 		return error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 272) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 273) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 274) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 275) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 276) int
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 277) affs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 278) 	   struct dentry *dentry, umode_t mode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 279) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 280) 	struct inode		*inode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 281) 	int			 error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 282) 
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 283) 	pr_debug("%s(%lu,\"%pd\",0%ho)\n",
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 284) 		 __func__, dir->i_ino, dentry, mode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 285) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 286) 	inode = affs_new_inode(dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 287) 	if (!inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 288) 		return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 289) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 290) 	inode->i_mode = S_IFDIR | mode;
c1618208511f0 (Fabian Frederick   2017-02-27 14:27:54 -0800 291) 	affs_mode_to_prot(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 292) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 293) 	inode->i_op = &affs_dir_inode_operations;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 294) 	inode->i_fop = &affs_dir_operations;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 295) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 296) 	error = affs_add_entry(dir, inode, dentry, ST_USERDIR);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 297) 	if (error) {
6d6b77f163c7e (Miklos Szeredi     2011-10-28 14:13:28 +0200 298) 		clear_nlink(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 299) 		mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 300) 		iput(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 301) 		return error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 302) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 303) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 304) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 305) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 306) int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 307) affs_rmdir(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 308) {
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800 309) 	pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino,
2b0143b5c986b (David Howells      2015-03-17 22:25:59 +0000 310) 		 d_inode(dentry)->i_ino, dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 311) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 312) 	return affs_remove_header(dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 313) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 314) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 315) int
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 316) affs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 317) 	     struct dentry *dentry, const char *symname)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 318) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 319) 	struct super_block	*sb = dir->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 320) 	struct buffer_head	*bh;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 321) 	struct inode		*inode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 322) 	char			*p;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 323) 	int			 i, maxlen, error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 324) 	char			 c, lc;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 325) 
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 326) 	pr_debug("%s(%lu,\"%pd\" -> \"%s\")\n",
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 327) 		 __func__, dir->i_ino, dentry, symname);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 328) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 329) 	maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 330) 	inode  = affs_new_inode(dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 331) 	if (!inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 332) 		return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 333) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 334) 	inode->i_op = &affs_symlink_inode_operations;
21fc61c73c390 (Al Viro            2015-11-17 01:07:57 -0500 335) 	inode_nohighmem(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 336) 	inode->i_data.a_ops = &affs_symlink_aops;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 337) 	inode->i_mode = S_IFLNK | 0777;
c1618208511f0 (Fabian Frederick   2017-02-27 14:27:54 -0800 338) 	affs_mode_to_prot(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 339) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 340) 	error = -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 341) 	bh = affs_bread(sb, inode->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 342) 	if (!bh)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 343) 		goto err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 344) 	i  = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 345) 	p  = (char *)AFFS_HEAD(bh)->table;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 346) 	lc = '/';
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 347) 	if (*symname == '/') {
29333920a5a46 (Al Viro            2010-01-24 00:04:07 -0500 348) 		struct affs_sb_info *sbi = AFFS_SB(sb);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 349) 		while (*symname == '/')
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 350) 			symname++;
29333920a5a46 (Al Viro            2010-01-24 00:04:07 -0500 351) 		spin_lock(&sbi->symlink_lock);
29333920a5a46 (Al Viro            2010-01-24 00:04:07 -0500 352) 		while (sbi->s_volume[i])	/* Cannot overflow */
29333920a5a46 (Al Viro            2010-01-24 00:04:07 -0500 353) 			*p++ = sbi->s_volume[i++];
29333920a5a46 (Al Viro            2010-01-24 00:04:07 -0500 354) 		spin_unlock(&sbi->symlink_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 355) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 356) 	while (i < maxlen && (c = *symname++)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 357) 		if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 358) 			*p++ = '/';
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 359) 			i++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 360) 			symname += 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 361) 			lc = '/';
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 362) 		} else if (c == '.' && lc == '/' && *symname == '/') {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 363) 			symname++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 364) 			lc = '/';
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 365) 		} else {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 366) 			*p++ = c;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 367) 			lc   = c;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 368) 			i++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 369) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 370) 		if (lc == '/')
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 371) 			while (*symname == '/')
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 372) 				symname++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 373) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 374) 	*p = 0;
f1bf90724de65 (Fabian Frederick   2017-04-15 08:54:36 +0200 375) 	inode->i_size = i + 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 376) 	mark_buffer_dirty_inode(bh, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 377) 	affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 378) 	mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 379) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 380) 	error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 381) 	if (error)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 382) 		goto err;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 383) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 384) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 385) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 386) err:
6d6b77f163c7e (Miklos Szeredi     2011-10-28 14:13:28 +0200 387) 	clear_nlink(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 388) 	mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 389) 	iput(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 390) 	return error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 391) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 392) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 393) int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 394) affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 395) {
2b0143b5c986b (David Howells      2015-03-17 22:25:59 +0000 396) 	struct inode *inode = d_inode(old_dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 397) 
08fe100d91bc0 (Geert Uytterhoeven 2015-02-17 13:46:10 -0800 398) 	pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino,
a455589f181e6 (Al Viro            2014-10-21 20:11:25 -0400 399) 		 dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 400) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 401) 	return affs_add_entry(dir, inode, dentry, ST_LINKFILE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 402) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 403) 
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 404) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 405) affs_rename(struct inode *old_dir, struct dentry *old_dentry,
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 406) 	    struct inode *new_dir, struct dentry *new_dentry)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 407) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 408) 	struct super_block *sb = old_dir->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 409) 	struct buffer_head *bh = NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 410) 	int retval;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 411) 
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 412) 	retval = affs_check_name(new_dentry->d_name.name,
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 413) 				 new_dentry->d_name.len,
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 414) 				 affs_nofilenametruncate(old_dentry));
8ca577223f752 (Fabian Frederick   2014-04-07 15:39:01 -0700 415) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 416) 	if (retval)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 417) 		return retval;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 418) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 419) 	/* Unlink destination if it already exists */
2b0143b5c986b (David Howells      2015-03-17 22:25:59 +0000 420) 	if (d_really_is_positive(new_dentry)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 421) 		retval = affs_remove_header(new_dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 422) 		if (retval)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 423) 			return retval;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 424) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 425) 
2b0143b5c986b (David Howells      2015-03-17 22:25:59 +0000 426) 	bh = affs_bread(sb, d_inode(old_dentry)->i_ino);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 427) 	if (!bh)
3ac8141366932 (Florin Malita      2006-05-25 18:44:23 -0700 428) 		return -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 429) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 430) 	/* Remove header from its parent directory. */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 431) 	affs_lock_dir(old_dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 432) 	retval = affs_remove_hash(old_dir, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 433) 	affs_unlock_dir(old_dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 434) 	if (retval)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 435) 		goto done;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 436) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 437) 	/* And insert it into the new directory with the new name. */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 438) 	affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 439) 	affs_fix_checksum(sb, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 440) 	affs_lock_dir(new_dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 441) 	retval = affs_insert_hash(new_dir, bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 442) 	affs_unlock_dir(new_dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 443) 	/* TODO: move it back to old_dir, if error? */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 444) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 445) done:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 446) 	mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 447) 	affs_brelse(bh);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 448) 	return retval;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 449) }
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 450) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 451) static int
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 452) affs_xrename(struct inode *old_dir, struct dentry *old_dentry,
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 453) 	     struct inode *new_dir, struct dentry *new_dentry)
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 454) {
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 455) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 456) 	struct super_block *sb = old_dir->i_sb;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 457) 	struct buffer_head *bh_old = NULL;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 458) 	struct buffer_head *bh_new = NULL;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 459) 	int retval;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 460) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 461) 	bh_old = affs_bread(sb, d_inode(old_dentry)->i_ino);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 462) 	if (!bh_old)
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 463) 		return -EIO;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 464) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 465) 	bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino);
70779b897395b (Pan Bian           2021-01-20 00:51:13 -0800 466) 	if (!bh_new) {
70779b897395b (Pan Bian           2021-01-20 00:51:13 -0800 467) 		affs_brelse(bh_old);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 468) 		return -EIO;
70779b897395b (Pan Bian           2021-01-20 00:51:13 -0800 469) 	}
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 470) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 471) 	/* Remove old header from its parent directory. */
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 472) 	affs_lock_dir(old_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 473) 	retval = affs_remove_hash(old_dir, bh_old);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 474) 	affs_unlock_dir(old_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 475) 	if (retval)
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 476) 		goto done;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 477) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 478) 	/* Remove new header from its parent directory. */
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 479) 	affs_lock_dir(new_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 480) 	retval = affs_remove_hash(new_dir, bh_new);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 481) 	affs_unlock_dir(new_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 482) 	if (retval)
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 483) 		goto done;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 484) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 485) 	/* Insert old into the new directory with the new name. */
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 486) 	affs_copy_name(AFFS_TAIL(sb, bh_old)->name, new_dentry);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 487) 	affs_fix_checksum(sb, bh_old);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 488) 	affs_lock_dir(new_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 489) 	retval = affs_insert_hash(new_dir, bh_old);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 490) 	affs_unlock_dir(new_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 491) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 492) 	/* Insert new into the old directory with the old name. */
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 493) 	affs_copy_name(AFFS_TAIL(sb, bh_new)->name, old_dentry);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 494) 	affs_fix_checksum(sb, bh_new);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 495) 	affs_lock_dir(old_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 496) 	retval = affs_insert_hash(old_dir, bh_new);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 497) 	affs_unlock_dir(old_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 498) done:
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 499) 	mark_buffer_dirty_inode(bh_old, new_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 500) 	mark_buffer_dirty_inode(bh_new, old_dir);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 501) 	affs_brelse(bh_old);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 502) 	affs_brelse(bh_new);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 503) 	return retval;
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 504) }
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 505) 
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 506) int affs_rename2(struct user_namespace *mnt_userns, struct inode *old_dir,
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 507) 		 struct dentry *old_dentry, struct inode *new_dir,
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 508) 		 struct dentry *new_dentry, unsigned int flags)
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 509) {
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 510) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 511) 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 512) 		return -EINVAL;
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 513) 
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 514) 	pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 515) 		 old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 516) 
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 517) 	if (flags & RENAME_EXCHANGE)
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 518) 		return affs_xrename(old_dir, old_dentry, new_dir, new_dentry);
6b4657667ba06 (Fabian Frederick   2017-05-05 20:52:07 +0200 519) 
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 520) 	return affs_rename(old_dir, old_dentry, new_dir, new_dentry);
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 521) }
c6184028a75cf (Fabian Frederick   2017-05-05 20:51:42 +0200 522) 
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 523) static struct dentry *affs_get_parent(struct dentry *child)
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 524) {
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 525) 	struct inode *parent;
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 526) 	struct buffer_head *bh;
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 527) 
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 528) 	bh = affs_bread(child->d_sb, d_inode(child)->i_ino);
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 529) 	if (!bh)
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 530) 		return ERR_PTR(-EIO);
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 531) 
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 532) 	parent = affs_iget(child->d_sb,
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 533) 			   be32_to_cpu(AFFS_TAIL(child->d_sb, bh)->parent));
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 534) 	brelse(bh);
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 535) 	if (IS_ERR(parent))
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 536) 		return ERR_CAST(parent);
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 537) 
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 538) 	return d_obtain_alias(parent);
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 539) }
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 540) 
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 541) static struct inode *affs_nfs_get_inode(struct super_block *sb, u64 ino,
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 542) 					u32 generation)
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 543) {
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 544) 	struct inode *inode;
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 545) 
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 546) 	if (!affs_validblock(sb, ino))
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 547) 		return ERR_PTR(-ESTALE);
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 548) 
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 549) 	inode = affs_iget(sb, ino);
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 550) 	if (IS_ERR(inode))
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 551) 		return ERR_CAST(inode);
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 552) 
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 553) 	return inode;
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 554) }
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 555) 
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 556) static struct dentry *affs_fh_to_dentry(struct super_block *sb, struct fid *fid,
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 557) 					int fh_len, int fh_type)
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 558) {
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 559) 	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 560) 				    affs_nfs_get_inode);
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 561) }
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 562) 
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 563) static struct dentry *affs_fh_to_parent(struct super_block *sb, struct fid *fid,
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 564) 					int fh_len, int fh_type)
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 565) {
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 566) 	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 567) 				    affs_nfs_get_inode);
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 568) }
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 569) 
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 570) const struct export_operations affs_export_ops = {
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 571) 	.fh_to_dentry = affs_fh_to_dentry,
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 572) 	.fh_to_parent = affs_fh_to_parent,
b3b42c0deaa1a (Fabian Frederick   2017-02-27 14:28:00 -0800 573) 	.get_parent = affs_get_parent,
ed4433d723941 (Fabian Frederick   2017-02-27 14:27:49 -0800 574) };
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 575) 
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 576) const struct dentry_operations affs_dentry_operations = {
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 577) 	.d_hash		= affs_hash_dentry,
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 578) 	.d_compare	= affs_compare_dentry,
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 579) };
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 580) 
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 581) const struct dentry_operations affs_intl_dentry_operations = {
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 582) 	.d_hash		= affs_intl_hash_dentry,
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 583) 	.d_compare	= affs_intl_compare_dentry,
f567accb3ff4a (Fabian Frederick   2017-02-27 14:27:57 -0800 584) };