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
Родитель 7747bd4bce ac6614b764
Коммит 63580e51bb
144 изменённых файлов: 1937 добавлений и 2824 удалений

Просмотреть файл

@ -414,7 +414,7 @@ prototypes:
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 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_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (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 *); unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

Просмотреть файл

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

Просмотреть файл

@ -777,7 +777,7 @@ struct file_operations {
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 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_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (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 *); unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_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 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 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 activity on this file and (optionally) go to sleep until there

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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' * remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from' * 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> #include <asm-generic/pgtable.h>
/* to cope with aliasing VIPT cache */ /* to cope with aliasing VIPT cache */

Просмотреть файл

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

Просмотреть файл

@ -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
#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN #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) #define pgtable_cache_init() do { } while (0)
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

Просмотреть файл

@ -320,13 +320,6 @@ extern int kern_addr_valid(unsigned long addr);
#include <asm-generic/pgtable.h> #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) #define pgtable_cache_init() do { } while (0)
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

Просмотреть файл

@ -362,9 +362,6 @@ typedef pte_t *pte_addr_t;
#define kern_addr_valid(addr) (1) #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 (?) */ /* No page table caches to initialize (?) */
#define pgtable_cache_init() do { } while(0) #define pgtable_cache_init() do { } while(0)

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -258,9 +258,6 @@ static inline pgd_t * pgd_offset(const struct mm_struct *mm, unsigned long addre
#define pgd_ERROR(e) \ #define pgd_ERROR(e) \
printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(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 */ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */

Просмотреть файл

@ -488,9 +488,6 @@ static inline int pte_file(pte_t pte)
#define PageSkip(page) (0) #define PageSkip(page) (0)
#define kern_addr_valid(addr) (1) #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_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT #define __HAVE_ARCH_PTEP_SET_WRPROTECT

Просмотреть файл

@ -52,9 +52,6 @@ extern int is_in_rom(unsigned long);
*/ */
#define pgtable_cache_init() do { } while (0) #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... * All 32bit addresses are effectively valid for vmalloc...
* Sort of meaningless for non-VM targets. * Sort of meaningless for non-VM targets.

Просмотреть файл

@ -452,10 +452,6 @@ static inline int pte_exec(pte_t pte)
#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #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 */ /* I think this is in case we have page table caches; needed by init/main.c */
#define pgtable_cache_init() do { } while (0) #define pgtable_cache_init() do { } while (0)

Просмотреть файл

@ -493,9 +493,6 @@ extern void paging_init (void);
#define pte_to_pgoff(pte) ((pte_val(pte) << 1) >> 3) #define pte_to_pgoff(pte) ((pte_val(pte) << 1) >> 3)
#define pgoff_to_pte(off) ((pte_t) { ((off) << 2) | _PAGE_FILE }) #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 * ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc.. * for zero-mapped memory areas etc..

Просмотреть файл

@ -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 */ /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
#define kern_addr_valid(addr) (1) #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_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT #define __HAVE_ARCH_PTEP_SET_WRPROTECT

Просмотреть файл

@ -135,9 +135,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1) #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 */ /* MMU-specific headers */
#ifdef CONFIG_SUN3 #ifdef CONFIG_SUN3

Просмотреть файл

@ -55,9 +55,6 @@ extern unsigned int kobjsize(const void *objp);
*/ */
#define pgtable_cache_init() do { } while (0) #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... * All 32bit addresses are effectively valid for vmalloc...
* Sort of meaningless for non-VM targets. * Sort of meaningless for non-VM targets.

Просмотреть файл

@ -333,9 +333,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1) #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 * No page table caches to initialise
*/ */

Просмотреть файл

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

Просмотреть файл

@ -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); 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); return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot);
} }
#else #define io_remap_pfn_range io_remap_pfn_range
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif #endif
#ifdef CONFIG_TRANSPARENT_HUGEPAGE #ifdef CONFIG_TRANSPARENT_HUGEPAGE

Просмотреть файл

@ -486,9 +486,6 @@ extern void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1) #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 MK_IOSPACE_PFN(space, pfn) (pfn)
#define GET_IOSPACE(pfn) 0 #define GET_IOSPACE(pfn) 0
#define GET_PFN(pfn) (pfn) #define GET_PFN(pfn) (pfn)

Просмотреть файл

@ -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 /* Leave vm_pgoff as-is, the PCI space address is the physical
* address on this platform. * address on this platform.
*/ */
vma->vm_flags |= VM_LOCKED | VM_IO; vma->vm_flags |= VM_LOCKED;
prot = pgprot_val(vma->vm_page_prot); prot = pgprot_val(vma->vm_page_prot);
prot &= ~_PAGE_CACHE; prot &= ~_PAGE_CACHE;

Просмотреть файл

@ -446,9 +446,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1) #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> #include <asm-generic/pgtable.h>
/* /*

Просмотреть файл

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

Просмотреть файл

@ -506,9 +506,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
#endif #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) #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_NO_CACHE)
/* We provide our own get_unmapped_area to provide cache coherency */ /* We provide our own get_unmapped_area to provide cache coherency */

Просмотреть файл

@ -198,9 +198,6 @@ extern void paging_init(void);
*/ */
#define kern_addr_valid(addr) (1) #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> #include <asm-generic/pgtable.h>

Просмотреть файл

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

Просмотреть файл

@ -58,9 +58,6 @@ extern unsigned long zero_page_mask;
#define __HAVE_COLOR_ZERO_PAGE #define __HAVE_COLOR_ZERO_PAGE
/* TODO: s390 cannot support io_remap_pfn_range... */ /* 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__ */ #endif /* !__ASSEMBLY__ */
/* /*

Просмотреть файл

@ -113,9 +113,6 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
#define pte_clear(mm, addr, xp) \ #define pte_clear(mm, addr, xp) \
do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) 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 * 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 * setup: the pgd is never bad, and a pmd always exists (as it's folded

Просмотреть файл

@ -124,9 +124,6 @@ typedef pte_t *pte_addr_t;
#define kern_addr_valid(addr) (1) #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))) #define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
/* /*

Просмотреть файл

@ -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); 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 __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \

Просмотреть файл

@ -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); 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/tlbflush.h>
#include <asm-generic/pgtable.h> #include <asm-generic/pgtable.h>

Просмотреть файл

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

Просмотреть файл

@ -362,9 +362,6 @@ do { \
#define kern_addr_valid(addr) (1) #define kern_addr_valid(addr) (1)
#endif /* CONFIG_FLATMEM */ #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); extern void vmalloc_sync_all(void);
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

Просмотреть файл

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

Просмотреть файл

@ -303,13 +303,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#include <asm-generic/pgtable.h> #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) #define pgtable_cache_init() do { } while (0)
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

Просмотреть файл

@ -506,9 +506,6 @@ static inline unsigned long pages_to_mb(unsigned long npg)
return npg >> (20 - PAGE_SHIFT); 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 #if PAGETABLE_LEVELS > 2
static inline int pud_none(pud_t pud) static inline int pud_none(pud_t pud)
{ {

Просмотреть файл

@ -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, extern void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t *ptep); 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; typedef pte_t *pte_addr_t;
#endif /* !defined (__ASSEMBLY__) */ #endif /* !defined (__ASSEMBLY__) */

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -617,7 +617,6 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
case _DRM_FRAME_BUFFER: case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS: case _DRM_REGISTERS:
offset = drm_core_get_reg_ofs(dev); 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); vma->vm_page_prot = drm_io_prot(map->type, vma);
if (io_remap_pfn_range(vma, vma->vm_start, if (io_remap_pfn_range(vma, vma->vm_start,
(map->offset + offset) >> PAGE_SHIFT, (map->offset + offset) >> PAGE_SHIFT,

Просмотреть файл

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

Просмотреть файл

@ -499,7 +499,6 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
} }
vma->vm_private_data = vdev; 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_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff; vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff;

Просмотреть файл

@ -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); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 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, if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_end - vma->vm_start,
vma->vm_page_prot)) { vma->vm_page_prot)) {

Просмотреть файл

@ -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); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ 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, return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_end - vma->vm_start,
vma->vm_page_prot); vma->vm_page_prot);
return 0;
} }
static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -45,7 +45,7 @@ static ssize_t bad_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
return -EIO; 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; return -EIO;
} }
@ -152,7 +152,7 @@ static const struct file_operations bad_file_ops =
.write = bad_file_write, .write = bad_file_write,
.aio_read = bad_file_aio_read, .aio_read = bad_file_aio_read,
.aio_write = bad_file_aio_write, .aio_write = bad_file_aio_write,
.readdir = bad_file_readdir, .iterate = bad_file_readdir,
.poll = bad_file_poll, .poll = bad_file_poll,
.unlocked_ioctl = bad_file_unlocked_ioctl, .unlocked_ioctl = bad_file_unlocked_ioctl,
.compat_ioctl = bad_file_compat_ioctl, .compat_ioctl = bad_file_compat_ioctl,

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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 * btrfs_readdir_delayed_dir_index - read dir info stored in the delayed tree
* *
*/ */
int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
filldir_t filldir,
struct list_head *ins_list) struct list_head *ins_list)
{ {
struct btrfs_dir_item *di; 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_for_each_entry_safe(curr, next, ins_list, readdir_list) {
list_del(&curr->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)) if (atomic_dec_and_test(&curr->refs))
kfree(curr); kfree(curr);
continue; continue;
} }
filp->f_pos = curr->key.offset; ctx->pos = curr->key.offset;
di = (struct btrfs_dir_item *)curr->data; di = (struct btrfs_dir_item *)curr->data;
name = (char *)(di + 1); 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]; d_type = btrfs_filetype_table[di->type];
btrfs_disk_key_to_cpu(&location, &di->location); 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); location.objectid, d_type);
if (atomic_dec_and_test(&curr->refs)) if (atomic_dec_and_test(&curr->refs))

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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 int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
extern const struct file_operations cifs_dir_ops; extern const struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file); 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 */ /* Functions related to dir entries */
extern const struct dentry_operations cifs_dentry_ops; extern const struct dentry_operations cifs_dentry_ops;

Просмотреть файл

@ -537,14 +537,14 @@ static int cifs_save_resume_key(const char *current_entry,
* every entry (do not increment for . or .. entry). * every entry (do not increment for . or .. entry).
*/ */
static int 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) struct file *file, char **current_entry, int *num_to_ret)
{ {
__u16 search_flags; __u16 search_flags;
int rc = 0; int rc = 0;
int pos_in_buf = 0; int pos_in_buf = 0;
loff_t first_entry_in_buffer; 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 cifsFileInfo *cfile = file->private_data;
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
struct TCP_Server_Info *server = tcon->ses->server; 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; return rc;
} }
static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, static int cifs_filldir(char *find_entry, struct file *file,
void *dirent, char *scratch_buf, unsigned int max_len) struct dir_context *ctx,
char *scratch_buf, unsigned int max_len)
{ {
struct cifsFileInfo *file_info = file->private_data; struct cifsFileInfo *file_info = file->private_data;
struct super_block *sb = file->f_path.dentry->d_sb; 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); cifs_prime_dcache(file->f_dentry, &name, &fattr);
ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
rc = filldir(dirent, name.name, name.len, file->f_pos, ino, return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
fattr.cf_dtype);
return rc;
} }
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) int cifs_readdir(struct file *file, struct dir_context *ctx)
{ {
int rc = 0; int rc = 0;
unsigned int xid; unsigned int xid;
@ -772,103 +771,86 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
goto rddir2_exit; goto rddir2_exit;
} }
switch ((int) file->f_pos) { if (!dir_emit_dots(file, ctx))
case 0: goto rddir2_exit;
if (filldir(direntry, ".", 1, file->f_pos,
file_inode(file)->i_ino, DT_DIR) < 0) { /* 1) If search is active,
cifs_dbg(VFS, "Filldir for current dir failed\n"); is in current search buffer?
rc = -ENOMEM; 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; break;
} }
file->f_pos++; /*
case 1: * if buggy server returns . and .. late do we want to
if (filldir(direntry, "..", 2, file->f_pos, * check for that here?
parent_ino(file->f_path.dentry), DT_DIR) < 0) { */
cifs_dbg(VFS, "Filldir for parent dir failed\n"); rc = cifs_filldir(current_entry, file, ctx,
rc = -ENOMEM; tmp_buf, max_len);
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 (rc) { if (rc) {
cifs_dbg(FYI, "fce error %d\n", rc); if (rc > 0)
goto rddir2_exit; rc = 0;
} 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;
break; break;
} }
for (i = 0; (i < num_to_fill) && (rc == 0); i++) { ctx->pos++;
if (current_entry == NULL) { if (ctx->pos ==
/* evaluate whether this case is an error */ cifsFile->srch_inf.index_of_last_entry) {
cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
num_to_fill, i); ctx->pos, tmp_buf);
break; cifs_save_resume_key(current_entry, cifsFile);
} break;
/* } else
* if buggy server returns . and .. late do we want to current_entry =
* check for that here? nxt_dir_entry(current_entry, end_of_smb,
*/ cifsFile->srch_inf.info_level);
rc = cifs_filldir(current_entry, file, filldir, }
direntry, tmp_buf, max_len); kfree(tmp_buf);
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 */
rddir2_exit: rddir2_exit:
free_xid(xid); free_xid(xid);

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -287,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
} }
static int static int
ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) ext2_readdir(struct file *file, struct dir_context *ctx)
{ {
loff_t pos = filp->f_pos; loff_t pos = ctx->pos;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
unsigned int offset = pos & ~PAGE_CACHE_MASK; unsigned int offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT; unsigned long n = pos >> PAGE_CACHE_SHIFT;
unsigned long npages = dir_pages(inode); unsigned long npages = dir_pages(inode);
unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
unsigned char *types = NULL; unsigned char *types = NULL;
int need_revalidate = filp->f_version != inode->i_version; int need_revalidate = file->f_version != inode->i_version;
if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
return 0; return 0;
@ -314,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
ext2_error(sb, __func__, ext2_error(sb, __func__,
"bad page in #%lu", "bad page in #%lu",
inode->i_ino); inode->i_ino);
filp->f_pos += PAGE_CACHE_SIZE - offset; ctx->pos += PAGE_CACHE_SIZE - offset;
return PTR_ERR(page); return PTR_ERR(page);
} }
kaddr = page_address(page); kaddr = page_address(page);
if (unlikely(need_revalidate)) { if (unlikely(need_revalidate)) {
if (offset) { if (offset) {
offset = ext2_validate_entry(kaddr, offset, chunk_mask); offset = ext2_validate_entry(kaddr, offset, chunk_mask);
filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset;
} }
filp->f_version = inode->i_version; file->f_version = inode->i_version;
need_revalidate = 0; need_revalidate = 0;
} }
de = (ext2_dirent *)(kaddr+offset); de = (ext2_dirent *)(kaddr+offset);
@ -336,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
return -EIO; return -EIO;
} }
if (de->inode) { if (de->inode) {
int over;
unsigned char d_type = DT_UNKNOWN; unsigned char d_type = DT_UNKNOWN;
if (types && de->file_type < EXT2_FT_MAX) if (types && de->file_type < EXT2_FT_MAX)
d_type = types[de->file_type]; d_type = types[de->file_type];
offset = (char *)de - kaddr; if (!dir_emit(ctx, de->name, de->name_len,
over = filldir(dirent, de->name, de->name_len, le32_to_cpu(de->inode),
(n<<PAGE_CACHE_SHIFT) | offset, d_type)) {
le32_to_cpu(de->inode), d_type);
if (over) {
ext2_put_page(page); ext2_put_page(page);
return 0; return 0;
} }
} }
filp->f_pos += ext2_rec_len_from_disk(de->rec_len); ctx->pos += ext2_rec_len_from_disk(de->rec_len);
} }
ext2_put_page(page); ext2_put_page(page);
} }
@ -724,7 +721,7 @@ not_empty:
const struct file_operations ext2_dir_operations = { const struct file_operations ext2_dir_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = ext2_readdir, .iterate = ext2_readdir,
.unlocked_ioctl = ext2_ioctl, .unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = ext2_compat_ioctl, .compat_ioctl = ext2_compat_ioctl,

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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, extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
const struct gfs2_inode *ip); const struct gfs2_inode *ip);
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); 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, extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
filldir_t filldir, struct file_ra_state *f_ra); struct file_ra_state *f_ra);
extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
const struct gfs2_inode *nip, unsigned int new_type); const struct gfs2_inode *nip, unsigned int new_type);

Просмотреть файл

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

Просмотреть файл

@ -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 * @file: The directory to read from
* @dirent: Buffer for dirents * @ctx: What to feed directory entries to
* @filldir: Function used to do the copying
* *
* Returns: errno * 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 inode *dir = file->f_mapping->host;
struct gfs2_inode *dip = GFS2_I(dir); struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh; struct gfs2_holder d_gh;
u64 offset = file->f_pos;
int error; int error;
gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
error = gfs2_glock_nq(&d_gh); if (error)
if (error) {
gfs2_holder_uninit(&d_gh);
return 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); gfs2_glock_dq_uninit(&d_gh);
file->f_pos = offset;
return error; return error;
} }
@ -1048,7 +1041,7 @@ const struct file_operations gfs2_file_fops = {
}; };
const struct file_operations gfs2_dir_fops = { const struct file_operations gfs2_dir_fops = {
.readdir = gfs2_readdir, .iterate = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl, .unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open, .open = gfs2_open,
.release = gfs2_release, .release = gfs2_release,
@ -1078,7 +1071,7 @@ const struct file_operations gfs2_file_fops_nolock = {
}; };
const struct file_operations gfs2_dir_fops_nolock = { const struct file_operations gfs2_dir_fops_nolock = {
.readdir = gfs2_readdir, .iterate = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl, .unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open, .open = gfs2_open,
.release = gfs2_release, .release = gfs2_release,

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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, extern int dtModify(tid_t tid, struct inode *ip, struct component_name * key,
ino_t * orig_ino, ino_t new_ino, int flag); 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 */ #endif /* !_H_JFS_DTREE */

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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 /* FIXME: readdir currently has it's own dir_walk code. I don't see a good
* way to combine the two copies */ * way to combine the two copies */
#define IMPLICIT_NODES 2 static int logfs_readdir(struct file *file, struct dir_context *ctx)
static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
{ {
struct inode *dir = file_inode(file); struct inode *dir = file_inode(file);
loff_t pos = file->f_pos - IMPLICIT_NODES; loff_t pos;
struct page *page; struct page *page;
struct logfs_disk_dentry *dd; 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); BUG_ON(pos < 0);
for (;; pos++) { for (;; pos++, ctx->pos++) {
bool full;
if (beyond_eof(dir, pos)) if (beyond_eof(dir, pos))
break; break;
if (!logfs_exist_block(dir, pos)) { 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); dd = kmap(page);
BUG_ON(dd->namelen == 0); BUG_ON(dd->namelen == 0);
full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen), full = !dir_emit(ctx, (char *)dd->name,
pos, be64_to_cpu(dd->ino), dd->type); be16_to_cpu(dd->namelen),
be64_to_cpu(dd->ino), dd->type);
kunmap(page); kunmap(page);
page_cache_release(page); page_cache_release(page);
if (full) if (full)
break; break;
} }
file->f_pos = pos + IMPLICIT_NODES;
return 0; 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) static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
{ {
dd->namelen = cpu_to_be16(name->len); 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 = { const struct file_operations logfs_dir_fops = {
.fsync = logfs_fsync, .fsync = logfs_fsync,
.unlocked_ioctl = logfs_ioctl, .unlocked_ioctl = logfs_ioctl,
.readdir = logfs_readdir, .iterate = logfs_readdir,
.read = generic_read_dir, .read = generic_read_dir,
.llseek = default_llseek, .llseek = default_llseek,
}; };

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше