diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-16 01:14:46 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:56:25 -0400 |
commit | 01122e06885f4aa220e7a7a31ce25e4876d159f2 (patch) | |
tree | 976117358c5dd0fdebb67ade2fbd86ea9fe696fd /fs/ubifs/dir.c | |
parent | 5add2ee198723c3fec3ce4a7d77de298344f6ba8 (diff) |
[readdir] convert ubifs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ubifs/dir.c')
-rw-r--r-- | fs/ubifs/dir.c | 57 |
1 files changed, 16 insertions, 41 deletions
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 605af512aec2..6b4947f75af7 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
@@ -346,19 +346,18 @@ static unsigned int vfs_dent_type(uint8_t type) | |||
346 | * This means that UBIFS cannot support NFS which requires full | 346 | * This means that UBIFS cannot support NFS which requires full |
347 | * 'seekdir()'/'telldir()' support. | 347 | * 'seekdir()'/'telldir()' support. |
348 | */ | 348 | */ |
349 | static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | 349 | static int ubifs_readdir(struct file *file, struct dir_context *ctx) |
350 | { | 350 | { |
351 | int err, over = 0; | 351 | int err; |
352 | loff_t pos = file->f_pos; | ||
353 | struct qstr nm; | 352 | struct qstr nm; |
354 | union ubifs_key key; | 353 | union ubifs_key key; |
355 | struct ubifs_dent_node *dent; | 354 | struct ubifs_dent_node *dent; |
356 | struct inode *dir = file_inode(file); | 355 | struct inode *dir = file_inode(file); |
357 | struct ubifs_info *c = dir->i_sb->s_fs_info; | 356 | struct ubifs_info *c = dir->i_sb->s_fs_info; |
358 | 357 | ||
359 | dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, pos); | 358 | dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos); |
360 | 359 | ||
361 | if (pos > UBIFS_S_KEY_HASH_MASK || pos == 2) | 360 | if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2) |
362 | /* | 361 | /* |
363 | * The directory was seek'ed to a senseless position or there | 362 | * The directory was seek'ed to a senseless position or there |
364 | * are no more entries. | 363 | * are no more entries. |
@@ -384,19 +383,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
384 | file->f_version = 1; | 383 | file->f_version = 1; |
385 | 384 | ||
386 | /* File positions 0 and 1 correspond to "." and ".." */ | 385 | /* File positions 0 and 1 correspond to "." and ".." */ |
387 | if (pos == 0) { | 386 | if (ctx->pos < 2) { |
388 | ubifs_assert(!file->private_data); | ||
389 | over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); | ||
390 | if (over) | ||
391 | return 0; | ||
392 | file->f_pos = pos = 1; | ||
393 | } | ||
394 | |||
395 | if (pos == 1) { | ||
396 | ubifs_assert(!file->private_data); | 387 | ubifs_assert(!file->private_data); |
397 | over = filldir(dirent, "..", 2, 1, | 388 | if (!dir_emit_dots(file, ctx)) |
398 | parent_ino(file->f_path.dentry), DT_DIR); | ||
399 | if (over) | ||
400 | return 0; | 389 | return 0; |
401 | 390 | ||
402 | /* Find the first entry in TNC and save it */ | 391 | /* Find the first entry in TNC and save it */ |
@@ -408,7 +397,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
408 | goto out; | 397 | goto out; |
409 | } | 398 | } |
410 | 399 | ||
411 | file->f_pos = pos = key_hash_flash(c, &dent->key); | 400 | ctx->pos = key_hash_flash(c, &dent->key); |
412 | file->private_data = dent; | 401 | file->private_data = dent; |
413 | } | 402 | } |
414 | 403 | ||
@@ -416,16 +405,16 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
416 | if (!dent) { | 405 | if (!dent) { |
417 | /* | 406 | /* |
418 | * The directory was seek'ed to and is now readdir'ed. | 407 | * The directory was seek'ed to and is now readdir'ed. |
419 | * Find the entry corresponding to @pos or the closest one. | 408 | * Find the entry corresponding to @ctx->pos or the closest one. |
420 | */ | 409 | */ |
421 | dent_key_init_hash(c, &key, dir->i_ino, pos); | 410 | dent_key_init_hash(c, &key, dir->i_ino, ctx->pos); |
422 | nm.name = NULL; | 411 | nm.name = NULL; |
423 | dent = ubifs_tnc_next_ent(c, &key, &nm); | 412 | dent = ubifs_tnc_next_ent(c, &key, &nm); |
424 | if (IS_ERR(dent)) { | 413 | if (IS_ERR(dent)) { |
425 | err = PTR_ERR(dent); | 414 | err = PTR_ERR(dent); |
426 | goto out; | 415 | goto out; |
427 | } | 416 | } |
428 | file->f_pos = pos = key_hash_flash(c, &dent->key); | 417 | ctx->pos = key_hash_flash(c, &dent->key); |
429 | file->private_data = dent; | 418 | file->private_data = dent; |
430 | } | 419 | } |
431 | 420 | ||
@@ -437,10 +426,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
437 | ubifs_inode(dir)->creat_sqnum); | 426 | ubifs_inode(dir)->creat_sqnum); |
438 | 427 | ||
439 | nm.len = le16_to_cpu(dent->nlen); | 428 | nm.len = le16_to_cpu(dent->nlen); |
440 | over = filldir(dirent, dent->name, nm.len, pos, | 429 | if (!dir_emit(ctx, dent->name, nm.len, |
441 | le64_to_cpu(dent->inum), | 430 | le64_to_cpu(dent->inum), |
442 | vfs_dent_type(dent->type)); | 431 | vfs_dent_type(dent->type))) |
443 | if (over) | ||
444 | return 0; | 432 | return 0; |
445 | 433 | ||
446 | /* Switch to the next entry */ | 434 | /* Switch to the next entry */ |
@@ -453,17 +441,9 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
453 | } | 441 | } |
454 | 442 | ||
455 | kfree(file->private_data); | 443 | kfree(file->private_data); |
456 | file->f_pos = pos = key_hash_flash(c, &dent->key); | 444 | ctx->pos = key_hash_flash(c, &dent->key); |
457 | file->private_data = dent; | 445 | file->private_data = dent; |
458 | cond_resched(); | 446 | cond_resched(); |
459 | |||
460 | if (file->f_version == 0) | ||
461 | /* | ||
462 | * The file was seek'ed meanwhile, lets return and start | ||
463 | * reading direntries from the new position on the next | ||
464 | * invocation. | ||
465 | */ | ||
466 | return 0; | ||
467 | } | 447 | } |
468 | 448 | ||
469 | out: | 449 | out: |
@@ -475,15 +455,10 @@ out: | |||
475 | kfree(file->private_data); | 455 | kfree(file->private_data); |
476 | file->private_data = NULL; | 456 | file->private_data = NULL; |
477 | /* 2 is a special value indicating that there are no more direntries */ | 457 | /* 2 is a special value indicating that there are no more direntries */ |
478 | file->f_pos = 2; | 458 | ctx->pos = 2; |
479 | return 0; | 459 | return 0; |
480 | } | 460 | } |
481 | 461 | ||
482 | static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) | ||
483 | { | ||
484 | return generic_file_llseek(file, offset, whence); | ||
485 | } | ||
486 | |||
487 | /* Free saved readdir() state when the directory is closed */ | 462 | /* Free saved readdir() state when the directory is closed */ |
488 | static int ubifs_dir_release(struct inode *dir, struct file *file) | 463 | static int ubifs_dir_release(struct inode *dir, struct file *file) |
489 | { | 464 | { |
@@ -1201,10 +1176,10 @@ const struct inode_operations ubifs_dir_inode_operations = { | |||
1201 | }; | 1176 | }; |
1202 | 1177 | ||
1203 | const struct file_operations ubifs_dir_operations = { | 1178 | const struct file_operations ubifs_dir_operations = { |
1204 | .llseek = ubifs_dir_llseek, | 1179 | .llseek = generic_file_llseek, |
1205 | .release = ubifs_dir_release, | 1180 | .release = ubifs_dir_release, |
1206 | .read = generic_read_dir, | 1181 | .read = generic_read_dir, |
1207 | .readdir = ubifs_readdir, | 1182 | .iterate = ubifs_readdir, |
1208 | .fsync = ubifs_fsync, | 1183 | .fsync = ubifs_fsync, |
1209 | .unlocked_ioctl = ubifs_ioctl, | 1184 | .unlocked_ioctl = ubifs_ioctl, |
1210 | #ifdef CONFIG_COMPAT | 1185 | #ifdef CONFIG_COMPAT |