diff options
-rw-r--r-- | fs/ext2/dir.c | 27 | ||||
-rw-r--r-- | fs/minix/dir.c | 42 | ||||
-rw-r--r-- | fs/sysv/dir.c | 37 | ||||
-rw-r--r-- | fs/ufs/dir.c | 28 |
4 files changed, 59 insertions, 75 deletions
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 4237722bfd27..6e1d4ab09d72 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -287,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode) | |||
287 | } | 287 | } |
288 | 288 | ||
289 | static int | 289 | static int |
290 | ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | 290 | ext2_readdir(struct file *file, struct dir_context *ctx) |
291 | { | 291 | { |
292 | loff_t pos = filp->f_pos; | 292 | loff_t pos = ctx->pos; |
293 | struct inode *inode = file_inode(filp); | 293 | struct inode *inode = file_inode(file); |
294 | struct super_block *sb = inode->i_sb; | 294 | struct super_block *sb = inode->i_sb; |
295 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 295 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
296 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 296 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
297 | unsigned long npages = dir_pages(inode); | 297 | unsigned long npages = dir_pages(inode); |
298 | unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); | 298 | unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); |
299 | unsigned char *types = NULL; | 299 | unsigned char *types = NULL; |
300 | int need_revalidate = filp->f_version != inode->i_version; | 300 | int need_revalidate = file->f_version != inode->i_version; |
301 | 301 | ||
302 | if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) | 302 | if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) |
303 | return 0; | 303 | return 0; |
@@ -314,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | |||
314 | ext2_error(sb, __func__, | 314 | ext2_error(sb, __func__, |
315 | "bad page in #%lu", | 315 | "bad page in #%lu", |
316 | inode->i_ino); | 316 | inode->i_ino); |
317 | filp->f_pos += PAGE_CACHE_SIZE - offset; | 317 | ctx->pos += PAGE_CACHE_SIZE - offset; |
318 | return PTR_ERR(page); | 318 | return PTR_ERR(page); |
319 | } | 319 | } |
320 | kaddr = page_address(page); | 320 | kaddr = page_address(page); |
321 | if (unlikely(need_revalidate)) { | 321 | if (unlikely(need_revalidate)) { |
322 | if (offset) { | 322 | if (offset) { |
323 | offset = ext2_validate_entry(kaddr, offset, chunk_mask); | 323 | offset = ext2_validate_entry(kaddr, offset, chunk_mask); |
324 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; | 324 | ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset; |
325 | } | 325 | } |
326 | filp->f_version = inode->i_version; | 326 | file->f_version = inode->i_version; |
327 | need_revalidate = 0; | 327 | need_revalidate = 0; |
328 | } | 328 | } |
329 | de = (ext2_dirent *)(kaddr+offset); | 329 | de = (ext2_dirent *)(kaddr+offset); |
@@ -336,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | |||
336 | return -EIO; | 336 | return -EIO; |
337 | } | 337 | } |
338 | if (de->inode) { | 338 | if (de->inode) { |
339 | int over; | ||
340 | unsigned char d_type = DT_UNKNOWN; | 339 | unsigned char d_type = DT_UNKNOWN; |
341 | 340 | ||
342 | if (types && de->file_type < EXT2_FT_MAX) | 341 | if (types && de->file_type < EXT2_FT_MAX) |
343 | d_type = types[de->file_type]; | 342 | d_type = types[de->file_type]; |
344 | 343 | ||
345 | offset = (char *)de - kaddr; | 344 | if (!dir_emit(ctx, de->name, de->name_len, |
346 | over = filldir(dirent, de->name, de->name_len, | 345 | le32_to_cpu(de->inode), |
347 | (n<<PAGE_CACHE_SHIFT) | offset, | 346 | d_type)) { |
348 | le32_to_cpu(de->inode), d_type); | ||
349 | if (over) { | ||
350 | ext2_put_page(page); | 347 | ext2_put_page(page); |
351 | return 0; | 348 | return 0; |
352 | } | 349 | } |
353 | } | 350 | } |
354 | filp->f_pos += ext2_rec_len_from_disk(de->rec_len); | 351 | ctx->pos += ext2_rec_len_from_disk(de->rec_len); |
355 | } | 352 | } |
356 | ext2_put_page(page); | 353 | ext2_put_page(page); |
357 | } | 354 | } |
@@ -724,7 +721,7 @@ not_empty: | |||
724 | const struct file_operations ext2_dir_operations = { | 721 | const struct file_operations ext2_dir_operations = { |
725 | .llseek = generic_file_llseek, | 722 | .llseek = generic_file_llseek, |
726 | .read = generic_read_dir, | 723 | .read = generic_read_dir, |
727 | .readdir = ext2_readdir, | 724 | .iterate = ext2_readdir, |
728 | .unlocked_ioctl = ext2_ioctl, | 725 | .unlocked_ioctl = ext2_ioctl, |
729 | #ifdef CONFIG_COMPAT | 726 | #ifdef CONFIG_COMPAT |
730 | .compat_ioctl = ext2_compat_ioctl, | 727 | .compat_ioctl = ext2_compat_ioctl, |
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index a9ed6f36e6ea..08c442902fcd 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
@@ -16,12 +16,12 @@ | |||
16 | typedef struct minix_dir_entry minix_dirent; | 16 | typedef struct minix_dir_entry minix_dirent; |
17 | typedef struct minix3_dir_entry minix3_dirent; | 17 | typedef struct minix3_dir_entry minix3_dirent; |
18 | 18 | ||
19 | static int minix_readdir(struct file *, void *, filldir_t); | 19 | static int minix_readdir(struct file *, struct dir_context *); |
20 | 20 | ||
21 | const struct file_operations minix_dir_operations = { | 21 | const struct file_operations minix_dir_operations = { |
22 | .llseek = generic_file_llseek, | 22 | .llseek = generic_file_llseek, |
23 | .read = generic_read_dir, | 23 | .read = generic_read_dir, |
24 | .readdir = minix_readdir, | 24 | .iterate = minix_readdir, |
25 | .fsync = generic_file_fsync, | 25 | .fsync = generic_file_fsync, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -82,22 +82,23 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi) | |||
82 | return (void*)((char*)de + sbi->s_dirsize); | 82 | return (void*)((char*)de + sbi->s_dirsize); |
83 | } | 83 | } |
84 | 84 | ||
85 | static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | 85 | static int minix_readdir(struct file *file, struct dir_context *ctx) |
86 | { | 86 | { |
87 | unsigned long pos = filp->f_pos; | 87 | struct inode *inode = file_inode(file); |
88 | struct inode *inode = file_inode(filp); | ||
89 | struct super_block *sb = inode->i_sb; | 88 | struct super_block *sb = inode->i_sb; |
90 | unsigned offset = pos & ~PAGE_CACHE_MASK; | ||
91 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | ||
92 | unsigned long npages = dir_pages(inode); | ||
93 | struct minix_sb_info *sbi = minix_sb(sb); | 89 | struct minix_sb_info *sbi = minix_sb(sb); |
94 | unsigned chunk_size = sbi->s_dirsize; | 90 | unsigned chunk_size = sbi->s_dirsize; |
95 | char *name; | 91 | unsigned long npages = dir_pages(inode); |
96 | __u32 inumber; | 92 | unsigned long pos = ctx->pos; |
93 | unsigned offset; | ||
94 | unsigned long n; | ||
97 | 95 | ||
98 | pos = (pos + chunk_size-1) & ~(chunk_size-1); | 96 | ctx->pos = pos = (pos + chunk_size-1) & ~(chunk_size-1); |
99 | if (pos >= inode->i_size) | 97 | if (pos >= inode->i_size) |
100 | goto done; | 98 | return 0; |
99 | |||
100 | offset = pos & ~PAGE_CACHE_MASK; | ||
101 | n = pos >> PAGE_CACHE_SHIFT; | ||
101 | 102 | ||
102 | for ( ; n < npages; n++, offset = 0) { | 103 | for ( ; n < npages; n++, offset = 0) { |
103 | char *p, *kaddr, *limit; | 104 | char *p, *kaddr, *limit; |
@@ -109,6 +110,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
109 | p = kaddr+offset; | 110 | p = kaddr+offset; |
110 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; | 111 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; |
111 | for ( ; p <= limit; p = minix_next_entry(p, sbi)) { | 112 | for ( ; p <= limit; p = minix_next_entry(p, sbi)) { |
113 | const char *name; | ||
114 | __u32 inumber; | ||
112 | if (sbi->s_version == MINIX_V3) { | 115 | if (sbi->s_version == MINIX_V3) { |
113 | minix3_dirent *de3 = (minix3_dirent *)p; | 116 | minix3_dirent *de3 = (minix3_dirent *)p; |
114 | name = de3->name; | 117 | name = de3->name; |
@@ -119,24 +122,17 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
119 | inumber = de->inode; | 122 | inumber = de->inode; |
120 | } | 123 | } |
121 | if (inumber) { | 124 | if (inumber) { |
122 | int over; | ||
123 | |||
124 | unsigned l = strnlen(name, sbi->s_namelen); | 125 | unsigned l = strnlen(name, sbi->s_namelen); |
125 | offset = p - kaddr; | 126 | if (!dir_emit(ctx, name, l, |
126 | over = filldir(dirent, name, l, | 127 | inumber, DT_UNKNOWN)) { |
127 | (n << PAGE_CACHE_SHIFT) | offset, | ||
128 | inumber, DT_UNKNOWN); | ||
129 | if (over) { | ||
130 | dir_put_page(page); | 128 | dir_put_page(page); |
131 | goto done; | 129 | return 0; |
132 | } | 130 | } |
133 | } | 131 | } |
132 | ctx->pos += chunk_size; | ||
134 | } | 133 | } |
135 | dir_put_page(page); | 134 | dir_put_page(page); |
136 | } | 135 | } |
137 | |||
138 | done: | ||
139 | filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; | ||
140 | return 0; | 136 | return 0; |
141 | } | 137 | } |
142 | 138 | ||
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index 3799e8dac3eb..d42291d08215 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -18,12 +18,12 @@ | |||
18 | #include <linux/swap.h> | 18 | #include <linux/swap.h> |
19 | #include "sysv.h" | 19 | #include "sysv.h" |
20 | 20 | ||
21 | static int sysv_readdir(struct file *, void *, filldir_t); | 21 | static int sysv_readdir(struct file *, struct dir_context *); |
22 | 22 | ||
23 | const struct file_operations sysv_dir_operations = { | 23 | const struct file_operations sysv_dir_operations = { |
24 | .llseek = generic_file_llseek, | 24 | .llseek = generic_file_llseek, |
25 | .read = generic_read_dir, | 25 | .read = generic_read_dir, |
26 | .readdir = sysv_readdir, | 26 | .iterate = sysv_readdir, |
27 | .fsync = generic_file_fsync, | 27 | .fsync = generic_file_fsync, |
28 | }; | 28 | }; |
29 | 29 | ||
@@ -65,18 +65,21 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n) | |||
65 | return page; | 65 | return page; |
66 | } | 66 | } |
67 | 67 | ||
68 | static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) | 68 | static int sysv_readdir(struct file *file, struct dir_context *ctx) |
69 | { | 69 | { |
70 | unsigned long pos = filp->f_pos; | 70 | unsigned long pos = ctx->pos; |
71 | struct inode *inode = file_inode(filp); | 71 | struct inode *inode = file_inode(file); |
72 | struct super_block *sb = inode->i_sb; | 72 | struct super_block *sb = inode->i_sb; |
73 | unsigned offset = pos & ~PAGE_CACHE_MASK; | ||
74 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | ||
75 | unsigned long npages = dir_pages(inode); | 73 | unsigned long npages = dir_pages(inode); |
74 | unsigned offset; | ||
75 | unsigned long n; | ||
76 | 76 | ||
77 | pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); | 77 | ctx->pos = pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); |
78 | if (pos >= inode->i_size) | 78 | if (pos >= inode->i_size) |
79 | goto done; | 79 | return 0; |
80 | |||
81 | offset = pos & ~PAGE_CACHE_MASK; | ||
82 | n = pos >> PAGE_CACHE_SHIFT; | ||
80 | 83 | ||
81 | for ( ; n < npages; n++, offset = 0) { | 84 | for ( ; n < npages; n++, offset = 0) { |
82 | char *kaddr, *limit; | 85 | char *kaddr, *limit; |
@@ -88,29 +91,21 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
88 | kaddr = (char *)page_address(page); | 91 | kaddr = (char *)page_address(page); |
89 | de = (struct sysv_dir_entry *)(kaddr+offset); | 92 | de = (struct sysv_dir_entry *)(kaddr+offset); |
90 | limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; | 93 | limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; |
91 | for ( ;(char*)de <= limit; de++) { | 94 | for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) { |
92 | char *name = de->name; | 95 | char *name = de->name; |
93 | int over; | ||
94 | 96 | ||
95 | if (!de->inode) | 97 | if (!de->inode) |
96 | continue; | 98 | continue; |
97 | 99 | ||
98 | offset = (char *)de - kaddr; | 100 | if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN), |
99 | |||
100 | over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN), | ||
101 | ((loff_t)n<<PAGE_CACHE_SHIFT) | offset, | ||
102 | fs16_to_cpu(SYSV_SB(sb), de->inode), | 101 | fs16_to_cpu(SYSV_SB(sb), de->inode), |
103 | DT_UNKNOWN); | 102 | DT_UNKNOWN)) { |
104 | if (over) { | ||
105 | dir_put_page(page); | 103 | dir_put_page(page); |
106 | goto done; | 104 | return 0; |
107 | } | 105 | } |
108 | } | 106 | } |
109 | dir_put_page(page); | 107 | dir_put_page(page); |
110 | } | 108 | } |
111 | |||
112 | done: | ||
113 | filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset; | ||
114 | return 0; | 109 | return 0; |
115 | } | 110 | } |
116 | 111 | ||
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 3a75ca09c506..0ecc2cebed8f 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c | |||
@@ -430,16 +430,16 @@ ufs_validate_entry(struct super_block *sb, char *base, | |||
430 | * This is blatantly stolen from ext2fs | 430 | * This is blatantly stolen from ext2fs |
431 | */ | 431 | */ |
432 | static int | 432 | static int |
433 | ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 433 | ufs_readdir(struct file *file, struct dir_context *ctx) |
434 | { | 434 | { |
435 | loff_t pos = filp->f_pos; | 435 | loff_t pos = ctx->pos; |
436 | struct inode *inode = file_inode(filp); | 436 | struct inode *inode = file_inode(file); |
437 | struct super_block *sb = inode->i_sb; | 437 | struct super_block *sb = inode->i_sb; |
438 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 438 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
439 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 439 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
440 | unsigned long npages = ufs_dir_pages(inode); | 440 | unsigned long npages = ufs_dir_pages(inode); |
441 | unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); | 441 | unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); |
442 | int need_revalidate = filp->f_version != inode->i_version; | 442 | int need_revalidate = file->f_version != inode->i_version; |
443 | unsigned flags = UFS_SB(sb)->s_flags; | 443 | unsigned flags = UFS_SB(sb)->s_flags; |
444 | 444 | ||
445 | UFSD("BEGIN\n"); | 445 | UFSD("BEGIN\n"); |
@@ -457,16 +457,16 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
457 | ufs_error(sb, __func__, | 457 | ufs_error(sb, __func__, |
458 | "bad page in #%lu", | 458 | "bad page in #%lu", |
459 | inode->i_ino); | 459 | inode->i_ino); |
460 | filp->f_pos += PAGE_CACHE_SIZE - offset; | 460 | ctx->pos += PAGE_CACHE_SIZE - offset; |
461 | return -EIO; | 461 | return -EIO; |
462 | } | 462 | } |
463 | kaddr = page_address(page); | 463 | kaddr = page_address(page); |
464 | if (unlikely(need_revalidate)) { | 464 | if (unlikely(need_revalidate)) { |
465 | if (offset) { | 465 | if (offset) { |
466 | offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); | 466 | offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); |
467 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; | 467 | ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset; |
468 | } | 468 | } |
469 | filp->f_version = inode->i_version; | 469 | file->f_version = inode->i_version; |
470 | need_revalidate = 0; | 470 | need_revalidate = 0; |
471 | } | 471 | } |
472 | de = (struct ufs_dir_entry *)(kaddr+offset); | 472 | de = (struct ufs_dir_entry *)(kaddr+offset); |
@@ -479,11 +479,8 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
479 | return -EIO; | 479 | return -EIO; |
480 | } | 480 | } |
481 | if (de->d_ino) { | 481 | if (de->d_ino) { |
482 | int over; | ||
483 | unsigned char d_type = DT_UNKNOWN; | 482 | unsigned char d_type = DT_UNKNOWN; |
484 | 483 | ||
485 | offset = (char *)de - kaddr; | ||
486 | |||
487 | UFSD("filldir(%s,%u)\n", de->d_name, | 484 | UFSD("filldir(%s,%u)\n", de->d_name, |
488 | fs32_to_cpu(sb, de->d_ino)); | 485 | fs32_to_cpu(sb, de->d_ino)); |
489 | UFSD("namlen %u\n", ufs_get_de_namlen(sb, de)); | 486 | UFSD("namlen %u\n", ufs_get_de_namlen(sb, de)); |
@@ -491,16 +488,15 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
491 | if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) | 488 | if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) |
492 | d_type = de->d_u.d_44.d_type; | 489 | d_type = de->d_u.d_44.d_type; |
493 | 490 | ||
494 | over = filldir(dirent, de->d_name, | 491 | if (!dir_emit(ctx, de->d_name, |
495 | ufs_get_de_namlen(sb, de), | 492 | ufs_get_de_namlen(sb, de), |
496 | (n<<PAGE_CACHE_SHIFT) | offset, | 493 | fs32_to_cpu(sb, de->d_ino), |
497 | fs32_to_cpu(sb, de->d_ino), d_type); | 494 | d_type)) { |
498 | if (over) { | ||
499 | ufs_put_page(page); | 495 | ufs_put_page(page); |
500 | return 0; | 496 | return 0; |
501 | } | 497 | } |
502 | } | 498 | } |
503 | filp->f_pos += fs16_to_cpu(sb, de->d_reclen); | 499 | ctx->pos += fs16_to_cpu(sb, de->d_reclen); |
504 | } | 500 | } |
505 | ufs_put_page(page); | 501 | ufs_put_page(page); |
506 | } | 502 | } |
@@ -660,7 +656,7 @@ not_empty: | |||
660 | 656 | ||
661 | const struct file_operations ufs_dir_operations = { | 657 | const struct file_operations ufs_dir_operations = { |
662 | .read = generic_read_dir, | 658 | .read = generic_read_dir, |
663 | .readdir = ufs_readdir, | 659 | .iterate = ufs_readdir, |
664 | .fsync = generic_file_fsync, | 660 | .fsync = generic_file_fsync, |
665 | .llseek = generic_file_llseek, | 661 | .llseek = generic_file_llseek, |
666 | }; | 662 | }; |