aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/readdir.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-09-16 00:47:30 -0400
committerSteve French <sfrench@us.ibm.com>2005-09-16 00:47:30 -0400
commiteafe87012159a40a1e7151cc576e99a22aea2f0b (patch)
tree5d9225494429ea235befb943581901d9c94aa236 /fs/cifs/readdir.c
parentab2f218f4fa2c36ecd39ac1406eec1e63cd430bd (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.c37
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 */
519static 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,