diff options
author | Steve French <sfrench@us.ibm.com> | 2005-09-16 00:47:30 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2005-09-16 00:47:30 -0400 |
commit | eafe87012159a40a1e7151cc576e99a22aea2f0b (patch) | |
tree | 5d9225494429ea235befb943581901d9c94aa236 /fs/cifs/readdir.c | |
parent | ab2f218f4fa2c36ecd39ac1406eec1e63cd430bd (diff) |
[CIFS] Fix readdir caching when unlink removes file in current search
buffer, and this is followed by a rewind search to just before
the deleted entry.
Signed-off-by: Steve French (sfrench@us.ibm.com)
Diffstat (limited to 'fs/cifs/readdir.c')
-rw-r--r-- | fs/cifs/readdir.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index a1e8dc901de4..a86bd1c07602 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -396,7 +396,8 @@ ffirst_retry: | |||
396 | 396 | ||
397 | rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, | 397 | rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, |
398 | &cifsFile->netfid, &cifsFile->srch_inf, | 398 | &cifsFile->netfid, &cifsFile->srch_inf, |
399 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); | 399 | cifs_sb->mnt_cifs_flags & |
400 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); | ||
400 | if(rc == 0) | 401 | if(rc == 0) |
401 | cifsFile->invalidHandle = FALSE; | 402 | cifsFile->invalidHandle = FALSE; |
402 | if((rc == -EOPNOTSUPP) && | 403 | if((rc == -EOPNOTSUPP) && |
@@ -513,6 +514,30 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) | |||
513 | return rc; | 514 | return rc; |
514 | } | 515 | } |
515 | 516 | ||
517 | /* Check if directory that we are searching has changed so we can decide | ||
518 | whether we can use the cached search results from the previous search */ | ||
519 | static int is_dir_changed(struct file * file) | ||
520 | { | ||
521 | struct inode * inode; | ||
522 | struct cifsInodeInfo *cifsInfo; | ||
523 | |||
524 | if(file->f_dentry == NULL) | ||
525 | return 0; | ||
526 | |||
527 | inode = file->f_dentry->d_inode; | ||
528 | |||
529 | if(inode == NULL) | ||
530 | return 0; | ||
531 | |||
532 | cifsInfo = CIFS_I(inode); | ||
533 | |||
534 | if(cifsInfo->time == 0) | ||
535 | return 1; /* directory was changed, perhaps due to unlink */ | ||
536 | else | ||
537 | return 0; | ||
538 | |||
539 | } | ||
540 | |||
516 | /* find the corresponding entry in the search */ | 541 | /* find the corresponding entry in the search */ |
517 | /* Note that the SMB server returns search entries for . and .. which | 542 | /* Note that the SMB server returns search entries for . and .. which |
518 | complicates logic here if we choose to parse for them and we do not | 543 | complicates logic here if we choose to parse for them and we do not |
@@ -529,7 +554,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
529 | struct cifsFileInfo * cifsFile = file->private_data; | 554 | struct cifsFileInfo * cifsFile = file->private_data; |
530 | /* check if index in the buffer */ | 555 | /* check if index in the buffer */ |
531 | 556 | ||
532 | if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL)) | 557 | if((cifsFile == NULL) || (ppCurrentEntry == NULL) || |
558 | (num_to_ret == NULL)) | ||
533 | return -ENOENT; | 559 | return -ENOENT; |
534 | 560 | ||
535 | *ppCurrentEntry = NULL; | 561 | *ppCurrentEntry = NULL; |
@@ -537,7 +563,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
537 | cifsFile->srch_inf.index_of_last_entry - | 563 | cifsFile->srch_inf.index_of_last_entry - |
538 | cifsFile->srch_inf.entries_in_buffer; | 564 | cifsFile->srch_inf.entries_in_buffer; |
539 | /* dump_cifs_file_struct(file, "In fce ");*/ | 565 | /* dump_cifs_file_struct(file, "In fce ");*/ |
540 | if(index_to_find < first_entry_in_buffer) { | 566 | if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && |
567 | is_dir_changed(file)) || | ||
568 | (index_to_find < first_entry_in_buffer)) { | ||
541 | /* close and restart search */ | 569 | /* close and restart search */ |
542 | cFYI(1,("search backing up - close and restart search")); | 570 | cFYI(1,("search backing up - close and restart search")); |
543 | cifsFile->invalidHandle = TRUE; | 571 | cifsFile->invalidHandle = TRUE; |
@@ -604,7 +632,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
604 | } | 632 | } |
605 | 633 | ||
606 | if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { | 634 | if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { |
607 | cFYI(1,("can not return entries when pos_in_buf beyond last entry")); | 635 | cFYI(1,("can not return entries pos_in_buf beyond last entry")); |
608 | *num_to_ret = 0; | 636 | *num_to_ret = 0; |
609 | } else | 637 | } else |
610 | *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; | 638 | *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; |
@@ -833,7 +861,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
833 | if(pTcon == NULL) | 861 | if(pTcon == NULL) |
834 | return -EINVAL; | 862 | return -EINVAL; |
835 | 863 | ||
836 | |||
837 | switch ((int) file->f_pos) { | 864 | switch ((int) file->f_pos) { |
838 | case 0: | 865 | case 0: |
839 | /*if (filldir(direntry, ".", 1, file->f_pos, | 866 | /*if (filldir(direntry, ".", 1, file->f_pos, |