diff options
author | Steve French <sfrench@us.ibm.com> | 2006-04-22 11:53:05 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-04-22 11:53:05 -0400 |
commit | 60808233f374aebba26488d06a5f25443f6763c3 (patch) | |
tree | e2f85a165398f0c6c7432a7fa715d18efc3d8d5b /fs/cifs/readdir.c | |
parent | 45af7a0f2ebad1304cab956e15f0b37318226fcd (diff) |
[CIFS] Readdir fixes to allow search to start at arbitrary position
in directory
Also includes first part of fix to compensate for servers which forget
to return . and .. as well as updates to changelog and cifs readme.
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/readdir.c')
-rw-r--r-- | fs/cifs/readdir.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 7b8591acc5ad..41c022e3c132 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -590,6 +590,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
590 | first_entry_in_buffer = | 590 | first_entry_in_buffer = |
591 | cifsFile->srch_inf.index_of_last_entry - | 591 | cifsFile->srch_inf.index_of_last_entry - |
592 | cifsFile->srch_inf.entries_in_buffer; | 592 | cifsFile->srch_inf.entries_in_buffer; |
593 | |||
594 | /* if first entry in buf is zero then is first buffer | ||
595 | in search response data which means it is likely . and .. | ||
596 | will be in this buffer, although some servers do not return | ||
597 | . and .. for the root of a drive and for those we need | ||
598 | to start two entries earlier */ | ||
599 | |||
593 | /* dump_cifs_file_struct(file, "In fce ");*/ | 600 | /* dump_cifs_file_struct(file, "In fce ");*/ |
594 | if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && | 601 | if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && |
595 | is_dir_changed(file)) || | 602 | is_dir_changed(file)) || |
@@ -632,23 +639,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
632 | char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + | 639 | char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + |
633 | smbCalcSize((struct smb_hdr *) | 640 | smbCalcSize((struct smb_hdr *) |
634 | cifsFile->srch_inf.ntwrk_buf_start); | 641 | cifsFile->srch_inf.ntwrk_buf_start); |
642 | |||
643 | current_entry = cifsFile->srch_inf.srch_entries_start; | ||
635 | first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry | 644 | first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry |
636 | - cifsFile->srch_inf.entries_in_buffer; | 645 | - cifsFile->srch_inf.entries_in_buffer; |
637 | pos_in_buf = index_to_find - first_entry_in_buffer; | 646 | pos_in_buf = index_to_find - first_entry_in_buffer; |
638 | cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); | 647 | cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); |
639 | current_entry = cifsFile->srch_inf.srch_entries_start; | ||
640 | for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { | 648 | for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { |
641 | /* go entry by entry figuring out which is first */ | 649 | /* go entry by entry figuring out which is first */ |
642 | /* if( . or ..) | ||
643 | skip */ | ||
644 | rc = cifs_entry_is_dot(current_entry,cifsFile); | ||
645 | if(rc == 1) /* is . or .. so skip */ { | ||
646 | cFYI(1,("Entry is .")); /* BB removeme BB */ | ||
647 | /* continue; */ | ||
648 | } else if (rc == 2 ) { | ||
649 | cFYI(1,("Entry is ..")); /* BB removeme BB */ | ||
650 | /* continue; */ | ||
651 | } | ||
652 | current_entry = nxt_dir_entry(current_entry,end_of_smb); | 650 | current_entry = nxt_dir_entry(current_entry,end_of_smb); |
653 | } | 651 | } |
654 | if((current_entry == NULL) && (i < pos_in_buf)) { | 652 | if((current_entry == NULL) && (i < pos_in_buf)) { |
@@ -768,6 +766,11 @@ static int cifs_filldir(char *pfindEntry, struct file *file, | |||
768 | if(file->f_dentry == NULL) | 766 | if(file->f_dentry == NULL) |
769 | return -ENOENT; | 767 | return -ENOENT; |
770 | 768 | ||
769 | rc = cifs_entry_is_dot(pfindEntry,cifsF); | ||
770 | /* skip . and .. since we added them first */ | ||
771 | if(rc != 0) | ||
772 | return 0; | ||
773 | |||
771 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); | 774 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); |
772 | 775 | ||
773 | qstring.name = scratch_buf; | 776 | qstring.name = scratch_buf; |
@@ -896,22 +899,22 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
896 | 899 | ||
897 | switch ((int) file->f_pos) { | 900 | switch ((int) file->f_pos) { |
898 | case 0: | 901 | case 0: |
899 | /*if (filldir(direntry, ".", 1, file->f_pos, | 902 | if (filldir(direntry, ".", 1, file->f_pos, |
900 | file->f_dentry->d_inode->i_ino, DT_DIR) < 0) { | 903 | file->f_dentry->d_inode->i_ino, DT_DIR) < 0) { |
901 | cERROR(1, ("Filldir for current dir failed ")); | 904 | cERROR(1, ("Filldir for current dir failed")); |
902 | rc = -ENOMEM; | 905 | rc = -ENOMEM; |
903 | break; | 906 | break; |
904 | } | 907 | } |
905 | file->f_pos++; */ | 908 | file->f_pos++; |
906 | case 1: | 909 | case 1: |
907 | /* if (filldir(direntry, "..", 2, file->f_pos, | 910 | if (filldir(direntry, "..", 2, file->f_pos, |
908 | file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { | 911 | file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { |
909 | cERROR(1, ("Filldir for parent dir failed ")); | 912 | cERROR(1, ("Filldir for parent dir failed ")); |
910 | rc = -ENOMEM; | 913 | rc = -ENOMEM; |
911 | break; | 914 | break; |
912 | } | 915 | } |
913 | file->f_pos++; */ | 916 | file->f_pos++; |
914 | case 2: | 917 | default: |
915 | /* 1) If search is active, | 918 | /* 1) If search is active, |
916 | is in current search buffer? | 919 | is in current search buffer? |
917 | if it before then restart search | 920 | if it before then restart search |
@@ -925,7 +928,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
925 | return rc; | 928 | return rc; |
926 | } | 929 | } |
927 | } | 930 | } |
928 | default: | ||
929 | if(file->private_data == NULL) { | 931 | if(file->private_data == NULL) { |
930 | rc = -EINVAL; | 932 | rc = -EINVAL; |
931 | FreeXid(xid); | 933 | FreeXid(xid); |
@@ -945,8 +947,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
945 | kfree(cifsFile->search_resume_name); | 947 | kfree(cifsFile->search_resume_name); |
946 | cifsFile->search_resume_name = NULL; */ | 948 | cifsFile->search_resume_name = NULL; */ |
947 | 949 | ||
948 | /* BB account for . and .. in f_pos as special case */ | ||
949 | |||
950 | rc = find_cifs_entry(xid,pTcon, file, | 950 | rc = find_cifs_entry(xid,pTcon, file, |
951 | ¤t_entry,&num_to_fill); | 951 | ¤t_entry,&num_to_fill); |
952 | if(rc) { | 952 | if(rc) { |
@@ -975,7 +975,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
975 | num_to_fill, i)); | 975 | num_to_fill, i)); |
976 | break; | 976 | break; |
977 | } | 977 | } |
978 | 978 | /* if buggy server returns . and .. late do | |
979 | we want to check for that here? */ | ||
979 | rc = cifs_filldir(current_entry, file, | 980 | rc = cifs_filldir(current_entry, file, |
980 | filldir, direntry,tmp_buf); | 981 | filldir, direntry,tmp_buf); |
981 | file->f_pos++; | 982 | file->f_pos++; |