Commit 80886298 authored by Al Viro's avatar Al Viro

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

ext2, ufs, minix, sysv
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent bb6f619b
...@@ -287,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode) ...@@ -287,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
} }
static int 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; loff_t pos = ctx->pos;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
unsigned int offset = pos & ~PAGE_CACHE_MASK; unsigned int offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT; unsigned long n = pos >> PAGE_CACHE_SHIFT;
unsigned long npages = dir_pages(inode); unsigned long npages = dir_pages(inode);
unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
unsigned char *types = NULL; 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)) if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
return 0; return 0;
...@@ -314,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) ...@@ -314,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
ext2_error(sb, __func__, ext2_error(sb, __func__,
"bad page in #%lu", "bad page in #%lu",
inode->i_ino); inode->i_ino);
filp->f_pos += PAGE_CACHE_SIZE - offset; ctx->pos += PAGE_CACHE_SIZE - offset;
return PTR_ERR(page); return PTR_ERR(page);
} }
kaddr = page_address(page); kaddr = page_address(page);
if (unlikely(need_revalidate)) { if (unlikely(need_revalidate)) {
if (offset) { if (offset) {
offset = ext2_validate_entry(kaddr, offset, chunk_mask); 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; need_revalidate = 0;
} }
de = (ext2_dirent *)(kaddr+offset); de = (ext2_dirent *)(kaddr+offset);
...@@ -336,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) ...@@ -336,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
return -EIO; return -EIO;
} }
if (de->inode) { if (de->inode) {
int over;
unsigned char d_type = DT_UNKNOWN; unsigned char d_type = DT_UNKNOWN;
if (types && de->file_type < EXT2_FT_MAX) if (types && de->file_type < EXT2_FT_MAX)
d_type = types[de->file_type]; d_type = types[de->file_type];
offset = (char *)de - kaddr; if (!dir_emit(ctx, de->name, de->name_len,
over = filldir(dirent, de->name, de->name_len, le32_to_cpu(de->inode),
(n<<PAGE_CACHE_SHIFT) | offset, d_type)) {
le32_to_cpu(de->inode), d_type);
if (over) {
ext2_put_page(page); ext2_put_page(page);
return 0; 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); ext2_put_page(page);
} }
...@@ -724,7 +721,7 @@ int ext2_empty_dir (struct inode * inode) ...@@ -724,7 +721,7 @@ int ext2_empty_dir (struct inode * inode)
const struct file_operations ext2_dir_operations = { const struct file_operations ext2_dir_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = ext2_readdir, .iterate = ext2_readdir,
.unlocked_ioctl = ext2_ioctl, .unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = ext2_compat_ioctl, .compat_ioctl = ext2_compat_ioctl,
......
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
typedef struct minix_dir_entry minix_dirent; typedef struct minix_dir_entry minix_dirent;
typedef struct minix3_dir_entry minix3_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 = { const struct file_operations minix_dir_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = minix_readdir, .iterate = minix_readdir,
.fsync = generic_file_fsync, .fsync = generic_file_fsync,
}; };
...@@ -82,22 +82,23 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi) ...@@ -82,22 +82,23 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
return (void*)((char*)de + sbi->s_dirsize); 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(file);
struct inode *inode = file_inode(filp);
struct super_block *sb = inode->i_sb; 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); struct minix_sb_info *sbi = minix_sb(sb);
unsigned chunk_size = sbi->s_dirsize; unsigned chunk_size = sbi->s_dirsize;
char *name; unsigned long npages = dir_pages(inode);
__u32 inumber; 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) 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) { for ( ; n < npages; n++, offset = 0) {
char *p, *kaddr, *limit; char *p, *kaddr, *limit;
...@@ -109,6 +110,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) ...@@ -109,6 +110,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
p = kaddr+offset; p = kaddr+offset;
limit = kaddr + minix_last_byte(inode, n) - chunk_size; limit = kaddr + minix_last_byte(inode, n) - chunk_size;
for ( ; p <= limit; p = minix_next_entry(p, sbi)) { for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
const char *name;
__u32 inumber;
if (sbi->s_version == MINIX_V3) { if (sbi->s_version == MINIX_V3) {
minix3_dirent *de3 = (minix3_dirent *)p; minix3_dirent *de3 = (minix3_dirent *)p;
name = de3->name; name = de3->name;
...@@ -119,24 +122,17 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) ...@@ -119,24 +122,17 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
inumber = de->inode; inumber = de->inode;
} }
if (inumber) { if (inumber) {
int over;
unsigned l = strnlen(name, sbi->s_namelen); unsigned l = strnlen(name, sbi->s_namelen);
offset = p - kaddr; if (!dir_emit(ctx, name, l,
over = filldir(dirent, name, l, inumber, DT_UNKNOWN)) {
(n << PAGE_CACHE_SHIFT) | offset,
inumber, DT_UNKNOWN);
if (over) {
dir_put_page(page); dir_put_page(page);
goto done; return 0;
} }
} }
ctx->pos += chunk_size;
} }
dir_put_page(page); dir_put_page(page);
} }
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
return 0; return 0;
} }
......
...@@ -18,12 +18,12 @@ ...@@ -18,12 +18,12 @@
#include <linux/swap.h> #include <linux/swap.h>
#include "sysv.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 = { const struct file_operations sysv_dir_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = sysv_readdir, .iterate = sysv_readdir,
.fsync = generic_file_fsync, .fsync = generic_file_fsync,
}; };
...@@ -65,18 +65,21 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n) ...@@ -65,18 +65,21 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
return page; 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; unsigned long pos = ctx->pos;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb; 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 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) 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) { for ( ; n < npages; n++, offset = 0) {
char *kaddr, *limit; char *kaddr, *limit;
...@@ -88,29 +91,21 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) ...@@ -88,29 +91,21 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
kaddr = (char *)page_address(page); kaddr = (char *)page_address(page);
de = (struct sysv_dir_entry *)(kaddr+offset); de = (struct sysv_dir_entry *)(kaddr+offset);
limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; 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; char *name = de->name;
int over;
if (!de->inode) if (!de->inode)
continue; continue;
offset = (char *)de - kaddr; if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
((loff_t)n<<PAGE_CACHE_SHIFT) | offset,
fs16_to_cpu(SYSV_SB(sb), de->inode), fs16_to_cpu(SYSV_SB(sb), de->inode),
DT_UNKNOWN); DT_UNKNOWN)) {
if (over) {
dir_put_page(page); dir_put_page(page);
goto done; return 0;
} }
} }
dir_put_page(page); dir_put_page(page);
} }
done:
filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
return 0; return 0;
} }
......
...@@ -430,16 +430,16 @@ ufs_validate_entry(struct super_block *sb, char *base, ...@@ -430,16 +430,16 @@ ufs_validate_entry(struct super_block *sb, char *base,
* This is blatantly stolen from ext2fs * This is blatantly stolen from ext2fs
*/ */
static int 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; loff_t pos = ctx->pos;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
unsigned int offset = pos & ~PAGE_CACHE_MASK; unsigned int offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT; unsigned long n = pos >> PAGE_CACHE_SHIFT;
unsigned long npages = ufs_dir_pages(inode); unsigned long npages = ufs_dir_pages(inode);
unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); 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; unsigned flags = UFS_SB(sb)->s_flags;
UFSD("BEGIN\n"); UFSD("BEGIN\n");
...@@ -457,16 +457,16 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -457,16 +457,16 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ufs_error(sb, __func__, ufs_error(sb, __func__,
"bad page in #%lu", "bad page in #%lu",
inode->i_ino); inode->i_ino);
filp->f_pos += PAGE_CACHE_SIZE - offset; ctx->pos += PAGE_CACHE_SIZE - offset;
return -EIO; return -EIO;
} }
kaddr = page_address(page); kaddr = page_address(page);
if (unlikely(need_revalidate)) { if (unlikely(need_revalidate)) {
if (offset) { if (offset) {
offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); 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; need_revalidate = 0;
} }
de = (struct ufs_dir_entry *)(kaddr+offset); de = (struct ufs_dir_entry *)(kaddr+offset);
...@@ -479,11 +479,8 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -479,11 +479,8 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
return -EIO; return -EIO;
} }
if (de->d_ino) { if (de->d_ino) {
int over;
unsigned char d_type = DT_UNKNOWN; unsigned char d_type = DT_UNKNOWN;
offset = (char *)de - kaddr;
UFSD("filldir(%s,%u)\n", de->d_name, UFSD("filldir(%s,%u)\n", de->d_name,
fs32_to_cpu(sb, de->d_ino)); fs32_to_cpu(sb, de->d_ino));
UFSD("namlen %u\n", ufs_get_de_namlen(sb, de)); UFSD("namlen %u\n", ufs_get_de_namlen(sb, de));
...@@ -491,16 +488,15 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -491,16 +488,15 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
d_type = de->d_u.d_44.d_type; 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), ufs_get_de_namlen(sb, de),
(n<<PAGE_CACHE_SHIFT) | offset, fs32_to_cpu(sb, de->d_ino),
fs32_to_cpu(sb, de->d_ino), d_type); d_type)) {
if (over) {
ufs_put_page(page); ufs_put_page(page);
return 0; 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); ufs_put_page(page);
} }
...@@ -660,7 +656,7 @@ int ufs_empty_dir(struct inode * inode) ...@@ -660,7 +656,7 @@ int ufs_empty_dir(struct inode * inode)
const struct file_operations ufs_dir_operations = { const struct file_operations ufs_dir_operations = {
.read = generic_read_dir, .read = generic_read_dir,
.readdir = ufs_readdir, .iterate = ufs_readdir,
.fsync = generic_file_fsync, .fsync = generic_file_fsync,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment