xref: /openbmc/linux/fs/bfs/dir.c (revision 73d9b9d0)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *	fs/bfs/dir.c
41da177e4SLinus Torvalds  *	BFS directory operations.
5d1877155STigran Aivazian  *	Copyright (C) 1999-2018  Tigran Aivazian <aivazian.tigran@gmail.com>
6fac92becSAndrew Stribblehill  *  Made endianness-clean by Andrew Stribblehill <ads@wompom.org> 2005
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #include <linux/time.h>
101da177e4SLinus Torvalds #include <linux/string.h>
111da177e4SLinus Torvalds #include <linux/fs.h>
121da177e4SLinus Torvalds #include <linux/buffer_head.h>
131da177e4SLinus Torvalds #include <linux/sched.h>
141da177e4SLinus Torvalds #include "bfs.h"
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #undef DEBUG
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds #ifdef DEBUG
191da177e4SLinus Torvalds #define dprintf(x...)	printf(x)
201da177e4SLinus Torvalds #else
211da177e4SLinus Torvalds #define dprintf(x...)
221da177e4SLinus Torvalds #endif
231da177e4SLinus Torvalds 
24b455ecd4SAl Viro static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino);
251da177e4SLinus Torvalds static struct buffer_head *bfs_find_entry(struct inode *dir,
2633ebdebeSAl Viro 				const struct qstr *child,
27f433dc56SDmitri Vorobiev 				struct bfs_dirent **res_dir);
281da177e4SLinus Torvalds 
bfs_readdir(struct file * f,struct dir_context * ctx)2981b9f66eSAl Viro static int bfs_readdir(struct file *f, struct dir_context *ctx)
301da177e4SLinus Torvalds {
31496ad9aaSAl Viro 	struct inode *dir = file_inode(f);
321da177e4SLinus Torvalds 	struct buffer_head *bh;
331da177e4SLinus Torvalds 	struct bfs_dirent *de;
341da177e4SLinus Torvalds 	unsigned int offset;
351da177e4SLinus Torvalds 	int block;
361da177e4SLinus Torvalds 
3781b9f66eSAl Viro 	if (ctx->pos & (BFS_DIRENT_SIZE - 1)) {
38f433dc56SDmitri Vorobiev 		printf("Bad f_pos=%08lx for %s:%08lx\n",
3981b9f66eSAl Viro 					(unsigned long)ctx->pos,
401da177e4SLinus Torvalds 					dir->i_sb->s_id, dir->i_ino);
4181b9f66eSAl Viro 		return -EINVAL;
421da177e4SLinus Torvalds 	}
431da177e4SLinus Torvalds 
4481b9f66eSAl Viro 	while (ctx->pos < dir->i_size) {
4581b9f66eSAl Viro 		offset = ctx->pos & (BFS_BSIZE - 1);
4681b9f66eSAl Viro 		block = BFS_I(dir)->i_sblock + (ctx->pos >> BFS_BSIZE_BITS);
471da177e4SLinus Torvalds 		bh = sb_bread(dir->i_sb, block);
481da177e4SLinus Torvalds 		if (!bh) {
4981b9f66eSAl Viro 			ctx->pos += BFS_BSIZE - offset;
501da177e4SLinus Torvalds 			continue;
511da177e4SLinus Torvalds 		}
521da177e4SLinus Torvalds 		do {
531da177e4SLinus Torvalds 			de = (struct bfs_dirent *)(bh->b_data + offset);
541da177e4SLinus Torvalds 			if (de->ino) {
551da177e4SLinus Torvalds 				int size = strnlen(de->name, BFS_NAMELEN);
5681b9f66eSAl Viro 				if (!dir_emit(ctx, de->name, size,
57f433dc56SDmitri Vorobiev 						le16_to_cpu(de->ino),
5881b9f66eSAl Viro 						DT_UNKNOWN)) {
591da177e4SLinus Torvalds 					brelse(bh);
601da177e4SLinus Torvalds 					return 0;
611da177e4SLinus Torvalds 				}
621da177e4SLinus Torvalds 			}
631da177e4SLinus Torvalds 			offset += BFS_DIRENT_SIZE;
6481b9f66eSAl Viro 			ctx->pos += BFS_DIRENT_SIZE;
6581b9f66eSAl Viro 		} while ((offset < BFS_BSIZE) && (ctx->pos < dir->i_size));
661da177e4SLinus Torvalds 		brelse(bh);
671da177e4SLinus Torvalds 	}
681da177e4SLinus Torvalds 	return 0;
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds 
714b6f5d20SArjan van de Ven const struct file_operations bfs_dir_operations = {
721da177e4SLinus Torvalds 	.read		= generic_read_dir,
73c51da20cSAl Viro 	.iterate_shared	= bfs_readdir,
741b061d92SChristoph Hellwig 	.fsync		= generic_file_fsync,
753222a3e5SChristoph Hellwig 	.llseek		= generic_file_llseek,
761da177e4SLinus Torvalds };
771da177e4SLinus Torvalds 
bfs_create(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,bool excl)786c960e68SChristian Brauner static int bfs_create(struct mnt_idmap *idmap, struct inode *dir,
79549c7297SChristian Brauner 		      struct dentry *dentry, umode_t mode, bool excl)
801da177e4SLinus Torvalds {
811da177e4SLinus Torvalds 	int err;
821da177e4SLinus Torvalds 	struct inode *inode;
831da177e4SLinus Torvalds 	struct super_block *s = dir->i_sb;
841da177e4SLinus Torvalds 	struct bfs_sb_info *info = BFS_SB(s);
851da177e4SLinus Torvalds 	unsigned long ino;
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds 	inode = new_inode(s);
881da177e4SLinus Torvalds 	if (!inode)
89c3fe5872SSanidhya Kashyap 		return -ENOMEM;
903f165e4cSDmitri Vorobiev 	mutex_lock(&info->bfs_lock);
9169b195beSAkinobu Mita 	ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1);
921da177e4SLinus Torvalds 	if (ino > info->si_lasti) {
933f165e4cSDmitri Vorobiev 		mutex_unlock(&info->bfs_lock);
941da177e4SLinus Torvalds 		iput(inode);
951da177e4SLinus Torvalds 		return -ENOSPC;
961da177e4SLinus Torvalds 	}
971da177e4SLinus Torvalds 	set_bit(ino, info->si_imap);
981da177e4SLinus Torvalds 	info->si_freei--;
99f2d40141SChristian Brauner 	inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
100*73d9b9d0SJeff Layton 	inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode);
101ba52de12STheodore Ts'o 	inode->i_blocks = 0;
1021da177e4SLinus Torvalds 	inode->i_op = &bfs_file_inops;
1031da177e4SLinus Torvalds 	inode->i_fop = &bfs_file_operations;
1041da177e4SLinus Torvalds 	inode->i_mapping->a_ops = &bfs_aops;
1051da177e4SLinus Torvalds 	inode->i_ino = ino;
106ce0fe7e7SAlexey Dobriyan 	BFS_I(inode)->i_dsk_ino = ino;
1071da177e4SLinus Torvalds 	BFS_I(inode)->i_sblock = 0;
1081da177e4SLinus Torvalds 	BFS_I(inode)->i_eblock = 0;
1091da177e4SLinus Torvalds 	insert_inode_hash(inode);
1101da177e4SLinus Torvalds         mark_inode_dirty(inode);
1111da85fdfSFabian Frederick 	bfs_dump_imap("create", s);
1121da177e4SLinus Torvalds 
113b455ecd4SAl Viro 	err = bfs_add_entry(dir, &dentry->d_name, inode->i_ino);
1141da177e4SLinus Torvalds 	if (err) {
1159a53c3a7SDave Hansen 		inode_dec_link_count(inode);
1163f165e4cSDmitri Vorobiev 		mutex_unlock(&info->bfs_lock);
1171558182fSEric Sesterhenn 		iput(inode);
1181da177e4SLinus Torvalds 		return err;
1191da177e4SLinus Torvalds 	}
1203f165e4cSDmitri Vorobiev 	mutex_unlock(&info->bfs_lock);
1211da177e4SLinus Torvalds 	d_instantiate(dentry, inode);
1221da177e4SLinus Torvalds 	return 0;
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds 
bfs_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)125f433dc56SDmitri Vorobiev static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
12600cd8dd3SAl Viro 						unsigned int flags)
1271da177e4SLinus Torvalds {
1281da177e4SLinus Torvalds 	struct inode *inode = NULL;
1291da177e4SLinus Torvalds 	struct buffer_head *bh;
1301da177e4SLinus Torvalds 	struct bfs_dirent *de;
1313f165e4cSDmitri Vorobiev 	struct bfs_sb_info *info = BFS_SB(dir->i_sb);
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 	if (dentry->d_name.len > BFS_NAMELEN)
1341da177e4SLinus Torvalds 		return ERR_PTR(-ENAMETOOLONG);
1351da177e4SLinus Torvalds 
1363f165e4cSDmitri Vorobiev 	mutex_lock(&info->bfs_lock);
13733ebdebeSAl Viro 	bh = bfs_find_entry(dir, &dentry->d_name, &de);
1381da177e4SLinus Torvalds 	if (bh) {
139fac92becSAndrew Stribblehill 		unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
1401da177e4SLinus Torvalds 		brelse(bh);
141e33ab086SDavid Howells 		inode = bfs_iget(dir->i_sb, ino);
1421da177e4SLinus Torvalds 	}
1433f165e4cSDmitri Vorobiev 	mutex_unlock(&info->bfs_lock);
144a596a23bSAl Viro 	return d_splice_alias(inode, dentry);
1451da177e4SLinus Torvalds }
1461da177e4SLinus Torvalds 
bfs_link(struct dentry * old,struct inode * dir,struct dentry * new)147f433dc56SDmitri Vorobiev static int bfs_link(struct dentry *old, struct inode *dir,
148f433dc56SDmitri Vorobiev 						struct dentry *new)
1491da177e4SLinus Torvalds {
1502b0143b5SDavid Howells 	struct inode *inode = d_inode(old);
1513f165e4cSDmitri Vorobiev 	struct bfs_sb_info *info = BFS_SB(inode->i_sb);
1521da177e4SLinus Torvalds 	int err;
1531da177e4SLinus Torvalds 
1543f165e4cSDmitri Vorobiev 	mutex_lock(&info->bfs_lock);
155b455ecd4SAl Viro 	err = bfs_add_entry(dir, &new->d_name, inode->i_ino);
1561da177e4SLinus Torvalds 	if (err) {
1573f165e4cSDmitri Vorobiev 		mutex_unlock(&info->bfs_lock);
1581da177e4SLinus Torvalds 		return err;
1591da177e4SLinus Torvalds 	}
160d8c76e6fSDave Hansen 	inc_nlink(inode);
161*73d9b9d0SJeff Layton 	inode_set_ctime_current(inode);
1621da177e4SLinus Torvalds 	mark_inode_dirty(inode);
1637de9c6eeSAl Viro 	ihold(inode);
1641da177e4SLinus Torvalds 	d_instantiate(new, inode);
1653f165e4cSDmitri Vorobiev 	mutex_unlock(&info->bfs_lock);
1661da177e4SLinus Torvalds 	return 0;
1671da177e4SLinus Torvalds }
1681da177e4SLinus Torvalds 
bfs_unlink(struct inode * dir,struct dentry * dentry)1691da177e4SLinus Torvalds static int bfs_unlink(struct inode *dir, struct dentry *dentry)
1701da177e4SLinus Torvalds {
1711da177e4SLinus Torvalds 	int error = -ENOENT;
1722b0143b5SDavid Howells 	struct inode *inode = d_inode(dentry);
1731da177e4SLinus Torvalds 	struct buffer_head *bh;
1741da177e4SLinus Torvalds 	struct bfs_dirent *de;
1753f165e4cSDmitri Vorobiev 	struct bfs_sb_info *info = BFS_SB(inode->i_sb);
1761da177e4SLinus Torvalds 
1773f165e4cSDmitri Vorobiev 	mutex_lock(&info->bfs_lock);
17833ebdebeSAl Viro 	bh = bfs_find_entry(dir, &dentry->d_name, &de);
179f433dc56SDmitri Vorobiev 	if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
1801da177e4SLinus Torvalds 		goto out_brelse;
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds 	if (!inode->i_nlink) {
183f433dc56SDmitri Vorobiev 		printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
184f433dc56SDmitri Vorobiev 					inode->i_sb->s_id, inode->i_ino,
185f433dc56SDmitri Vorobiev 					inode->i_nlink);
186bfe86848SMiklos Szeredi 		set_nlink(inode, 1);
1871da177e4SLinus Torvalds 	}
1881da177e4SLinus Torvalds 	de->ino = 0;
1894427f0c3SAl Viro 	mark_buffer_dirty_inode(bh, dir);
190*73d9b9d0SJeff Layton 	dir->i_mtime = inode_set_ctime_current(dir);
1911da177e4SLinus Torvalds 	mark_inode_dirty(dir);
192*73d9b9d0SJeff Layton 	inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
1939a53c3a7SDave Hansen 	inode_dec_link_count(inode);
1941da177e4SLinus Torvalds 	error = 0;
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds out_brelse:
1971da177e4SLinus Torvalds 	brelse(bh);
1983f165e4cSDmitri Vorobiev 	mutex_unlock(&info->bfs_lock);
1991da177e4SLinus Torvalds 	return error;
2001da177e4SLinus Torvalds }
2011da177e4SLinus Torvalds 
bfs_rename(struct mnt_idmap * idmap,struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)202e18275aeSChristian Brauner static int bfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
203549c7297SChristian Brauner 		      struct dentry *old_dentry, struct inode *new_dir,
204549c7297SChristian Brauner 		      struct dentry *new_dentry, unsigned int flags)
2051da177e4SLinus Torvalds {
2061da177e4SLinus Torvalds 	struct inode *old_inode, *new_inode;
2071da177e4SLinus Torvalds 	struct buffer_head *old_bh, *new_bh;
2081da177e4SLinus Torvalds 	struct bfs_dirent *old_de, *new_de;
2093f165e4cSDmitri Vorobiev 	struct bfs_sb_info *info;
2101da177e4SLinus Torvalds 	int error = -ENOENT;
2111da177e4SLinus Torvalds 
212f03b8ad8SMiklos Szeredi 	if (flags & ~RENAME_NOREPLACE)
213f03b8ad8SMiklos Szeredi 		return -EINVAL;
214f03b8ad8SMiklos Szeredi 
2151da177e4SLinus Torvalds 	old_bh = new_bh = NULL;
2162b0143b5SDavid Howells 	old_inode = d_inode(old_dentry);
2171da177e4SLinus Torvalds 	if (S_ISDIR(old_inode->i_mode))
2181da177e4SLinus Torvalds 		return -EINVAL;
2191da177e4SLinus Torvalds 
2203f165e4cSDmitri Vorobiev 	info = BFS_SB(old_inode->i_sb);
2213f165e4cSDmitri Vorobiev 
2223f165e4cSDmitri Vorobiev 	mutex_lock(&info->bfs_lock);
22333ebdebeSAl Viro 	old_bh = bfs_find_entry(old_dir, &old_dentry->d_name, &old_de);
2241da177e4SLinus Torvalds 
225f433dc56SDmitri Vorobiev 	if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
2261da177e4SLinus Torvalds 		goto end_rename;
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds 	error = -EPERM;
2292b0143b5SDavid Howells 	new_inode = d_inode(new_dentry);
23033ebdebeSAl Viro 	new_bh = bfs_find_entry(new_dir, &new_dentry->d_name, &new_de);
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds 	if (new_bh && !new_inode) {
2331da177e4SLinus Torvalds 		brelse(new_bh);
2341da177e4SLinus Torvalds 		new_bh = NULL;
2351da177e4SLinus Torvalds 	}
2361da177e4SLinus Torvalds 	if (!new_bh) {
237b455ecd4SAl Viro 		error = bfs_add_entry(new_dir, &new_dentry->d_name,
238f433dc56SDmitri Vorobiev 					old_inode->i_ino);
2391da177e4SLinus Torvalds 		if (error)
2401da177e4SLinus Torvalds 			goto end_rename;
2411da177e4SLinus Torvalds 	}
2421da177e4SLinus Torvalds 	old_de->ino = 0;
243*73d9b9d0SJeff Layton 	old_dir->i_mtime = inode_set_ctime_current(old_dir);
2441da177e4SLinus Torvalds 	mark_inode_dirty(old_dir);
2451da177e4SLinus Torvalds 	if (new_inode) {
246*73d9b9d0SJeff Layton 		inode_set_ctime_current(new_inode);
2479a53c3a7SDave Hansen 		inode_dec_link_count(new_inode);
2481da177e4SLinus Torvalds 	}
2494427f0c3SAl Viro 	mark_buffer_dirty_inode(old_bh, old_dir);
2501da177e4SLinus Torvalds 	error = 0;
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds end_rename:
2533f165e4cSDmitri Vorobiev 	mutex_unlock(&info->bfs_lock);
2541da177e4SLinus Torvalds 	brelse(old_bh);
2551da177e4SLinus Torvalds 	brelse(new_bh);
2561da177e4SLinus Torvalds 	return error;
2571da177e4SLinus Torvalds }
2581da177e4SLinus Torvalds 
259754661f1SArjan van de Ven const struct inode_operations bfs_dir_inops = {
2601da177e4SLinus Torvalds 	.create			= bfs_create,
2611da177e4SLinus Torvalds 	.lookup			= bfs_lookup,
2621da177e4SLinus Torvalds 	.link			= bfs_link,
2631da177e4SLinus Torvalds 	.unlink			= bfs_unlink,
2641da177e4SLinus Torvalds 	.rename			= bfs_rename,
2651da177e4SLinus Torvalds };
2661da177e4SLinus Torvalds 
bfs_add_entry(struct inode * dir,const struct qstr * child,int ino)267b455ecd4SAl Viro static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino)
2681da177e4SLinus Torvalds {
269b455ecd4SAl Viro 	const unsigned char *name = child->name;
270b455ecd4SAl Viro 	int namelen = child->len;
2711da177e4SLinus Torvalds 	struct buffer_head *bh;
2721da177e4SLinus Torvalds 	struct bfs_dirent *de;
273f433dc56SDmitri Vorobiev 	int block, sblock, eblock, off, pos;
2741da177e4SLinus Torvalds 	int i;
2751da177e4SLinus Torvalds 
2761da177e4SLinus Torvalds 	dprintf("name=%s, namelen=%d\n", name, namelen);
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds 	if (!namelen)
2791da177e4SLinus Torvalds 		return -ENOENT;
2801da177e4SLinus Torvalds 	if (namelen > BFS_NAMELEN)
2811da177e4SLinus Torvalds 		return -ENAMETOOLONG;
2821da177e4SLinus Torvalds 
2831da177e4SLinus Torvalds 	sblock = BFS_I(dir)->i_sblock;
2841da177e4SLinus Torvalds 	eblock = BFS_I(dir)->i_eblock;
2851da177e4SLinus Torvalds 	for (block = sblock; block <= eblock; block++) {
2861da177e4SLinus Torvalds 		bh = sb_bread(dir->i_sb, block);
2871da177e4SLinus Torvalds 		if (!bh)
288c3fe5872SSanidhya Kashyap 			return -EIO;
2891da177e4SLinus Torvalds 		for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) {
2901da177e4SLinus Torvalds 			de = (struct bfs_dirent *)(bh->b_data + off);
2911da177e4SLinus Torvalds 			if (!de->ino) {
292f433dc56SDmitri Vorobiev 				pos = (block - sblock) * BFS_BSIZE + off;
293f433dc56SDmitri Vorobiev 				if (pos >= dir->i_size) {
2941da177e4SLinus Torvalds 					dir->i_size += BFS_DIRENT_SIZE;
295*73d9b9d0SJeff Layton 					inode_set_ctime_current(dir);
2961da177e4SLinus Torvalds 				}
297*73d9b9d0SJeff Layton 				dir->i_mtime = inode_set_ctime_current(dir);
2981da177e4SLinus Torvalds 				mark_inode_dirty(dir);
299fac92becSAndrew Stribblehill 				de->ino = cpu_to_le16((u16)ino);
3001da177e4SLinus Torvalds 				for (i = 0; i < BFS_NAMELEN; i++)
301f433dc56SDmitri Vorobiev 					de->name[i] =
302f433dc56SDmitri Vorobiev 						(i < namelen) ? name[i] : 0;
3034427f0c3SAl Viro 				mark_buffer_dirty_inode(bh, dir);
3041da177e4SLinus Torvalds 				brelse(bh);
3051da177e4SLinus Torvalds 				return 0;
3061da177e4SLinus Torvalds 			}
3071da177e4SLinus Torvalds 		}
3081da177e4SLinus Torvalds 		brelse(bh);
3091da177e4SLinus Torvalds 	}
3101da177e4SLinus Torvalds 	return -ENOSPC;
3111da177e4SLinus Torvalds }
3121da177e4SLinus Torvalds 
bfs_namecmp(int len,const unsigned char * name,const char * buffer)313f433dc56SDmitri Vorobiev static inline int bfs_namecmp(int len, const unsigned char *name,
314f433dc56SDmitri Vorobiev 							const char *buffer)
3151da177e4SLinus Torvalds {
316f433dc56SDmitri Vorobiev 	if ((len < BFS_NAMELEN) && buffer[len])
3171da177e4SLinus Torvalds 		return 0;
3181da177e4SLinus Torvalds 	return !memcmp(name, buffer, len);
3191da177e4SLinus Torvalds }
3201da177e4SLinus Torvalds 
bfs_find_entry(struct inode * dir,const struct qstr * child,struct bfs_dirent ** res_dir)3211da177e4SLinus Torvalds static struct buffer_head *bfs_find_entry(struct inode *dir,
32233ebdebeSAl Viro 			const struct qstr *child,
323f433dc56SDmitri Vorobiev 			struct bfs_dirent **res_dir)
3241da177e4SLinus Torvalds {
325f433dc56SDmitri Vorobiev 	unsigned long block = 0, offset = 0;
326f433dc56SDmitri Vorobiev 	struct buffer_head *bh = NULL;
3271da177e4SLinus Torvalds 	struct bfs_dirent *de;
32833ebdebeSAl Viro 	const unsigned char *name = child->name;
32933ebdebeSAl Viro 	int namelen = child->len;
3301da177e4SLinus Torvalds 
3311da177e4SLinus Torvalds 	*res_dir = NULL;
3321da177e4SLinus Torvalds 	if (namelen > BFS_NAMELEN)
3331da177e4SLinus Torvalds 		return NULL;
334f433dc56SDmitri Vorobiev 
3351da177e4SLinus Torvalds 	while (block * BFS_BSIZE + offset < dir->i_size) {
3361da177e4SLinus Torvalds 		if (!bh) {
3371da177e4SLinus Torvalds 			bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block);
3381da177e4SLinus Torvalds 			if (!bh) {
3391da177e4SLinus Torvalds 				block++;
3401da177e4SLinus Torvalds 				continue;
3411da177e4SLinus Torvalds 			}
3421da177e4SLinus Torvalds 		}
3431da177e4SLinus Torvalds 		de = (struct bfs_dirent *)(bh->b_data + offset);
3441da177e4SLinus Torvalds 		offset += BFS_DIRENT_SIZE;
345f433dc56SDmitri Vorobiev 		if (le16_to_cpu(de->ino) &&
346f433dc56SDmitri Vorobiev 				bfs_namecmp(namelen, name, de->name)) {
3471da177e4SLinus Torvalds 			*res_dir = de;
3481da177e4SLinus Torvalds 			return bh;
3491da177e4SLinus Torvalds 		}
3501da177e4SLinus Torvalds 		if (offset < bh->b_size)
3511da177e4SLinus Torvalds 			continue;
3521da177e4SLinus Torvalds 		brelse(bh);
3531da177e4SLinus Torvalds 		bh = NULL;
3541da177e4SLinus Torvalds 		offset = 0;
3551da177e4SLinus Torvalds 		block++;
3561da177e4SLinus Torvalds 	}
3571da177e4SLinus Torvalds 	brelse(bh);
3581da177e4SLinus Torvalds 	return NULL;
3591da177e4SLinus Torvalds }
360