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/dir.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) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  10)  *
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  11)  *  (C) 1991  Linus Torvalds - minix filesystem
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  12)  *
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  13)  *  affs directory handling functions
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  14)  *
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  15)  */
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  16) 
9dffe569d942a (Jeff Layton         2017-12-11 06:35:10 -0500  17) #include <linux/iversion.h>
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  18) #include "affs.h"
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  19) 
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  20) static int affs_readdir(struct file *, struct dir_context *);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  21) 
4b6f5d20b04dc (Arjan van de Ven    2006-03-28 01:56:42 -0800  22) const struct file_operations affs_dir_operations = {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  23) 	.read		= generic_read_dir,
59af1584bf338 (Al Viro             2008-08-24 07:24:41 -0400  24) 	.llseek		= generic_file_llseek,
3b0a3c1ac1598 (Al Viro             2016-04-20 23:42:46 -0400  25) 	.iterate_shared	= affs_readdir,
c475879556a86 (Al Viro             2009-06-08 01:22:00 -0400  26) 	.fsync		= affs_file_fsync,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  27) };
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  28) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  29) /*
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  30)  * directories can handle most operations...
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  31)  */
754661f143e70 (Arjan van de Ven    2007-02-12 00:55:38 -0800  32) const struct inode_operations affs_dir_inode_operations = {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  33) 	.create		= affs_create,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  34) 	.lookup		= affs_lookup,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  35) 	.link		= affs_link,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  36) 	.unlink		= affs_unlink,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  37) 	.symlink	= affs_symlink,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  38) 	.mkdir		= affs_mkdir,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  39) 	.rmdir		= affs_rmdir,
c6184028a75cf (Fabian Frederick    2017-05-05 20:51:42 +0200  40) 	.rename		= affs_rename2,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  41) 	.setattr	= affs_notify_change,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  42) };
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  43) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  44) static int
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  45) affs_readdir(struct file *file, struct dir_context *ctx)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  46) {
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  47) 	struct inode		*inode = file_inode(file);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  48) 	struct super_block	*sb = inode->i_sb;
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  49) 	struct buffer_head	*dir_bh = NULL;
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  50) 	struct buffer_head	*fh_bh = NULL;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  51) 	unsigned char		*name;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  52) 	int			 namelen;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  53) 	u32			 i;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  54) 	int			 hash_pos;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  55) 	int			 chain_pos;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  56) 	u32			 ino;
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700  57) 	int			 error = 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  58) 
08fe100d91bc0 (Geert Uytterhoeven  2015-02-17 13:46:10 -0800  59) 	pr_debug("%s(ino=%lu,f_pos=%llx)\n", __func__, inode->i_ino, ctx->pos);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  60) 
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  61) 	if (ctx->pos < 2) {
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  62) 		file->private_data = (void *)0;
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  63) 		if (!dir_emit_dots(file, ctx))
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  64) 			return 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  65) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  66) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  67) 	affs_lock_dir(inode);
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  68) 	chain_pos = (ctx->pos - 2) & 0xffff;
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  69) 	hash_pos  = (ctx->pos - 2) >> 16;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  70) 	if (chain_pos == 0xffff) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  71) 		affs_warning(sb, "readdir", "More than 65535 entries in chain");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  72) 		chain_pos = 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  73) 		hash_pos++;
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  74) 		ctx->pos = ((hash_pos << 16) | chain_pos) + 2;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  75) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  76) 	dir_bh = affs_bread(sb, inode->i_ino);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  77) 	if (!dir_bh)
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700  78) 		goto out_unlock_dir;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  79) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  80) 	/* If the directory hasn't changed since the last call to readdir(),
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  81) 	 * we can jump directly to where we left off.
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  82) 	 */
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400  83) 	ino = (u32)(long)file->private_data;
c472c07bfed9c (Goffredo Baroncelli 2018-02-01 08:15:25 -0500  84) 	if (ino && inode_eq_iversion(inode, file->f_version)) {
9606d9aa858ae (Fabian Frederick    2014-06-06 14:37:25 -0700  85) 		pr_debug("readdir() left off=%d\n", ino);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  86) 		goto inside;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  87) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  88) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  89) 	ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  90) 	for (i = 0; ino && i < chain_pos; i++) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  91) 		fh_bh = affs_bread(sb, ino);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  92) 		if (!fh_bh) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  93) 			affs_error(sb, "readdir","Cannot read block %d", i);
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700  94) 			error = -EIO;
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700  95) 			goto out_brelse_dir;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  96) 		}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  97) 		ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  98) 		affs_brelse(fh_bh);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  99) 		fh_bh = NULL;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 100) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 101) 	if (ino)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 102) 		goto inside;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 103) 	hash_pos++;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 104) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 105) 	for (; hash_pos < AFFS_SB(sb)->s_hashsize; hash_pos++) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 106) 		ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 107) 		if (!ino)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 108) 			continue;
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400 109) 		ctx->pos = (hash_pos << 16) + 2;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 110) inside:
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 111) 		do {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 112) 			fh_bh = affs_bread(sb, ino);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 113) 			if (!fh_bh) {
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 114) 				affs_error(sb, "readdir",
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 115) 					   "Cannot read block %d", ino);
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400 116) 				break;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 117) 			}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 118) 
f157853e407c0 (Fabian Frederick    2015-02-17 13:46:23 -0800 119) 			namelen = min(AFFS_TAIL(sb, fh_bh)->name[0],
f157853e407c0 (Fabian Frederick    2015-02-17 13:46:23 -0800 120) 				      (u8)AFFSNAMEMAX);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 121) 			name = AFFS_TAIL(sb, fh_bh)->name + 1;
08fe100d91bc0 (Geert Uytterhoeven  2015-02-17 13:46:10 -0800 122) 			pr_debug("readdir(): dir_emit(\"%.*s\", ino=%u), hash=%d, f_pos=%llx\n",
08fe100d91bc0 (Geert Uytterhoeven  2015-02-17 13:46:10 -0800 123) 				 namelen, name, ino, hash_pos, ctx->pos);
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 124) 
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400 125) 			if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN))
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 126) 				goto done;
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400 127) 			ctx->pos++;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 128) 			ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 129) 			affs_brelse(fh_bh);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 130) 			fh_bh = NULL;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 131) 		} while (ino);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 132) 	}
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 133) done:
9dffe569d942a (Jeff Layton         2017-12-11 06:35:10 -0500 134) 	file->f_version = inode_query_iversion(inode);
0edf977d2ae32 (Al Viro             2013-05-17 17:44:42 -0400 135) 	file->private_data = (void *)(long)ino;
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 136) 	affs_brelse(fh_bh);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 137) 
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 138) out_brelse_dir:
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 139) 	affs_brelse(dir_bh);
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 140) 
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 141) out_unlock_dir:
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 142) 	affs_unlock_dir(inode);
d40c4d46eaa22 (Fabian Frederick    2014-04-07 15:39:00 -0700 143) 	return error;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 144) }