diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-22 16:17:25 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:56:54 -0400 |
commit | be4ccdcc2575ae154426083765b8b8eb9253c925 (patch) | |
tree | 4e1c33e014257ce83facb250226b7c9c37579cd8 /fs | |
parent | 9b5d5a170781f8d6adb7ea94571d83ed5a3b7605 (diff) |
[readdir] convert cifs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 178 |
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 | ||
970 | const struct file_operations cifs_dir_ops = { | 970 | const 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 *); | |||
101 | extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); | 101 | extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); |
102 | extern const struct file_operations cifs_dir_ops; | 102 | extern const struct file_operations cifs_dir_ops; |
103 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 103 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
104 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 104 | extern int cifs_readdir(struct file *file, struct dir_context *ctx); |
105 | 105 | ||
106 | /* Functions related to dir entries */ | 106 | /* Functions related to dir entries */ |
107 | extern const struct dentry_operations cifs_dentry_ops; | 107 | extern 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 | */ |
539 | static int | 539 | static int |
540 | find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, | 540 | find_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 | ||
662 | static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, | 662 | static 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 | ||
749 | int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | 748 | int 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, ¤t_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, ¤t_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 | ||
873 | rddir2_exit: | 855 | rddir2_exit: |
874 | free_xid(xid); | 856 | free_xid(xid); |