generic: early (incomplete!) 4.0 support
[openwrt/staging/yousong.git] / target / linux / generic / patches-4.0 / 503-yaffs-3.12-convert-readdir-to-iterate.patch
diff --git a/target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch b/target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch
new file mode 100644 (file)
index 0000000..586c141
--- /dev/null
@@ -0,0 +1,129 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -1701,6 +1701,110 @@ static void yaffs_remove_obj_callback(st
+ /*-----------------------------------------------------------------*/
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
++static int yaffs_readdir(struct file *file, struct dir_context *ctx)
++{
++      struct yaffs_obj *obj;
++      struct yaffs_dev *dev;
++      struct yaffs_search_context *sc;
++      struct inode *inode = file->f_dentry->d_inode;
++      unsigned long offset, curoffs;
++      struct yaffs_obj *l;
++      int ret_val = 0;
++
++      char name[YAFFS_MAX_NAME_LENGTH + 1];
++
++      obj = yaffs_dentry_to_obj(file->f_dentry);
++      dev = obj->my_dev;
++
++      yaffs_gross_lock(dev);
++
++      yaffs_dev_to_lc(dev)->readdir_process = current;
++
++      offset = ctx->pos;
++
++      sc = yaffs_new_search(obj);
++      if (!sc) {
++              ret_val = -ENOMEM;
++              goto out;
++      }
++
++      yaffs_trace(YAFFS_TRACE_OS,
++              "yaffs_readdir: starting at %d", (int)offset);
++
++      if (offset == 0) {
++              yaffs_trace(YAFFS_TRACE_OS,
++                      "yaffs_readdir: entry . ino %d",
++                      (int)inode->i_ino);
++              yaffs_gross_unlock(dev);
++              if (!dir_emit_dot(file, ctx)) {
++                      yaffs_gross_lock(dev);
++                      goto out;
++              }
++              yaffs_gross_lock(dev);
++              offset++;
++              ctx->pos++;
++      }
++      if (offset == 1) {
++              yaffs_trace(YAFFS_TRACE_OS,
++                      "yaffs_readdir: entry .. ino %d",
++                      (int)file->f_dentry->d_parent->d_inode->i_ino);
++              yaffs_gross_unlock(dev);
++              if (!dir_emit_dotdot(file, ctx)) {
++                      yaffs_gross_lock(dev);
++                      goto out;
++              }
++              yaffs_gross_lock(dev);
++              offset++;
++              ctx->pos++;
++      }
++
++      curoffs = 1;
++
++      /* If the directory has changed since the open or last call to
++         readdir, rewind to after the 2 canned entries. */
++      if (file->f_version != inode->i_version) {
++              offset = 2;
++              ctx->pos = offset;
++              file->f_version = inode->i_version;
++      }
++
++      while (sc->next_return) {
++              curoffs++;
++              l = sc->next_return;
++              if (curoffs >= offset) {
++                      int this_inode = yaffs_get_obj_inode(l);
++                      int this_type = yaffs_get_obj_type(l);
++
++                      yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
++                      yaffs_trace(YAFFS_TRACE_OS,
++                              "yaffs_readdir: %s inode %d",
++                              name, yaffs_get_obj_inode(l));
++
++                      yaffs_gross_unlock(dev);
++
++                      if (!dir_emit(ctx, name, strlen(name),
++                                    this_inode, this_type) < 0) {
++                              yaffs_gross_lock(dev);
++                              goto out;
++                      }
++
++                      yaffs_gross_lock(dev);
++
++                      offset++;
++                      ctx->pos++;
++              }
++              yaffs_search_advance(sc);
++      }
++
++out:
++      yaffs_search_end(sc);
++      yaffs_dev_to_lc(dev)->readdir_process = NULL;
++      yaffs_gross_unlock(dev);
++
++      return ret_val;
++}
++#else
+ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
+ {
+       struct yaffs_obj *obj;
+@@ -1807,10 +1911,15 @@ out:
+       return ret_val;
+ }
++#endif
+ static const struct file_operations yaffs_dir_operations = {
+       .read = generic_read_dir,
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
++      .iterate = yaffs_readdir,
++#else
+       .readdir = yaffs_readdir,
++#endif
+       .fsync = yaffs_sync_object,
+       .llseek = generic_file_llseek,
+ };