aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/readdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/readdir.c')
-rw-r--r--fs/cifs/readdir.c84
1 files changed, 65 insertions, 19 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 22557716f9af..a86bd1c07602 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -91,7 +91,10 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
91 } 91 }
92 92
93 *ptmp_inode = new_inode(file->f_dentry->d_sb); 93 *ptmp_inode = new_inode(file->f_dentry->d_sb);
94 tmp_dentry->d_op = &cifs_dentry_ops; 94 if (pTcon->nocase)
95 tmp_dentry->d_op = &cifs_ci_dentry_ops;
96 else
97 tmp_dentry->d_op = &cifs_dentry_ops;
95 if(*ptmp_inode == NULL) 98 if(*ptmp_inode == NULL)
96 return rc; 99 return rc;
97 rc = 1; 100 rc = 1;
@@ -148,6 +151,13 @@ static void fill_in_inode(struct inode *tmp_inode,
148 tmp_inode->i_mode = cifs_sb->mnt_dir_mode; 151 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
149 } 152 }
150 tmp_inode->i_mode |= S_IFDIR; 153 tmp_inode->i_mode |= S_IFDIR;
154 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
155 (attr & ATTR_SYSTEM) && (end_of_file == 0)) {
156 *pobject_type = DT_FIFO;
157 tmp_inode->i_mode |= S_IFIFO;
158/* BB Finish for SFU style symlinks and devies */
159/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
160 (attr & ATTR_SYSTEM) && ) { */
151/* we no longer mark these because we could not follow them */ 161/* we no longer mark these because we could not follow them */
152/* } else if (attr & ATTR_REPARSE) { 162/* } else if (attr & ATTR_REPARSE) {
153 *pobject_type = DT_LNK; 163 *pobject_type = DT_LNK;
@@ -187,11 +197,17 @@ static void fill_in_inode(struct inode *tmp_inode,
187 tmp_inode->i_fop = &cifs_file_direct_ops; 197 tmp_inode->i_fop = &cifs_file_direct_ops;
188 else 198 else
189 tmp_inode->i_fop = &cifs_file_ops; 199 tmp_inode->i_fop = &cifs_file_ops;
200 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
201 tmp_inode->i_fop->lock = NULL;
190 tmp_inode->i_data.a_ops = &cifs_addr_ops; 202 tmp_inode->i_data.a_ops = &cifs_addr_ops;
191 203 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
204 (cifs_sb->tcon->ses->server->maxBuf <
205 4096 + MAX_CIFS_HDR_SIZE))
206 tmp_inode->i_data.a_ops->readpages = NULL;
192 if(isNewInode) 207 if(isNewInode)
193 return; /* No sense invalidating pages for new inode since we 208 return; /* No sense invalidating pages for new inode
194 have not started caching readahead file data yet */ 209 since have not started caching readahead file
210 data yet */
195 211
196 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && 212 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
197 (local_size == tmp_inode->i_size)) { 213 (local_size == tmp_inode->i_size)) {
@@ -290,7 +306,13 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
290 tmp_inode->i_fop = &cifs_file_direct_ops; 306 tmp_inode->i_fop = &cifs_file_direct_ops;
291 else 307 else
292 tmp_inode->i_fop = &cifs_file_ops; 308 tmp_inode->i_fop = &cifs_file_ops;
309 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
310 tmp_inode->i_fop->lock = NULL;
293 tmp_inode->i_data.a_ops = &cifs_addr_ops; 311 tmp_inode->i_data.a_ops = &cifs_addr_ops;
312 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
313 (cifs_sb->tcon->ses->server->maxBuf <
314 4096 + MAX_CIFS_HDR_SIZE))
315 tmp_inode->i_data.a_ops->readpages = NULL;
294 316
295 if(isNewInode) 317 if(isNewInode)
296 return; /* No sense invalidating pages for new inode since we 318 return; /* No sense invalidating pages for new inode since we
@@ -374,7 +396,8 @@ ffirst_retry:
374 396
375 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 397 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
376 &cifsFile->netfid, &cifsFile->srch_inf, 398 &cifsFile->netfid, &cifsFile->srch_inf,
377 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 399 cifs_sb->mnt_cifs_flags &
400 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
378 if(rc == 0) 401 if(rc == 0)
379 cifsFile->invalidHandle = FALSE; 402 cifsFile->invalidHandle = FALSE;
380 if((rc == -EOPNOTSUPP) && 403 if((rc == -EOPNOTSUPP) &&
@@ -491,6 +514,30 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
491 return rc; 514 return rc;
492} 515}
493 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
494/* find the corresponding entry in the search */ 541/* find the corresponding entry in the search */
495/* Note that the SMB server returns search entries for . and .. which 542/* Note that the SMB server returns search entries for . and .. which
496 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
@@ -507,7 +554,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
507 struct cifsFileInfo * cifsFile = file->private_data; 554 struct cifsFileInfo * cifsFile = file->private_data;
508 /* check if index in the buffer */ 555 /* check if index in the buffer */
509 556
510 if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL)) 557 if((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
558 (num_to_ret == NULL))
511 return -ENOENT; 559 return -ENOENT;
512 560
513 *ppCurrentEntry = NULL; 561 *ppCurrentEntry = NULL;
@@ -515,7 +563,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
515 cifsFile->srch_inf.index_of_last_entry - 563 cifsFile->srch_inf.index_of_last_entry -
516 cifsFile->srch_inf.entries_in_buffer; 564 cifsFile->srch_inf.entries_in_buffer;
517/* dump_cifs_file_struct(file, "In fce ");*/ 565/* dump_cifs_file_struct(file, "In fce ");*/
518 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)) {
519 /* close and restart search */ 569 /* close and restart search */
520 cFYI(1,("search backing up - close and restart search")); 570 cFYI(1,("search backing up - close and restart search"));
521 cifsFile->invalidHandle = TRUE; 571 cifsFile->invalidHandle = TRUE;
@@ -536,7 +586,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
536 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 586 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
537 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ 587 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
538 cFYI(1,("calling findnext2")); 588 cFYI(1,("calling findnext2"));
539 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf); 589 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
590 &cifsFile->srch_inf);
540 if(rc) 591 if(rc)
541 return -ENOENT; 592 return -ENOENT;
542 } 593 }
@@ -548,14 +599,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
548 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 599 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
549 smbCalcSize((struct smb_hdr *) 600 smbCalcSize((struct smb_hdr *)
550 cifsFile->srch_inf.ntwrk_buf_start); 601 cifsFile->srch_inf.ntwrk_buf_start);
551/* dump_cifs_file_struct(file,"found entry in fce "); */
552 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry 602 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
553 - cifsFile->srch_inf.entries_in_buffer; 603 - cifsFile->srch_inf.entries_in_buffer;
554 pos_in_buf = index_to_find - first_entry_in_buffer; 604 pos_in_buf = index_to_find - first_entry_in_buffer;
555 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 605 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
556 current_entry = cifsFile->srch_inf.srch_entries_start; 606 current_entry = cifsFile->srch_inf.srch_entries_start;
557 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { 607 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
558 /* go entry to next entry figuring out which we need to start with */ 608 /* go entry by entry figuring out which is first */
559 /* if( . or ..) 609 /* if( . or ..)
560 skip */ 610 skip */
561 rc = cifs_entry_is_dot(current_entry,cifsFile); 611 rc = cifs_entry_is_dot(current_entry,cifsFile);
@@ -582,11 +632,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
582 } 632 }
583 633
584 if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { 634 if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
585 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"));
586 *num_to_ret = 0; 636 *num_to_ret = 0;
587 } else 637 } else
588 *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;
589/* dump_cifs_file_struct(file, "end fce ");*/
590 639
591 return rc; 640 return rc;
592} 641}
@@ -721,7 +770,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
721 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); 770 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
722 } 771 }
723 772
724 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); 773 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
774 tmp_inode->i_ino,obj_type);
725 if(rc) { 775 if(rc) {
726 cFYI(1,("filldir rc = %d",rc)); 776 cFYI(1,("filldir rc = %d",rc));
727 } 777 }
@@ -805,15 +855,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
805 FreeXid(xid); 855 FreeXid(xid);
806 return -EIO; 856 return -EIO;
807 } 857 }
808/* dump_cifs_file_struct(file, "Begin rdir "); */
809 858
810 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 859 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
811 pTcon = cifs_sb->tcon; 860 pTcon = cifs_sb->tcon;
812 if(pTcon == NULL) 861 if(pTcon == NULL)
813 return -EINVAL; 862 return -EINVAL;
814 863
815/* cFYI(1,("readdir2 pos: %lld",file->f_pos)); */
816
817 switch ((int) file->f_pos) { 864 switch ((int) file->f_pos) {
818 case 0: 865 case 0:
819 /*if (filldir(direntry, ".", 1, file->f_pos, 866 /*if (filldir(direntry, ".", 1, file->f_pos,
@@ -866,7 +913,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
866 cifsFile->search_resume_name = NULL; */ 913 cifsFile->search_resume_name = NULL; */
867 914
868 /* BB account for . and .. in f_pos as special case */ 915 /* BB account for . and .. in f_pos as special case */
869 /* dump_cifs_file_struct(file, "rdir after default ");*/
870 916
871 rc = find_cifs_entry(xid,pTcon, file, 917 rc = find_cifs_entry(xid,pTcon, file,
872 &current_entry,&num_to_fill); 918 &current_entry,&num_to_fill);
@@ -906,14 +952,14 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
906 cifs_save_resume_key(current_entry,cifsFile); 952 cifs_save_resume_key(current_entry,cifsFile);
907 break; 953 break;
908 } else 954 } else
909 current_entry = nxt_dir_entry(current_entry,end_of_smb); 955 current_entry = nxt_dir_entry(current_entry,
956 end_of_smb);
910 } 957 }
911 kfree(tmp_buf); 958 kfree(tmp_buf);
912 break; 959 break;
913 } /* end switch */ 960 } /* end switch */
914 961
915rddir2_exit: 962rddir2_exit:
916 /* dump_cifs_file_struct(file, "end rdir "); */
917 FreeXid(xid); 963 FreeXid(xid);
918 return rc; 964 return rc;
919} 965}