Commit be4ccdcc2575ae154426083765b8b8eb9253c925
1 parent
9b5d5a1707
Exists in
master
and in
20 other branches
[readdir] convert cifs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 3 changed files with 82 additions and 100 deletions Side-by-side Diff
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
... | ... | @@ -101,7 +101,7 @@ |
101 | 101 | extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); |
102 | 102 | extern const struct file_operations cifs_dir_ops; |
103 | 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 | 106 | /* Functions related to dir entries */ |
107 | 107 | extern const struct dentry_operations cifs_dentry_ops; |
fs/cifs/readdir.c
... | ... | @@ -537,14 +537,14 @@ |
537 | 537 | * every entry (do not increment for . or .. entry). |
538 | 538 | */ |
539 | 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 | 541 | struct file *file, char **current_entry, int *num_to_ret) |
542 | 542 | { |
543 | 543 | __u16 search_flags; |
544 | 544 | int rc = 0; |
545 | 545 | int pos_in_buf = 0; |
546 | 546 | loff_t first_entry_in_buffer; |
547 | - loff_t index_to_find = file->f_pos; | |
547 | + loff_t index_to_find = pos; | |
548 | 548 | struct cifsFileInfo *cfile = file->private_data; |
549 | 549 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
550 | 550 | struct TCP_Server_Info *server = tcon->ses->server; |
... | ... | @@ -659,8 +659,9 @@ |
659 | 659 | return rc; |
660 | 660 | } |
661 | 661 | |
662 | -static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, | |
663 | - void *dirent, char *scratch_buf, unsigned int max_len) | |
662 | +static int cifs_filldir(char *find_entry, struct file *file, | |
663 | + struct dir_context *ctx, | |
664 | + char *scratch_buf, unsigned int max_len) | |
664 | 665 | { |
665 | 666 | struct cifsFileInfo *file_info = file->private_data; |
666 | 667 | struct super_block *sb = file->f_path.dentry->d_sb; |
667 | 668 | |
... | ... | @@ -740,13 +741,11 @@ |
740 | 741 | cifs_prime_dcache(file->f_dentry, &name, &fattr); |
741 | 742 | |
742 | 743 | ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); |
743 | - rc = filldir(dirent, name.name, name.len, file->f_pos, ino, | |
744 | - fattr.cf_dtype); | |
745 | - return rc; | |
744 | + return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); | |
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 | 750 | int rc = 0; |
752 | 751 | unsigned int xid; |
753 | 752 | |
754 | 753 | |
755 | 754 | |
756 | 755 | |
757 | 756 | |
758 | 757 | |
759 | 758 | |
760 | 759 | |
... | ... | @@ -772,103 +771,86 @@ |
772 | 771 | goto rddir2_exit; |
773 | 772 | } |
774 | 773 | |
775 | - switch ((int) file->f_pos) { | |
776 | - case 0: | |
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 */ | |
774 | + if (!dir_emit_dots(file, ctx)) | |
775 | + goto rddir2_exit; | |
797 | 776 | |
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 | - } */ | |
777 | + /* 1) If search is active, | |
778 | + is in current search buffer? | |
779 | + if it before then restart search | |
780 | + if after then keep searching till find it */ | |
814 | 781 | |
815 | - tcon = tlink_tcon(cifsFile->tlink); | |
816 | - rc = find_cifs_entry(xid, tcon, file, ¤t_entry, | |
817 | - &num_to_fill); | |
818 | - if (rc) { | |
819 | - cifs_dbg(FYI, "fce error %d\n", rc); | |
782 | + if (file->private_data == NULL) { | |
783 | + rc = -EINVAL; | |
784 | + goto rddir2_exit; | |
785 | + } | |
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; | |
820 | 791 | goto rddir2_exit; |
821 | - } else if (current_entry != NULL) { | |
822 | - cifs_dbg(FYI, "entry %lld found\n", file->f_pos); | |
823 | - } else { | |
824 | - cifs_dbg(FYI, "could not find entry\n"); | |
825 | - goto rddir2_exit; | |
826 | 792 | } |
827 | - cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", | |
828 | - num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); | |
829 | - max_len = tcon->ses->server->ops->calc_smb_size( | |
830 | - cifsFile->srch_inf.ntwrk_buf_start); | |
831 | - end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; | |
793 | + } /* else { | |
794 | + cifsFile->invalidHandle = true; | |
795 | + tcon->ses->server->close(xid, tcon, &cifsFile->fid); | |
796 | + } */ | |
832 | 797 | |
833 | - tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); | |
834 | - if (tmp_buf == NULL) { | |
835 | - rc = -ENOMEM; | |
798 | + tcon = tlink_tcon(cifsFile->tlink); | |
799 | + rc = find_cifs_entry(xid, tcon, ctx->pos, file, ¤t_entry, | |
800 | + &num_to_fill); | |
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 | 827 | break; |
837 | 828 | } |
838 | - | |
839 | - for (i = 0; (i < num_to_fill) && (rc == 0); i++) { | |
840 | - if (current_entry == NULL) { | |
841 | - /* evaluate whether this case is an error */ | |
842 | - cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", | |
843 | - num_to_fill, i); | |
844 | - break; | |
845 | - } | |
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) { | |
829 | + /* | |
830 | + * if buggy server returns . and .. late do we want to | |
831 | + * check for that here? | |
832 | + */ | |
833 | + rc = cifs_filldir(current_entry, file, ctx, | |
834 | + tmp_buf, max_len); | |
835 | + if (rc) { | |
836 | + if (rc > 0) | |
853 | 837 | rc = 0; |
854 | - 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); | |
838 | + break; | |
868 | 839 | } |
869 | - kfree(tmp_buf); | |
870 | - break; | |
871 | - } /* end switch */ | |
840 | + | |
841 | + ctx->pos++; | |
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 | 855 | rddir2_exit: |
874 | 856 | free_xid(xid); |