From: Erez Zadok Date: Wed, 27 Nov 2013 03:01:34 +0000 (-0500) Subject: Unionfs: port to 3.11 X-Git-Url: https://git.fsl.cs.sunysb.edu/?a=commitdiff_plain;h=f7af56b881de3e81996bedcc43565b017f3beb20;p=unionfs-3.13.y.git Unionfs: port to 3.11 Readdir VFS interface overhauled between 3.10 and 3.11. Signed-off-by: Erez Zadok --- diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c index 72a9c1a04a1..7b2f3cfd8af 100644 --- a/fs/unionfs/dirfops.c +++ b/fs/unionfs/dirfops.c @@ -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, diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c index bd1c1fcf324..08d12eca39a 100644 --- a/fs/unionfs/dirhelper.c +++ b/fs/unionfs/dirhelper.c @@ -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; } diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c index 8a04063930e..f67db0ab6e6 100644 --- a/fs/unionfs/file.c +++ b/fs/unionfs/file.c @@ -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,