ext2, ufs, minix, sysv
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-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;
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;
if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
return 0;
ext2_error(sb, __func__,
"bad page in #%lu",
inode->i_ino);
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);
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);
need_revalidate = 0;
}
de = (ext2_dirent *)(kaddr+offset);
return -EIO;
}
if (de->inode) {
return -EIO;
}
if (de->inode) {
unsigned char d_type = DT_UNKNOWN;
if (types && de->file_type < EXT2_FT_MAX)
d_type = types[de->file_type];
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;
}
}
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);
const struct file_operations ext2_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
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,
.unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext2_compat_ioctl,
typedef struct minix_dir_entry minix_dirent;
typedef struct minix3_dir_entry minix3_dirent;
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,
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,
};
.fsync = generic_file_fsync,
};
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(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);
struct minix_sb_info *sbi = minix_sb(sb);
unsigned chunk_size = sbi->s_dirsize;
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)
if (pos >= inode->i_size)
+ return 0;
+
+ offset = pos & ~PAGE_CACHE_MASK;
+ n = pos >> PAGE_CACHE_SHIFT;
for ( ; n < npages; n++, offset = 0) {
char *p, *kaddr, *limit;
for ( ; n < npages; n++, offset = 0) {
char *p, *kaddr, *limit;
p = kaddr+offset;
limit = kaddr + minix_last_byte(inode, n) - chunk_size;
for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
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;
if (sbi->s_version == MINIX_V3) {
minix3_dirent *de3 = (minix3_dirent *)p;
name = de3->name;
inumber = de->inode;
}
if (inumber) {
inumber = de->inode;
}
if (inumber) {
unsigned l = strnlen(name, sbi->s_namelen);
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)) {
+ ctx->pos += chunk_size;
-
-done:
- filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
#include <linux/swap.h>
#include "sysv.h"
#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,
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,
};
.fsync = generic_file_fsync,
};
-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;
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)
+ return 0;
+
+ offset = pos & ~PAGE_CACHE_MASK;
+ n = pos >> PAGE_CACHE_SHIFT;
for ( ; n < npages; n++, offset = 0) {
char *kaddr, *limit;
for ( ; n < npages; n++, offset = 0) {
char *kaddr, *limit;
kaddr = (char *)page_address(page);
de = (struct sysv_dir_entry *)(kaddr+offset);
limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE;
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)) {
if (!de->inode)
continue;
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),
fs16_to_cpu(SYSV_SB(sb), de->inode),
- DT_UNKNOWN);
- if (over) {
}
}
dir_put_page(page);
}
}
}
dir_put_page(page);
}
-
-done:
- filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
* This is blatantly stolen from ext2fs
*/
static int
* 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);
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");
unsigned flags = UFS_SB(sb)->s_flags;
UFSD("BEGIN\n");
ufs_error(sb, __func__,
"bad page in #%lu",
inode->i_ino);
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);
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);
need_revalidate = 0;
}
de = (struct ufs_dir_entry *)(kaddr+offset);
return -EIO;
}
if (de->d_ino) {
return -EIO;
}
if (de->d_ino) {
unsigned char d_type = DT_UNKNOWN;
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));
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));
if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
d_type = de->d_u.d_44.d_type;
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),
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;
}
}
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);
const struct file_operations ufs_dir_operations = {
.read = generic_read_dir,
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,
};
.fsync = generic_file_fsync,
.llseek = generic_file_llseek,
};