aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ubifs/dir.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 8e587afd7732..605af512aec2 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -365,6 +365,24 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
365 */ 365 */
366 return 0; 366 return 0;
367 367
368 if (file->f_version == 0) {
369 /*
370 * The file was seek'ed, which means that @file->private_data
371 * is now invalid. This may also be just the first
372 * 'ubifs_readdir()' invocation, in which case
373 * @file->private_data is NULL, and the below code is
374 * basically a no-op.
375 */
376 kfree(file->private_data);
377 file->private_data = NULL;
378 }
379
380 /*
381 * 'generic_file_llseek()' unconditionally sets @file->f_version to
382 * zero, and we use this for detecting whether the file was seek'ed.
383 */
384 file->f_version = 1;
385
368 /* File positions 0 and 1 correspond to "." and ".." */ 386 /* File positions 0 and 1 correspond to "." and ".." */
369 if (pos == 0) { 387 if (pos == 0) {
370 ubifs_assert(!file->private_data); 388 ubifs_assert(!file->private_data);
@@ -438,6 +456,14 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
438 file->f_pos = pos = key_hash_flash(c, &dent->key); 456 file->f_pos = pos = key_hash_flash(c, &dent->key);
439 file->private_data = dent; 457 file->private_data = dent;
440 cond_resched(); 458 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;
441 } 467 }
442 468
443out: 469out:
@@ -448,15 +474,13 @@ out:
448 474
449 kfree(file->private_data); 475 kfree(file->private_data);
450 file->private_data = NULL; 476 file->private_data = NULL;
477 /* 2 is a special value indicating that there are no more direntries */
451 file->f_pos = 2; 478 file->f_pos = 2;
452 return 0; 479 return 0;
453} 480}
454 481
455/* If a directory is seeked, we have to free saved readdir() state */
456static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) 482static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence)
457{ 483{
458 kfree(file->private_data);
459 file->private_data = NULL;
460 return generic_file_llseek(file, offset, whence); 484 return generic_file_llseek(file, offset, whence);
461} 485}
462 486