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.c215
1 files changed, 117 insertions, 98 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 770d5a9781c1..69d2c826a23b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -111,6 +111,14 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
111 return; 111 return;
112 } 112 }
113 113
114 /*
115 * If we know that the inode will need to be revalidated immediately,
116 * then don't create a new dentry for it. We'll end up doing an on
117 * the wire call either way and this spares us an invalidation.
118 */
119 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
120 return;
121
114 dentry = d_alloc(parent, name); 122 dentry = d_alloc(parent, name);
115 if (!dentry) 123 if (!dentry)
116 return; 124 return;
@@ -126,6 +134,22 @@ out:
126 dput(dentry); 134 dput(dentry);
127} 135}
128 136
137/*
138 * Is it possible that this directory might turn out to be a DFS referral
139 * once we go to try and use it?
140 */
141static bool
142cifs_dfs_is_possible(struct cifs_sb_info *cifs_sb)
143{
144#ifdef CONFIG_CIFS_DFS_UPCALL
145 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
146
147 if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
148 return true;
149#endif
150 return false;
151}
152
129static void 153static void
130cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) 154cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
131{ 155{
@@ -135,6 +159,19 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
135 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 159 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
136 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; 160 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
137 fattr->cf_dtype = DT_DIR; 161 fattr->cf_dtype = DT_DIR;
162 /*
163 * Windows CIFS servers generally make DFS referrals look
164 * like directories in FIND_* responses with the reparse
165 * attribute flag also set (since DFS junctions are
166 * reparse points). We must revalidate at least these
167 * directory inodes before trying to use them (if
168 * they are DFS we will get PATH_NOT_COVERED back
169 * when queried directly and can then try to connect
170 * to the DFS target)
171 */
172 if (cifs_dfs_is_possible(cifs_sb) &&
173 (fattr->cf_cifsattrs & ATTR_REPARSE))
174 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
138 } else { 175 } else {
139 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; 176 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
140 fattr->cf_dtype = DT_REG; 177 fattr->cf_dtype = DT_REG;
@@ -537,14 +574,14 @@ static int cifs_save_resume_key(const char *current_entry,
537 * every entry (do not increment for . or .. entry). 574 * every entry (do not increment for . or .. entry).
538 */ 575 */
539static int 576static int
540find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, 577find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
541 struct file *file, char **current_entry, int *num_to_ret) 578 struct file *file, char **current_entry, int *num_to_ret)
542{ 579{
543 __u16 search_flags; 580 __u16 search_flags;
544 int rc = 0; 581 int rc = 0;
545 int pos_in_buf = 0; 582 int pos_in_buf = 0;
546 loff_t first_entry_in_buffer; 583 loff_t first_entry_in_buffer;
547 loff_t index_to_find = file->f_pos; 584 loff_t index_to_find = pos;
548 struct cifsFileInfo *cfile = file->private_data; 585 struct cifsFileInfo *cfile = file->private_data;
549 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 586 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
550 struct TCP_Server_Info *server = tcon->ses->server; 587 struct TCP_Server_Info *server = tcon->ses->server;
@@ -659,8 +696,9 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
659 return rc; 696 return rc;
660} 697}
661 698
662static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, 699static int cifs_filldir(char *find_entry, struct file *file,
663 void *dirent, char *scratch_buf, unsigned int max_len) 700 struct dir_context *ctx,
701 char *scratch_buf, unsigned int max_len)
664{ 702{
665 struct cifsFileInfo *file_info = file->private_data; 703 struct cifsFileInfo *file_info = file->private_data;
666 struct super_block *sb = file->f_path.dentry->d_sb; 704 struct super_block *sb = file->f_path.dentry->d_sb;
@@ -740,13 +778,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
740 cifs_prime_dcache(file->f_dentry, &name, &fattr); 778 cifs_prime_dcache(file->f_dentry, &name, &fattr);
741 779
742 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); 780 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
743 rc = filldir(dirent, name.name, name.len, file->f_pos, ino, 781 return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
744 fattr.cf_dtype);
745 return rc;
746} 782}
747 783
748 784
749int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) 785int cifs_readdir(struct file *file, struct dir_context *ctx)
750{ 786{
751 int rc = 0; 787 int rc = 0;
752 unsigned int xid; 788 unsigned int xid;
@@ -772,103 +808,86 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
772 goto rddir2_exit; 808 goto rddir2_exit;
773 } 809 }
774 810
775 switch ((int) file->f_pos) { 811 if (!dir_emit_dots(file, ctx))
776 case 0: 812 goto rddir2_exit;
777 if (filldir(direntry, ".", 1, file->f_pos,
778 file_inode(file)->i_ino, DT_DIR) < 0) {
779 cifs_dbg(VFS, "Filldir for current dir failed\n");
780 rc = -ENOMEM;
781 break;
782 }
783 file->f_pos++;
784 case 1:
785 if (filldir(direntry, "..", 2, file->f_pos,
786 parent_ino(file->f_path.dentry), DT_DIR) < 0) {
787 cifs_dbg(VFS, "Filldir for parent dir failed\n");
788 rc = -ENOMEM;
789 break;
790 }
791 file->f_pos++;
792 default:
793 /* 1) If search is active,
794 is in current search buffer?
795 if it before then restart search
796 if after then keep searching till find it */
797
798 if (file->private_data == NULL) {
799 rc = -EINVAL;
800 free_xid(xid);
801 return rc;
802 }
803 cifsFile = file->private_data;
804 if (cifsFile->srch_inf.endOfSearch) {
805 if (cifsFile->srch_inf.emptyDir) {
806 cifs_dbg(FYI, "End of search, empty dir\n");
807 rc = 0;
808 break;
809 }
810 } /* else {
811 cifsFile->invalidHandle = true;
812 tcon->ses->server->close(xid, tcon, &cifsFile->fid);
813 } */
814 813
815 tcon = tlink_tcon(cifsFile->tlink); 814 /* 1) If search is active,
816 rc = find_cifs_entry(xid, tcon, file, &current_entry, 815 is in current search buffer?
817 &num_to_fill); 816 if it before then restart search
818 if (rc) { 817 if after then keep searching till find it */
819 cifs_dbg(FYI, "fce error %d\n", rc); 818
820 goto rddir2_exit; 819 if (file->private_data == NULL) {
821 } else if (current_entry != NULL) { 820 rc = -EINVAL;
822 cifs_dbg(FYI, "entry %lld found\n", file->f_pos); 821 goto rddir2_exit;
823 } else { 822 }
824 cifs_dbg(FYI, "could not find entry\n"); 823 cifsFile = file->private_data;
824 if (cifsFile->srch_inf.endOfSearch) {
825 if (cifsFile->srch_inf.emptyDir) {
826 cifs_dbg(FYI, "End of search, empty dir\n");
827 rc = 0;
825 goto rddir2_exit; 828 goto rddir2_exit;
826 } 829 }
827 cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", 830 } /* else {
828 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); 831 cifsFile->invalidHandle = true;
829 max_len = tcon->ses->server->ops->calc_smb_size( 832 tcon->ses->server->close(xid, tcon, &cifsFile->fid);
830 cifsFile->srch_inf.ntwrk_buf_start); 833 } */
831 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 834
832 835 tcon = tlink_tcon(cifsFile->tlink);
833 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); 836 rc = find_cifs_entry(xid, tcon, ctx->pos, file, &current_entry,
834 if (tmp_buf == NULL) { 837 &num_to_fill);
835 rc = -ENOMEM; 838 if (rc) {
839 cifs_dbg(FYI, "fce error %d\n", rc);
840 goto rddir2_exit;
841 } else if (current_entry != NULL) {
842 cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
843 } else {
844 cifs_dbg(FYI, "could not find entry\n");
845 goto rddir2_exit;
846 }
847 cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
848 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
849 max_len = tcon->ses->server->ops->calc_smb_size(
850 cifsFile->srch_inf.ntwrk_buf_start);
851 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
852
853 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
854 if (tmp_buf == NULL) {
855 rc = -ENOMEM;
856 goto rddir2_exit;
857 }
858
859 for (i = 0; i < num_to_fill; i++) {
860 if (current_entry == NULL) {
861 /* evaluate whether this case is an error */
862 cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
863 num_to_fill, i);
836 break; 864 break;
837 } 865 }
838 866 /*
839 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 867 * if buggy server returns . and .. late do we want to
840 if (current_entry == NULL) { 868 * check for that here?
841 /* evaluate whether this case is an error */ 869 */
842 cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", 870 rc = cifs_filldir(current_entry, file, ctx,
843 num_to_fill, i); 871 tmp_buf, max_len);
844 break; 872 if (rc) {
845 } 873 if (rc > 0)
846 /*
847 * if buggy server returns . and .. late do we want to
848 * check for that here?
849 */
850 rc = cifs_filldir(current_entry, file, filldir,
851 direntry, tmp_buf, max_len);
852 if (rc == -EOVERFLOW) {
853 rc = 0; 874 rc = 0;
854 break; 875 break;
855 }
856
857 file->f_pos++;
858 if (file->f_pos ==
859 cifsFile->srch_inf.index_of_last_entry) {
860 cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
861 file->f_pos, tmp_buf);
862 cifs_save_resume_key(current_entry, cifsFile);
863 break;
864 } else
865 current_entry =
866 nxt_dir_entry(current_entry, end_of_smb,
867 cifsFile->srch_inf.info_level);
868 } 876 }
869 kfree(tmp_buf); 877
870 break; 878 ctx->pos++;
871 } /* end switch */ 879 if (ctx->pos ==
880 cifsFile->srch_inf.index_of_last_entry) {
881 cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
882 ctx->pos, tmp_buf);
883 cifs_save_resume_key(current_entry, cifsFile);
884 break;
885 } else
886 current_entry =
887 nxt_dir_entry(current_entry, end_of_smb,
888 cifsFile->srch_inf.info_level);
889 }
890 kfree(tmp_buf);
872 891
873rddir2_exit: 892rddir2_exit:
874 free_xid(xid); 893 free_xid(xid);