aboutsummaryrefslogtreecommitdiffstats
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
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)
-rw-r--r--fs/cifs/CHANGES5
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/readdir.c37
3 files changed, 38 insertions, 6 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 6c73f020ef40..8b55e56cf1fe 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,8 @@
1Version 1.37
2------------
3Fix readdir caching when unlink removes file in current search buffer,
4and this is followed by a rewind search to just before the deleted entry.
5
1Version 1.36 6Version 1.36
2------------ 7------------
3Add support for mounting to older pre-CIFS servers such as Windows9x and ME. 8Add support for mounting to older pre-CIFS servers such as Windows9x and ME.
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index bb3404a99e5f..0f6d352ab813 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -97,5 +97,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
97extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 97extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
98extern int cifs_ioctl (struct inode * inode, struct file * filep, 98extern int cifs_ioctl (struct inode * inode, struct file * filep,
99 unsigned int command, unsigned long arg); 99 unsigned int command, unsigned long arg);
100#define CIFS_VERSION "1.36" 100#define CIFS_VERSION "1.37"
101#endif /* _CIFSFS_H */ 101#endif /* _CIFSFS_H */
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,