Commit eafe8701 authored by Steve French's avatar Steve French

[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)
parent ab2f218f
Version 1.37
------------
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.
Version 1.36 Version 1.36
------------ ------------
Add support for mounting to older pre-CIFS servers such as Windows9x and ME. Add support for mounting to older pre-CIFS servers such as Windows9x and ME.
......
...@@ -97,5 +97,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); ...@@ -97,5 +97,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep, extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg); unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.36" #define CIFS_VERSION "1.37"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -396,7 +396,8 @@ static int initiate_cifs_search(const int xid, struct file *file) ...@@ -396,7 +396,8 @@ static int initiate_cifs_search(const int xid, struct file *file)
rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
&cifsFile->netfid, &cifsFile->srch_inf, &cifsFile->netfid, &cifsFile->srch_inf,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
if(rc == 0) if(rc == 0)
cifsFile->invalidHandle = FALSE; cifsFile->invalidHandle = FALSE;
if((rc == -EOPNOTSUPP) && if((rc == -EOPNOTSUPP) &&
...@@ -513,6 +514,30 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) ...@@ -513,6 +514,30 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
return rc; return rc;
} }
/* Check if directory that we are searching has changed so we can decide
whether we can use the cached search results from the previous search */
static int is_dir_changed(struct file * file)
{
struct inode * inode;
struct cifsInodeInfo *cifsInfo;
if(file->f_dentry == NULL)
return 0;
inode = file->f_dentry->d_inode;
if(inode == NULL)
return 0;
cifsInfo = CIFS_I(inode);
if(cifsInfo->time == 0)
return 1; /* directory was changed, perhaps due to unlink */
else
return 0;
}
/* find the corresponding entry in the search */ /* find the corresponding entry in the search */
/* Note that the SMB server returns search entries for . and .. which /* Note that the SMB server returns search entries for . and .. which
complicates logic here if we choose to parse for them and we do not 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,7 +554,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
struct cifsFileInfo * cifsFile = file->private_data; struct cifsFileInfo * cifsFile = file->private_data;
/* check if index in the buffer */ /* check if index in the buffer */
if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL)) if((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
(num_to_ret == NULL))
return -ENOENT; return -ENOENT;
*ppCurrentEntry = NULL; *ppCurrentEntry = NULL;
...@@ -537,7 +563,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -537,7 +563,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.index_of_last_entry -
cifsFile->srch_inf.entries_in_buffer; cifsFile->srch_inf.entries_in_buffer;
/* dump_cifs_file_struct(file, "In fce ");*/ /* dump_cifs_file_struct(file, "In fce ");*/
if(index_to_find < first_entry_in_buffer) { if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
is_dir_changed(file)) ||
(index_to_find < first_entry_in_buffer)) {
/* close and restart search */ /* close and restart search */
cFYI(1,("search backing up - close and restart search")); cFYI(1,("search backing up - close and restart search"));
cifsFile->invalidHandle = TRUE; cifsFile->invalidHandle = TRUE;
...@@ -604,7 +632,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -604,7 +632,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
} }
if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
cFYI(1,("can not return entries when pos_in_buf beyond last entry")); cFYI(1,("can not return entries pos_in_buf beyond last entry"));
*num_to_ret = 0; *num_to_ret = 0;
} else } else
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; *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,7 +861,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
if(pTcon == NULL) if(pTcon == NULL)
return -EINVAL; return -EINVAL;
switch ((int) file->f_pos) { switch ((int) file->f_pos) {
case 0: case 0:
/*if (filldir(direntry, ".", 1, file->f_pos, /*if (filldir(direntry, ".", 1, file->f_pos,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment