Unionfs: port to 3.11
authorErez Zadok <ezk@cs.sunysb.edu>
Wed, 27 Nov 2013 03:01:34 +0000 (22:01 -0500)
committerErez Zadok <ezk@cs.sunysb.edu>
Tue, 11 Nov 2014 01:43:41 +0000 (20:43 -0500)
Readdir VFS interface overhauled between 3.10 and 3.11.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/dirfops.c
fs/unionfs/dirhelper.c
fs/unionfs/file.c

index 72a9c1a04a1072bf0e371978ceba9bc5bfa9ce2b..7b2f3cfd8aff2ad9bbbf92ef4869486fb96e8225 100644 (file)
@@ -26,20 +26,21 @@ static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
 }
 
 struct unionfs_getdents_callback {
+       struct dir_context ctx; /* must be first field */
+       struct dir_context *caller;
        struct unionfs_dir_state *rdstate;
-       void *dirent;
        int entries_written;
        int filldir_called;
        int filldir_error;
-       filldir_t filldir;
        struct super_block *sb;
 };
 
 /* based on generic filldir in fs/readir.c */
-static int unionfs_filldir(void *dirent, const char *oname, int namelen,
+static int unionfs_filldir(void *__buf, const char *oname, int namelen,
                           loff_t offset, u64 ino, unsigned int d_type)
 {
-       struct unionfs_getdents_callback *buf = dirent;
+       struct unionfs_getdents_callback *buf =
+               (struct unionfs_getdents_callback *) __buf;
        struct filldir_node *found = NULL;
        int err = 0;
        int is_whiteout;
@@ -63,11 +64,12 @@ static int unionfs_filldir(void *dirent, const char *oname, int namelen,
 
        /* if 'name' isn't a whiteout, filldir it. */
        if (!is_whiteout) {
+#if 0
+               // XXX: old code, not sure if needed
                off_t pos = rdstate2offset(buf->rdstate);
-               u64 unionfs_ino = ino;
-
-               err = buf->filldir(buf->dirent, name, namelen, pos,
-                                  unionfs_ino, d_type);
+#endif
+               buf->caller->pos = buf->ctx.pos;
+               err = !dir_emit(buf->caller, name, namelen, ino, d_type);
                buf->rdstate->offset++;
                verify_rdstate_offset(buf->rdstate);
        }
@@ -89,14 +91,16 @@ out:
        return err;
 }
 
-static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+static int unionfs_readdir(struct file *file, struct dir_context *ctx)
 {
        int err = 0;
        struct file *lower_file = NULL;
        struct dentry *dentry = file->f_path.dentry;
        struct dentry *parent;
        struct inode *inode = NULL;
-       struct unionfs_getdents_callback buf;
+       struct unionfs_getdents_callback buf = {
+               .ctx.actor = unionfs_filldir,
+       };
        struct unionfs_dir_state *uds;
        int bend;
        loff_t offset;
@@ -141,10 +145,9 @@ static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
                buf.filldir_called = 0;
                buf.filldir_error = 0;
                buf.entries_written = 0;
-               buf.dirent = dirent;
-               buf.filldir = filldir;
                buf.rdstate = uds;
                buf.sb = inode->i_sb;
+               buf.caller = ctx;
 
                /* Read starting from where we last left off. */
                offset = vfs_llseek(lower_file, uds->dirpos, SEEK_SET);
@@ -152,7 +155,10 @@ static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
                        err = offset;
                        goto out;
                }
-               err = vfs_readdir(lower_file, unionfs_filldir, &buf);
+
+               lower_file->f_pos = ctx->pos;
+               err = iterate_dir(lower_file, &buf.ctx);
+               ctx->pos = buf.ctx.pos;
 
                /* Save the position for when we continue. */
                offset = vfs_llseek(lower_file, 0, SEEK_CUR);
@@ -183,9 +189,9 @@ static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
                UNIONFS_I(inode)->hashsize = uds->hashentries;
                free_rdstate(uds);
                UNIONFS_F(file)->rdstate = NULL;
-               file->f_pos = DIREOF;
+               ctx->pos = DIREOF;
        } else {
-               file->f_pos = rdstate2offset(uds);
+               ctx->pos = rdstate2offset(uds);
        }
 
 out:
@@ -292,7 +298,7 @@ out:
 struct file_operations unionfs_dir_fops = {
        .llseek         = unionfs_dir_llseek,
        .read           = generic_read_dir,
-       .readdir        = unionfs_readdir,
+       .iterate        = unionfs_readdir,
        .unlocked_ioctl = unionfs_ioctl,
        .open           = unionfs_open,
        .release        = unionfs_file_release,
index bd1c1fcf3249842e1dd69a3965df2fe2c237d895..08d12eca39a6834ffba62641afd0b23d27cb3aac 100644 (file)
@@ -22,6 +22,7 @@
 #define RD_CHECK_EMPTY 1
 /* The callback structure for check_empty. */
 struct unionfs_rdutil_callback {
+       struct dir_context ctx; // NEW: must be first in callback struct
        int err;
        int filldir_called;
        struct unionfs_dir_state *rdstate;
@@ -76,7 +77,9 @@ int check_empty(struct dentry *dentry, struct dentry *parent,
        struct vfsmount *mnt;
        struct super_block *sb;
        struct file *lower_file;
-       struct unionfs_rdutil_callback *buf = NULL;
+       struct unionfs_rdutil_callback buf = {
+               .ctx.actor = readdir_util_callback,
+       };
        int bindex, bstart, bend, bopaque;
        struct path path;
 
@@ -95,15 +98,12 @@ int check_empty(struct dentry *dentry, struct dentry *parent,
        if (0 <= bopaque && bopaque < bend)
                bend = bopaque;
 
-       buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
-       if (unlikely(!buf)) {
-               err = -ENOMEM;
-               goto out;
-       }
-       buf->err = 0;
-       buf->mode = RD_CHECK_EMPTY;
-       buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
-       if (unlikely(!buf->rdstate)) {
+       buf.err = 0;
+       buf.filldir_called = 0;
+       buf.mode = RD_CHECK_EMPTY;
+       buf.ctx.pos = 0; /* XXX: needed?! */
+       buf.rdstate = alloc_rdstate(dentry->d_inode, bstart);
+       if (unlikely(!buf.rdstate)) {
                err = -ENOMEM;
                goto out;
        }
@@ -132,13 +132,12 @@ int check_empty(struct dentry *dentry, struct dentry *parent,
                }
 
                do {
-                       buf->filldir_called = 0;
-                       buf->rdstate->bindex = bindex;
-                       err = vfs_readdir(lower_file,
-                                         readdir_util_callback, buf);
-                       if (buf->err)
-                               err = buf->err;
-               } while ((err >= 0) && buf->filldir_called);
+                       buf.filldir_called = 0;
+                       buf.rdstate->bindex = bindex;
+                       err = iterate_dir(lower_file, &buf.ctx);
+                       if (buf.err)
+                               err = buf.err;
+               } while ((err >= 0) && buf.filldir_called);
 
                /* fput calls dput for lower_dentry */
                fput(lower_file);
@@ -149,14 +148,10 @@ int check_empty(struct dentry *dentry, struct dentry *parent,
        }
 
 out:
-       if (buf) {
-               if (namelist && !err)
-                       *namelist = buf->rdstate;
-               else if (buf->rdstate)
-                       free_rdstate(buf->rdstate);
-               kfree(buf);
-       }
-
+       if (namelist && !err)
+               *namelist = buf.rdstate;
+       else if (buf.rdstate)
+               free_rdstate(buf.rdstate);
 
        return err;
 }
index 8a04063930e5f513f445c1bbcfe04779bb91c61f..f67db0ab6e669217785fda3ac02727d8f0c24248 100644 (file)
@@ -85,8 +85,7 @@ out:
        return err;
 }
 
-static int unionfs_file_readdir(struct file *file, void *dirent,
-                               filldir_t filldir)
+static int unionfs_file_readdir(struct file *file, struct dir_context *ctx)
 {
        return -ENOTDIR;
 }
@@ -371,7 +370,7 @@ struct file_operations unionfs_main_fops = {
        .llseek         = generic_file_llseek,
        .read           = unionfs_read,
        .write          = unionfs_write,
-       .readdir        = unionfs_file_readdir,
+       .iterate        = unionfs_file_readdir,
        .unlocked_ioctl = unionfs_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = unionfs_ioctl,