diff options
Diffstat (limited to 'fs/omfs/dir.c')
| -rw-r--r-- | fs/omfs/dir.c | 94 |
1 files changed, 38 insertions, 56 deletions
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index acbaebcad3a8..1b8e9e8405b2 100644 --- a/fs/omfs/dir.c +++ b/fs/omfs/dir.c | |||
| @@ -327,26 +327,23 @@ int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header, | |||
| 327 | return is_bad; | 327 | return is_bad; |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, | 330 | static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx, |
| 331 | u64 fsblock, int hindex) | 331 | u64 fsblock, int hindex) |
| 332 | { | 332 | { |
| 333 | struct inode *dir = file_inode(filp); | ||
| 334 | struct buffer_head *bh; | ||
| 335 | struct omfs_inode *oi; | ||
| 336 | u64 self; | ||
| 337 | int res = 0; | ||
| 338 | unsigned char d_type; | ||
| 339 | |||
| 340 | /* follow chain in this bucket */ | 333 | /* follow chain in this bucket */ |
| 341 | while (fsblock != ~0) { | 334 | while (fsblock != ~0) { |
| 342 | bh = omfs_bread(dir->i_sb, fsblock); | 335 | struct buffer_head *bh = omfs_bread(dir->i_sb, fsblock); |
| 336 | struct omfs_inode *oi; | ||
| 337 | u64 self; | ||
| 338 | unsigned char d_type; | ||
| 339 | |||
| 343 | if (!bh) | 340 | if (!bh) |
| 344 | goto out; | 341 | return true; |
| 345 | 342 | ||
| 346 | oi = (struct omfs_inode *) bh->b_data; | 343 | oi = (struct omfs_inode *) bh->b_data; |
| 347 | if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) { | 344 | if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) { |
| 348 | brelse(bh); | 345 | brelse(bh); |
| 349 | goto out; | 346 | return true; |
| 350 | } | 347 | } |
| 351 | 348 | ||
| 352 | self = fsblock; | 349 | self = fsblock; |
| @@ -361,15 +358,16 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, | |||
| 361 | 358 | ||
| 362 | d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG; | 359 | d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG; |
| 363 | 360 | ||
| 364 | res = filldir(dirent, oi->i_name, strnlen(oi->i_name, | 361 | if (!dir_emit(ctx, oi->i_name, |
| 365 | OMFS_NAMELEN), filp->f_pos, self, d_type); | 362 | strnlen(oi->i_name, OMFS_NAMELEN), |
| 363 | self, d_type)) { | ||
| 364 | brelse(bh); | ||
| 365 | return false; | ||
| 366 | } | ||
| 366 | brelse(bh); | 367 | brelse(bh); |
| 367 | if (res < 0) | 368 | ctx->pos++; |
| 368 | break; | ||
| 369 | filp->f_pos++; | ||
| 370 | } | 369 | } |
| 371 | out: | 370 | return true; |
| 372 | return res; | ||
| 373 | } | 371 | } |
| 374 | 372 | ||
| 375 | static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 373 | static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
| @@ -403,60 +401,44 @@ out: | |||
| 403 | return err; | 401 | return err; |
| 404 | } | 402 | } |
| 405 | 403 | ||
| 406 | static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 404 | static int omfs_readdir(struct file *file, struct dir_context *ctx) |
| 407 | { | 405 | { |
| 408 | struct inode *dir = file_inode(filp); | 406 | struct inode *dir = file_inode(file); |
| 409 | struct buffer_head *bh; | 407 | struct buffer_head *bh; |
| 410 | loff_t offset, res; | 408 | __be64 *p; |
| 411 | unsigned int hchain, hindex; | 409 | unsigned int hchain, hindex; |
| 412 | int nbuckets; | 410 | int nbuckets; |
| 413 | u64 fsblock; | 411 | |
| 414 | int ret = -EINVAL; | 412 | if (ctx->pos >> 32) |
| 415 | 413 | return -EINVAL; | |
| 416 | if (filp->f_pos >> 32) | 414 | |
| 417 | goto success; | 415 | if (ctx->pos < 1 << 20) { |
| 418 | 416 | if (!dir_emit_dots(file, ctx)) | |
| 419 | switch ((unsigned long) filp->f_pos) { | 417 | return 0; |
| 420 | case 0: | 418 | ctx->pos = 1 << 20; |
| 421 | if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0) | ||
| 422 | goto success; | ||
| 423 | filp->f_pos++; | ||
| 424 | /* fall through */ | ||
| 425 | case 1: | ||
| 426 | if (filldir(dirent, "..", 2, 1, | ||
| 427 | parent_ino(filp->f_dentry), DT_DIR) < 0) | ||
| 428 | goto success; | ||
| 429 | filp->f_pos = 1 << 20; | ||
| 430 | /* fall through */ | ||
| 431 | } | 419 | } |
| 432 | 420 | ||
| 433 | nbuckets = (dir->i_size - OMFS_DIR_START) / 8; | 421 | nbuckets = (dir->i_size - OMFS_DIR_START) / 8; |
| 434 | 422 | ||
| 435 | /* high 12 bits store bucket + 1 and low 20 bits store hash index */ | 423 | /* high 12 bits store bucket + 1 and low 20 bits store hash index */ |
| 436 | hchain = (filp->f_pos >> 20) - 1; | 424 | hchain = (ctx->pos >> 20) - 1; |
| 437 | hindex = filp->f_pos & 0xfffff; | 425 | hindex = ctx->pos & 0xfffff; |
| 438 | 426 | ||
| 439 | bh = omfs_bread(dir->i_sb, dir->i_ino); | 427 | bh = omfs_bread(dir->i_sb, dir->i_ino); |
| 440 | if (!bh) | 428 | if (!bh) |
| 441 | goto out; | 429 | return -EINVAL; |
| 442 | 430 | ||
| 443 | offset = OMFS_DIR_START + hchain * 8; | 431 | p = (__be64 *)(bh->b_data + OMFS_DIR_START) + hchain; |
| 444 | 432 | ||
| 445 | for (; hchain < nbuckets; hchain++, offset += 8) { | 433 | for (; hchain < nbuckets; hchain++) { |
| 446 | fsblock = be64_to_cpu(*((__be64 *) &bh->b_data[offset])); | 434 | __u64 fsblock = be64_to_cpu(*p++); |
| 447 | 435 | if (!omfs_fill_chain(dir, ctx, fsblock, hindex)) | |
| 448 | res = omfs_fill_chain(filp, dirent, filldir, fsblock, hindex); | ||
| 449 | hindex = 0; | ||
| 450 | if (res < 0) | ||
| 451 | break; | 436 | break; |
| 452 | 437 | hindex = 0; | |
| 453 | filp->f_pos = (hchain+2) << 20; | 438 | ctx->pos = (hchain+2) << 20; |
| 454 | } | 439 | } |
| 455 | brelse(bh); | 440 | brelse(bh); |
| 456 | success: | 441 | return 0; |
| 457 | ret = 0; | ||
| 458 | out: | ||
| 459 | return ret; | ||
| 460 | } | 442 | } |
| 461 | 443 | ||
| 462 | const struct inode_operations omfs_dir_inops = { | 444 | const struct inode_operations omfs_dir_inops = { |
| @@ -470,6 +452,6 @@ const struct inode_operations omfs_dir_inops = { | |||
| 470 | 452 | ||
| 471 | const struct file_operations omfs_dir_operations = { | 453 | const struct file_operations omfs_dir_operations = { |
| 472 | .read = generic_read_dir, | 454 | .read = generic_read_dir, |
| 473 | .readdir = omfs_readdir, | 455 | .iterate = omfs_readdir, |
| 474 | .llseek = generic_file_llseek, | 456 | .llseek = generic_file_llseek, |
| 475 | }; | 457 | }; |
