Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80886298 authored by Al Viro's avatar Al Viro
Browse files

[readdir] simple local unixlike: switch to ->iterate()



ext2, ufs, minix, sysv

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent bb6f619b
Loading
Loading
Loading
Loading
+12 −15
Original line number Diff line number Diff line
@@ -287,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
}

static int
ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
ext2_readdir(struct file *file, struct dir_context *ctx)
{
	loff_t pos = filp->f_pos;
	struct inode *inode = file_inode(filp);
	loff_t pos = ctx->pos;
	struct inode *inode = file_inode(file);
	struct super_block *sb = inode->i_sb;
	unsigned int offset = pos & ~PAGE_CACHE_MASK;
	unsigned long n = pos >> PAGE_CACHE_SHIFT;
	unsigned long npages = dir_pages(inode);
	unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
	unsigned char *types = NULL;
	int need_revalidate = filp->f_version != inode->i_version;
	int need_revalidate = file->f_version != inode->i_version;

	if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
		return 0;
@@ -314,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
			ext2_error(sb, __func__,
				   "bad page in #%lu",
				   inode->i_ino);
			filp->f_pos += PAGE_CACHE_SIZE - offset;
			ctx->pos += PAGE_CACHE_SIZE - offset;
			return PTR_ERR(page);
		}
		kaddr = page_address(page);
		if (unlikely(need_revalidate)) {
			if (offset) {
				offset = ext2_validate_entry(kaddr, offset, chunk_mask);
				filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
				ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset;
			}
			filp->f_version = inode->i_version;
			file->f_version = inode->i_version;
			need_revalidate = 0;
		}
		de = (ext2_dirent *)(kaddr+offset);
@@ -336,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
				return -EIO;
			}
			if (de->inode) {
				int over;
				unsigned char d_type = DT_UNKNOWN;

				if (types && de->file_type < EXT2_FT_MAX)
					d_type = types[de->file_type];

				offset = (char *)de - kaddr;
				over = filldir(dirent, de->name, de->name_len,
						(n<<PAGE_CACHE_SHIFT) | offset,
						le32_to_cpu(de->inode), d_type);
				if (over) {
				if (!dir_emit(ctx, de->name, de->name_len,
						le32_to_cpu(de->inode),
						d_type)) {
					ext2_put_page(page);
					return 0;
				}
			}
			filp->f_pos += ext2_rec_len_from_disk(de->rec_len);
			ctx->pos += ext2_rec_len_from_disk(de->rec_len);
		}
		ext2_put_page(page);
	}
@@ -724,7 +721,7 @@ int ext2_empty_dir (struct inode * inode)
const struct file_operations ext2_dir_operations = {
	.llseek		= generic_file_llseek,
	.read		= generic_read_dir,
	.readdir	= ext2_readdir,
	.iterate	= ext2_readdir,
	.unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl	= ext2_compat_ioctl,
+19 −23
Original line number Diff line number Diff line
@@ -16,12 +16,12 @@
typedef struct minix_dir_entry minix_dirent;
typedef struct minix3_dir_entry minix3_dirent;

static int minix_readdir(struct file *, void *, filldir_t);
static int minix_readdir(struct file *, struct dir_context *);

const struct file_operations minix_dir_operations = {
	.llseek		= generic_file_llseek,
	.read		= generic_read_dir,
	.readdir	= minix_readdir,
	.iterate	= minix_readdir,
	.fsync		= generic_file_fsync,
};

@@ -82,22 +82,23 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
	return (void*)((char*)de + sbi->s_dirsize);
}

static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
static int minix_readdir(struct file *file, struct dir_context *ctx)
{
	unsigned long pos = filp->f_pos;
	struct inode *inode = file_inode(filp);
	struct inode *inode = file_inode(file);
	struct super_block *sb = inode->i_sb;
	unsigned offset = pos & ~PAGE_CACHE_MASK;
	unsigned long n = pos >> PAGE_CACHE_SHIFT;
	unsigned long npages = dir_pages(inode);
	struct minix_sb_info *sbi = minix_sb(sb);
	unsigned chunk_size = sbi->s_dirsize;
	char *name;
	__u32 inumber;
	unsigned long npages = dir_pages(inode);
	unsigned long pos = ctx->pos;
	unsigned offset;
	unsigned long n;

	pos = (pos + chunk_size-1) & ~(chunk_size-1);
	ctx->pos = pos = (pos + chunk_size-1) & ~(chunk_size-1);
	if (pos >= inode->i_size)
		goto done;
		return 0;

	offset = pos & ~PAGE_CACHE_MASK;
	n = pos >> PAGE_CACHE_SHIFT;

	for ( ; n < npages; n++, offset = 0) {
		char *p, *kaddr, *limit;
@@ -109,6 +110,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
		p = kaddr+offset;
		limit = kaddr + minix_last_byte(inode, n) - chunk_size;
		for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
			const char *name;
			__u32 inumber;
			if (sbi->s_version == MINIX_V3) {
				minix3_dirent *de3 = (minix3_dirent *)p;
				name = de3->name;
@@ -119,24 +122,17 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
				inumber = de->inode;
			}
			if (inumber) {
				int over;

				unsigned l = strnlen(name, sbi->s_namelen);
				offset = p - kaddr;
				over = filldir(dirent, name, l,
					(n << PAGE_CACHE_SHIFT) | offset,
					inumber, DT_UNKNOWN);
				if (over) {
				if (!dir_emit(ctx, name, l,
					      inumber, DT_UNKNOWN)) {
					dir_put_page(page);
					goto done;
					return 0;
				}
			}
			ctx->pos += chunk_size;
		}
		dir_put_page(page);
	}

done:
	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
	return 0;
}

+16 −21
Original line number Diff line number Diff line
@@ -18,12 +18,12 @@
#include <linux/swap.h>
#include "sysv.h"

static int sysv_readdir(struct file *, void *, filldir_t);
static int sysv_readdir(struct file *, struct dir_context *);

const struct file_operations sysv_dir_operations = {
	.llseek		= generic_file_llseek,
	.read		= generic_read_dir,
	.readdir	= sysv_readdir,
	.iterate	= sysv_readdir,
	.fsync		= generic_file_fsync,
};

@@ -65,18 +65,21 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
	return page;
}

static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
static int sysv_readdir(struct file *file, struct dir_context *ctx)
{
	unsigned long pos = filp->f_pos;
	struct inode *inode = file_inode(filp);
	unsigned long pos = ctx->pos;
	struct inode *inode = file_inode(file);
	struct super_block *sb = inode->i_sb;
	unsigned offset = pos & ~PAGE_CACHE_MASK;
	unsigned long n = pos >> PAGE_CACHE_SHIFT;
	unsigned long npages = dir_pages(inode);
	unsigned offset;
	unsigned long n;

	pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
	ctx->pos = pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
	if (pos >= inode->i_size)
		goto done;
		return 0;

	offset = pos & ~PAGE_CACHE_MASK;
	n = pos >> PAGE_CACHE_SHIFT;

	for ( ; n < npages; n++, offset = 0) {
		char *kaddr, *limit;
@@ -88,29 +91,21 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
		kaddr = (char *)page_address(page);
		de = (struct sysv_dir_entry *)(kaddr+offset);
		limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE;
		for ( ;(char*)de <= limit; de++) {
		for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) {
			char *name = de->name;
			int over;

			if (!de->inode)
				continue;

			offset = (char *)de - kaddr;

			over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
					((loff_t)n<<PAGE_CACHE_SHIFT) | offset,
			if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
					fs16_to_cpu(SYSV_SB(sb), de->inode),
					DT_UNKNOWN);
			if (over) {
					DT_UNKNOWN)) {
				dir_put_page(page);
				goto done;
				return 0;
			}
		}
		dir_put_page(page);
	}

done:
	filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
	return 0;
}

+12 −16
Original line number Diff line number Diff line
@@ -430,16 +430,16 @@ ufs_validate_entry(struct super_block *sb, char *base,
 * This is blatantly stolen from ext2fs
 */
static int
ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ufs_readdir(struct file *file, struct dir_context *ctx)
{
	loff_t pos = filp->f_pos;
	struct inode *inode = file_inode(filp);
	loff_t pos = ctx->pos;
	struct inode *inode = file_inode(file);
	struct super_block *sb = inode->i_sb;
	unsigned int offset = pos & ~PAGE_CACHE_MASK;
	unsigned long n = pos >> PAGE_CACHE_SHIFT;
	unsigned long npages = ufs_dir_pages(inode);
	unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
	int need_revalidate = filp->f_version != inode->i_version;
	int need_revalidate = file->f_version != inode->i_version;
	unsigned flags = UFS_SB(sb)->s_flags;

	UFSD("BEGIN\n");
@@ -457,16 +457,16 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
			ufs_error(sb, __func__,
				  "bad page in #%lu",
				  inode->i_ino);
			filp->f_pos += PAGE_CACHE_SIZE - offset;
			ctx->pos += PAGE_CACHE_SIZE - offset;
			return -EIO;
		}
		kaddr = page_address(page);
		if (unlikely(need_revalidate)) {
			if (offset) {
				offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask);
				filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
				ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset;
			}
			filp->f_version = inode->i_version;
			file->f_version = inode->i_version;
			need_revalidate = 0;
		}
		de = (struct ufs_dir_entry *)(kaddr+offset);
@@ -479,11 +479,8 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
				return -EIO;
			}
			if (de->d_ino) {
				int over;
				unsigned char d_type = DT_UNKNOWN;

				offset = (char *)de - kaddr;

				UFSD("filldir(%s,%u)\n", de->d_name,
				      fs32_to_cpu(sb, de->d_ino));
				UFSD("namlen %u\n", ufs_get_de_namlen(sb, de));
@@ -491,16 +488,15 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
				if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
					d_type = de->d_u.d_44.d_type;

				over = filldir(dirent, de->d_name,
				if (!dir_emit(ctx, de->d_name,
					       ufs_get_de_namlen(sb, de),
						(n<<PAGE_CACHE_SHIFT) | offset,
					       fs32_to_cpu(sb, de->d_ino), d_type);
				if (over) {
					       fs32_to_cpu(sb, de->d_ino),
					       d_type)) {
					ufs_put_page(page);
					return 0;
				}
			}
			filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
			ctx->pos += fs16_to_cpu(sb, de->d_reclen);
		}
		ufs_put_page(page);
	}
@@ -660,7 +656,7 @@ int ufs_empty_dir(struct inode * inode)

const struct file_operations ufs_dir_operations = {
	.read		= generic_read_dir,
	.readdir	= ufs_readdir,
	.iterate	= ufs_readdir,
	.fsync		= generic_file_fsync,
	.llseek		= generic_file_llseek,
};