aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-05-22 16:17:25 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-06-29 04:56:54 -0400
commitbe4ccdcc2575ae154426083765b8b8eb9253c925 (patch)
tree4e1c33e014257ce83facb250226b7c9c37579cd8 /fs
parent9b5d5a170781f8d6adb7ea94571d83ed5a3b7605 (diff)
[readdir] convert cifs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/readdir.c178
3 files changed, 82 insertions, 100 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 3752b9f6d9e4..540c1ccfcdb2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -968,7 +968,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
968}; 968};
969 969
970const struct file_operations cifs_dir_ops = { 970const struct file_operations cifs_dir_ops = {
971 .readdir = cifs_readdir, 971 .iterate = cifs_readdir,
972 .release = cifs_closedir, 972 .release = cifs_closedir,
973 .read = generic_read_dir, 973 .read = generic_read_dir,
974 .unlocked_ioctl = cifs_ioctl, 974 .unlocked_ioctl = cifs_ioctl,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 0e32c3446ce9..d05b3028e3b9 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -101,7 +101,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
101extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); 101extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
102extern const struct file_operations cifs_dir_ops; 102extern const struct file_operations cifs_dir_ops;
103extern int cifs_dir_open(struct inode *inode, struct file *file); 103extern int cifs_dir_open(struct inode *inode, struct file *file);
104extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); 104extern int cifs_readdir(struct file *file, struct dir_context *ctx);
105 105
106/* Functions related to dir entries */ 106/* Functions related to dir entries */
107extern const struct dentry_operations cifs_dentry_ops; 107extern const struct dentry_operations cifs_dentry_ops;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 770d5a9781c1..f1213799de1a 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -537,14 +537,14 @@ static int cifs_save_resume_key(const char *current_entry,
537 * every entry (do not increment for . or .. entry). 537 * every entry (do not increment for . or .. entry).
538 */ 538 */
539static int 539static int
540find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, 540find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
541 struct file *file, char **current_entry, int *num_to_ret) 541 struct file *file, char **current_entry, int *num_to_ret)
542{ 542{
543 __u16 search_flags; 543 __u16 search_flags;
544 int rc = 0; 544 int rc = 0;
545 int pos_in_buf = 0; 545 int pos_in_buf = 0;
546 loff_t first_entry_in_buffer; 546 loff_t first_entry_in_buffer;
547 loff_t index_to_find = file->f_pos; 547 loff_t index_to_find = pos;
548 struct cifsFileInfo *cfile = file->private_data; 548 struct cifsFileInfo *cfile = file->private_data;
549 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 549 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
550 struct TCP_Server_Info *server = tcon->ses->server; 550 struct TCP_Server_Info *server = tcon->ses->server;
@@ -659,8 +659,9 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
659 return rc; 659 return rc;
660} 660}
661 661
662static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, 662static int cifs_filldir(char *find_entry, struct file *file,
663 void *dirent, char *scratch_buf, unsigned int max_len) 663 struct dir_context *ctx,
664 char *scratch_buf, unsigned int max_len)
664{ 665{
665 struct cifsFileInfo *file_info = file->private_data; 666 struct cifsFileInfo *file_info = file->private_data;
666 struct super_block *sb = file->f_path.dentry->d_sb; 667 struct super_block *sb = file->f_path.dentry->d_sb;
@@ -740,13 +741,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
740 cifs_prime_dcache(file->f_dentry, &name, &fattr); 741 cifs_prime_dcache(file->f_dentry, &name, &fattr);
741 742
742 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); 743 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
743 rc = filldir(dirent, name.name, name.len, file->f_pos, ino, 744 return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
744 fattr.cf_dtype);
745 return rc;
746} 745}
747 746
748 747
749int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) 748int cifs_readdir(struct file *file, struct dir_context *ctx)
750{ 749{
751 int rc = 0; 750 int rc = 0;
752 unsigned int xid; 751 unsigned int xid;
@@ -772,103 +771,86 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
772 goto rddir2_exit; 771 goto rddir2_exit;
773 } 772 }
774 773
775 switch ((int) file->f_pos) { 774 if (!dir_emit_dots(file, ctx))
776 case 0: 775 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 776
815 tcon = tlink_tcon(cifsFile->tlink); 777 /* 1) If search is active,
816 rc = find_cifs_entry(xid, tcon, file, &current_entry, 778 is in current search buffer?
817 &num_to_fill); 779 if it before then restart search
818 if (rc) { 780 if after then keep searching till find it */
819 cifs_dbg(FYI, "fce error %d\n", rc); 781
820 goto rddir2_exit; 782 if (file->private_data == NULL) {
821 } else if (current_entry != NULL) { 783 rc = -EINVAL;
822 cifs_dbg(FYI, "entry %lld found\n", file->f_pos); 784 goto rddir2_exit;
823 } else { 785 }
824 cifs_dbg(FYI, "could not find entry\n"); 786 cifsFile = file->private_data;
787 if (cifsFile->srch_inf.endOfSearch) {
788 if (cifsFile->srch_inf.emptyDir) {
789 cifs_dbg(FYI, "End of search, empty dir\n");
790 rc = 0;
825 goto rddir2_exit; 791 goto rddir2_exit;
826 } 792 }
827 cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", 793 } /* else {
828 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); 794 cifsFile->invalidHandle = true;
829 max_len = tcon->ses->server->ops->calc_smb_size( 795 tcon->ses->server->close(xid, tcon, &cifsFile->fid);
830 cifsFile->srch_inf.ntwrk_buf_start); 796 } */
831 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 797
832 798 tcon = tlink_tcon(cifsFile->tlink);
833 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); 799 rc = find_cifs_entry(xid, tcon, ctx->pos, file, &current_entry,
834 if (tmp_buf == NULL) { 800 &num_to_fill);
835 rc = -ENOMEM; 801 if (rc) {
802 cifs_dbg(FYI, "fce error %d\n", rc);
803 goto rddir2_exit;
804 } else if (current_entry != NULL) {
805 cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
806 } else {
807 cifs_dbg(FYI, "could not find entry\n");
808 goto rddir2_exit;
809 }
810 cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
811 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
812 max_len = tcon->ses->server->ops->calc_smb_size(
813 cifsFile->srch_inf.ntwrk_buf_start);
814 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
815
816 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
817 if (tmp_buf == NULL) {
818 rc = -ENOMEM;
819 goto rddir2_exit;
820 }
821
822 for (i = 0; i < num_to_fill; i++) {
823 if (current_entry == NULL) {
824 /* evaluate whether this case is an error */
825 cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
826 num_to_fill, i);
836 break; 827 break;
837 } 828 }
838 829 /*
839 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 830 * if buggy server returns . and .. late do we want to
840 if (current_entry == NULL) { 831 * check for that here?
841 /* evaluate whether this case is an error */ 832 */
842 cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", 833 rc = cifs_filldir(current_entry, file, ctx,
843 num_to_fill, i); 834 tmp_buf, max_len);
844 break; 835 if (rc) {
845 } 836 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; 837 rc = 0;
854 break; 838 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 } 839 }
869 kfree(tmp_buf); 840
870 break; 841 ctx->pos++;
871 } /* end switch */ 842 if (ctx->pos ==
843 cifsFile->srch_inf.index_of_last_entry) {
844 cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
845 ctx->pos, tmp_buf);
846 cifs_save_resume_key(current_entry, cifsFile);
847 break;
848 } else
849 current_entry =
850 nxt_dir_entry(current_entry, end_of_smb,
851 cifsFile->srch_inf.info_level);
852 }
853 kfree(tmp_buf);
872 854
873rddir2_exit: 855rddir2_exit:
874 free_xid(xid); 856 free_xid(xid);