Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[readdir] convert cifs

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro be4ccdcc 9b5d5a17

+83 -101
+1 -1
fs/cifs/cifsfs.c
··· 968 968 }; 969 969 970 970 const struct file_operations cifs_dir_ops = { 971 - .readdir = cifs_readdir, 971 + .iterate = cifs_readdir, 972 972 .release = cifs_closedir, 973 973 .read = generic_read_dir, 974 974 .unlocked_ioctl = cifs_ioctl,
+1 -1
fs/cifs/cifsfs.h
··· 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;
+81 -99
fs/cifs/readdir.c
··· 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 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; ··· 741 740 cifs_prime_dcache(file->f_dentry, &name, &fattr); 742 741 743 742 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); 744 - rc = filldir(dirent, name.name, name.len, file->f_pos, ino, 745 - fattr.cf_dtype); 746 - return rc; 743 + return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); 747 744 } 748 745 749 746 750 - int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) 747 + int cifs_readdir(struct file *file, struct dir_context *ctx) 751 748 { 752 749 int rc = 0; 753 750 unsigned int xid; ··· 771 772 goto rddir2_exit; 772 773 } 773 774 774 - switch ((int) file->f_pos) { 775 - case 0: 776 - if (filldir(direntry, ".", 1, file->f_pos, 777 - file_inode(file)->i_ino, DT_DIR) < 0) { 778 - cifs_dbg(VFS, "Filldir for current dir failed\n"); 779 - rc = -ENOMEM; 775 + if (!dir_emit_dots(file, ctx)) 776 + goto rddir2_exit; 777 + 778 + /* 1) If search is active, 779 + is in current search buffer? 780 + if it before then restart search 781 + if after then keep searching till find it */ 782 + 783 + if (file->private_data == NULL) { 784 + rc = -EINVAL; 785 + goto rddir2_exit; 786 + } 787 + cifsFile = file->private_data; 788 + if (cifsFile->srch_inf.endOfSearch) { 789 + if (cifsFile->srch_inf.emptyDir) { 790 + cifs_dbg(FYI, "End of search, empty dir\n"); 791 + rc = 0; 792 + goto rddir2_exit; 793 + } 794 + } /* else { 795 + cifsFile->invalidHandle = true; 796 + tcon->ses->server->close(xid, tcon, &cifsFile->fid); 797 + } */ 798 + 799 + tcon = tlink_tcon(cifsFile->tlink); 800 + rc = find_cifs_entry(xid, tcon, ctx->pos, file, &current_entry, 801 + &num_to_fill); 802 + if (rc) { 803 + cifs_dbg(FYI, "fce error %d\n", rc); 804 + goto rddir2_exit; 805 + } else if (current_entry != NULL) { 806 + cifs_dbg(FYI, "entry %lld found\n", ctx->pos); 807 + } else { 808 + cifs_dbg(FYI, "could not find entry\n"); 809 + goto rddir2_exit; 810 + } 811 + cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", 812 + num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); 813 + max_len = tcon->ses->server->ops->calc_smb_size( 814 + cifsFile->srch_inf.ntwrk_buf_start); 815 + end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 816 + 817 + tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); 818 + if (tmp_buf == NULL) { 819 + rc = -ENOMEM; 820 + goto rddir2_exit; 821 + } 822 + 823 + for (i = 0; i < num_to_fill; i++) { 824 + if (current_entry == NULL) { 825 + /* evaluate whether this case is an error */ 826 + cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", 827 + num_to_fill, i); 780 828 break; 781 829 } 782 - file->f_pos++; 783 - case 1: 784 - if (filldir(direntry, "..", 2, file->f_pos, 785 - parent_ino(file->f_path.dentry), DT_DIR) < 0) { 786 - cifs_dbg(VFS, "Filldir for parent dir failed\n"); 787 - rc = -ENOMEM; 788 - break; 789 - } 790 - file->f_pos++; 791 - default: 792 - /* 1) If search is active, 793 - is in current search buffer? 794 - if it before then restart search 795 - if after then keep searching till find it */ 796 - 797 - if (file->private_data == NULL) { 798 - rc = -EINVAL; 799 - free_xid(xid); 800 - return rc; 801 - } 802 - cifsFile = file->private_data; 803 - if (cifsFile->srch_inf.endOfSearch) { 804 - if (cifsFile->srch_inf.emptyDir) { 805 - cifs_dbg(FYI, "End of search, empty dir\n"); 806 - rc = 0; 807 - break; 808 - } 809 - } /* else { 810 - cifsFile->invalidHandle = true; 811 - tcon->ses->server->close(xid, tcon, &cifsFile->fid); 812 - } */ 813 - 814 - tcon = tlink_tcon(cifsFile->tlink); 815 - rc = find_cifs_entry(xid, tcon, file, &current_entry, 816 - &num_to_fill); 830 + /* 831 + * if buggy server returns . and .. late do we want to 832 + * check for that here? 833 + */ 834 + rc = cifs_filldir(current_entry, file, ctx, 835 + tmp_buf, max_len); 817 836 if (rc) { 818 - cifs_dbg(FYI, "fce error %d\n", rc); 819 - goto rddir2_exit; 820 - } else if (current_entry != NULL) { 821 - cifs_dbg(FYI, "entry %lld found\n", file->f_pos); 822 - } else { 823 - cifs_dbg(FYI, "could not find entry\n"); 824 - goto rddir2_exit; 825 - } 826 - cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", 827 - num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); 828 - max_len = tcon->ses->server->ops->calc_smb_size( 829 - cifsFile->srch_inf.ntwrk_buf_start); 830 - end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 831 - 832 - tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); 833 - if (tmp_buf == NULL) { 834 - rc = -ENOMEM; 837 + if (rc > 0) 838 + rc = 0; 835 839 break; 836 840 } 837 841 838 - for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 839 - if (current_entry == NULL) { 840 - /* evaluate whether this case is an error */ 841 - cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n", 842 - num_to_fill, i); 843 - break; 844 - } 845 - /* 846 - * if buggy server returns . and .. late do we want to 847 - * check for that here? 848 - */ 849 - rc = cifs_filldir(current_entry, file, filldir, 850 - direntry, tmp_buf, max_len); 851 - if (rc == -EOVERFLOW) { 852 - rc = 0; 853 - break; 854 - } 855 - 856 - file->f_pos++; 857 - if (file->f_pos == 858 - cifsFile->srch_inf.index_of_last_entry) { 859 - cifs_dbg(FYI, "last entry in buf at pos %lld %s\n", 860 - file->f_pos, tmp_buf); 861 - cifs_save_resume_key(current_entry, cifsFile); 862 - break; 863 - } else 864 - current_entry = 865 - nxt_dir_entry(current_entry, end_of_smb, 866 - cifsFile->srch_inf.info_level); 867 - } 868 - kfree(tmp_buf); 869 - break; 870 - } /* end switch */ 842 + ctx->pos++; 843 + if (ctx->pos == 844 + cifsFile->srch_inf.index_of_last_entry) { 845 + cifs_dbg(FYI, "last entry in buf at pos %lld %s\n", 846 + ctx->pos, tmp_buf); 847 + cifs_save_resume_key(current_entry, cifsFile); 848 + break; 849 + } else 850 + current_entry = 851 + nxt_dir_entry(current_entry, end_of_smb, 852 + cifsFile->srch_inf.info_level); 853 + } 854 + kfree(tmp_buf); 871 855 872 856 rddir2_exit: 873 857 free_xid(xid);