[readdir] convert cifs
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 22 May 2013 20:17:25 +0000 (16:17 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:56:54 +0000 (12:56 +0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/readdir.c

index 3752b9f..540c1cc 100644 (file)
@@ -968,7 +968,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
 };
 
 const struct file_operations cifs_dir_ops = {
-       .readdir = cifs_readdir,
+       .iterate = cifs_readdir,
        .release = cifs_closedir,
        .read    = generic_read_dir,
        .unlocked_ioctl  = cifs_ioctl,
index 0e32c34..d05b302 100644 (file)
@@ -101,7 +101,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
 extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
 extern const struct file_operations cifs_dir_ops;
 extern int cifs_dir_open(struct inode *inode, struct file *file);
-extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
+extern int cifs_readdir(struct file *file, struct dir_context *ctx);
 
 /* Functions related to dir entries */
 extern const struct dentry_operations cifs_dentry_ops;
index 770d5a9..f121379 100644 (file)
@@ -537,14 +537,14 @@ static int cifs_save_resume_key(const char *current_entry,
  * every entry (do not increment for . or .. entry).
  */
 static int
-find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
+find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
                struct file *file, char **current_entry, int *num_to_ret)
 {
        __u16 search_flags;
        int rc = 0;
        int pos_in_buf = 0;
        loff_t first_entry_in_buffer;
-       loff_t index_to_find = file->f_pos;
+       loff_t index_to_find = pos;
        struct cifsFileInfo *cfile = file->private_data;
        struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        struct TCP_Server_Info *server = tcon->ses->server;
@@ -659,8 +659,9 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
        return rc;
 }
 
-static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
-               void *dirent, char *scratch_buf, unsigned int max_len)
+static int cifs_filldir(char *find_entry, struct file *file,
+               struct dir_context *ctx,
+               char *scratch_buf, unsigned int max_len)
 {
        struct cifsFileInfo *file_info = file->private_data;
        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,
        cifs_prime_dcache(file->f_dentry, &name, &fattr);
 
        ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
-       rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
-                    fattr.cf_dtype);
-       return rc;
+       return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
 }
 
 
-int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
+int cifs_readdir(struct file *file, struct dir_context *ctx)
 {
        int rc = 0;
        unsigned int xid;
@@ -772,103 +771,86 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
                        goto rddir2_exit;
        }
 
-       switch ((int) file->f_pos) {
-       case 0:
-               if (filldir(direntry, ".", 1, file->f_pos,
-                    file_inode(file)->i_ino, DT_DIR) < 0) {
-                       cifs_dbg(VFS, "Filldir for current dir failed\n");
-                       rc = -ENOMEM;
-                       break;
-               }
-               file->f_pos++;
-       case 1:
-               if (filldir(direntry, "..", 2, file->f_pos,
-                    parent_ino(file->f_path.dentry), DT_DIR) < 0) {
-                       cifs_dbg(VFS, "Filldir for parent dir failed\n");
-                       rc = -ENOMEM;
-                       break;
-               }
-               file->f_pos++;
-       default:
-               /* 1) If search is active,
-                       is in current search buffer?
-                       if it before then restart search
-                       if after then keep searching till find it */
-
-               if (file->private_data == NULL) {
-                       rc = -EINVAL;
-                       free_xid(xid);
-                       return rc;
-               }
-               cifsFile = file->private_data;
-               if (cifsFile->srch_inf.endOfSearch) {
-                       if (cifsFile->srch_inf.emptyDir) {
-                               cifs_dbg(FYI, "End of search, empty dir\n");
-                               rc = 0;
-                               break;
-                       }
-               } /* else {
-                       cifsFile->invalidHandle = true;
-                       tcon->ses->server->close(xid, tcon, &cifsFile->fid);
-               } */
+       if (!dir_emit_dots(file, ctx))
+               goto rddir2_exit;
 
-               tcon = tlink_tcon(cifsFile->tlink);
-               rc = find_cifs_entry(xid, tcon, file, &current_entry,
-                                    &num_to_fill);
-               if (rc) {
-                       cifs_dbg(FYI, "fce error %d\n", rc);
-                       goto rddir2_exit;
-               } else if (current_entry != NULL) {
-                       cifs_dbg(FYI, "entry %lld found\n", file->f_pos);
-               } else {
-                       cifs_dbg(FYI, "could not find entry\n");
+       /* 1) If search is active,
+               is in current search buffer?
+               if it before then restart search
+               if after then keep searching till find it */
+
+       if (file->private_data == NULL) {
+               rc = -EINVAL;
+               goto rddir2_exit;
+       }
+       cifsFile = file->private_data;
+       if (cifsFile->srch_inf.endOfSearch) {
+               if (cifsFile->srch_inf.emptyDir) {
+                       cifs_dbg(FYI, "End of search, empty dir\n");
+                       rc = 0;
                        goto rddir2_exit;
                }
-               cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
-                        num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
-               max_len = tcon->ses->server->ops->calc_smb_size(
-                               cifsFile->srch_inf.ntwrk_buf_start);
-               end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
-
-               tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
-               if (tmp_buf == NULL) {
-                       rc = -ENOMEM;
+       } /* else {
+               cifsFile->invalidHandle = true;
+               tcon->ses->server->close(xid, tcon, &cifsFile->fid);
+       } */
+
+       tcon = tlink_tcon(cifsFile->tlink);
+       rc = find_cifs_entry(xid, tcon, ctx->pos, file, &current_entry,
+                            &num_to_fill);
+       if (rc) {
+               cifs_dbg(FYI, "fce error %d\n", rc);
+               goto rddir2_exit;
+       } else if (current_entry != NULL) {
+               cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
+       } else {
+               cifs_dbg(FYI, "could not find entry\n");
+               goto rddir2_exit;
+       }
+       cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
+                num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
+       max_len = tcon->ses->server->ops->calc_smb_size(
+                       cifsFile->srch_inf.ntwrk_buf_start);
+       end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
+
+       tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
+       if (tmp_buf == NULL) {
+               rc = -ENOMEM;
+               goto rddir2_exit;
+       }
+
+       for (i = 0; i < num_to_fill; i++) {
+               if (current_entry == NULL) {
+                       /* evaluate whether this case is an error */
+                       cifs_dbg(VFS, "past SMB end,  num to fill %d i %d\n",
+                                num_to_fill, i);
                        break;
                }
-
-               for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
-                       if (current_entry == NULL) {
-                               /* evaluate whether this case is an error */
-                               cifs_dbg(VFS, "past SMB end,  num to fill %d i %d\n",
-                                        num_to_fill, i);
-                               break;
-                       }
-                       /*
-                        * if buggy server returns . and .. late do we want to
-                        * check for that here?
-                        */
-                       rc = cifs_filldir(current_entry, file, filldir,
-                                         direntry, tmp_buf, max_len);
-                       if (rc == -EOVERFLOW) {
+               /*
+                * if buggy server returns . and .. late do we want to
+                * check for that here?
+                */
+               rc = cifs_filldir(current_entry, file, ctx,
+                                 tmp_buf, max_len);
+               if (rc) {
+                       if (rc > 0)
                                rc = 0;
-                               break;
-                       }
-
-                       file->f_pos++;
-                       if (file->f_pos ==
-                               cifsFile->srch_inf.index_of_last_entry) {
-                               cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
-                                        file->f_pos, tmp_buf);
-                               cifs_save_resume_key(current_entry, cifsFile);
-                               break;
-                       } else
-                               current_entry =
-                                       nxt_dir_entry(current_entry, end_of_smb,
-                                               cifsFile->srch_inf.info_level);
+                       break;
                }
-               kfree(tmp_buf);
-               break;
-       } /* end switch */
+
+               ctx->pos++;
+               if (ctx->pos ==
+                       cifsFile->srch_inf.index_of_last_entry) {
+                       cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
+                                ctx->pos, tmp_buf);
+                       cifs_save_resume_key(current_entry, cifsFile);
+                       break;
+               } else
+                       current_entry =
+                               nxt_dir_entry(current_entry, end_of_smb,
+                                       cifsFile->srch_inf.info_level);
+       }
+       kfree(tmp_buf);
 
 rddir2_exit:
        free_xid(xid);