Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull VFS patches (part 1) from Al Viro:
 "The major change in this pile is ->readdir() replacement with
  ->iterate(), dealing with ->f_pos races in ->readdir() instances for
  good.

  There's a lot more, but I'd prefer to split the pull request into
  several stages and this is the first obvious cutoff point."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (67 commits)
  [readdir] constify ->actor
  [readdir] ->readdir() is gone
  [readdir] convert ecryptfs
  [readdir] convert coda
  [readdir] convert ocfs2
  [readdir] convert fatfs
  [readdir] convert xfs
  [readdir] convert btrfs
  [readdir] convert hostfs
  [readdir] convert afs
  [readdir] convert ncpfs
  [readdir] convert hfsplus
  [readdir] convert hfs
  [readdir] convert befs
  [readdir] convert cifs
  [readdir] convert freevxfs
  [readdir] convert fuse
  [readdir] convert hpfs
  reiserfs: switch reiserfs_readdir_dentry to inode
  reiserfs: is_privroot_deh() needs only directory inode, actually
  ...
This commit is contained in:
Linus Torvalds 2013-07-02 09:28:37 -07:00
commit 63580e51bb
144 changed files with 1937 additions and 2824 deletions

View File

@ -414,7 +414,7 @@ prototypes:
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

View File

@ -445,3 +445,9 @@ object doesn't exist. It's remote/distributed ones that might care...
[mandatory]
FS_REVAL_DOT is gone; if you used to have it, add ->d_weak_revalidate()
in your dentry operations instead.
--
[mandatory]
vfs_readdir() is gone; switch to iterate_dir() instead
--
[mandatory]
->readdir() is gone now; switch to ->iterate()

View File

@ -777,7 +777,7 @@ struct file_operations {
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
@ -815,7 +815,7 @@ otherwise noted.
aio_write: called by io_submit(2) and other asynchronous I/O operations
readdir: called when the VFS needs to read the directory contents
iterate: called when the VFS needs to read the directory contents
poll: called by the VFS when a process wants to check if there is
activity on this file and (optionally) go to sleep until there

View File

@ -354,9 +354,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
#define kern_addr_valid(addr) (1)
#endif
#define io_remap_pfn_range(vma, start, pfn, size, prot) \
remap_pfn_range(vma, start, pfn, size, prot)
#define pte_ERROR(e) \
printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \

View File

@ -96,6 +96,7 @@ struct osf_dirent {
};
struct osf_dirent_callback {
struct dir_context ctx;
struct osf_dirent __user *dirent;
long __user *basep;
unsigned int count;
@ -146,17 +147,17 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
{
int error;
struct fd arg = fdget(fd);
struct osf_dirent_callback buf;
struct osf_dirent_callback buf = {
.ctx.actor = osf_filldir,
.dirent = dirent,
.basep = basep,
.count = count
};
if (!arg.file)
return -EBADF;
buf.dirent = dirent;
buf.basep = basep;
buf.count = count;
buf.error = 0;
error = vfs_readdir(arg.file, osf_filldir, &buf);
error = iterate_dir(arg.file, &buf.ctx);
if (error >= 0)
error = buf.error;
if (count != buf.count)

View File

@ -26,7 +26,6 @@ static int hose_mmap_page_range(struct pci_controller *hose,
base = sparse ? hose->sparse_io_base : hose->dense_io_base;
vma->vm_pgoff += base >> PAGE_SHIFT;
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start,

View File

@ -394,9 +394,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
#define io_remap_pfn_range(vma, from, pfn, size, prot) \
remap_pfn_range(vma, from, pfn, size, prot)
#include <asm-generic/pgtable.h>
/* to cope with aliasing VIPT cache */

View File

@ -79,8 +79,6 @@ extern unsigned int kobjsize(const void *objp);
* No page table caches to initialise.
*/
#define pgtable_cache_init() do { } while (0)
#define io_remap_pfn_range remap_pfn_range
/*
* All 32bit addresses are effectively valid for vmalloc...

View File

@ -318,13 +318,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#define HAVE_ARCH_UNMAPPED_AREA
#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
/*
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
#define pgtable_cache_init() do { } while (0)
#endif /* !__ASSEMBLY__ */

View File

@ -320,13 +320,6 @@ extern int kern_addr_valid(unsigned long addr);
#include <asm-generic/pgtable.h>
/*
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
#define pgtable_cache_init() do { } while (0)
#endif /* !__ASSEMBLY__ */

View File

@ -362,9 +362,6 @@ typedef pte_t *pte_addr_t;
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/* No page table caches to initialize (?) */
#define pgtable_cache_init() do { } while(0)

View File

@ -88,7 +88,6 @@ extern char empty_zero_page[];
* No page table caches to initialise.
*/
#define pgtable_cache_init() do { } while (0)
#define io_remap_pfn_range remap_pfn_range
/*
* All 32bit addresses are effectively valid for vmalloc...

View File

@ -71,7 +71,6 @@ extern unsigned long empty_zero_page;
* No page table caches to initialise
*/
#define pgtable_cache_init() do { } while (0)
#define io_remap_pfn_range remap_pfn_range
#include <asm-generic/pgtable.h>

View File

@ -258,9 +258,6 @@ static inline pgd_t * pgd_offset(const struct mm_struct *mm, unsigned long addre
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */

View File

@ -488,9 +488,6 @@ static inline int pte_file(pte_t pte)
#define PageSkip(page) (0)
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT

View File

@ -52,9 +52,6 @@ extern int is_in_rom(unsigned long);
*/
#define pgtable_cache_init() do { } while (0)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/*
* All 32bit addresses are effectively valid for vmalloc...
* Sort of meaningless for non-VM targets.

View File

@ -452,10 +452,6 @@ static inline int pte_exec(pte_t pte)
#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
/* Nothing special about IO remapping at this point */
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/* I think this is in case we have page table caches; needed by init/main.c */
#define pgtable_cache_init() do { } while (0)

View File

@ -493,9 +493,6 @@ extern void paging_init (void);
#define pte_to_pgoff(pte) ((pte_val(pte) << 1) >> 3)
#define pgoff_to_pte(off) ((pte_t) { ((off) << 2) | _PAGE_FILE })
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/*
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..

View File

@ -347,9 +347,6 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT

View File

@ -135,9 +135,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/* MMU-specific headers */
#ifdef CONFIG_SUN3

View File

@ -55,9 +55,6 @@ extern unsigned int kobjsize(const void *objp);
*/
#define pgtable_cache_init() do { } while (0)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/*
* All 32bit addresses are effectively valid for vmalloc...
* Sort of meaningless for non-VM targets.

View File

@ -333,9 +333,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/*
* No page table caches to initialise
*/

View File

@ -13,9 +13,6 @@
#include <asm/setup.h>
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#ifndef __ASSEMBLY__
extern int mem_init_done;
#endif

View File

@ -394,9 +394,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
phys_t phys_addr_high = fixup_bigphys_addr(pfn << PAGE_SHIFT, size);
return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot);
}
#else
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#define io_remap_pfn_range io_remap_pfn_range
#endif
#ifdef CONFIG_TRANSPARENT_HUGEPAGE

View File

@ -486,9 +486,6 @@ extern void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range((vma), (vaddr), (pfn), (size), (prot))
#define MK_IOSPACE_PFN(space, pfn) (pfn)
#define GET_IOSPACE(pfn) 0
#define GET_PFN(pfn) (pfn)

View File

@ -221,7 +221,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
/* Leave vm_pgoff as-is, the PCI space address is the physical
* address on this platform.
*/
vma->vm_flags |= VM_LOCKED | VM_IO;
vma->vm_flags |= VM_LOCKED;
prot = pgprot_val(vma->vm_page_prot);
prot &= ~_PAGE_CACHE;

View File

@ -446,9 +446,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#include <asm-generic/pgtable.h>
/*

View File

@ -60,6 +60,7 @@ struct hpux_dirent {
};
struct getdents_callback {
struct dir_context ctx;
struct hpux_dirent __user *current_dir;
struct hpux_dirent __user *previous;
int count;
@ -110,24 +111,23 @@ int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned i
{
struct fd arg;
struct hpux_dirent __user * lastdirent;
struct getdents_callback buf;
struct getdents_callback buf = {
.ctx.actor = filldir,
.current_dir = dirent,
.count = count
};
int error;
arg = fdget(fd);
if (!arg.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(arg.file, filldir, &buf);
error = iterate_dir(arg.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
if (put_user(arg.file->f_pos, &lastdirent->d_off))
if (put_user(buf.ctx.pos, &lastdirent->d_off))
error = -EFAULT;
else
error = count - buf.count;

View File

@ -506,9 +506,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
#endif
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_NO_CACHE)
/* We provide our own get_unmapped_area to provide cache coherency */

View File

@ -198,9 +198,6 @@ extern void paging_init(void);
*/
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#include <asm-generic/pgtable.h>

View File

@ -238,7 +238,7 @@ const struct file_operations spufs_context_fops = {
.release = spufs_dir_close,
.llseek = dcache_dir_lseek,
.read = generic_read_dir,
.readdir = dcache_readdir,
.iterate = dcache_readdir,
.fsync = noop_fsync,
};
EXPORT_SYMBOL_GPL(spufs_context_fops);

View File

@ -58,9 +58,6 @@ extern unsigned long zero_page_mask;
#define __HAVE_COLOR_ZERO_PAGE
/* TODO: s390 cannot support io_remap_pfn_range... */
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif /* !__ASSEMBLY__ */
/*

View File

@ -113,9 +113,6 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
#define pte_clear(mm, addr, xp) \
do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/*
* The "pgd_xxx()" functions here are trivial for a folded two-level
* setup: the pgd is never bad, and a pmd always exists (as it's folded

View File

@ -124,9 +124,6 @@ typedef pte_t *pte_addr_t;
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
/*

View File

@ -443,6 +443,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
}
#define io_remap_pfn_range io_remap_pfn_range
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \

View File

@ -914,6 +914,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
}
#define io_remap_pfn_range io_remap_pfn_range
#include <asm/tlbflush.h>
#include <asm-generic/pgtable.h>

View File

@ -773,15 +773,6 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev,
return 0;
}
/* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
* mapping.
*/
static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
}
/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
@ -809,7 +800,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
if (ret < 0)
return ret;
__pci_mmap_set_flags(dev, vma, mmap_state);
__pci_mmap_set_pgprot(dev, vma, mmap_state);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

View File

@ -362,9 +362,6 @@ do { \
#define kern_addr_valid(addr) (1)
#endif /* CONFIG_FLATMEM */
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
extern void vmalloc_sync_all(void);
#endif /* !__ASSEMBLY__ */

View File

@ -69,8 +69,6 @@ extern unsigned long end_iomem;
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
#define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC)
#define io_remap_pfn_range remap_pfn_range
/*
* The i386 can't do page protection for execute, and considers that the same
* are read.

View File

@ -303,13 +303,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#include <asm-generic/pgtable.h>
/*
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
#define io_remap_pfn_range(vma, from, pfn, size, prot) \
remap_pfn_range(vma, from, pfn, size, prot)
#define pgtable_cache_init() do { } while (0)
#endif /* !__ASSEMBLY__ */

View File

@ -506,9 +506,6 @@ static inline unsigned long pages_to_mb(unsigned long npg)
return npg >> (20 - PAGE_SHIFT);
}
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#if PAGETABLE_LEVELS > 2
static inline int pud_none(pud_t pud)
{

View File

@ -393,14 +393,6 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
extern void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t *ptep);
/*
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
typedef pte_t *pte_addr_t;
#endif /* !defined (__ASSEMBLY__) */

View File

@ -25,9 +25,9 @@
#include <linux/string.h>
#include <linux/crypto.h>
#include <linux/blkdev.h>
#include <linux/loop.h>
#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include "loop.h"
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("loop blockdevice transferfunction adaptor / CryptoAPI");

View File

@ -63,7 +63,6 @@
#include <linux/init.h>
#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/loop.h>
#include <linux/compat.h>
#include <linux/suspend.h>
#include <linux/freezer.h>
@ -76,6 +75,7 @@
#include <linux/sysfs.h>
#include <linux/miscdevice.h>
#include <linux/falloc.h>
#include "loop.h"
#include <asm/uaccess.h>

View File

@ -1,5 +1,5 @@
/*
* include/linux/loop.h
* loop.h
*
* Written by Theodore Ts'o, 3/29/93.
*

View File

@ -617,7 +617,6 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
offset = drm_core_get_reg_ofs(dev);
vma->vm_flags |= VM_IO; /* not in core dump */
vma->vm_page_prot = drm_io_prot(map->type, vma);
if (io_remap_pfn_range(vma, vma->vm_start,
(map->offset + offset) >> PAGE_SHIFT,

View File

@ -97,7 +97,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
buf = dev_priv->mmap_buffer;
buf_priv = buf->dev_private;
vma->vm_flags |= (VM_IO | VM_DONTCOPY);
vma->vm_flags |= VM_DONTCOPY;
buf_priv->currently_mapped = I810_BUF_MAPPED;

View File

@ -499,7 +499,6 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
}
vma->vm_private_data = vdev;
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff;

View File

@ -385,8 +385,6 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
vma->vm_flags |= VM_IO;
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) {

View File

@ -1258,13 +1258,9 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
vma->vm_flags |= VM_IO;
return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
return 0;
}
static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)

View File

@ -494,7 +494,6 @@ pxa3xx_gcu_misc_mmap(struct file *file, struct vm_area_struct *vma)
if (size != resource_size(priv->resource_mem))
return -EINVAL;
vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
return io_remap_pfn_range(vma, vma->vm_start,

View File

@ -101,16 +101,15 @@ static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen)
}
/**
* v9fs_dir_readdir - read a directory
* @filp: opened file structure
* @dirent: directory structure ???
* @filldir: function to populate directory structure ???
* v9fs_dir_readdir - iterate through a directory
* @file: opened file structure
* @ctx: actor we feed the entries to
*
*/
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
{
int over;
bool over;
struct p9_wstat st;
int err = 0;
struct p9_fid *fid;
@ -118,19 +117,19 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
int reclen = 0;
struct p9_rdir *rdir;
p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
fid = filp->private_data;
p9_debug(P9_DEBUG_VFS, "name %s\n", file->f_path.dentry->d_name.name);
fid = file->private_data;
buflen = fid->clnt->msize - P9_IOHDRSZ;
rdir = v9fs_alloc_rdir_buf(filp, buflen);
rdir = v9fs_alloc_rdir_buf(file, buflen);
if (!rdir)
return -ENOMEM;
while (1) {
if (rdir->tail == rdir->head) {
err = v9fs_file_readn(filp, rdir->buf, NULL,
buflen, filp->f_pos);
err = v9fs_file_readn(file, rdir->buf, NULL,
buflen, ctx->pos);
if (err <= 0)
return err;
@ -148,51 +147,45 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
reclen = st.size+2;
over = filldir(dirent, st.name, strlen(st.name),
filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st));
over = !dir_emit(ctx, st.name, strlen(st.name),
v9fs_qid2ino(&st.qid), dt_type(&st));
p9stat_free(&st);
if (over)
return 0;
rdir->head += reclen;
filp->f_pos += reclen;
ctx->pos += reclen;
}
}
}
/**
* v9fs_dir_readdir_dotl - read a directory
* @filp: opened file structure
* @dirent: buffer to fill dirent structures
* @filldir: function to populate dirent structures
* v9fs_dir_readdir_dotl - iterate through a directory
* @file: opened file structure
* @ctx: actor we feed the entries to
*
*/
static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent,
filldir_t filldir)
static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
{
int over;
int err = 0;
struct p9_fid *fid;
int buflen;
struct p9_rdir *rdir;
struct p9_dirent curdirent;
u64 oldoffset = 0;
p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
fid = filp->private_data;
p9_debug(P9_DEBUG_VFS, "name %s\n", file->f_path.dentry->d_name.name);
fid = file->private_data;
buflen = fid->clnt->msize - P9_READDIRHDRSZ;
rdir = v9fs_alloc_rdir_buf(filp, buflen);
rdir = v9fs_alloc_rdir_buf(file, buflen);
if (!rdir)
return -ENOMEM;
while (1) {
if (rdir->tail == rdir->head) {
err = p9_client_readdir(fid, rdir->buf, buflen,
filp->f_pos);
ctx->pos);
if (err <= 0)
return err;
@ -210,22 +203,13 @@ static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent,
return -EIO;
}
/* d_off in dirent structure tracks the offset into
* the next dirent in the dir. However, filldir()
* expects offset into the current dirent. Hence
* while calling filldir send the offset from the
* previous dirent structure.
*/
over = filldir(dirent, curdirent.d_name,
strlen(curdirent.d_name),
oldoffset, v9fs_qid2ino(&curdirent.qid),
curdirent.d_type);
oldoffset = curdirent.d_off;
if (over)
if (!dir_emit(ctx, curdirent.d_name,
strlen(curdirent.d_name),
v9fs_qid2ino(&curdirent.qid),
curdirent.d_type))
return 0;
filp->f_pos = curdirent.d_off;
ctx->pos = curdirent.d_off;
rdir->head += err;
}
}
@ -254,7 +238,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
const struct file_operations v9fs_dir_operations = {
.read = generic_read_dir,
.llseek = generic_file_llseek,
.readdir = v9fs_dir_readdir,
.iterate = v9fs_dir_readdir,
.open = v9fs_file_open,
.release = v9fs_dir_release,
};
@ -262,7 +246,7 @@ const struct file_operations v9fs_dir_operations = {
const struct file_operations v9fs_dir_operations_dotl = {
.read = generic_read_dir,
.llseek = generic_file_llseek,
.readdir = v9fs_dir_readdir_dotl,
.iterate = v9fs_dir_readdir_dotl,
.open = v9fs_file_open,
.release = v9fs_dir_release,
.fsync = v9fs_file_fsync_dotl,

View File

@ -17,47 +17,43 @@
static DEFINE_RWLOCK(adfs_dir_lock);
static int
adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
adfs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
struct object_info obj;
struct adfs_dir dir;
int ret = 0;
if (filp->f_pos >> 32)
goto out;
if (ctx->pos >> 32)
return 0;
ret = ops->read(sb, inode->i_ino, inode->i_size, &dir);
if (ret)
goto out;
return ret;
switch ((unsigned long)filp->f_pos) {
case 0:
if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
if (ctx->pos == 0) {
if (!dir_emit_dot(file, ctx))
goto free_out;
filp->f_pos += 1;
case 1:
if (filldir(dirent, "..", 2, 1, dir.parent_id, DT_DIR) < 0)
ctx->pos = 1;
}
if (ctx->pos == 1) {
if (!dir_emit(ctx, "..", 2, dir.parent_id, DT_DIR))
goto free_out;
filp->f_pos += 1;
default:
break;
ctx->pos = 2;
}
read_lock(&adfs_dir_lock);
ret = ops->setpos(&dir, filp->f_pos - 2);
ret = ops->setpos(&dir, ctx->pos - 2);
if (ret)
goto unlock_out;
while (ops->getnext(&dir, &obj) == 0) {
if (filldir(dirent, obj.name, obj.name_len,
filp->f_pos, obj.file_id, DT_UNKNOWN) < 0)
goto unlock_out;
filp->f_pos += 1;
if (!dir_emit(ctx, obj.name, obj.name_len,
obj.file_id, DT_UNKNOWN))
break;
ctx->pos++;
}
unlock_out:
@ -65,8 +61,6 @@ adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
free_out:
ops->free(&dir);
out:
return ret;
}
@ -192,7 +186,7 @@ adfs_dir_lookup_byname(struct inode *inode, struct qstr *name, struct object_inf
const struct file_operations adfs_dir_operations = {
.read = generic_read_dir,
.llseek = generic_file_llseek,
.readdir = adfs_readdir,
.iterate = adfs_readdir,
.fsync = generic_file_fsync,
};

View File

@ -15,12 +15,12 @@
#include "affs.h"
static int affs_readdir(struct file *, void *, filldir_t);
static int affs_readdir(struct file *, struct dir_context *);
const struct file_operations affs_dir_operations = {
.read = generic_read_dir,
.llseek = generic_file_llseek,
.readdir = affs_readdir,
.iterate = affs_readdir,
.fsync = affs_file_fsync,
};
@ -40,52 +40,35 @@ const struct inode_operations affs_dir_inode_operations = {
};
static int
affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
affs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
struct buffer_head *dir_bh;
struct buffer_head *fh_bh;
struct buffer_head *dir_bh = NULL;
struct buffer_head *fh_bh = NULL;
unsigned char *name;
int namelen;
u32 i;
int hash_pos;
int chain_pos;
u32 f_pos;
u32 ino;
int stored;
int res;
pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)filp->f_pos);
pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)ctx->pos);
stored = 0;
res = -EIO;
dir_bh = NULL;
fh_bh = NULL;
f_pos = filp->f_pos;
if (f_pos == 0) {
filp->private_data = (void *)0;
if (filldir(dirent, ".", 1, f_pos, inode->i_ino, DT_DIR) < 0)
if (ctx->pos < 2) {
file->private_data = (void *)0;
if (!dir_emit_dots(file, ctx))
return 0;
filp->f_pos = f_pos = 1;
stored++;
}
if (f_pos == 1) {
if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0)
return stored;
filp->f_pos = f_pos = 2;
stored++;
}
affs_lock_dir(inode);
chain_pos = (f_pos - 2) & 0xffff;
hash_pos = (f_pos - 2) >> 16;
chain_pos = (ctx->pos - 2) & 0xffff;
hash_pos = (ctx->pos - 2) >> 16;
if (chain_pos == 0xffff) {
affs_warning(sb, "readdir", "More than 65535 entries in chain");
chain_pos = 0;
hash_pos++;
filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
ctx->pos = ((hash_pos << 16) | chain_pos) + 2;
}
dir_bh = affs_bread(sb, inode->i_ino);
if (!dir_bh)
@ -94,8 +77,8 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* If the directory hasn't changed since the last call to readdir(),
* we can jump directly to where we left off.
*/
ino = (u32)(long)filp->private_data;
if (ino && filp->f_version == inode->i_version) {
ino = (u32)(long)file->private_data;
if (ino && file->f_version == inode->i_version) {
pr_debug("AFFS: readdir() left off=%d\n", ino);
goto inside;
}
@ -105,7 +88,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
fh_bh = affs_bread(sb, ino);
if (!fh_bh) {
affs_error(sb, "readdir","Cannot read block %d", i);
goto readdir_out;
return -EIO;
}
ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
affs_brelse(fh_bh);
@ -119,38 +102,34 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
if (!ino)
continue;
f_pos = (hash_pos << 16) + 2;
ctx->pos = (hash_pos << 16) + 2;
inside:
do {
fh_bh = affs_bread(sb, ino);
if (!fh_bh) {
affs_error(sb, "readdir","Cannot read block %d", ino);
goto readdir_done;
break;
}
namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
name = AFFS_TAIL(sb, fh_bh)->name + 1;
pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n",
namelen, name, ino, hash_pos, f_pos);
if (filldir(dirent, name, namelen, f_pos, ino, DT_UNKNOWN) < 0)
namelen, name, ino, hash_pos, (u32)ctx->pos);
if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN))
goto readdir_done;
stored++;
f_pos++;
ctx->pos++;
ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
affs_brelse(fh_bh);
fh_bh = NULL;
} while (ino);
}
readdir_done:
filp->f_pos = f_pos;
filp->f_version = inode->i_version;
filp->private_data = (void *)(long)ino;
res = stored;
file->f_version = inode->i_version;
file->private_data = (void *)(long)ino;
readdir_out:
affs_brelse(dir_bh);
affs_brelse(fh_bh);
affs_unlock_dir(inode);
pr_debug("AFFS: readdir()=%d\n", stored);
return res;
return 0;
}

View File

@ -22,7 +22,7 @@
static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags);
static int afs_dir_open(struct inode *inode, struct file *file);
static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
static int afs_readdir(struct file *file, struct dir_context *ctx);
static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
static int afs_d_delete(const struct dentry *dentry);
static void afs_d_release(struct dentry *dentry);
@ -43,7 +43,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
const struct file_operations afs_dir_file_operations = {
.open = afs_dir_open,
.release = afs_release,
.readdir = afs_readdir,
.iterate = afs_readdir,
.lock = afs_lock,
.llseek = generic_file_llseek,
};
@ -119,9 +119,9 @@ struct afs_dir_page {
};
struct afs_lookup_cookie {
struct dir_context ctx;
struct afs_fid fid;
const char *name;
size_t nlen;
struct qstr name;
int found;
};
@ -228,20 +228,18 @@ static int afs_dir_open(struct inode *inode, struct file *file)
/*
* deal with one block in an AFS directory
*/
static int afs_dir_iterate_block(unsigned *fpos,
static int afs_dir_iterate_block(struct dir_context *ctx,
union afs_dir_block *block,
unsigned blkoff,
void *cookie,
filldir_t filldir)
unsigned blkoff)
{
union afs_dirent *dire;
unsigned offset, next, curr;
size_t nlen;
int tmp, ret;
int tmp;
_enter("%u,%x,%p,,",*fpos,blkoff,block);
_enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block);
curr = (*fpos - blkoff) / sizeof(union afs_dirent);
curr = (ctx->pos - blkoff) / sizeof(union afs_dirent);
/* walk through the block, an entry at a time */
for (offset = AFS_DIRENT_PER_BLOCK - block->pagehdr.nentries;
@ -256,7 +254,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
_debug("ENT[%Zu.%u]: unused",
blkoff / sizeof(union afs_dir_block), offset);
if (offset >= curr)
*fpos = blkoff +
ctx->pos = blkoff +
next * sizeof(union afs_dirent);
continue;
}
@ -302,19 +300,15 @@ static int afs_dir_iterate_block(unsigned *fpos,
continue;
/* found the next entry */
ret = filldir(cookie,
dire->u.name,
nlen,
blkoff + offset * sizeof(union afs_dirent),
if (!dir_emit(ctx, dire->u.name, nlen,
ntohl(dire->u.vnode),
filldir == afs_lookup_filldir ?
ntohl(dire->u.unique) : DT_UNKNOWN);
if (ret < 0) {
ctx->actor == afs_lookup_filldir ?
ntohl(dire->u.unique) : DT_UNKNOWN)) {
_leave(" = 0 [full]");
return 0;
}
*fpos = blkoff + next * sizeof(union afs_dirent);
ctx->pos = blkoff + next * sizeof(union afs_dirent);
}
_leave(" = 1 [more]");
@ -324,8 +318,8 @@ static int afs_dir_iterate_block(unsigned *fpos,
/*
* iterate through the data blob that lists the contents of an AFS directory
*/
static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
filldir_t filldir, struct key *key)
static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
struct key *key)
{
union afs_dir_block *dblock;
struct afs_dir_page *dbuf;
@ -333,7 +327,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
unsigned blkoff, limit;
int ret;
_enter("{%lu},%u,,", dir->i_ino, *fpos);
_enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos);
if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
_leave(" = -ESTALE");
@ -341,13 +335,13 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
}
/* round the file position up to the next entry boundary */
*fpos += sizeof(union afs_dirent) - 1;
*fpos &= ~(sizeof(union afs_dirent) - 1);
ctx->pos += sizeof(union afs_dirent) - 1;
ctx->pos &= ~(sizeof(union afs_dirent) - 1);
/* walk through the blocks in sequence */
ret = 0;
while (*fpos < dir->i_size) {
blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1);
while (ctx->pos < dir->i_size) {
blkoff = ctx->pos & ~(sizeof(union afs_dir_block) - 1);
/* fetch the appropriate page from the directory */
page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key);
@ -364,8 +358,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
do {
dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
sizeof(union afs_dir_block)];
ret = afs_dir_iterate_block(fpos, dblock, blkoff,
cookie, filldir);
ret = afs_dir_iterate_block(ctx, dblock, blkoff);
if (ret != 1) {
afs_dir_put_page(page);
goto out;
@ -373,7 +366,7 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
blkoff += sizeof(union afs_dir_block);
} while (*fpos < dir->i_size && blkoff < limit);
} while (ctx->pos < dir->i_size && blkoff < limit);
afs_dir_put_page(page);
ret = 0;
@ -387,23 +380,10 @@ static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
/*
* read an AFS directory
*/
static int afs_readdir(struct file *file, void *cookie, filldir_t filldir)
static int afs_readdir(struct file *file, struct dir_context *ctx)
{
unsigned fpos;
int ret;
_enter("{%Ld,{%lu}}",
file->f_pos, file_inode(file)->i_ino);
ASSERT(file->private_data != NULL);
fpos = file->f_pos;
ret = afs_dir_iterate(file_inode(file), &fpos,
cookie, filldir, file->private_data);
file->f_pos = fpos;
_leave(" = %d", ret);
return ret;
return afs_dir_iterate(file_inode(file),
ctx, file->private_data);
}
/*
@ -416,15 +396,16 @@ static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
{
struct afs_lookup_cookie *cookie = _cookie;
_enter("{%s,%Zu},%s,%u,,%llu,%u",
cookie->name, cookie->nlen, name, nlen,
_enter("{%s,%u},%s,%u,,%llu,%u",
cookie->name.name, cookie->name.len, name, nlen,
(unsigned long long) ino, dtype);
/* insanity checks first */
BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) {
if (cookie->name.len != nlen ||
memcmp(cookie->name.name, name, nlen) != 0) {
_leave(" = 0 [no]");
return 0;
}
@ -444,24 +425,18 @@ static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
struct afs_fid *fid, struct key *key)
{
struct afs_lookup_cookie cookie;
struct afs_super_info *as;
unsigned fpos;
struct afs_super_info *as = dir->i_sb->s_fs_info;
struct afs_lookup_cookie cookie = {
.ctx.actor = afs_lookup_filldir,
.name = dentry->d_name,
.fid.vid = as->volume->vid
};
int ret;
_enter("{%lu},%p{%s},", dir->i_ino, dentry, dentry->d_name.name);
as = dir->i_sb->s_fs_info;
/* search the directory */
cookie.name = dentry->d_name.name;
cookie.nlen = dentry->d_name.len;
cookie.fid.vid = as->volume->vid;
cookie.found = 0;
fpos = 0;
ret = afs_dir_iterate(dir, &fpos, &cookie, afs_lookup_filldir,
key);
ret = afs_dir_iterate(dir, &cookie.ctx, key);
if (ret < 0) {
_leave(" = %d [iter]", ret);
return ret;

View File

@ -41,7 +41,7 @@ const struct file_operations autofs4_root_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.read = generic_read_dir,
.readdir = dcache_readdir,
.iterate = dcache_readdir,
.llseek = dcache_dir_lseek,
.unlocked_ioctl = autofs4_root_ioctl,
#ifdef CONFIG_COMPAT
@ -53,7 +53,7 @@ const struct file_operations autofs4_dir_operations = {
.open = autofs4_dir_open,
.release = dcache_dir_close,
.read = generic_read_dir,
.readdir = dcache_readdir,
.iterate = dcache_readdir,
.llseek = dcache_dir_lseek,
};

View File

@ -45,7 +45,7 @@ static ssize_t bad_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
return -EIO;
}
static int bad_file_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int bad_file_readdir(struct file *file, struct dir_context *ctx)
{
return -EIO;
}
@ -152,7 +152,7 @@ static const struct file_operations bad_file_ops =
.write = bad_file_write,
.aio_read = bad_file_aio_read,
.aio_write = bad_file_aio_write,
.readdir = bad_file_readdir,
.iterate = bad_file_readdir,
.poll = bad_file_poll,
.unlocked_ioctl = bad_file_unlocked_ioctl,
.compat_ioctl = bad_file_compat_ioctl,

View File

@ -31,7 +31,7 @@ MODULE_LICENSE("GPL");
/* The units the vfs expects inode->i_blocks to be in */
#define VFS_BLOCK_SIZE 512
static int befs_readdir(struct file *, void *, filldir_t);
static int befs_readdir(struct file *, struct dir_context *);
static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
static int befs_readpage(struct file *file, struct page *page);
static sector_t befs_bmap(struct address_space *mapping, sector_t block);
@ -66,7 +66,7 @@ static struct kmem_cache *befs_inode_cachep;
static const struct file_operations befs_dir_operations = {
.read = generic_read_dir,
.readdir = befs_readdir,
.iterate = befs_readdir,
.llseek = generic_file_llseek,
};
@ -211,9 +211,9 @@ befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
}
static int
befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
befs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
befs_off_t value;
@ -221,15 +221,14 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
size_t keysize;
unsigned char d_type;
char keybuf[BEFS_NAME_LEN + 1];
char *nlsname;
int nlsnamelen;
const char *dirname = filp->f_path.dentry->d_name.name;
const char *dirname = file->f_path.dentry->d_name.name;
befs_debug(sb, "---> befs_readdir() "
"name %s, inode %ld, filp->f_pos %Ld",
dirname, inode->i_ino, filp->f_pos);
"name %s, inode %ld, ctx->pos %Ld",
dirname, inode->i_ino, ctx->pos);
result = befs_btree_read(sb, ds, filp->f_pos, BEFS_NAME_LEN + 1,
more:
result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1,
keybuf, &keysize, &value);
if (result == BEFS_ERR) {
@ -251,24 +250,29 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Convert to NLS */
if (BEFS_SB(sb)->nls) {
char *nlsname;
int nlsnamelen;
result =
befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen);
if (result < 0) {
befs_debug(sb, "<--- befs_readdir() ERROR");
return result;
}
result = filldir(dirent, nlsname, nlsnamelen, filp->f_pos,
(ino_t) value, d_type);
if (!dir_emit(ctx, nlsname, nlsnamelen,
(ino_t) value, d_type)) {
kfree(nlsname);
return 0;
}
kfree(nlsname);
} else {
result = filldir(dirent, keybuf, keysize, filp->f_pos,
(ino_t) value, d_type);
if (!dir_emit(ctx, keybuf, keysize,
(ino_t) value, d_type))
return 0;
}
if (!result)
filp->f_pos++;
ctx->pos++;
goto more;
befs_debug(sb, "<--- befs_readdir() filp->f_pos %Ld", filp->f_pos);
befs_debug(sb, "<--- befs_readdir() pos %Ld", ctx->pos);
return 0;
}

View File

@ -26,58 +26,51 @@ static struct buffer_head *bfs_find_entry(struct inode *dir,
const unsigned char *name, int namelen,
struct bfs_dirent **res_dir);
static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
static int bfs_readdir(struct file *f, struct dir_context *ctx)
{
struct inode *dir = file_inode(f);
struct buffer_head *bh;
struct bfs_dirent *de;
struct bfs_sb_info *info = BFS_SB(dir->i_sb);
unsigned int offset;
int block;
mutex_lock(&info->bfs_lock);
if (f->f_pos & (BFS_DIRENT_SIZE - 1)) {
if (ctx->pos & (BFS_DIRENT_SIZE - 1)) {
printf("Bad f_pos=%08lx for %s:%08lx\n",
(unsigned long)f->f_pos,
(unsigned long)ctx->pos,
dir->i_sb->s_id, dir->i_ino);
mutex_unlock(&info->bfs_lock);
return -EBADF;
return -EINVAL;
}
while (f->f_pos < dir->i_size) {
offset = f->f_pos & (BFS_BSIZE - 1);
block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS);
while (ctx->pos < dir->i_size) {
offset = ctx->pos & (BFS_BSIZE - 1);
block = BFS_I(dir)->i_sblock + (ctx->pos >> BFS_BSIZE_BITS);
bh = sb_bread(dir->i_sb, block);
if (!bh) {
f->f_pos += BFS_BSIZE - offset;
ctx->pos += BFS_BSIZE - offset;
continue;
}
do {
de = (struct bfs_dirent *)(bh->b_data + offset);
if (de->ino) {
int size = strnlen(de->name, BFS_NAMELEN);
if (filldir(dirent, de->name, size, f->f_pos,
if (!dir_emit(ctx, de->name, size,
le16_to_cpu(de->ino),
DT_UNKNOWN) < 0) {
DT_UNKNOWN)) {
brelse(bh);
mutex_unlock(&info->bfs_lock);
return 0;
}
}
offset += BFS_DIRENT_SIZE;
f->f_pos += BFS_DIRENT_SIZE;
} while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size));
ctx->pos += BFS_DIRENT_SIZE;
} while ((offset < BFS_BSIZE) && (ctx->pos < dir->i_size));
brelse(bh);
}
mutex_unlock(&info->bfs_lock);
return 0;
return 0;
}
const struct file_operations bfs_dir_operations = {
.read = generic_read_dir,
.readdir = bfs_readdir,
.iterate = bfs_readdir,
.fsync = generic_file_fsync,
.llseek = generic_file_llseek,
};

View File

@ -1681,8 +1681,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list,
* btrfs_readdir_delayed_dir_index - read dir info stored in the delayed tree
*
*/
int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
filldir_t filldir,
int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
struct list_head *ins_list)
{
struct btrfs_dir_item *di;
@ -1704,13 +1703,13 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
list_for_each_entry_safe(curr, next, ins_list, readdir_list) {
list_del(&curr->readdir_list);
if (curr->key.offset < filp->f_pos) {
if (curr->key.offset < ctx->pos) {
if (atomic_dec_and_test(&curr->refs))
kfree(curr);
continue;
}
filp->f_pos = curr->key.offset;
ctx->pos = curr->key.offset;
di = (struct btrfs_dir_item *)curr->data;
name = (char *)(di + 1);
@ -1719,7 +1718,7 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
d_type = btrfs_filetype_table[di->type];
btrfs_disk_key_to_cpu(&location, &di->location);
over = filldir(dirent, name, name_len, curr->key.offset,
over = !dir_emit(ctx, name, name_len,
location.objectid, d_type);
if (atomic_dec_and_test(&curr->refs))

View File

@ -139,8 +139,7 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
struct list_head *del_list);
int btrfs_should_delete_dir_index(struct list_head *del_list,
u64 index);
int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
filldir_t filldir,
int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
struct list_head *ins_list);
/* for init */

View File

@ -5137,10 +5137,9 @@ unsigned char btrfs_filetype_table[] = {
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
};
static int btrfs_real_readdir(struct file *filp, void *dirent,
filldir_t filldir)
static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_item *item;
struct btrfs_dir_item *di;
@ -5161,29 +5160,15 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
char tmp_name[32];
char *name_ptr;
int name_len;
int is_curr = 0; /* filp->f_pos points to the current index? */
int is_curr = 0; /* ctx->pos points to the current index? */
/* FIXME, use a real flag for deciding about the key type */
if (root->fs_info->tree_root == root)
key_type = BTRFS_DIR_ITEM_KEY;
/* special case for "." */
if (filp->f_pos == 0) {
over = filldir(dirent, ".", 1,
filp->f_pos, btrfs_ino(inode), DT_DIR);
if (over)
return 0;
filp->f_pos = 1;
}
/* special case for .., just use the back ref */
if (filp->f_pos == 1) {
u64 pino = parent_ino(filp->f_path.dentry);
over = filldir(dirent, "..", 2,
filp->f_pos, pino, DT_DIR);
if (over)
return 0;
filp->f_pos = 2;
}
if (!dir_emit_dots(file, ctx))
return 0;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
@ -5197,7 +5182,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
}
btrfs_set_key_type(&key, key_type);
key.offset = filp->f_pos;
key.offset = ctx->pos;
key.objectid = btrfs_ino(inode);
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
@ -5223,14 +5208,14 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
break;
if (btrfs_key_type(&found_key) != key_type)
break;
if (found_key.offset < filp->f_pos)
if (found_key.offset < ctx->pos)
goto next;
if (key_type == BTRFS_DIR_INDEX_KEY &&
btrfs_should_delete_dir_index(&del_list,
found_key.offset))
goto next;
filp->f_pos = found_key.offset;
ctx->pos = found_key.offset;
is_curr = 1;
di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
@ -5274,9 +5259,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
over = 0;
goto skip;
}
over = filldir(dirent, name_ptr, name_len,
found_key.offset, location.objectid,
d_type);
over = !dir_emit(ctx, name_ptr, name_len,
location.objectid, d_type);
skip:
if (name_ptr != tmp_name)
@ -5295,9 +5279,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
if (key_type == BTRFS_DIR_INDEX_KEY) {
if (is_curr)
filp->f_pos++;
ret = btrfs_readdir_delayed_dir_index(filp, dirent, filldir,
&ins_list);
ctx->pos++;
ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
if (ret)
goto nopos;
}
@ -5308,9 +5291,9 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
* 32-bit glibc will use getdents64, but then strtol -
* so the last number we can serve is this.
*/
filp->f_pos = 0x7fffffff;
ctx->pos = 0x7fffffff;
else
filp->f_pos++;
ctx->pos++;
nopos:
ret = 0;
err:
@ -8731,7 +8714,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = {
static const struct file_operations btrfs_dir_file_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = btrfs_real_readdir,
.iterate = btrfs_real_readdir,
.unlocked_ioctl = btrfs_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = btrfs_ioctl,

View File

@ -111,11 +111,10 @@ static unsigned fpos_off(loff_t p)
* defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by
* the MDS if/when the directory is modified).
*/
static int __dcache_readdir(struct file *filp,
void *dirent, filldir_t filldir)
static int __dcache_readdir(struct file *file, struct dir_context *ctx)
{
struct ceph_file_info *fi = filp->private_data;
struct dentry *parent = filp->f_dentry;
struct ceph_file_info *fi = file->private_data;
struct dentry *parent = file->f_dentry;
struct inode *dir = parent->d_inode;
struct list_head *p;
struct dentry *dentry, *last;
@ -126,14 +125,14 @@ static int __dcache_readdir(struct file *filp,
last = fi->dentry;
fi->dentry = NULL;
dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos,
dout("__dcache_readdir %p at %llu (last %p)\n", dir, ctx->pos,
last);
spin_lock(&parent->d_lock);
/* start at beginning? */
if (filp->f_pos == 2 || last == NULL ||
filp->f_pos < ceph_dentry(last)->offset) {
if (ctx->pos == 2 || last == NULL ||
ctx->pos < ceph_dentry(last)->offset) {
if (list_empty(&parent->d_subdirs))
goto out_unlock;
p = parent->d_subdirs.prev;
@ -157,11 +156,11 @@ static int __dcache_readdir(struct file *filp,
if (!d_unhashed(dentry) && dentry->d_inode &&
ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
filp->f_pos <= di->offset)
ctx->pos <= di->offset)
break;
dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry,
dentry->d_name.len, dentry->d_name.name, di->offset,
filp->f_pos, d_unhashed(dentry) ? " unhashed" : "",
ctx->pos, d_unhashed(dentry) ? " unhashed" : "",
!dentry->d_inode ? " null" : "");
spin_unlock(&dentry->d_lock);
p = p->prev;
@ -173,29 +172,27 @@ static int __dcache_readdir(struct file *filp,
spin_unlock(&dentry->d_lock);
spin_unlock(&parent->d_lock);
dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos,
dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, ctx->pos,
dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
filp->f_pos = di->offset;
err = filldir(dirent, dentry->d_name.name,
dentry->d_name.len, di->offset,
ctx->pos = di->offset;
if (!dir_emit(ctx, dentry->d_name.name,
dentry->d_name.len,
ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino),
dentry->d_inode->i_mode >> 12);
if (last) {
if (err < 0) {
dentry->d_inode->i_mode >> 12)) {
if (last) {
/* remember our position */
fi->dentry = last;
fi->next_offset = di->offset;
} else {
dput(last);
}
dput(dentry);
return 0;
}
if (last)
dput(last);
last = dentry;
if (err < 0)
goto out;
filp->f_pos++;
ctx->pos++;
/* make sure a dentry wasn't dropped while we didn't have parent lock */
if (!ceph_dir_is_complete(dir)) {
@ -235,59 +232,59 @@ static int note_last_dentry(struct ceph_file_info *fi, const char *name,
return 0;
}
static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int ceph_readdir(struct file *file, struct dir_context *ctx)
{
struct ceph_file_info *fi = filp->private_data;
struct inode *inode = file_inode(filp);
struct ceph_file_info *fi = file->private_data;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
struct ceph_mds_client *mdsc = fsc->mdsc;
unsigned frag = fpos_frag(filp->f_pos);
int off = fpos_off(filp->f_pos);
unsigned frag = fpos_frag(ctx->pos);
int off = fpos_off(ctx->pos);
int err;
u32 ftype;
struct ceph_mds_reply_info_parsed *rinfo;
const int max_entries = fsc->mount_options->max_readdir;
const int max_bytes = fsc->mount_options->max_readdir_bytes;
dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off);
dout("readdir %p file %p frag %u off %u\n", inode, file, frag, off);
if (fi->flags & CEPH_F_ATEND)
return 0;
/* always start with . and .. */
if (filp->f_pos == 0) {
if (ctx->pos == 0) {
/* note dir version at start of readdir so we can tell
* if any dentries get dropped */
fi->dir_release_count = atomic_read(&ci->i_release_count);
dout("readdir off 0 -> '.'\n");
if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0),
if (!dir_emit(ctx, ".", 1,
ceph_translate_ino(inode->i_sb, inode->i_ino),
inode->i_mode >> 12) < 0)
inode->i_mode >> 12))
return 0;
filp->f_pos = 1;
ctx->pos = 1;
off = 1;
}
if (filp->f_pos == 1) {
ino_t ino = parent_ino(filp->f_dentry);
if (ctx->pos == 1) {
ino_t ino = parent_ino(file->f_dentry);
dout("readdir off 1 -> '..'\n");
if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1),
if (!dir_emit(ctx, "..", 2,
ceph_translate_ino(inode->i_sb, ino),
inode->i_mode >> 12) < 0)
inode->i_mode >> 12))
return 0;
filp->f_pos = 2;
ctx->pos = 2;
off = 2;
}
/* can we use the dcache? */
spin_lock(&ci->i_ceph_lock);
if ((filp->f_pos == 2 || fi->dentry) &&
if ((ctx->pos == 2 || fi->dentry) &&
!ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
ceph_snap(inode) != CEPH_SNAPDIR &&
__ceph_dir_is_complete(ci) &&
__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) {
spin_unlock(&ci->i_ceph_lock);
err = __dcache_readdir(filp, dirent, filldir);
err = __dcache_readdir(file, ctx);
if (err != -EAGAIN)
return err;
} else {
@ -327,7 +324,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
return PTR_ERR(req);
req->r_inode = inode;
ihold(inode);
req->r_dentry = dget(filp->f_dentry);
req->r_dentry = dget(file->f_dentry);
/* hints to request -> mds selection code */
req->r_direct_mode = USE_AUTH_MDS;
req->r_direct_hash = ceph_frag_value(frag);
@ -379,15 +376,16 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
rinfo = &fi->last_readdir->r_reply_info;
dout("readdir frag %x num %d off %d chunkoff %d\n", frag,
rinfo->dir_nr, off, fi->offset);
ctx->pos = ceph_make_fpos(frag, off);
while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) {
u64 pos = ceph_make_fpos(frag, off);
struct ceph_mds_reply_inode *in =
rinfo->dir_in[off - fi->offset].in;
struct ceph_vino vino;
ino_t ino;
dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n",
off, off - fi->offset, rinfo->dir_nr, pos,
off, off - fi->offset, rinfo->dir_nr, ctx->pos,
rinfo->dir_dname_len[off - fi->offset],
rinfo->dir_dname[off - fi->offset], in);
BUG_ON(!in);
@ -395,16 +393,15 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
vino.ino = le64_to_cpu(in->ino);
vino.snap = le64_to_cpu(in->snapid);
ino = ceph_vino_to_ino(vino);
if (filldir(dirent,
if (!dir_emit(ctx,
rinfo->dir_dname[off - fi->offset],
rinfo->dir_dname_len[off - fi->offset],
pos,
ceph_translate_ino(inode->i_sb, ino), ftype) < 0) {
ceph_translate_ino(inode->i_sb, ino), ftype)) {
dout("filldir stopping us...\n");
return 0;
}
off++;
filp->f_pos = pos + 1;
ctx->pos++;
}
if (fi->last_name) {
@ -417,7 +414,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (!ceph_frag_is_rightmost(frag)) {
frag = ceph_frag_next(frag);
off = 0;
filp->f_pos = ceph_make_fpos(frag, off);
ctx->pos = ceph_make_fpos(frag, off);
dout("readdir next frag is %x\n", frag);
goto more;
}
@ -432,11 +429,11 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (atomic_read(&ci->i_release_count) == fi->dir_release_count) {
dout(" marking %p complete\n", inode);
__ceph_dir_set_complete(ci, fi->dir_release_count);
ci->i_max_offset = filp->f_pos;
ci->i_max_offset = ctx->pos;
}
spin_unlock(&ci->i_ceph_lock);
dout("readdir %p filp %p done.\n", inode, filp);
dout("readdir %p file %p done.\n", inode, file);
return 0;
}
@ -1268,7 +1265,7 @@ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
const struct file_operations ceph_dir_fops = {
.read = ceph_read_dir,
.readdir = ceph_readdir,
.iterate = ceph_readdir,
.llseek = ceph_dir_llseek,
.open = ceph_open,
.release = ceph_release,

View File

@ -968,7 +968,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
};
const struct file_operations cifs_dir_ops = {
.readdir = cifs_readdir,
.iterate = cifs_readdir,
.release = cifs_closedir,
.read = generic_read_dir,
.unlocked_ioctl = cifs_ioctl,

View File

@ -101,7 +101,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
extern const struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file);
extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
extern int cifs_readdir(struct file *file, struct dir_context *ctx);
/* Functions related to dir entries */
extern const struct dentry_operations cifs_dentry_ops;

View File

@ -537,14 +537,14 @@ static int cifs_save_resume_key(const char *current_entry,
* every entry (do not increment for . or .. entry).
*/
static int
find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
struct file *file, char **current_entry, int *num_to_ret)
{
__u16 search_flags;
int rc = 0;
int pos_in_buf = 0;
loff_t first_entry_in_buffer;
loff_t index_to_find = file->f_pos;
loff_t index_to_find = pos;
struct cifsFileInfo *cfile = file->private_data;
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
struct TCP_Server_Info *server = tcon->ses->server;
@ -659,8 +659,9 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
return rc;
}
static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
void *dirent, char *scratch_buf, unsigned int max_len)
static int cifs_filldir(char *find_entry, struct file *file,
struct dir_context *ctx,
char *scratch_buf, unsigned int max_len)
{
struct cifsFileInfo *file_info = file->private_data;
struct super_block *sb = file->f_path.dentry->d_sb;
@ -740,13 +741,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
cifs_prime_dcache(file->f_dentry, &name, &fattr);
ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
fattr.cf_dtype);
return rc;
return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
}
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
int cifs_readdir(struct file *file, struct dir_context *ctx)
{
int rc = 0;
unsigned int xid;
@ -772,103 +771,86 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
goto rddir2_exit;
}
switch ((int) file->f_pos) {
case 0:
if (filldir(direntry, ".", 1, file->f_pos,
file_inode(file)->i_ino, DT_DIR) < 0) {
cifs_dbg(VFS, "Filldir for current dir failed\n");
rc = -ENOMEM;
if (!dir_emit_dots(file, ctx))
goto rddir2_exit;
/* 1) If search is active,
is in current search buffer?
if it before then restart search
if after then keep searching till find it */
if (file->private_data == NULL) {
rc = -EINVAL;
goto rddir2_exit;
}
cifsFile = file->private_data;
if (cifsFile->srch_inf.endOfSearch) {
if (cifsFile->srch_inf.emptyDir) {
cifs_dbg(FYI, "End of search, empty dir\n");
rc = 0;
goto rddir2_exit;
}
} /* else {
cifsFile->invalidHandle = true;
tcon->ses->server->close(xid, tcon, &cifsFile->fid);
} */
tcon = tlink_tcon(cifsFile->tlink);
rc = find_cifs_entry(xid, tcon, ctx->pos, file, &current_entry,
&num_to_fill);
if (rc) {
cifs_dbg(FYI, "fce error %d\n", rc);
goto rddir2_exit;
} else if (current_entry != NULL) {
cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
} else {
cifs_dbg(FYI, "could not find entry\n");
goto rddir2_exit;
}
cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
max_len = tcon->ses->server->ops->calc_smb_size(
cifsFile->srch_inf.ntwrk_buf_start);
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
if (tmp_buf == NULL) {
rc = -ENOMEM;
goto rddir2_exit;
}
for (i = 0; i < num_to_fill; i++) {
if (current_entry == NULL) {
/* evaluate whether this case is an error */
cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
num_to_fill, i);
break;
}
file->f_pos++;
case 1:
if (filldir(direntry, "..", 2, file->f_pos,
parent_ino(file->f_path.dentry), DT_DIR) < 0) {
cifs_dbg(VFS, "Filldir for parent dir failed\n");
rc = -ENOMEM;
break;
}
file->f_pos++;
default:
/* 1) If search is active,
is in current search buffer?
if it before then restart search
if after then keep searching till find it */
if (file->private_data == NULL) {
rc = -EINVAL;
free_xid(xid);
return rc;
}
cifsFile = file->private_data;
if (cifsFile->srch_inf.endOfSearch) {
if (cifsFile->srch_inf.emptyDir) {
cifs_dbg(FYI, "End of search, empty dir\n");
rc = 0;
break;
}
} /* else {
cifsFile->invalidHandle = true;
tcon->ses->server->close(xid, tcon, &cifsFile->fid);
} */
tcon = tlink_tcon(cifsFile->tlink);
rc = find_cifs_entry(xid, tcon, file, &current_entry,
&num_to_fill);
/*
* if buggy server returns . and .. late do we want to
* check for that here?
*/
rc = cifs_filldir(current_entry, file, ctx,
tmp_buf, max_len);
if (rc) {
cifs_dbg(FYI, "fce error %d\n", rc);
goto rddir2_exit;
} else if (current_entry != NULL) {
cifs_dbg(FYI, "entry %lld found\n", file->f_pos);
} else {
cifs_dbg(FYI, "could not find entry\n");
goto rddir2_exit;
}
cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
max_len = tcon->ses->server->ops->calc_smb_size(
cifsFile->srch_inf.ntwrk_buf_start);
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
if (tmp_buf == NULL) {
rc = -ENOMEM;
if (rc > 0)
rc = 0;
break;
}
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if (current_entry == NULL) {
/* evaluate whether this case is an error */
cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
num_to_fill, i);
break;
}
/*
* if buggy server returns . and .. late do we want to
* check for that here?
*/
rc = cifs_filldir(current_entry, file, filldir,
direntry, tmp_buf, max_len);
if (rc == -EOVERFLOW) {
rc = 0;
break;
}
file->f_pos++;
if (file->f_pos ==
cifsFile->srch_inf.index_of_last_entry) {
cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
file->f_pos, tmp_buf);
cifs_save_resume_key(current_entry, cifsFile);
break;
} else
current_entry =
nxt_dir_entry(current_entry, end_of_smb,
cifsFile->srch_inf.info_level);
}
kfree(tmp_buf);
break;
} /* end switch */
ctx->pos++;
if (ctx->pos ==
cifsFile->srch_inf.index_of_last_entry) {
cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
ctx->pos, tmp_buf);
cifs_save_resume_key(current_entry, cifsFile);
break;
} else
current_entry =
nxt_dir_entry(current_entry, end_of_smb,
cifsFile->srch_inf.info_level);
}
kfree(tmp_buf);
rddir2_exit:
free_xid(xid);

View File

@ -43,15 +43,14 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry);
/* dir file-ops */
static int coda_readdir(struct file *file, void *buf, filldir_t filldir);
static int coda_readdir(struct file *file, struct dir_context *ctx);
/* dentry ops */
static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
static int coda_dentry_delete(const struct dentry *);
/* support routines */
static int coda_venus_readdir(struct file *coda_file, void *buf,
filldir_t filldir);
static int coda_venus_readdir(struct file *, struct dir_context *);
/* same as fs/bad_inode.c */
static int coda_return_EIO(void)
@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations =
const struct file_operations coda_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = coda_readdir,
.iterate = coda_readdir,
.open = coda_open,
.release = coda_release,
.fsync = coda_fsync,
@ -378,7 +377,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
/* file operations for directories */
static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
{
struct coda_file_info *cfi;
struct file *host_file;
@ -391,30 +390,19 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
if (!host_file->f_op)
return -ENOTDIR;
if (host_file->f_op->readdir)
{
/* potemkin case: we were handed a directory inode.
* We can't use vfs_readdir because we have to keep the file
* position in sync between the coda_file and the host_file.
* and as such we need grab the inode mutex. */
if (host_file->f_op->iterate) {
struct inode *host_inode = file_inode(host_file);
mutex_lock(&host_inode->i_mutex);
host_file->f_pos = coda_file->f_pos;
ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) {
ret = host_file->f_op->readdir(host_file, buf, filldir);
ret = host_file->f_op->iterate(host_file, ctx);
file_accessed(host_file);
}
coda_file->f_pos = host_file->f_pos;
mutex_unlock(&host_inode->i_mutex);
return ret;
}
else /* Venus: we must read Venus dirents from a file */
ret = coda_venus_readdir(coda_file, buf, filldir);
return ret;
/* Venus: we must read Venus dirents from a file */
return coda_venus_readdir(coda_file, ctx);
}
static inline unsigned int CDT2DT(unsigned char cdt)
@ -437,10 +425,8 @@ static inline unsigned int CDT2DT(unsigned char cdt)
}
/* support routines */
static int coda_venus_readdir(struct file *coda_file, void *buf,
filldir_t filldir)
static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
{
int result = 0; /* # of entries returned */
struct coda_file_info *cfi;
struct coda_inode_info *cii;
struct file *host_file;
@ -462,23 +448,12 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
if (!vdir) return -ENOMEM;
if (coda_file->f_pos == 0) {
ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR);
if (ret < 0)
goto out;
result++;
coda_file->f_pos++;
}
if (coda_file->f_pos == 1) {
ret = filldir(buf, "..", 2, 1, parent_ino(de), DT_DIR);
if (ret < 0)
goto out;
result++;
coda_file->f_pos++;
}
if (!dir_emit_dots(coda_file, ctx))
goto out;
while (1) {
/* read entries from the directory file */
ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir,
ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir,
sizeof(*vdir));
if (ret < 0) {
printk(KERN_ERR "coda readdir: read dir %s failed %d\n",
@ -507,7 +482,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
/* Make sure we skip '.' and '..', we already got those */
if (name.name[0] == '.' && (name.len == 1 ||
(vdir->d_name[1] == '.' && name.len == 2)))
(name.name[1] == '.' && name.len == 2)))
vdir->d_fileno = name.len = 0;
/* skip null entries */
@ -520,19 +495,16 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
if (!ino) ino = vdir->d_fileno;
type = CDT2DT(vdir->d_type);
ret = filldir(buf, name.name, name.len,
coda_file->f_pos, ino, type);
/* failure means no space for filling in this round */
if (ret < 0) break;
result++;
if (!dir_emit(ctx, name.name, name.len, ino, type))
break;
}
/* we'll always have progress because d_reclen is unsigned and
* we've already established it is non-zero. */
coda_file->f_pos += vdir->d_reclen;
ctx->pos += vdir->d_reclen;
}
out:
kfree(vdir);
return result ? result : ret;
return 0;
}
/* called when a cache lookup succeeds */

View File

@ -832,6 +832,7 @@ struct compat_old_linux_dirent {
};
struct compat_readdir_callback {
struct dir_context ctx;
struct compat_old_linux_dirent __user *dirent;
int result;
};
@ -873,15 +874,15 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
{
int error;
struct fd f = fdget(fd);
struct compat_readdir_callback buf;
struct compat_readdir_callback buf = {
.ctx.actor = compat_fillonedir,
.dirent = dirent
};
if (!f.file)
return -EBADF;
buf.result = 0;
buf.dirent = dirent;
error = vfs_readdir(f.file, compat_fillonedir, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (buf.result)
error = buf.result;
@ -897,6 +898,7 @@ struct compat_linux_dirent {
};
struct compat_getdents_callback {
struct dir_context ctx;
struct compat_linux_dirent __user *current_dir;
struct compat_linux_dirent __user *previous;
int count;
@ -951,7 +953,11 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
{
struct fd f;
struct compat_linux_dirent __user * lastdirent;
struct compat_getdents_callback buf;
struct compat_getdents_callback buf = {
.ctx.actor = compat_filldir,
.current_dir = dirent,
.count = count
};
int error;
if (!access_ok(VERIFY_WRITE, dirent, count))
@ -961,17 +967,12 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
if (!f.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(f.file, compat_filldir, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
if (put_user(f.file->f_pos, &lastdirent->d_off))
if (put_user(buf.ctx.pos, &lastdirent->d_off))
error = -EFAULT;
else
error = count - buf.count;
@ -983,6 +984,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64
struct compat_getdents_callback64 {
struct dir_context ctx;
struct linux_dirent64 __user *current_dir;
struct linux_dirent64 __user *previous;
int count;
@ -1036,7 +1038,11 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
{
struct fd f;
struct linux_dirent64 __user * lastdirent;
struct compat_getdents_callback64 buf;
struct compat_getdents_callback64 buf = {
.ctx.actor = compat_filldir64,
.current_dir = dirent,
.count = count
};
int error;
if (!access_ok(VERIFY_WRITE, dirent, count))
@ -1046,17 +1052,12 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
if (!f.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(f.file, compat_filldir64, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
typeof(lastdirent->d_off) d_off = f.file->f_pos;
typeof(lastdirent->d_off) d_off = buf.ctx.pos;
if (__put_user_unaligned(d_off, &lastdirent->d_off))
error = -EFAULT;
else

View File

@ -66,7 +66,6 @@
#include <linux/gigaset_dev.h>
#ifdef CONFIG_BLOCK
#include <linux/loop.h>
#include <linux/cdrom.h>
#include <linux/fd.h>
#include <scsi/scsi.h>
@ -954,8 +953,6 @@ COMPATIBLE_IOCTL(MTIOCTOP)
/* Socket level stuff */
COMPATIBLE_IOCTL(FIOQSIZE)
#ifdef CONFIG_BLOCK
/* loop */
IGNORE_IOCTL(LOOP_CLR_FD)
/* md calls this on random blockdevs */
IGNORE_IOCTL(RAID_VERSION)
/* qemu/qemu-img might call these two on plain files for probing */

View File

@ -1532,84 +1532,66 @@ static inline unsigned char dt_type(struct configfs_dirent *sd)
return (sd->s_mode >> 12) & 15;
}
static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
static int configfs_readdir(struct file *file, struct dir_context *ctx)
{
struct dentry *dentry = filp->f_path.dentry;
struct dentry *dentry = file->f_path.dentry;
struct super_block *sb = dentry->d_sb;
struct configfs_dirent * parent_sd = dentry->d_fsdata;
struct configfs_dirent *cursor = filp->private_data;
struct configfs_dirent *cursor = file->private_data;
struct list_head *p, *q = &cursor->s_sibling;
ino_t ino = 0;
int i = filp->f_pos;
switch (i) {
case 0:
ino = dentry->d_inode->i_ino;
if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
break;
filp->f_pos++;
i++;
/* fallthrough */
case 1:
ino = parent_ino(dentry);
if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
break;
filp->f_pos++;
i++;
/* fallthrough */
default:
if (filp->f_pos == 2) {
spin_lock(&configfs_dirent_lock);
list_move(q, &parent_sd->s_children);
spin_unlock(&configfs_dirent_lock);
}
for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
struct configfs_dirent *next;
const char * name;
int len;
struct inode *inode = NULL;
if (!dir_emit_dots(file, ctx))
return 0;
if (ctx->pos == 2) {
spin_lock(&configfs_dirent_lock);
list_move(q, &parent_sd->s_children);
spin_unlock(&configfs_dirent_lock);
}
for (p = q->next; p != &parent_sd->s_children; p = p->next) {
struct configfs_dirent *next;
const char *name;
int len;
struct inode *inode = NULL;
next = list_entry(p, struct configfs_dirent,
s_sibling);
if (!next->s_element)
continue;
next = list_entry(p, struct configfs_dirent, s_sibling);
if (!next->s_element)
continue;
name = configfs_get_name(next);
len = strlen(name);
name = configfs_get_name(next);
len = strlen(name);
/*
* We'll have a dentry and an inode for
* PINNED items and for open attribute
* files. We lock here to prevent a race
* with configfs_d_iput() clearing
* s_dentry before calling iput().
*
* Why do we go to the trouble? If
* someone has an attribute file open,
* the inode number should match until
* they close it. Beyond that, we don't
* care.
*/
spin_lock(&configfs_dirent_lock);
dentry = next->s_dentry;
if (dentry)
inode = dentry->d_inode;
if (inode)
ino = inode->i_ino;
spin_unlock(&configfs_dirent_lock);
if (!inode)
ino = iunique(sb, 2);
/*
* We'll have a dentry and an inode for
* PINNED items and for open attribute
* files. We lock here to prevent a race
* with configfs_d_iput() clearing
* s_dentry before calling iput().
*
* Why do we go to the trouble? If
* someone has an attribute file open,
* the inode number should match until
* they close it. Beyond that, we don't
* care.
*/
spin_lock(&configfs_dirent_lock);
dentry = next->s_dentry;
if (dentry)
inode = dentry->d_inode;
if (inode)
ino = inode->i_ino;
spin_unlock(&configfs_dirent_lock);
if (!inode)
ino = iunique(sb, 2);
if (filldir(dirent, name, len, filp->f_pos, ino,
dt_type(next)) < 0)
return 0;
if (!dir_emit(ctx, name, len, ino, dt_type(next)))
return 0;
spin_lock(&configfs_dirent_lock);
list_move(q, p);
spin_unlock(&configfs_dirent_lock);
p = q;
filp->f_pos++;
}
spin_lock(&configfs_dirent_lock);
list_move(q, p);
spin_unlock(&configfs_dirent_lock);
p = q;
ctx->pos++;
}
return 0;
}
@ -1661,7 +1643,7 @@ const struct file_operations configfs_dir_operations = {
.release = configfs_dir_close,
.llseek = configfs_dir_lseek,
.read = generic_read_dir,
.readdir = configfs_readdir,
.iterate = configfs_readdir,
};
int configfs_register_subsystem(struct configfs_subsystem *subsys)

View File

@ -349,18 +349,17 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
/*
* Read a cramfs directory entry.
*/
static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int cramfs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
char *buf;
unsigned int offset;
int copied;
/* Offset within the thing. */
offset = filp->f_pos;
if (offset >= inode->i_size)
if (ctx->pos >= inode->i_size)
return 0;
offset = ctx->pos;
/* Directory entries are always 4-byte aligned */
if (offset & 3)
return -EINVAL;
@ -369,14 +368,13 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (!buf)
return -ENOMEM;
copied = 0;
while (offset < inode->i_size) {
struct cramfs_inode *de;
unsigned long nextoffset;
char *name;
ino_t ino;
umode_t mode;
int namelen, error;
int namelen;
mutex_lock(&read_mutex);
de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN);
@ -402,13 +400,10 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
break;
namelen--;
}
error = filldir(dirent, buf, namelen, offset, ino, mode >> 12);
if (error)
if (!dir_emit(ctx, buf, namelen, ino, mode >> 12))
break;
offset = nextoffset;
filp->f_pos = offset;
copied++;
ctx->pos = offset = nextoffset;
}
kfree(buf);
return 0;
@ -547,7 +542,7 @@ static const struct address_space_operations cramfs_aops = {
static const struct file_operations cramfs_directory_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = cramfs_readdir,
.iterate = cramfs_readdir,
};
static const struct inode_operations cramfs_dir_inode_operations = {

View File

@ -68,9 +68,9 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
}
struct ecryptfs_getdents_callback {
void *dirent;
struct dir_context ctx;
struct dir_context *caller;
struct dentry *dentry;
filldir_t filldir;
int filldir_called;
int entries_written;
};
@ -96,9 +96,10 @@ ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen,
rc);
goto out;
}
rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type);
buf->caller->pos = buf->ctx.pos;
rc = !dir_emit(buf->caller, name, name_size, ino, d_type);
kfree(name);
if (rc >= 0)
if (!rc)
buf->entries_written++;
out:
return rc;
@ -107,27 +108,23 @@ ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen,
/**
* ecryptfs_readdir
* @file: The eCryptfs directory file
* @dirent: Directory entry handle
* @filldir: The filldir callback function
* @ctx: The actor to feed the entries to
*/
static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
static int ecryptfs_readdir(struct file *file, struct dir_context *ctx)
{
int rc;
struct file *lower_file;
struct inode *inode;
struct ecryptfs_getdents_callback buf;
struct ecryptfs_getdents_callback buf = {
.ctx.actor = ecryptfs_filldir,
.caller = ctx,
.dentry = file->f_path.dentry
};
lower_file = ecryptfs_file_to_lower(file);
lower_file->f_pos = file->f_pos;
lower_file->f_pos = ctx->pos;
inode = file_inode(file);
memset(&buf, 0, sizeof(buf));
buf.dirent = dirent;
buf.dentry = file->f_path.dentry;
buf.filldir = filldir;
buf.filldir_called = 0;
buf.entries_written = 0;
rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf);
file->f_pos = lower_file->f_pos;
rc = iterate_dir(lower_file, &buf.ctx);
ctx->pos = buf.ctx.pos;
if (rc < 0)
goto out;
if (buf.filldir_called && !buf.entries_written)
@ -344,7 +341,7 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#endif
const struct file_operations ecryptfs_dir_fops = {
.readdir = ecryptfs_readdir,
.iterate = ecryptfs_readdir,
.read = generic_read_dir,
.unlocked_ioctl = ecryptfs_unlocked_ioctl,
#ifdef CONFIG_COMPAT
@ -365,7 +362,7 @@ const struct file_operations ecryptfs_main_fops = {
.aio_read = ecryptfs_read_update_atime,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.readdir = ecryptfs_readdir,
.iterate = ecryptfs_readdir,
.unlocked_ioctl = ecryptfs_unlocked_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ecryptfs_compat_ioctl,

View File

@ -7,40 +7,38 @@
#include <linux/buffer_head.h>
#include "efs.h"
static int efs_readdir(struct file *, void *, filldir_t);
static int efs_readdir(struct file *, struct dir_context *);
const struct file_operations efs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = efs_readdir,
.iterate = efs_readdir,
};
const struct inode_operations efs_dir_inode_operations = {
.lookup = efs_lookup,
};
static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
struct inode *inode = file_inode(filp);
struct buffer_head *bh;
struct efs_dir *dirblock;
struct efs_dentry *dirslot;
efs_ino_t inodenum;
static int efs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(file);
efs_block_t block;
int slot, namelen;
char *nameptr;
int slot;
if (inode->i_size & (EFS_DIRBSIZE-1))
printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n");
/* work out where this entry can be found */
block = filp->f_pos >> EFS_DIRBSIZE_BITS;
block = ctx->pos >> EFS_DIRBSIZE_BITS;
/* each block contains at most 256 slots */
slot = filp->f_pos & 0xff;
slot = ctx->pos & 0xff;
/* look at all blocks */
while (block < inode->i_blocks) {
struct efs_dir *dirblock;
struct buffer_head *bh;
/* read the dir block */
bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
@ -57,11 +55,14 @@ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
break;
}
while (slot < dirblock->slots) {
if (dirblock->space[slot] == 0) {
slot++;
for (; slot < dirblock->slots; slot++) {
struct efs_dentry *dirslot;
efs_ino_t inodenum;
const char *nameptr;
int namelen;
if (dirblock->space[slot] == 0)
continue;
}
dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
@ -72,39 +73,29 @@ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
#ifdef DEBUG
printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen);
#endif
if (namelen > 0) {
/* found the next entry */
filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
if (!namelen)
continue;
/* found the next entry */
ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot;
/* copy filename and data in dirslot */
filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN);
/* sanity check */
if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot);
slot++;
continue;
}
/* store position of next slot */
if (++slot == dirblock->slots) {
slot = 0;
block++;
}
brelse(bh);
filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
goto out;
/* sanity check */
if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot);
continue;
}
/* copy filename and data in dirslot */
if (!dir_emit(ctx, nameptr, namelen, inodenum, DT_UNKNOWN)) {
brelse(bh);
return 0;
}
slot++;
}
brelse(bh);
slot = 0;
block++;
}
filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
out:
ctx->pos = (block << EFS_DIRBSIZE_BITS) | slot;
return 0;
}

View File

@ -239,22 +239,19 @@ void exofs_set_de_type(struct exofs_dir_entry *de, struct inode *inode)
}
static int
exofs_readdir(struct file *filp, void *dirent, filldir_t filldir)
exofs_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);
unsigned int offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT;
unsigned long npages = dir_pages(inode);
unsigned chunk_mask = ~(exofs_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 - EXOFS_DIR_REC_LEN(1))
return 0;
types = exofs_filetype_table;
for ( ; n < npages; n++, offset = 0) {
char *kaddr, *limit;
struct exofs_dir_entry *de;
@ -263,7 +260,7 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (IS_ERR(page)) {
EXOFS_ERR("ERROR: bad page in directory(0x%lx)\n",
inode->i_ino);
filp->f_pos += PAGE_CACHE_SIZE - offset;
ctx->pos += PAGE_CACHE_SIZE - offset;
return PTR_ERR(page);
}
kaddr = page_address(page);
@ -271,9 +268,9 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (offset) {
offset = exofs_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 = (struct exofs_dir_entry *)(kaddr + offset);
@ -288,27 +285,24 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir)
return -EIO;
}
if (de->inode_no) {
int over;
unsigned char d_type = DT_UNKNOWN;
unsigned char t;
if (types && de->file_type < EXOFS_FT_MAX)
d_type = types[de->file_type];
if (de->file_type < EXOFS_FT_MAX)
t = exofs_filetype_table[de->file_type];
else
t = DT_UNKNOWN;
offset = (char *)de - kaddr;
over = filldir(dirent, de->name, de->name_len,
(n<<PAGE_CACHE_SHIFT) | offset,
if (!dir_emit(ctx, de->name, de->name_len,
le64_to_cpu(de->inode_no),
d_type);
if (over) {
t)) {
exofs_put_page(page);
return 0;
}
}
filp->f_pos += le16_to_cpu(de->rec_len);
ctx->pos += le16_to_cpu(de->rec_len);
}
exofs_put_page(page);
}
return 0;
}
@ -669,5 +663,5 @@ int exofs_empty_dir(struct inode *inode)
const struct file_operations exofs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = exofs_readdir,
.iterate = exofs_readdir,
};

View File

@ -212,6 +212,7 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
}
struct getdents_callback {
struct dir_context ctx;
char *name; /* name that was found. It already points to a
buffer NAME_MAX+1 is size */
unsigned long ino; /* the inum we are looking for */
@ -254,7 +255,11 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
struct inode *dir = path->dentry->d_inode;
int error;
struct file *file;
struct getdents_callback buffer;
struct getdents_callback buffer = {
.ctx.actor = filldir_one,
.name = name,
.ino = child->d_inode->i_ino
};
error = -ENOTDIR;
if (!dir || !S_ISDIR(dir->i_mode))
@ -271,17 +276,14 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
goto out;
error = -EINVAL;
if (!file->f_op->readdir)
if (!file->f_op->iterate)
goto out_close;
buffer.name = name;
buffer.ino = child->d_inode->i_ino;
buffer.found = 0;
buffer.sequence = 0;
while (1) {
int old_seq = buffer.sequence;
error = vfs_readdir(file, filldir_one, &buffer);
error = iterate_dir(file, &buffer.ctx);
if (buffer.found) {
error = 0;
break;

View File

@ -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,

View File

@ -28,8 +28,7 @@ static unsigned char ext3_filetype_table[] = {
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
};
static int ext3_dx_readdir(struct file * filp,
void * dirent, filldir_t filldir);
static int ext3_dx_readdir(struct file *, struct dir_context *);
static unsigned char get_dtype(struct super_block *sb, int filetype)
{
@ -91,36 +90,30 @@ int ext3_check_dir_entry (const char * function, struct inode * dir,
return error_msg == NULL ? 1 : 0;
}
static int ext3_readdir(struct file * filp,
void * dirent, filldir_t filldir)
static int ext3_readdir(struct file *file, struct dir_context *ctx)
{
int error = 0;
unsigned long offset;
int i, stored;
int i;
struct ext3_dir_entry_2 *de;
int err;
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
int ret = 0;
int dir_has_error = 0;
if (is_dx_dir(inode)) {
err = ext3_dx_readdir(filp, dirent, filldir);
if (err != ERR_BAD_DX_DIR) {
ret = err;
goto out;
}
err = ext3_dx_readdir(file, ctx);
if (err != ERR_BAD_DX_DIR)
return err;
/*
* We don't set the inode dirty flag since it's not
* critical that it get flushed back to the disk.
*/
EXT3_I(file_inode(filp))->i_flags &= ~EXT3_INDEX_FL;
EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
}
stored = 0;
offset = filp->f_pos & (sb->s_blocksize - 1);
offset = ctx->pos & (sb->s_blocksize - 1);
while (!error && !stored && filp->f_pos < inode->i_size) {
unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb);
while (ctx->pos < inode->i_size) {
unsigned long blk = ctx->pos >> EXT3_BLOCK_SIZE_BITS(sb);
struct buffer_head map_bh;
struct buffer_head *bh = NULL;
@ -129,12 +122,12 @@ static int ext3_readdir(struct file * filp,
if (err > 0) {
pgoff_t index = map_bh.b_blocknr >>
(PAGE_CACHE_SHIFT - inode->i_blkbits);
if (!ra_has_index(&filp->f_ra, index))
if (!ra_has_index(&file->f_ra, index))
page_cache_sync_readahead(
sb->s_bdev->bd_inode->i_mapping,
&filp->f_ra, filp,
&file->f_ra, file,
index, 1);
filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
bh = ext3_bread(NULL, inode, blk, 0, &err);
}
@ -146,22 +139,21 @@ static int ext3_readdir(struct file * filp,
if (!dir_has_error) {
ext3_error(sb, __func__, "directory #%lu "
"contains a hole at offset %lld",
inode->i_ino, filp->f_pos);
inode->i_ino, ctx->pos);
dir_has_error = 1;
}
/* corrupt size? Maybe no more blocks to read */
if (filp->f_pos > inode->i_blocks << 9)
if (ctx->pos > inode->i_blocks << 9)
break;
filp->f_pos += sb->s_blocksize - offset;
ctx->pos += sb->s_blocksize - offset;
continue;
}
revalidate:
/* If the dir block has changed since the last call to
* readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the block
* to make sure. */
if (filp->f_version != inode->i_version) {
if (offset && file->f_version != inode->i_version) {
for (i = 0; i < sb->s_blocksize && i < offset; ) {
de = (struct ext3_dir_entry_2 *)
(bh->b_data + i);
@ -177,53 +169,40 @@ static int ext3_readdir(struct file * filp,
i += ext3_rec_len_from_disk(de->rec_len);
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
| offset;
filp->f_version = inode->i_version;
file->f_version = inode->i_version;
}
while (!error && filp->f_pos < inode->i_size
while (ctx->pos < inode->i_size
&& offset < sb->s_blocksize) {
de = (struct ext3_dir_entry_2 *) (bh->b_data + offset);
if (!ext3_check_dir_entry ("ext3_readdir", inode, de,
bh, offset)) {
/* On error, skip the f_pos to the
/* On error, skip the to the
next block. */
filp->f_pos = (filp->f_pos |
ctx->pos = (ctx->pos |
(sb->s_blocksize - 1)) + 1;
brelse (bh);
ret = stored;
goto out;
break;
}
offset += ext3_rec_len_from_disk(de->rec_len);
if (le32_to_cpu(de->inode)) {
/* We might block in the next section
* if the data destination is
* currently swapped out. So, use a
* version stamp to detect whether or
* not the directory has been modified
* during the copy operation.
*/
u64 version = filp->f_version;
error = filldir(dirent, de->name,
de->name_len,
filp->f_pos,
le32_to_cpu(de->inode),
get_dtype(sb, de->file_type));
if (error)
break;
if (version != filp->f_version)
goto revalidate;
stored ++;
if (!dir_emit(ctx, de->name, de->name_len,
le32_to_cpu(de->inode),
get_dtype(sb, de->file_type))) {
brelse(bh);
return 0;
}
}
filp->f_pos += ext3_rec_len_from_disk(de->rec_len);
ctx->pos += ext3_rec_len_from_disk(de->rec_len);
}
offset = 0;
brelse (bh);
if (ctx->pos < inode->i_size)
if (!dir_relax(inode))
return 0;
}
out:
return ret;
return 0;
}
static inline int is_32bit_api(void)
@ -452,62 +431,54 @@ int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
* for all entres on the fname linked list. (Normally there is only
* one entry on the linked list, unless there are 62 bit hash collisions.)
*/
static int call_filldir(struct file * filp, void * dirent,
filldir_t filldir, struct fname *fname)
static bool call_filldir(struct file *file, struct dir_context *ctx,
struct fname *fname)
{
struct dir_private_info *info = filp->private_data;
loff_t curr_pos;
struct inode *inode = file_inode(filp);
struct super_block * sb;
int error;
sb = inode->i_sb;
struct dir_private_info *info = file->private_data;
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
if (!fname) {
printk("call_filldir: called with null fname?!?\n");
return 0;
return true;
}
curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
ctx->pos = hash2pos(file, fname->hash, fname->minor_hash);
while (fname) {
error = filldir(dirent, fname->name,
fname->name_len, curr_pos,
if (!dir_emit(ctx, fname->name, fname->name_len,
fname->inode,
get_dtype(sb, fname->file_type));
if (error) {
filp->f_pos = curr_pos;
get_dtype(sb, fname->file_type))) {
info->extra_fname = fname;
return error;
return false;
}
fname = fname->next;
}
return 0;
return true;
}
static int ext3_dx_readdir(struct file * filp,
void * dirent, filldir_t filldir)
static int ext3_dx_readdir(struct file *file, struct dir_context *ctx)
{
struct dir_private_info *info = filp->private_data;
struct inode *inode = file_inode(filp);
struct dir_private_info *info = file->private_data;
struct inode *inode = file_inode(file);
struct fname *fname;
int ret;
if (!info) {
info = ext3_htree_create_dir_info(filp, filp->f_pos);
info = ext3_htree_create_dir_info(file, ctx->pos);
if (!info)
return -ENOMEM;
filp->private_data = info;
file->private_data = info;
}
if (filp->f_pos == ext3_get_htree_eof(filp))
if (ctx->pos == ext3_get_htree_eof(file))
return 0; /* EOF */
/* Some one has messed with f_pos; reset the world */
if (info->last_pos != filp->f_pos) {
if (info->last_pos != ctx->pos) {
free_rb_tree_fname(&info->root);
info->curr_node = NULL;
info->extra_fname = NULL;
info->curr_hash = pos2maj_hash(filp, filp->f_pos);
info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
info->curr_hash = pos2maj_hash(file, ctx->pos);
info->curr_minor_hash = pos2min_hash(file, ctx->pos);
}
/*
@ -515,7 +486,7 @@ static int ext3_dx_readdir(struct file * filp,
* chain, return them first.
*/
if (info->extra_fname) {
if (call_filldir(filp, dirent, filldir, info->extra_fname))
if (!call_filldir(file, ctx, info->extra_fname))
goto finished;
info->extra_fname = NULL;
goto next_node;
@ -529,17 +500,17 @@ static int ext3_dx_readdir(struct file * filp,
* cached entries.
*/
if ((!info->curr_node) ||
(filp->f_version != inode->i_version)) {
(file->f_version != inode->i_version)) {
info->curr_node = NULL;
free_rb_tree_fname(&info->root);
filp->f_version = inode->i_version;
ret = ext3_htree_fill_tree(filp, info->curr_hash,
file->f_version = inode->i_version;
ret = ext3_htree_fill_tree(file, info->curr_hash,
info->curr_minor_hash,
&info->next_hash);
if (ret < 0)
return ret;
if (ret == 0) {
filp->f_pos = ext3_get_htree_eof(filp);
ctx->pos = ext3_get_htree_eof(file);
break;
}
info->curr_node = rb_first(&info->root);
@ -548,7 +519,7 @@ static int ext3_dx_readdir(struct file * filp,
fname = rb_entry(info->curr_node, struct fname, rb_hash);
info->curr_hash = fname->hash;
info->curr_minor_hash = fname->minor_hash;
if (call_filldir(filp, dirent, filldir, fname))
if (!call_filldir(file, ctx, fname))
break;
next_node:
info->curr_node = rb_next(info->curr_node);
@ -559,7 +530,7 @@ static int ext3_dx_readdir(struct file * filp,
info->curr_minor_hash = fname->minor_hash;
} else {
if (info->next_hash == ~0) {
filp->f_pos = ext3_get_htree_eof(filp);
ctx->pos = ext3_get_htree_eof(file);
break;
}
info->curr_hash = info->next_hash;
@ -567,7 +538,7 @@ static int ext3_dx_readdir(struct file * filp,
}
}
finished:
info->last_pos = filp->f_pos;
info->last_pos = ctx->pos;
return 0;
}
@ -582,7 +553,7 @@ static int ext3_release_dir (struct inode * inode, struct file * filp)
const struct file_operations ext3_dir_operations = {
.llseek = ext3_dir_llseek,
.read = generic_read_dir,
.readdir = ext3_readdir,
.iterate = ext3_readdir,
.unlocked_ioctl = ext3_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext3_compat_ioctl,

View File

@ -29,8 +29,7 @@
#include "ext4.h"
#include "xattr.h"
static int ext4_dx_readdir(struct file *filp,
void *dirent, filldir_t filldir);
static int ext4_dx_readdir(struct file *, struct dir_context *);
/**
* Check if the given dir-inode refers to an htree-indexed directory
@ -103,60 +102,56 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
return 1;
}
static int ext4_readdir(struct file *filp,
void *dirent, filldir_t filldir)
static int ext4_readdir(struct file *file, struct dir_context *ctx)
{
int error = 0;
unsigned int offset;
int i, stored;
struct ext4_dir_entry_2 *de;
int err;
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
int ret = 0;
int dir_has_error = 0;
if (is_dx_dir(inode)) {
err = ext4_dx_readdir(filp, dirent, filldir);
err = ext4_dx_readdir(file, ctx);
if (err != ERR_BAD_DX_DIR) {
ret = err;
goto out;
return err;
}
/*
* We don't set the inode dirty flag since it's not
* critical that it get flushed back to the disk.
*/
ext4_clear_inode_flag(file_inode(filp),
ext4_clear_inode_flag(file_inode(file),
EXT4_INODE_INDEX);
}
if (ext4_has_inline_data(inode)) {
int has_inline_data = 1;
ret = ext4_read_inline_dir(filp, dirent, filldir,
int ret = ext4_read_inline_dir(file, ctx,
&has_inline_data);
if (has_inline_data)
return ret;
}
stored = 0;
offset = filp->f_pos & (sb->s_blocksize - 1);
offset = ctx->pos & (sb->s_blocksize - 1);
while (!error && !stored && filp->f_pos < inode->i_size) {
while (ctx->pos < inode->i_size) {
struct ext4_map_blocks map;
struct buffer_head *bh = NULL;
map.m_lblk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb);
map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
map.m_len = 1;
err = ext4_map_blocks(NULL, inode, &map, 0);
if (err > 0) {
pgoff_t index = map.m_pblk >>
(PAGE_CACHE_SHIFT - inode->i_blkbits);
if (!ra_has_index(&filp->f_ra, index))
if (!ra_has_index(&file->f_ra, index))
page_cache_sync_readahead(
sb->s_bdev->bd_inode->i_mapping,
&filp->f_ra, filp,
&file->f_ra, file,
index, 1);
filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err);
}
@ -166,16 +161,16 @@ static int ext4_readdir(struct file *filp,
*/
if (!bh) {
if (!dir_has_error) {
EXT4_ERROR_FILE(filp, 0,
EXT4_ERROR_FILE(file, 0,
"directory contains a "
"hole at offset %llu",
(unsigned long long) filp->f_pos);
(unsigned long long) ctx->pos);
dir_has_error = 1;
}
/* corrupt size? Maybe no more blocks to read */
if (filp->f_pos > inode->i_blocks << 9)
if (ctx->pos > inode->i_blocks << 9)
break;
filp->f_pos += sb->s_blocksize - offset;
ctx->pos += sb->s_blocksize - offset;
continue;
}
@ -183,21 +178,20 @@ static int ext4_readdir(struct file *filp,
if (!buffer_verified(bh) &&
!ext4_dirent_csum_verify(inode,
(struct ext4_dir_entry *)bh->b_data)) {
EXT4_ERROR_FILE(filp, 0, "directory fails checksum "
EXT4_ERROR_FILE(file, 0, "directory fails checksum "
"at offset %llu",
(unsigned long long)filp->f_pos);
filp->f_pos += sb->s_blocksize - offset;
(unsigned long long)ctx->pos);
ctx->pos += sb->s_blocksize - offset;
brelse(bh);
continue;
}
set_buffer_verified(bh);
revalidate:
/* If the dir block has changed since the last call to
* readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the block
* to make sure. */
if (filp->f_version != inode->i_version) {
if (file->f_version != inode->i_version) {
for (i = 0; i < sb->s_blocksize && i < offset; ) {
de = (struct ext4_dir_entry_2 *)
(bh->b_data + i);
@ -214,57 +208,46 @@ static int ext4_readdir(struct file *filp,
sb->s_blocksize);
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
| offset;
filp->f_version = inode->i_version;
file->f_version = inode->i_version;
}
while (!error && filp->f_pos < inode->i_size
while (ctx->pos < inode->i_size
&& offset < sb->s_blocksize) {
de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
if (ext4_check_dir_entry(inode, filp, de, bh,
if (ext4_check_dir_entry(inode, file, de, bh,
bh->b_data, bh->b_size,
offset)) {
/*
* On error, skip the f_pos to the next block
* On error, skip to the next block
*/
filp->f_pos = (filp->f_pos |
ctx->pos = (ctx->pos |
(sb->s_blocksize - 1)) + 1;
brelse(bh);
ret = stored;
goto out;
break;
}
offset += ext4_rec_len_from_disk(de->rec_len,
sb->s_blocksize);
if (le32_to_cpu(de->inode)) {
/* We might block in the next section
* if the data destination is
* currently swapped out. So, use a
* version stamp to detect whether or
* not the directory has been modified
* during the copy operation.
*/
u64 version = filp->f_version;
error = filldir(dirent, de->name,
if (!dir_emit(ctx, de->name,
de->name_len,
filp->f_pos,
le32_to_cpu(de->inode),
get_dtype(sb, de->file_type));
if (error)
break;
if (version != filp->f_version)
goto revalidate;
stored++;
get_dtype(sb, de->file_type))) {
brelse(bh);
return 0;
}
}
filp->f_pos += ext4_rec_len_from_disk(de->rec_len,
ctx->pos += ext4_rec_len_from_disk(de->rec_len,
sb->s_blocksize);
}
offset = 0;
brelse(bh);
if (ctx->pos < inode->i_size) {
if (!dir_relax(inode))
return 0;
}
}
out:
return ret;
return 0;
}
static inline int is_32bit_api(void)
@ -492,16 +475,12 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
* for all entres on the fname linked list. (Normally there is only
* one entry on the linked list, unless there are 62 bit hash collisions.)
*/
static int call_filldir(struct file *filp, void *dirent,
filldir_t filldir, struct fname *fname)
static int call_filldir(struct file *file, struct dir_context *ctx,
struct fname *fname)
{
struct dir_private_info *info = filp->private_data;
loff_t curr_pos;
struct inode *inode = file_inode(filp);
struct super_block *sb;
int error;
sb = inode->i_sb;
struct dir_private_info *info = file->private_data;
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
if (!fname) {
ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: comm %s: "
@ -509,47 +488,44 @@ static int call_filldir(struct file *filp, void *dirent,
inode->i_ino, current->comm);
return 0;
}
curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
ctx->pos = hash2pos(file, fname->hash, fname->minor_hash);
while (fname) {
error = filldir(dirent, fname->name,
fname->name_len, curr_pos,
if (!dir_emit(ctx, fname->name,
fname->name_len,
fname->inode,
get_dtype(sb, fname->file_type));
if (error) {
filp->f_pos = curr_pos;
get_dtype(sb, fname->file_type))) {
info->extra_fname = fname;
return error;
return 1;
}
fname = fname->next;
}
return 0;
}
static int ext4_dx_readdir(struct file *filp,
void *dirent, filldir_t filldir)
static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
{
struct dir_private_info *info = filp->private_data;
struct inode *inode = file_inode(filp);
struct dir_private_info *info = file->private_data;
struct inode *inode = file_inode(file);
struct fname *fname;
int ret;
if (!info) {
info = ext4_htree_create_dir_info(filp, filp->f_pos);
info = ext4_htree_create_dir_info(file, ctx->pos);
if (!info)
return -ENOMEM;
filp->private_data = info;
file->private_data = info;
}
if (filp->f_pos == ext4_get_htree_eof(filp))
if (ctx->pos == ext4_get_htree_eof(file))
return 0; /* EOF */
/* Some one has messed with f_pos; reset the world */
if (info->last_pos != filp->f_pos) {
if (info->last_pos != ctx->pos) {
free_rb_tree_fname(&info->root);
info->curr_node = NULL;
info->extra_fname = NULL;
info->curr_hash = pos2maj_hash(filp, filp->f_pos);
info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
info->curr_hash = pos2maj_hash(file, ctx->pos);
info->curr_minor_hash = pos2min_hash(file, ctx->pos);
}
/*
@ -557,7 +533,7 @@ static int ext4_dx_readdir(struct file *filp,
* chain, return them first.
*/
if (info->extra_fname) {
if (call_filldir(filp, dirent, filldir, info->extra_fname))
if (call_filldir(file, ctx, info->extra_fname))
goto finished;
info->extra_fname = NULL;
goto next_node;
@ -571,17 +547,17 @@ static int ext4_dx_readdir(struct file *filp,
* cached entries.
*/
if ((!info->curr_node) ||
(filp->f_version != inode->i_version)) {
(file->f_version != inode->i_version)) {
info->curr_node = NULL;
free_rb_tree_fname(&info->root);
filp->f_version = inode->i_version;
ret = ext4_htree_fill_tree(filp, info->curr_hash,
file->f_version = inode->i_version;
ret = ext4_htree_fill_tree(file, info->curr_hash,
info->curr_minor_hash,
&info->next_hash);
if (ret < 0)
return ret;
if (ret == 0) {
filp->f_pos = ext4_get_htree_eof(filp);
ctx->pos = ext4_get_htree_eof(file);
break;
}
info->curr_node = rb_first(&info->root);
@ -590,7 +566,7 @@ static int ext4_dx_readdir(struct file *filp,
fname = rb_entry(info->curr_node, struct fname, rb_hash);
info->curr_hash = fname->hash;
info->curr_minor_hash = fname->minor_hash;
if (call_filldir(filp, dirent, filldir, fname))
if (call_filldir(file, ctx, fname))
break;
next_node:
info->curr_node = rb_next(info->curr_node);
@ -601,7 +577,7 @@ static int ext4_dx_readdir(struct file *filp,
info->curr_minor_hash = fname->minor_hash;
} else {
if (info->next_hash == ~0) {
filp->f_pos = ext4_get_htree_eof(filp);
ctx->pos = ext4_get_htree_eof(file);
break;
}
info->curr_hash = info->next_hash;
@ -609,7 +585,7 @@ static int ext4_dx_readdir(struct file *filp,
}
}
finished:
info->last_pos = filp->f_pos;
info->last_pos = ctx->pos;
return 0;
}
@ -624,7 +600,7 @@ static int ext4_release_dir(struct inode *inode, struct file *filp)
const struct file_operations ext4_dir_operations = {
.llseek = ext4_dir_llseek,
.read = generic_read_dir,
.readdir = ext4_readdir,
.iterate = ext4_readdir,
.unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext4_compat_ioctl,

View File

@ -2515,7 +2515,7 @@ extern int ext4_try_create_inline_dir(handle_t *handle,
struct inode *parent,
struct inode *inode);
extern int ext4_read_inline_dir(struct file *filp,
void *dirent, filldir_t filldir,
struct dir_context *ctx,
int *has_inline_data);
extern int htree_inlinedir_to_tree(struct file *dir_file,
struct inode *dir, ext4_lblk_t block,

View File

@ -1404,16 +1404,15 @@ int htree_inlinedir_to_tree(struct file *dir_file,
* offset as if '.' and '..' really take place.
*
*/
int ext4_read_inline_dir(struct file *filp,
void *dirent, filldir_t filldir,
int ext4_read_inline_dir(struct file *file,
struct dir_context *ctx,
int *has_inline_data)
{
int error = 0;
unsigned int offset, parent_ino;
int i, stored;
int i;
struct ext4_dir_entry_2 *de;
struct super_block *sb;
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
int ret, inline_size = 0;
struct ext4_iloc iloc;
void *dir_buf = NULL;
@ -1444,9 +1443,8 @@ int ext4_read_inline_dir(struct file *filp,
goto out;
sb = inode->i_sb;
stored = 0;
parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode);
offset = filp->f_pos;
offset = ctx->pos;
/*
* dotdot_offset and dotdot_size is the real offset and
@ -1460,104 +1458,74 @@ int ext4_read_inline_dir(struct file *filp,
extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE;
extra_size = extra_offset + inline_size;
while (!error && !stored && filp->f_pos < extra_size) {
revalidate:
/*
* If the version has changed since the last call to
* readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the inline
* dir to make sure.
*/
if (filp->f_version != inode->i_version) {
for (i = 0; i < extra_size && i < offset;) {
/*
* "." is with offset 0 and
* ".." is dotdot_offset.
*/
if (!i) {
i = dotdot_offset;
continue;
} else if (i == dotdot_offset) {
i = dotdot_size;
continue;
}
/* for other entry, the real offset in
* the buf has to be tuned accordingly.
*/
de = (struct ext4_dir_entry_2 *)
(dir_buf + i - extra_offset);
/* It's too expensive to do a full
* dirent test each time round this
* loop, but we do have to test at
* least that it is non-zero. A
* failure will be detected in the
* dirent test below. */
if (ext4_rec_len_from_disk(de->rec_len,
extra_size) < EXT4_DIR_REC_LEN(1))
break;
i += ext4_rec_len_from_disk(de->rec_len,
extra_size);
}
offset = i;
filp->f_pos = offset;
filp->f_version = inode->i_version;
}
while (!error && filp->f_pos < extra_size) {
if (filp->f_pos == 0) {
error = filldir(dirent, ".", 1, 0, inode->i_ino,
DT_DIR);
if (error)
break;
stored++;
filp->f_pos = dotdot_offset;
/*
* If the version has changed since the last call to
* readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the inline
* dir to make sure.
*/
if (file->f_version != inode->i_version) {
for (i = 0; i < extra_size && i < offset;) {
/*
* "." is with offset 0 and
* ".." is dotdot_offset.
*/
if (!i) {
i = dotdot_offset;
continue;
} else if (i == dotdot_offset) {
i = dotdot_size;
continue;
}
if (filp->f_pos == dotdot_offset) {
error = filldir(dirent, "..", 2,
dotdot_offset,
parent_ino, DT_DIR);
if (error)
break;
stored++;
filp->f_pos = dotdot_size;
continue;
}
/* for other entry, the real offset in
* the buf has to be tuned accordingly.
*/
de = (struct ext4_dir_entry_2 *)
(dir_buf + filp->f_pos - extra_offset);
if (ext4_check_dir_entry(inode, filp, de,
iloc.bh, dir_buf,
extra_size, filp->f_pos)) {
ret = stored;
goto out;
}
if (le32_to_cpu(de->inode)) {
/* We might block in the next section
* if the data destination is
* currently swapped out. So, use a
* version stamp to detect whether or
* not the directory has been modified
* during the copy operation.
*/
u64 version = filp->f_version;
error = filldir(dirent, de->name,
de->name_len,
filp->f_pos,
le32_to_cpu(de->inode),
get_dtype(sb, de->file_type));
if (error)
break;
if (version != filp->f_version)
goto revalidate;
stored++;
}
filp->f_pos += ext4_rec_len_from_disk(de->rec_len,
extra_size);
(dir_buf + i - extra_offset);
/* It's too expensive to do a full
* dirent test each time round this
* loop, but we do have to test at
* least that it is non-zero. A
* failure will be detected in the
* dirent test below. */
if (ext4_rec_len_from_disk(de->rec_len, extra_size)
< EXT4_DIR_REC_LEN(1))
break;
i += ext4_rec_len_from_disk(de->rec_len,
extra_size);
}
offset = i;
ctx->pos = offset;
file->f_version = inode->i_version;
}
while (ctx->pos < extra_size) {
if (ctx->pos == 0) {
if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR))
goto out;
ctx->pos = dotdot_offset;
continue;
}
if (ctx->pos == dotdot_offset) {
if (!dir_emit(ctx, "..", 2, parent_ino, DT_DIR))
goto out;
ctx->pos = dotdot_size;
continue;
}
de = (struct ext4_dir_entry_2 *)
(dir_buf + ctx->pos - extra_offset);
if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf,
extra_size, ctx->pos))
goto out;
if (le32_to_cpu(de->inode)) {
if (!dir_emit(ctx, de->name, de->name_len,
le32_to_cpu(de->inode),
get_dtype(sb, de->file_type)))
goto out;
}
ctx->pos += ext4_rec_len_from_disk(de->rec_len, extra_size);
}
out:
kfree(dir_buf);

View File

@ -591,24 +591,19 @@ bool f2fs_empty_dir(struct inode *dir)
return true;
}
static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir)
static int f2fs_readdir(struct file *file, struct dir_context *ctx)
{
unsigned long pos = file->f_pos;
struct inode *inode = file_inode(file);
unsigned long npages = dir_blocks(inode);
unsigned char *types = NULL;
unsigned int bit_pos = 0, start_bit_pos = 0;
int over = 0;
struct f2fs_dentry_block *dentry_blk = NULL;
struct f2fs_dir_entry *de = NULL;
struct page *dentry_page = NULL;
unsigned int n = 0;
unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK);
unsigned char d_type = DT_UNKNOWN;
int slots;
types = f2fs_filetype_table;
bit_pos = (pos % NR_DENTRY_IN_BLOCK);
n = (pos / NR_DENTRY_IN_BLOCK);
bit_pos = ((unsigned long)ctx->pos % NR_DENTRY_IN_BLOCK);
for ( ; n < npages; n++) {
dentry_page = get_lock_data_page(inode, n);
@ -618,31 +613,28 @@ static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir)
start_bit_pos = bit_pos;
dentry_blk = kmap(dentry_page);
while (bit_pos < NR_DENTRY_IN_BLOCK) {
d_type = DT_UNKNOWN;
bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
NR_DENTRY_IN_BLOCK,
bit_pos);
if (bit_pos >= NR_DENTRY_IN_BLOCK)
break;
ctx->pos += bit_pos - start_bit_pos;
de = &dentry_blk->dentry[bit_pos];
if (types && de->file_type < F2FS_FT_MAX)
d_type = types[de->file_type];
over = filldir(dirent,
dentry_blk->filename[bit_pos],
le16_to_cpu(de->name_len),
(n * NR_DENTRY_IN_BLOCK) + bit_pos,
le32_to_cpu(de->ino), d_type);
if (over) {
file->f_pos += bit_pos - start_bit_pos;
if (de->file_type < F2FS_FT_MAX)
d_type = f2fs_filetype_table[de->file_type];
else
d_type = DT_UNKNOWN;
if (!dir_emit(ctx,
dentry_blk->filename[bit_pos],
le16_to_cpu(de->name_len),
le32_to_cpu(de->ino), d_type))
goto success;
}
slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
bit_pos += slots;
}
bit_pos = 0;
file->f_pos = (n + 1) * NR_DENTRY_IN_BLOCK;
ctx->pos = (n + 1) * NR_DENTRY_IN_BLOCK;
kunmap(dentry_page);
f2fs_put_page(dentry_page, 1);
dentry_page = NULL;
@ -659,7 +651,7 @@ static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir)
const struct file_operations f2fs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = f2fs_readdir,
.iterate = f2fs_readdir,
.fsync = f2fs_sync_file,
.unlocked_ioctl = f2fs_ioctl,
};

View File

@ -543,6 +543,7 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
EXPORT_SYMBOL_GPL(fat_search_long);
struct fat_ioctl_filldir_callback {
struct dir_context ctx;
void __user *dirent;
int result;
/* for dir ioctl */
@ -552,8 +553,9 @@ struct fat_ioctl_filldir_callback {
int short_len;
};
static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
filldir_t filldir, int short_only, int both)
static int __fat_readdir(struct inode *inode, struct file *file,
struct dir_context *ctx, int short_only,
struct fat_ioctl_filldir_callback *both)
{
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
@ -564,27 +566,20 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
unsigned char bufname[FAT_MAX_SHORT_SIZE];
int isvfat = sbi->options.isvfat;
const char *fill_name = NULL;
unsigned long inum;
unsigned long lpos, dummy, *furrfu = &lpos;
int fake_offset = 0;
loff_t cpos;
int short_len = 0, fill_len = 0;
int ret = 0;
mutex_lock(&sbi->s_lock);
cpos = filp->f_pos;
cpos = ctx->pos;
/* Fake . and .. for the root directory. */
if (inode->i_ino == MSDOS_ROOT_INO) {
while (cpos < 2) {
if (filldir(dirent, "..", cpos+1, cpos,
MSDOS_ROOT_INO, DT_DIR) < 0)
goto out;
cpos++;
filp->f_pos++;
}
if (cpos == 2) {
dummy = 2;
furrfu = &dummy;
if (!dir_emit_dots(file, ctx))
goto out;
if (ctx->pos == 2) {
fake_offset = 1;
cpos = 0;
}
}
@ -619,7 +614,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
int status = fat_parse_long(inode, &cpos, &bh, &de,
&unicode, &nr_slots);
if (status < 0) {
filp->f_pos = cpos;
ctx->pos = cpos;
ret = status;
goto out;
} else if (status == PARSE_INVALID)
@ -639,6 +634,19 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
/* !both && !short_only, so we don't need shortname. */
if (!both)
goto start_filldir;
short_len = fat_parse_short(sb, de, bufname,
sbi->options.dotsOK);
if (short_len == 0)
goto record_end;
/* hack for fat_ioctl_filldir() */
both->longname = fill_name;
both->long_len = fill_len;
both->shortname = bufname;
both->short_len = short_len;
fill_name = NULL;
fill_len = 0;
goto start_filldir;
}
}
@ -646,28 +654,21 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
if (short_len == 0)
goto record_end;
if (nr_slots) {
/* hack for fat_ioctl_filldir() */
struct fat_ioctl_filldir_callback *p = dirent;
p->longname = fill_name;
p->long_len = fill_len;
p->shortname = bufname;
p->short_len = short_len;
fill_name = NULL;
fill_len = 0;
} else {
fill_name = bufname;
fill_len = short_len;
}
fill_name = bufname;
fill_len = short_len;
start_filldir:
lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
inum = inode->i_ino;
else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
inum = parent_ino(filp->f_path.dentry);
if (!fake_offset)
ctx->pos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) {
if (!dir_emit_dot(file, ctx))
goto fill_failed;
} else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
if (!dir_emit_dotdot(file, ctx))
goto fill_failed;
} else {
unsigned long inum;
loff_t i_pos = fat_make_i_pos(sb, bh, de);
struct inode *tmp = fat_iget(sb, i_pos);
if (tmp) {
@ -675,18 +676,17 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
iput(tmp);
} else
inum = iunique(sb, MSDOS_ROOT_INO);
if (!dir_emit(ctx, fill_name, fill_len, inum,
(de->attr & ATTR_DIR) ? DT_DIR : DT_REG))
goto fill_failed;
}
if (filldir(dirent, fill_name, fill_len, *furrfu, inum,
(de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
goto fill_failed;
record_end:
furrfu = &lpos;
filp->f_pos = cpos;
fake_offset = 0;
ctx->pos = cpos;
goto get_new;
end_of_dir:
filp->f_pos = cpos;
ctx->pos = cpos;
fill_failed:
brelse(bh);
if (unicode)
@ -696,10 +696,9 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
return ret;
}
static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int fat_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
return __fat_readdir(file_inode(file), file, ctx, 0, NULL);
}
#define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \
@ -755,20 +754,25 @@ efault: \
FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
static int fat_ioctl_readdir(struct inode *inode, struct file *file,
void __user *dirent, filldir_t filldir,
int short_only, int both)
{
struct fat_ioctl_filldir_callback buf;
struct fat_ioctl_filldir_callback buf = {
.ctx.actor = filldir,
.dirent = dirent
};
int ret;
buf.dirent = dirent;
buf.result = 0;
mutex_lock(&inode->i_mutex);
buf.ctx.pos = file->f_pos;
ret = -ENOENT;
if (!IS_DEADDIR(inode)) {
ret = __fat_readdir(inode, filp, &buf, filldir,
short_only, both);
ret = __fat_readdir(inode, file, &buf.ctx,
short_only, both ? &buf : NULL);
file->f_pos = buf.ctx.pos;
}
mutex_unlock(&inode->i_mutex);
if (ret >= 0)
@ -854,7 +858,7 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd,
const struct file_operations fat_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = fat_readdir,
.iterate = fat_readdir,
.unlocked_ioctl = fat_dir_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fat_compat_dir_ioctl,

View File

@ -49,7 +49,7 @@
static struct dentry * vxfs_lookup(struct inode *, struct dentry *, unsigned int);
static int vxfs_readdir(struct file *, void *, filldir_t);
static int vxfs_readdir(struct file *, struct dir_context *);
const struct inode_operations vxfs_dir_inode_ops = {
.lookup = vxfs_lookup,
@ -58,7 +58,7 @@ const struct inode_operations vxfs_dir_inode_ops = {
const struct file_operations vxfs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = vxfs_readdir,
.iterate = vxfs_readdir,
};
@ -235,7 +235,7 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
* Zero.
*/
static int
vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
vxfs_readdir(struct file *fp, struct dir_context *ctx)
{
struct inode *ip = file_inode(fp);
struct super_block *sbp = ip->i_sb;
@ -243,20 +243,17 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
u_long page, npages, block, pblocks, nblocks, offset;
loff_t pos;
switch ((long)fp->f_pos) {
case 0:
if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
goto out;
fp->f_pos++;
/* fallthrough */
case 1:
if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0)
goto out;
fp->f_pos++;
/* fallthrough */
if (ctx->pos == 0) {
if (!dir_emit_dot(fp, ctx))
return 0;
ctx->pos = 1;
}
pos = fp->f_pos - 2;
if (ctx->pos == 1) {
if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
return 0;
ctx->pos = 2;
}
pos = ctx->pos - 2;
if (pos > VXFS_DIRROUND(ip->i_size))
return 0;
@ -270,16 +267,16 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
for (; page < npages; page++, block = 0) {
caddr_t kaddr;
char *kaddr;
struct page *pp;
pp = vxfs_get_page(ip->i_mapping, page);
if (IS_ERR(pp))
continue;
kaddr = (caddr_t)page_address(pp);
kaddr = (char *)page_address(pp);
for (; block <= nblocks && block <= pblocks; block++) {
caddr_t baddr, limit;
char *baddr, *limit;
struct vxfs_dirblk *dbp;
struct vxfs_direct *de;
@ -292,21 +289,18 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
(kaddr + offset) :
(baddr + VXFS_DIRBLKOV(dbp)));
for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
int over;
for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
if (!de->d_reclen)
break;
if (!de->d_ino)
continue;
offset = (caddr_t)de - kaddr;
over = filler(retp, de->d_name, de->d_namelen,
((page << PAGE_CACHE_SHIFT) | offset) + 2,
de->d_ino, DT_UNKNOWN);
if (over) {
offset = (char *)de - kaddr;
ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
if (!dir_emit(ctx, de->d_name, de->d_namelen,
de->d_ino, DT_UNKNOWN)) {
vxfs_put_page(pp);
goto done;
return 0;
}
}
offset = 0;
@ -314,9 +308,6 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
vxfs_put_page(pp);
offset = 0;
}
done:
fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
out:
ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
return 0;
}

View File

@ -14,7 +14,7 @@
#include <linux/namei.h>
#include <linux/slab.h>
static bool fuse_use_readdirplus(struct inode *dir, struct file *filp)
static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
{
struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_inode *fi = get_fuse_inode(dir);
@ -25,7 +25,7 @@ static bool fuse_use_readdirplus(struct inode *dir, struct file *filp)
return true;
if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
return true;
if (filp->f_pos == 0)
if (ctx->pos == 0)
return true;
return false;
}
@ -1165,25 +1165,23 @@ static int fuse_permission(struct inode *inode, int mask)
}
static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
void *dstbuf, filldir_t filldir)
struct dir_context *ctx)
{
while (nbytes >= FUSE_NAME_OFFSET) {
struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
size_t reclen = FUSE_DIRENT_SIZE(dirent);
int over;
if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
return -EIO;
if (reclen > nbytes)
break;
over = filldir(dstbuf, dirent->name, dirent->namelen,
file->f_pos, dirent->ino, dirent->type);
if (over)
if (!dir_emit(ctx, dirent->name, dirent->namelen,
dirent->ino, dirent->type))
break;
buf += reclen;
nbytes -= reclen;
file->f_pos = dirent->off;
ctx->pos = dirent->off;
}
return 0;
@ -1284,7 +1282,7 @@ static int fuse_direntplus_link(struct file *file,
}
static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
void *dstbuf, filldir_t filldir, u64 attr_version)
struct dir_context *ctx, u64 attr_version)
{
struct fuse_direntplus *direntplus;
struct fuse_dirent *dirent;
@ -1309,10 +1307,9 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
we need to send a FORGET for each of those
which we did not link.
*/
over = filldir(dstbuf, dirent->name, dirent->namelen,
file->f_pos, dirent->ino,
dirent->type);
file->f_pos = dirent->off;
over = !dir_emit(ctx, dirent->name, dirent->namelen,
dirent->ino, dirent->type);
ctx->pos = dirent->off;
}
buf += reclen;
@ -1326,7 +1323,7 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
return 0;
}
static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
static int fuse_readdir(struct file *file, struct dir_context *ctx)
{
int plus, err;
size_t nbytes;
@ -1349,17 +1346,17 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
return -ENOMEM;
}
plus = fuse_use_readdirplus(inode, file);
plus = fuse_use_readdirplus(inode, ctx);
req->out.argpages = 1;
req->num_pages = 1;
req->pages[0] = page;
req->page_descs[0].length = PAGE_SIZE;
if (plus) {
attr_version = fuse_get_attr_version(fc);
fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
FUSE_READDIRPLUS);
} else {
fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
FUSE_READDIR);
}
fuse_request_send(fc, req);
@ -1369,11 +1366,11 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
if (!err) {
if (plus) {
err = parse_dirplusfile(page_address(page), nbytes,
file, dstbuf, filldir,
file, ctx,
attr_version);
} else {
err = parse_dirfile(page_address(page), nbytes, file,
dstbuf, filldir);
ctx);
}
}
@ -1886,7 +1883,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
static const struct file_operations fuse_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = fuse_readdir,
.iterate = fuse_readdir,
.open = fuse_dir_open,
.release = fuse_dir_release,
.fsync = fuse_dir_fsync,

View File

@ -1212,9 +1212,7 @@ static int compare_dents(const void *a, const void *b)
/**
* do_filldir_main - read out directory entries
* @dip: The GFS2 inode
* @offset: The offset in the file to read from
* @opaque: opaque data to pass to filldir
* @filldir: The function to pass entries to
* @ctx: what to feed the entries to
* @darr: an array of struct gfs2_dirent pointers to read
* @entries: the number of entries in darr
* @copied: pointer to int that's non-zero if a entry has been copied out
@ -1224,11 +1222,10 @@ static int compare_dents(const void *a, const void *b)
* the possibility that they will fall into different readdir buffers or
* that someone will want to seek to that location.
*
* Returns: errno, >0 on exception from filldir
* Returns: errno, >0 if the actor tells you to stop
*/
static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
void *opaque, filldir_t filldir,
static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx,
const struct gfs2_dirent **darr, u32 entries,
int *copied)
{
@ -1236,7 +1233,6 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
u64 off, off_next;
unsigned int x, y;
int run = 0;
int error = 0;
sort(darr, entries, sizeof(struct gfs2_dirent *), compare_dents, NULL);
@ -1253,9 +1249,9 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
off_next = be32_to_cpu(dent_next->de_hash);
off_next = gfs2_disk_hash2offset(off_next);
if (off < *offset)
if (off < ctx->pos)
continue;
*offset = off;
ctx->pos = off;
if (off_next == off) {
if (*copied && !run)
@ -1264,26 +1260,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
} else
run = 0;
} else {
if (off < *offset)
if (off < ctx->pos)
continue;
*offset = off;
ctx->pos = off;
}
error = filldir(opaque, (const char *)(dent + 1),
if (!dir_emit(ctx, (const char *)(dent + 1),
be16_to_cpu(dent->de_name_len),
off, be64_to_cpu(dent->de_inum.no_addr),
be16_to_cpu(dent->de_type));
if (error)
be64_to_cpu(dent->de_inum.no_addr),
be16_to_cpu(dent->de_type)))
return 1;
*copied = 1;
}
/* Increment the *offset by one, so the next time we come into the
/* Increment the ctx->pos by one, so the next time we come into the
do_filldir fxn, we get the next entry instead of the last one in the
current leaf */
(*offset)++;
ctx->pos++;
return 0;
}
@ -1307,8 +1302,8 @@ static void gfs2_free_sort_buffer(void *ptr)
kfree(ptr);
}
static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir, int *copied, unsigned *depth,
static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
int *copied, unsigned *depth,
u64 leaf_no)
{
struct gfs2_inode *ip = GFS2_I(inode);
@ -1386,8 +1381,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
} while(lfn);
BUG_ON(entries2 != entries);
error = do_filldir_main(ip, offset, opaque, filldir, darr,
entries, copied);
error = do_filldir_main(ip, ctx, darr, entries, copied);
out_free:
for(i = 0; i < leaf; i++)
brelse(larr[i]);
@ -1446,15 +1440,13 @@ static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index,
/**
* dir_e_read - Reads the entries from a directory into a filldir buffer
* @dip: dinode pointer
* @offset: the hash of the last entry read shifted to the right once
* @opaque: buffer for the filldir function to fill
* @filldir: points to the filldir function to use
* @ctx: actor to feed the entries to
*
* Returns: errno
*/
static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir, struct file_ra_state *f_ra)
static int dir_e_read(struct inode *inode, struct dir_context *ctx,
struct file_ra_state *f_ra)
{
struct gfs2_inode *dip = GFS2_I(inode);
u32 hsize, len = 0;
@ -1465,7 +1457,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
unsigned depth = 0;
hsize = 1 << dip->i_depth;
hash = gfs2_dir_offset2hash(*offset);
hash = gfs2_dir_offset2hash(ctx->pos);
index = hash >> (32 - dip->i_depth);
if (dip->i_hash_cache == NULL)
@ -1477,7 +1469,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
gfs2_dir_readahead(inode, hsize, index, f_ra);
while (index < hsize) {
error = gfs2_dir_read_leaf(inode, offset, opaque, filldir,
error = gfs2_dir_read_leaf(inode, ctx,
&copied, &depth,
be64_to_cpu(lp[index]));
if (error)
@ -1492,8 +1484,8 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
return error;
}
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir, struct file_ra_state *f_ra)
int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
struct file_ra_state *f_ra)
{
struct gfs2_inode *dip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
@ -1507,7 +1499,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
return 0;
if (dip->i_diskflags & GFS2_DIF_EXHASH)
return dir_e_read(inode, offset, opaque, filldir, f_ra);
return dir_e_read(inode, ctx, f_ra);
if (!gfs2_is_stuffed(dip)) {
gfs2_consist_inode(dip);
@ -1539,7 +1531,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
error = -EIO;
goto out;
}
error = do_filldir_main(dip, offset, opaque, filldir, darr,
error = do_filldir_main(dip, ctx, darr,
dip->i_entries, &copied);
out:
kfree(darr);

View File

@ -24,8 +24,8 @@ extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
const struct gfs2_inode *ip);
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir, struct file_ra_state *f_ra);
extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
struct file_ra_state *f_ra);
extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
const struct gfs2_inode *nip, unsigned int new_type);

View File

@ -64,6 +64,7 @@ static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len,
}
struct get_name_filldir {
struct dir_context ctx;
struct gfs2_inum_host inum;
char *name;
};
@ -88,9 +89,11 @@ static int gfs2_get_name(struct dentry *parent, char *name,
struct inode *dir = parent->d_inode;
struct inode *inode = child->d_inode;
struct gfs2_inode *dip, *ip;
struct get_name_filldir gnfd;
struct get_name_filldir gnfd = {
.ctx.actor = get_name_filldir,
.name = name
};
struct gfs2_holder gh;
u64 offset = 0;
int error;
struct file_ra_state f_ra = { .start = 0 };
@ -106,13 +109,12 @@ static int gfs2_get_name(struct dentry *parent, char *name,
*name = 0;
gnfd.inum.no_addr = ip->i_no_addr;
gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
gnfd.name = name;
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
if (error)
return error;
error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir, &f_ra);
error = gfs2_dir_read(dir, &gnfd.ctx, &f_ra);
gfs2_glock_dq_uninit(&gh);

View File

@ -82,35 +82,28 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int whence)
}
/**
* gfs2_readdir - Read directory entries from a directory
* gfs2_readdir - Iterator for a directory
* @file: The directory to read from
* @dirent: Buffer for dirents
* @filldir: Function used to do the copying
* @ctx: What to feed directory entries to
*
* Returns: errno
*/
static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
static int gfs2_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *dir = file->f_mapping->host;
struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh;
u64 offset = file->f_pos;
int error;
gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
error = gfs2_glock_nq(&d_gh);
if (error) {
gfs2_holder_uninit(&d_gh);
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
if (error)
return error;
}
error = gfs2_dir_read(dir, &offset, dirent, filldir, &file->f_ra);
error = gfs2_dir_read(dir, ctx, &file->f_ra);
gfs2_glock_dq_uninit(&d_gh);
file->f_pos = offset;
return error;
}
@ -1048,7 +1041,7 @@ const struct file_operations gfs2_file_fops = {
};
const struct file_operations gfs2_dir_fops = {
.readdir = gfs2_readdir,
.iterate = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open,
.release = gfs2_release,
@ -1078,7 +1071,7 @@ const struct file_operations gfs2_file_fops_nolock = {
};
const struct file_operations gfs2_dir_fops_nolock = {
.readdir = gfs2_readdir,
.iterate = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open,
.release = gfs2_release,

View File

@ -51,9 +51,9 @@ static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
/*
* hfs_readdir
*/
static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int hfs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
int len, err;
char strbuf[HFS_MAX_NAMELEN];
@ -62,7 +62,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct hfs_readdir_data *rd;
u16 type;
if (filp->f_pos >= inode->i_size)
if (ctx->pos >= inode->i_size)
return 0;
err = hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
@ -73,14 +73,13 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (err)
goto out;
switch ((u32)filp->f_pos) {
case 0:
if (ctx->pos == 0) {
/* This is completely artificial... */
if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
if (!dir_emit_dot(file, ctx))
goto out;
filp->f_pos++;
/* fall through */
case 1:
ctx->pos = 1;
}
if (ctx->pos == 1) {
if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
err = -EIO;
goto out;
@ -97,18 +96,16 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
// err = -EIO;
// goto out;
//}
if (filldir(dirent, "..", 2, 1,
if (!dir_emit(ctx, "..", 2,
be32_to_cpu(entry.thread.ParID), DT_DIR))
goto out;
filp->f_pos++;
/* fall through */
default:
if (filp->f_pos >= inode->i_size)
goto out;
err = hfs_brec_goto(&fd, filp->f_pos - 1);
if (err)
goto out;
ctx->pos = 2;
}
if (ctx->pos >= inode->i_size)
goto out;
err = hfs_brec_goto(&fd, ctx->pos - 1);
if (err)
goto out;
for (;;) {
if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) {
@ -131,7 +128,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
err = -EIO;
goto out;
}
if (filldir(dirent, strbuf, len, filp->f_pos,
if (!dir_emit(ctx, strbuf, len,
be32_to_cpu(entry.dir.DirID), DT_DIR))
break;
} else if (type == HFS_CDR_FIL) {
@ -140,7 +137,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
err = -EIO;
goto out;
}
if (filldir(dirent, strbuf, len, filp->f_pos,
if (!dir_emit(ctx, strbuf, len,
be32_to_cpu(entry.file.FlNum), DT_REG))
break;
} else {
@ -148,22 +145,22 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
err = -EIO;
goto out;
}
filp->f_pos++;
if (filp->f_pos >= inode->i_size)
ctx->pos++;
if (ctx->pos >= inode->i_size)
goto out;
err = hfs_brec_goto(&fd, 1);
if (err)
goto out;
}
rd = filp->private_data;
rd = file->private_data;
if (!rd) {
rd = kmalloc(sizeof(struct hfs_readdir_data), GFP_KERNEL);
if (!rd) {
err = -ENOMEM;
goto out;
}
filp->private_data = rd;
rd->file = filp;
file->private_data = rd;
rd->file = file;
list_add(&rd->list, &HFS_I(inode)->open_dir_list);
}
memcpy(&rd->key, &fd.key, sizeof(struct hfs_cat_key));
@ -306,7 +303,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
const struct file_operations hfs_dir_operations = {
.read = generic_read_dir,
.readdir = hfs_readdir,
.iterate = hfs_readdir,
.llseek = generic_file_llseek,
.release = hfs_dir_release,
};

View File

@ -121,9 +121,9 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
return ERR_PTR(err);
}
static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
int len, err;
char strbuf[HFSPLUS_MAX_STRLEN + 1];
@ -132,7 +132,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct hfsplus_readdir_data *rd;
u16 type;
if (filp->f_pos >= inode->i_size)
if (file->f_pos >= inode->i_size)
return 0;
err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
@ -143,14 +143,13 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (err)
goto out;
switch ((u32)filp->f_pos) {
case 0:
if (ctx->pos == 0) {
/* This is completely artificial... */
if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
if (!dir_emit_dot(file, ctx))
goto out;
filp->f_pos++;
/* fall through */
case 1:
ctx->pos = 1;
}
if (ctx->pos == 1) {
if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
err = -EIO;
goto out;
@ -168,19 +167,16 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
err = -EIO;
goto out;
}
if (filldir(dirent, "..", 2, 1,
if (!dir_emit(ctx, "..", 2,
be32_to_cpu(entry.thread.parentID), DT_DIR))
goto out;
filp->f_pos++;
/* fall through */
default:
if (filp->f_pos >= inode->i_size)
goto out;
err = hfs_brec_goto(&fd, filp->f_pos - 1);
if (err)
goto out;
ctx->pos = 2;
}
if (ctx->pos >= inode->i_size)
goto out;
err = hfs_brec_goto(&fd, ctx->pos - 1);
if (err)
goto out;
for (;;) {
if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
pr_err("walked past end of dir\n");
@ -211,7 +207,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
HFSPLUS_SB(sb)->hidden_dir->i_ino ==
be32_to_cpu(entry.folder.id))
goto next;
if (filldir(dirent, strbuf, len, filp->f_pos,
if (!dir_emit(ctx, strbuf, len,
be32_to_cpu(entry.folder.id), DT_DIR))
break;
} else if (type == HFSPLUS_FILE) {
@ -220,7 +216,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
err = -EIO;
goto out;
}
if (filldir(dirent, strbuf, len, filp->f_pos,
if (!dir_emit(ctx, strbuf, len,
be32_to_cpu(entry.file.id), DT_REG))
break;
} else {
@ -229,22 +225,22 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto out;
}
next:
filp->f_pos++;
if (filp->f_pos >= inode->i_size)
ctx->pos++;
if (ctx->pos >= inode->i_size)
goto out;
err = hfs_brec_goto(&fd, 1);
if (err)
goto out;
}
rd = filp->private_data;
rd = file->private_data;
if (!rd) {
rd = kmalloc(sizeof(struct hfsplus_readdir_data), GFP_KERNEL);
if (!rd) {
err = -ENOMEM;
goto out;
}
filp->private_data = rd;
rd->file = filp;
file->private_data = rd;
rd->file = file;
list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list);
}
memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key));
@ -538,7 +534,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
const struct file_operations hfsplus_dir_operations = {
.fsync = hfsplus_file_fsync,
.read = generic_read_dir,
.readdir = hfsplus_readdir,
.iterate = hfsplus_readdir,
.unlocked_ioctl = hfsplus_ioctl,
.llseek = generic_file_llseek,
.release = hfsplus_dir_release,

View File

@ -277,7 +277,7 @@ static const struct super_operations hostfs_sbops = {
.show_options = hostfs_show_options,
};
int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
int hostfs_readdir(struct file *file, struct dir_context *ctx)
{
void *dir;
char *name;
@ -292,12 +292,11 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
__putname(name);
if (dir == NULL)
return -error;
next = file->f_pos;
next = ctx->pos;
while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) {
error = (*filldir)(ent, name, len, file->f_pos,
ino, type);
if (error) break;
file->f_pos = next;
if (!dir_emit(ctx, name, len, ino, type))
break;
ctx->pos = next;
}
close_dir(dir);
return 0;
@ -393,7 +392,7 @@ static const struct file_operations hostfs_file_fops = {
static const struct file_operations hostfs_dir_fops = {
.llseek = generic_file_llseek,
.readdir = hostfs_readdir,
.iterate = hostfs_readdir,
.read = generic_read_dir,
};

View File

@ -57,14 +57,14 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
return -ESPIPE;
}
static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int hpfs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
struct quad_buffer_head qbh;
struct hpfs_dirent *de;
int lc;
long old_pos;
loff_t next_pos;
unsigned char *tempname;
int c1, c2 = 0;
int ret = 0;
@ -105,11 +105,11 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
}
lc = hpfs_sb(inode->i_sb)->sb_lowercase;
if (filp->f_pos == 12) { /* diff -r requires this (note, that diff -r */
filp->f_pos = 13; /* also fails on msdos filesystem in 2.0) */
if (ctx->pos == 12) { /* diff -r requires this (note, that diff -r */
ctx->pos = 13; /* also fails on msdos filesystem in 2.0) */
goto out;
}
if (filp->f_pos == 13) {
if (ctx->pos == 13) {
ret = -ENOENT;
goto out;
}
@ -120,33 +120,34 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
accepted by filldir, but what can I do?
maybe killall -9 ls helps */
if (hpfs_sb(inode->i_sb)->sb_chk)
if (hpfs_stop_cycles(inode->i_sb, filp->f_pos, &c1, &c2, "hpfs_readdir")) {
if (hpfs_stop_cycles(inode->i_sb, ctx->pos, &c1, &c2, "hpfs_readdir")) {
ret = -EFSERROR;
goto out;
}
if (filp->f_pos == 12)
if (ctx->pos == 12)
goto out;
if (filp->f_pos == 3 || filp->f_pos == 4 || filp->f_pos == 5) {
printk("HPFS: warning: pos==%d\n",(int)filp->f_pos);
if (ctx->pos == 3 || ctx->pos == 4 || ctx->pos == 5) {
printk("HPFS: warning: pos==%d\n",(int)ctx->pos);
goto out;
}
if (filp->f_pos == 0) {
if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0)
if (ctx->pos == 0) {
if (!dir_emit_dot(file, ctx))
goto out;
filp->f_pos = 11;
ctx->pos = 11;
}
if (filp->f_pos == 11) {
if (filldir(dirent, "..", 2, filp->f_pos, hpfs_inode->i_parent_dir, DT_DIR) < 0)
if (ctx->pos == 11) {
if (!dir_emit(ctx, "..", 2, hpfs_inode->i_parent_dir, DT_DIR))
goto out;
filp->f_pos = 1;
ctx->pos = 1;
}
if (filp->f_pos == 1) {
filp->f_pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1;
hpfs_add_pos(inode, &filp->f_pos);
filp->f_version = inode->i_version;
if (ctx->pos == 1) {
ctx->pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1;
hpfs_add_pos(inode, &file->f_pos);
file->f_version = inode->i_version;
}
old_pos = filp->f_pos;
if (!(de = map_pos_dirent(inode, &filp->f_pos, &qbh))) {
next_pos = ctx->pos;
if (!(de = map_pos_dirent(inode, &next_pos, &qbh))) {
ctx->pos = next_pos;
ret = -EIOERROR;
goto out;
}
@ -154,20 +155,21 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (hpfs_sb(inode->i_sb)->sb_chk) {
if (de->first && !de->last && (de->namelen != 2
|| de ->name[0] != 1 || de->name[1] != 1))
hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", old_pos);
hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", (unsigned long)ctx->pos);
if (de->last && (de->namelen != 1 || de ->name[0] != 255))
hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", old_pos);
hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", (unsigned long)ctx->pos);
}
hpfs_brelse4(&qbh);
ctx->pos = next_pos;
goto again;
}
tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
if (filldir(dirent, tempname, de->namelen, old_pos, le32_to_cpu(de->fnode), DT_UNKNOWN) < 0) {
filp->f_pos = old_pos;
if (!dir_emit(ctx, tempname, de->namelen, le32_to_cpu(de->fnode), DT_UNKNOWN)) {
if (tempname != de->name) kfree(tempname);
hpfs_brelse4(&qbh);
goto out;
}
ctx->pos = next_pos;
if (tempname != de->name) kfree(tempname);
hpfs_brelse4(&qbh);
}
@ -322,7 +324,7 @@ const struct file_operations hpfs_dir_ops =
{
.llseek = hpfs_dir_lseek,
.read = generic_read_dir,
.readdir = hpfs_readdir,
.iterate = hpfs_readdir,
.release = hpfs_dir_release,
.fsync = hpfs_file_fsync,
};

View File

@ -542,8 +542,8 @@ static const struct file_operations hppfs_file_fops = {
};
struct hppfs_dirent {
void *vfs_dirent;
filldir_t filldir;
struct dir_context ctx;
struct dir_context *caller;
struct dentry *dentry;
};
@ -555,34 +555,29 @@ static int hppfs_filldir(void *d, const char *name, int size,
if (file_removed(dirent->dentry, name))
return 0;
return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
inode, type);
dirent->caller->pos = dirent->ctx.pos;
return !dir_emit(dirent->caller, name, size, inode, type);
}
static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
static int hppfs_readdir(struct file *file, struct dir_context *ctx)
{
struct hppfs_private *data = file->private_data;
struct file *proc_file = data->proc_file;
int (*readdir)(struct file *, void *, filldir_t);
struct hppfs_dirent dirent = ((struct hppfs_dirent)
{ .vfs_dirent = ent,
.filldir = filldir,
.dentry = file->f_path.dentry
});
struct hppfs_dirent d = {
.ctx.actor = hppfs_filldir,
.caller = ctx,
.dentry = file->f_path.dentry
};
int err;
readdir = file_inode(proc_file)->i_fop->readdir;
proc_file->f_pos = file->f_pos;
err = (*readdir)(proc_file, &dirent, hppfs_filldir);
file->f_pos = proc_file->f_pos;
proc_file->f_pos = ctx->pos;
err = iterate_dir(proc_file, &d.ctx);
ctx->pos = d.ctx.pos;
return err;
}
static const struct file_operations hppfs_dir_fops = {
.owner = NULL,
.readdir = hppfs_readdir,
.iterate = hppfs_readdir,
.open = hppfs_dir_open,
.llseek = default_llseek,
.release = hppfs_release,

View File

@ -78,8 +78,8 @@ int get_acorn_filename(struct iso_directory_record *de,
/*
* This should _really_ be cleaned up some day..
*/
static int do_isofs_readdir(struct inode *inode, struct file *filp,
void *dirent, filldir_t filldir,
static int do_isofs_readdir(struct inode *inode, struct file *file,
struct dir_context *ctx,
char *tmpname, struct iso_directory_record *tmpde)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
@ -94,10 +94,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
struct iso_directory_record *de;
struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
offset = filp->f_pos & (bufsize - 1);
block = filp->f_pos >> bufbits;
offset = ctx->pos & (bufsize - 1);
block = ctx->pos >> bufbits;
while (filp->f_pos < inode->i_size) {
while (ctx->pos < inode->i_size) {
int de_len;
if (!bh) {
@ -108,7 +108,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
de = (struct iso_directory_record *) (bh->b_data + offset);
de_len = *(unsigned char *) de;
de_len = *(unsigned char *)de;
/*
* If the length byte is zero, we should move on to the next
@ -119,8 +119,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
if (de_len == 0) {
brelse(bh);
bh = NULL;
filp->f_pos = (filp->f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
block = filp->f_pos >> bufbits;
ctx->pos = (ctx->pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
block = ctx->pos >> bufbits;
offset = 0;
continue;
}
@ -164,16 +164,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
if (de->flags[-sbi->s_high_sierra] & 0x80) {
first_de = 0;
filp->f_pos += de_len;
ctx->pos += de_len;
continue;
}
first_de = 1;
/* Handle the case of the '.' directory */
if (de->name_len[0] == 1 && de->name[0] == 0) {
if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0)
if (!dir_emit_dot(file, ctx))
break;
filp->f_pos += de_len;
ctx->pos += de_len;
continue;
}
@ -181,10 +181,9 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
/* Handle the case of the '..' directory */
if (de->name_len[0] == 1 && de->name[0] == 1) {
inode_number = parent_ino(filp->f_path.dentry);
if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0)
if (!dir_emit_dotdot(file, ctx))
break;
filp->f_pos += de_len;
ctx->pos += de_len;
continue;
}
@ -198,7 +197,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
if ((sbi->s_hide && (de->flags[-sbi->s_high_sierra] & 1)) ||
(!sbi->s_showassoc &&
(de->flags[-sbi->s_high_sierra] & 4))) {
filp->f_pos += de_len;
ctx->pos += de_len;
continue;
}
@ -230,10 +229,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
}
}
if (len > 0) {
if (filldir(dirent, p, len, filp->f_pos, inode_number, DT_UNKNOWN) < 0)
if (!dir_emit(ctx, p, len, inode_number, DT_UNKNOWN))
break;
}
filp->f_pos += de_len;
ctx->pos += de_len;
continue;
}
@ -247,13 +246,12 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
* handling split directory entries.. The real work is done by
* "do_isofs_readdir()".
*/
static int isofs_readdir(struct file *filp,
void *dirent, filldir_t filldir)
static int isofs_readdir(struct file *file, struct dir_context *ctx)
{
int result;
char *tmpname;
struct iso_directory_record *tmpde;
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
tmpname = (char *)__get_free_page(GFP_KERNEL);
if (tmpname == NULL)
@ -261,7 +259,7 @@ static int isofs_readdir(struct file *filp,
tmpde = (struct iso_directory_record *) (tmpname+1024);
result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
result = do_isofs_readdir(inode, file, ctx, tmpname, tmpde);
free_page((unsigned long) tmpname);
return result;
@ -271,7 +269,7 @@ const struct file_operations isofs_dir_operations =
{
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = isofs_readdir,
.iterate = isofs_readdir,
};
/*

View File

@ -22,7 +22,7 @@
#include <linux/time.h>
#include "nodelist.h"
static int jffs2_readdir (struct file *, void *, filldir_t);
static int jffs2_readdir (struct file *, struct dir_context *);
static int jffs2_create (struct inode *,struct dentry *,umode_t,
bool);
@ -40,7 +40,7 @@ static int jffs2_rename (struct inode *, struct dentry *,
const struct file_operations jffs2_dir_operations =
{
.read = generic_read_dir,
.readdir = jffs2_readdir,
.iterate = jffs2_readdir,
.unlocked_ioctl=jffs2_ioctl,
.fsync = jffs2_fsync,
.llseek = generic_file_llseek,
@ -114,60 +114,40 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
/***********************************************************************/
static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int jffs2_readdir(struct file *file, struct dir_context *ctx)
{
struct jffs2_inode_info *f;
struct inode *inode = file_inode(filp);
struct inode *inode = file_inode(file);
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_full_dirent *fd;
unsigned long offset, curofs;
unsigned long curofs = 1;
jffs2_dbg(1, "jffs2_readdir() for dir_i #%lu\n",
file_inode(filp)->i_ino);
jffs2_dbg(1, "jffs2_readdir() for dir_i #%lu\n", inode->i_ino);
f = JFFS2_INODE_INFO(inode);
if (!dir_emit_dots(file, ctx))
return 0;
offset = filp->f_pos;
if (offset == 0) {
jffs2_dbg(1, "Dirent 0: \".\", ino #%lu\n", inode->i_ino);
if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
goto out;
offset++;
}
if (offset == 1) {
unsigned long pino = parent_ino(filp->f_path.dentry);
jffs2_dbg(1, "Dirent 1: \"..\", ino #%lu\n", pino);
if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0)
goto out;
offset++;
}
curofs=1;
mutex_lock(&f->sem);
for (fd = f->dents; fd; fd = fd->next) {
curofs++;
/* First loop: curofs = 2; offset = 2 */
if (curofs < offset) {
/* First loop: curofs = 2; pos = 2 */
if (curofs < ctx->pos) {
jffs2_dbg(2, "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n",
fd->name, fd->ino, fd->type, curofs, offset);
fd->name, fd->ino, fd->type, curofs, (unsigned long)ctx->pos);
continue;
}
if (!fd->ino) {
jffs2_dbg(2, "Skipping deletion dirent \"%s\"\n",
fd->name);
offset++;
ctx->pos++;
continue;
}
jffs2_dbg(2, "Dirent %ld: \"%s\", ino #%u, type %d\n",
offset, fd->name, fd->ino, fd->type);
if (filldir(dirent, fd->name, strlen(fd->name), offset, fd->ino, fd->type) < 0)
(unsigned long)ctx->pos, fd->name, fd->ino, fd->type);
if (!dir_emit(ctx, fd->name, strlen(fd->name), fd->ino, fd->type))
break;
offset++;
ctx->pos++;
}
mutex_unlock(&f->sem);
out:
filp->f_pos = offset;
return 0;
}

View File

@ -3002,9 +3002,9 @@ static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
* return: offset = (pn, index) of start entry
* of next jfs_readdir()/dtRead()
*/
int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
int jfs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *ip = file_inode(filp);
struct inode *ip = file_inode(file);
struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
int rc = 0;
loff_t dtpos; /* legacy OS/2 style position */
@ -3033,7 +3033,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
int overflow, fix_page, page_fixed = 0;
static int unique_pos = 2; /* If we can't fix broken index */
if (filp->f_pos == DIREND)
if (ctx->pos == DIREND)
return 0;
if (DO_INDEX(ip)) {
@ -3045,7 +3045,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
*/
do_index = 1;
dir_index = (u32) filp->f_pos;
dir_index = (u32) ctx->pos;
if (dir_index > 1) {
struct dir_table_slot dirtab_slot;
@ -3053,25 +3053,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (dtEmpty(ip) ||
(dir_index >= JFS_IP(ip)->next_index)) {
/* Stale position. Directory has shrunk */
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
repeat:
rc = read_index(ip, dir_index, &dirtab_slot);
if (rc) {
filp->f_pos = DIREND;
ctx->pos = DIREND;
return rc;
}
if (dirtab_slot.flag == DIR_INDEX_FREE) {
if (loop_count++ > JFS_IP(ip)->next_index) {
jfs_err("jfs_readdir detected "
"infinite loop!");
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
dir_index = le32_to_cpu(dirtab_slot.addr2);
if (dir_index == -1) {
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
goto repeat;
@ -3080,13 +3080,13 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
index = dirtab_slot.slot;
DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc) {
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
if (p->header.flag & BT_INTERNAL) {
jfs_err("jfs_readdir: bad index table");
DT_PUTPAGE(mp);
filp->f_pos = -1;
ctx->pos = -1;
return 0;
}
} else {
@ -3094,23 +3094,22 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/*
* self "."
*/
filp->f_pos = 0;
if (filldir(dirent, ".", 1, 0, ip->i_ino,
DT_DIR))
ctx->pos = 0;
if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
return 0;
}
/*
* parent ".."
*/
filp->f_pos = 1;
if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
ctx->pos = 1;
if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
return 0;
/*
* Find first entry of left-most leaf
*/
if (dtEmpty(ip)) {
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
@ -3128,23 +3127,19 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
* pn > 0: Real entries, pn=1 -> leftmost page
* pn = index = -1: No more entries
*/
dtpos = filp->f_pos;
dtpos = ctx->pos;
if (dtpos == 0) {
/* build "." entry */
if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
DT_DIR))
if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
return 0;
dtoffset->index = 1;
filp->f_pos = dtpos;
ctx->pos = dtpos;
}
if (dtoffset->pn == 0) {
if (dtoffset->index == 1) {
/* build ".." entry */
if (filldir(dirent, "..", 2, filp->f_pos,
PARENT(ip), DT_DIR))
if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
return 0;
} else {
jfs_err("jfs_readdir called with "
@ -3152,18 +3147,18 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
dtoffset->pn = 1;
dtoffset->index = 0;
filp->f_pos = dtpos;
ctx->pos = dtpos;
}
if (dtEmpty(ip)) {
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
if ((rc = dtReadNext(ip, &filp->f_pos, &btstack))) {
if ((rc = dtReadNext(ip, &ctx->pos, &btstack))) {
jfs_err("jfs_readdir: unexpected rc = %d "
"from dtReadNext", rc);
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
/* get start leaf page and index */
@ -3171,7 +3166,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* offset beyond directory eof ? */
if (bn < 0) {
filp->f_pos = DIREND;
ctx->pos = DIREND;
return 0;
}
}
@ -3180,7 +3175,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (dirent_buf == 0) {
DT_PUTPAGE(mp);
jfs_warn("jfs_readdir: __get_free_page failed!");
filp->f_pos = DIREND;
ctx->pos = DIREND;
return -ENOMEM;
}
@ -3295,9 +3290,9 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
jfs_dirent = (struct jfs_dirent *) dirent_buf;
while (jfs_dirents--) {
filp->f_pos = jfs_dirent->position;
if (filldir(dirent, jfs_dirent->name,
jfs_dirent->name_len, filp->f_pos,
ctx->pos = jfs_dirent->position;
if (!dir_emit(ctx, jfs_dirent->name,
jfs_dirent->name_len,
jfs_dirent->ino, DT_UNKNOWN))
goto out;
jfs_dirent = next_jfs_dirent(jfs_dirent);
@ -3309,7 +3304,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
if (!overflow && (bn == 0)) {
filp->f_pos = DIREND;
ctx->pos = DIREND;
break;
}

View File

@ -265,5 +265,5 @@ extern int dtDelete(tid_t tid, struct inode *ip, struct component_name * key,
extern int dtModify(tid_t tid, struct inode *ip, struct component_name * key,
ino_t * orig_ino, ino_t new_ino, int flag);
extern int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir);
extern int jfs_readdir(struct file *file, struct dir_context *ctx);
#endif /* !_H_JFS_DTREE */

View File

@ -1529,7 +1529,7 @@ const struct inode_operations jfs_dir_inode_operations = {
const struct file_operations jfs_dir_operations = {
.read = generic_read_dir,
.readdir = jfs_readdir,
.iterate = jfs_readdir,
.fsync = jfs_fsync,
.unlocked_ioctl = jfs_ioctl,
#ifdef CONFIG_COMPAT

View File

@ -135,60 +135,40 @@ static inline unsigned char dt_type(struct inode *inode)
* both impossible due to the lock on directory.
*/
int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
int dcache_readdir(struct file *file, struct dir_context *ctx)
{
struct dentry *dentry = filp->f_path.dentry;
struct dentry *cursor = filp->private_data;
struct dentry *dentry = file->f_path.dentry;
struct dentry *cursor = file->private_data;
struct list_head *p, *q = &cursor->d_u.d_child;
ino_t ino;
int i = filp->f_pos;
switch (i) {
case 0:
ino = dentry->d_inode->i_ino;
if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
break;
filp->f_pos++;
i++;
/* fallthrough */
case 1:
ino = parent_ino(dentry);
if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
break;
filp->f_pos++;
i++;
/* fallthrough */
default:
spin_lock(&dentry->d_lock);
if (filp->f_pos == 2)
list_move(q, &dentry->d_subdirs);
if (!dir_emit_dots(file, ctx))
return 0;
spin_lock(&dentry->d_lock);
if (ctx->pos == 2)
list_move(q, &dentry->d_subdirs);
for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
struct dentry *next;
next = list_entry(p, struct dentry, d_u.d_child);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
if (!simple_positive(next)) {
spin_unlock(&next->d_lock);
continue;
}
for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
if (!simple_positive(next)) {
spin_unlock(&next->d_lock);
continue;
}
spin_unlock(&next->d_lock);
spin_unlock(&dentry->d_lock);
if (filldir(dirent, next->d_name.name,
next->d_name.len, filp->f_pos,
next->d_inode->i_ino,
dt_type(next->d_inode)) < 0)
return 0;
spin_lock(&dentry->d_lock);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
/* next is still alive */
list_move(q, p);
spin_unlock(&next->d_lock);
p = q;
filp->f_pos++;
}
spin_unlock(&dentry->d_lock);
spin_unlock(&next->d_lock);
spin_unlock(&dentry->d_lock);
if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
next->d_inode->i_ino, dt_type(next->d_inode)))
return 0;
spin_lock(&dentry->d_lock);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
/* next is still alive */
list_move(q, p);
spin_unlock(&next->d_lock);
p = q;
ctx->pos++;
}
spin_unlock(&dentry->d_lock);
return 0;
}
@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = {
.release = dcache_dir_close,
.llseek = dcache_dir_lseek,
.read = generic_read_dir,
.readdir = dcache_readdir,
.iterate = dcache_readdir,
.fsync = noop_fsync,
};

View File

@ -281,17 +281,23 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry)
/* FIXME: readdir currently has it's own dir_walk code. I don't see a good
* way to combine the two copies */
#define IMPLICIT_NODES 2
static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
static int logfs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *dir = file_inode(file);
loff_t pos = file->f_pos - IMPLICIT_NODES;
loff_t pos;
struct page *page;
struct logfs_disk_dentry *dd;
int full;
if (ctx->pos < 0)
return -EINVAL;
if (!dir_emit_dots(file, ctx))
return 0;
pos = ctx->pos - 2;
BUG_ON(pos < 0);
for (;; pos++) {
for (;; pos++, ctx->pos++) {
bool full;
if (beyond_eof(dir, pos))
break;
if (!logfs_exist_block(dir, pos)) {
@ -306,42 +312,17 @@ static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
dd = kmap(page);
BUG_ON(dd->namelen == 0);
full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
pos, be64_to_cpu(dd->ino), dd->type);
full = !dir_emit(ctx, (char *)dd->name,
be16_to_cpu(dd->namelen),
be64_to_cpu(dd->ino), dd->type);
kunmap(page);
page_cache_release(page);
if (full)
break;
}
file->f_pos = pos + IMPLICIT_NODES;
return 0;
}
static int logfs_readdir(struct file *file, void *buf, filldir_t filldir)
{
struct inode *inode = file_inode(file);
ino_t pino = parent_ino(file->f_dentry);
int err;
if (file->f_pos < 0)
return -EINVAL;
if (file->f_pos == 0) {
if (filldir(buf, ".", 1, 1, inode->i_ino, DT_DIR) < 0)
return 0;
file->f_pos++;
}
if (file->f_pos == 1) {
if (filldir(buf, "..", 2, 2, pino, DT_DIR) < 0)
return 0;
file->f_pos++;
}
err = __logfs_readdir(file, buf, filldir);
return err;
}
static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
{
dd->namelen = cpu_to_be16(name->len);
@ -814,7 +795,7 @@ const struct inode_operations logfs_dir_iops = {
const struct file_operations logfs_dir_fops = {
.fsync = logfs_fsync,
.unlocked_ioctl = logfs_ioctl,
.readdir = logfs_readdir,
.iterate = logfs_readdir,
.read = generic_read_dir,
.llseek = default_llseek,
};

Some files were not shown because too many files have changed in this diff Show More