]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zpl_ctldir.c
Fix typo/etc in module/zfs/zfs_ctldir.c
[mirror_zfs.git] / module / zfs / zpl_ctldir.c
index 1bb646fdf728ac1a0e3d041dbf1d97372c143c89..6df367b8176a77b7a1f7ff39feaabb2c053e9e39 100644 (file)
@@ -43,49 +43,50 @@ zpl_common_open(struct inode *ip, struct file *filp)
        if (filp->f_mode & FMODE_WRITE)
                return (-EACCES);
 
-       return generic_file_open(ip, filp);
+       return (generic_file_open(ip, filp));
 }
 
 /*
  * Get root directory contents.
  */
 static int
-zpl_root_iterate(struct file *filp, struct dir_context *ctx)
+zpl_root_iterate(struct file *filp, zpl_dir_context_t *ctx)
 {
-       zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode);
+       zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
        int error = 0;
 
-       ZFS_ENTER(zsb);
+       ZFS_ENTER(zfsvfs);
 
-       if (!dir_emit_dots(filp, ctx))
+       if (!zpl_dir_emit_dots(filp, ctx))
                goto out;
 
        if (ctx->pos == 2) {
-               if (!dir_emit(ctx, ZFS_SNAPDIR_NAME, strlen(ZFS_SNAPDIR_NAME),
-                   ZFSCTL_INO_SNAPDIR, DT_DIR))
+               if (!zpl_dir_emit(ctx, ZFS_SNAPDIR_NAME,
+                   strlen(ZFS_SNAPDIR_NAME), ZFSCTL_INO_SNAPDIR, DT_DIR))
                        goto out;
 
                ctx->pos++;
        }
 
        if (ctx->pos == 3) {
-               if (!dir_emit(ctx, ZFS_SHAREDIR_NAME, strlen(ZFS_SHAREDIR_NAME),
-                   ZFSCTL_INO_SHARES, DT_DIR))
+               if (!zpl_dir_emit(ctx, ZFS_SHAREDIR_NAME,
+                   strlen(ZFS_SHAREDIR_NAME), ZFSCTL_INO_SHARES, DT_DIR))
                        goto out;
 
                ctx->pos++;
        }
 out:
-       ZFS_EXIT(zsb);
+       ZFS_EXIT(zfsvfs);
 
        return (error);
 }
 
-#if !defined(HAVE_VFS_ITERATE)
+#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
 static int
 zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dir_context ctx = DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
+       zpl_dir_context_t ctx =
+           ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
        int error;
 
        error = zpl_root_iterate(filp, &ctx);
@@ -93,23 +94,24 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        return (error);
 }
-#endif /* HAVE_VFS_ITERATE */
+#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
 
 /*
  * Get root directory attributes.
  */
 /* ARGSUSED */
 static int
-zpl_root_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_root_getattr_impl(const struct path *path, struct kstat *stat,
+    u32 request_mask, unsigned int query_flags)
 {
-       int error;
+       struct inode *ip = path->dentry->d_inode;
 
-       error = simple_getattr(mnt, dentry, stat);
-       stat->atime = CURRENT_TIME;
+       generic_fillattr(ip, stat);
+       stat->atime = current_time(ip);
 
-       return (error);
+       return (0);
 }
+ZPL_GETATTR_WRAPPER(zpl_root_getattr);
 
 static struct dentry *
 #ifdef HAVE_LOOKUP_NAMEIDATA
@@ -129,12 +131,12 @@ zpl_root_lookup(struct inode *dip, struct dentry *dentry, unsigned int flags)
 
        if (error) {
                if (error == -ENOENT)
-                       return d_splice_alias(NULL, dentry);
+                       return (d_splice_alias(NULL, dentry));
                else
-                       return ERR_PTR(error);
+                       return (ERR_PTR(error));
        }
 
-        return d_splice_alias(ip, dentry);
+       return (d_splice_alias(ip, dentry));
 }
 
 /*
@@ -144,7 +146,9 @@ const struct file_operations zpl_fops_root = {
        .open           = zpl_common_open,
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-#ifdef HAVE_VFS_ITERATE
+#ifdef HAVE_VFS_ITERATE_SHARED
+       .iterate_shared = zpl_root_iterate,
+#elif defined(HAVE_VFS_ITERATE)
        .iterate        = zpl_root_iterate,
 #else
        .readdir        = zpl_root_readdir,
@@ -160,21 +164,11 @@ const struct inode_operations zpl_ops_root = {
 static struct vfsmount *
 zpl_snapdir_automount(struct path *path)
 {
-       struct dentry *dentry = path->dentry;
        int error;
 
-       /*
-        * We must briefly disable automounts for this dentry because the
-        * user space mount utility will trigger another lookup on this
-        * directory.  That will result in zpl_snapdir_automount() being
-        * called repeatedly.  The DCACHE_NEED_AUTOMOUNT flag can be
-        * safely reset once the mount completes.
-        */
-       dentry->d_flags &= ~DCACHE_NEED_AUTOMOUNT;
-       error = -zfsctl_mount_snapshot(path, 0);
-       dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+       error = -zfsctl_snapshot_mount(path, 0);
        if (error)
-               return ERR_PTR(error);
+               return (ERR_PTR(error));
 
        /*
         * Rather than returning the new vfsmount for the snapshot we must
@@ -188,8 +182,10 @@ zpl_snapdir_automount(struct path *path)
 #endif /* HAVE_AUTOMOUNT */
 
 /*
- * Revalidate any dentry in the snapshot directory on lookup, since a snapshot
- * having the same name have been created or destroyed since it was cached.
+ * Negative dentries must always be revalidated so newly created snapshots
+ * can be detected and automounted.  Normal dentries should be kept because
+ * as of the 3.18 kernel revaliding the mountpoint dentry will result in
+ * the snapshot being immediately unmounted.
  */
 static int
 #ifdef HAVE_D_REVALIDATE_NAMEIDATA
@@ -198,7 +194,7 @@ zpl_snapdir_revalidate(struct dentry *dentry, struct nameidata *i)
 zpl_snapdir_revalidate(struct dentry *dentry, unsigned int flags)
 #endif
 {
-       return 0;
+       return (!!dentry->d_inode);
 }
 
 dentry_operations_t zpl_dops_snapdirs = {
@@ -226,52 +222,66 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
 #endif
 
 {
+       fstrans_cookie_t cookie;
        cred_t *cr = CRED();
        struct inode *ip = NULL;
        int error;
 
        crhold(cr);
+       cookie = spl_fstrans_mark();
        error = -zfsctl_snapdir_lookup(dip, dname(dentry), &ip,
            0, cr, NULL, NULL);
        ASSERT3S(error, <=, 0);
+       spl_fstrans_unmark(cookie);
        crfree(cr);
 
        if (error && error != -ENOENT)
-               return ERR_PTR(error);
+               return (ERR_PTR(error));
 
        ASSERT(error == 0 || ip == NULL);
        d_clear_d_op(dentry);
        d_set_d_op(dentry, &zpl_dops_snapdirs);
+#ifdef HAVE_AUTOMOUNT
+       dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+#endif
 
-       return d_splice_alias(ip, dentry);
+       return (d_splice_alias(ip, dentry));
 }
 
 static int
-zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
+zpl_snapdir_iterate(struct file *filp, zpl_dir_context_t *ctx)
 {
-       zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode);
+       zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
+       fstrans_cookie_t cookie;
        char snapname[MAXNAMELEN];
        boolean_t case_conflict;
-       uint64_t id;
+       uint64_t id, pos;
        int error = 0;
 
-       ZFS_ENTER(zsb);
+       ZFS_ENTER(zfsvfs);
+       cookie = spl_fstrans_mark();
 
-       if (!dir_emit_dots(filp, ctx))
+       if (!zpl_dir_emit_dots(filp, ctx))
                goto out;
 
+       pos = ctx->pos;
        while (error == 0) {
-               error = -dmu_snapshot_list_next(zsb->z_os, MAXNAMELEN,
-                   snapname, &id, &(ctx->pos), &case_conflict);
+               dsl_pool_config_enter(dmu_objset_pool(zfsvfs->z_os), FTAG);
+               error = -dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN,
+                   snapname, &id, &pos, &case_conflict);
+               dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG);
                if (error)
                        goto out;
 
-               if (!dir_emit(ctx, snapname, strlen(snapname),
+               if (!zpl_dir_emit(ctx, snapname, strlen(snapname),
                    ZFSCTL_INO_SHARES - id, DT_DIR))
                        goto out;
+
+               ctx->pos = pos;
        }
 out:
-       ZFS_EXIT(zsb);
+       spl_fstrans_unmark(cookie);
+       ZFS_EXIT(zfsvfs);
 
        if (error == -ENOENT)
                return (0);
@@ -279,11 +289,12 @@ out:
        return (error);
 }
 
-#if !defined(HAVE_VFS_ITERATE)
+#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
 static int
 zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dir_context ctx = DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
+       zpl_dir_context_t ctx =
+           ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
        int error;
 
        error = zpl_snapdir_iterate(filp, &ctx);
@@ -291,15 +302,19 @@ zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        return (error);
 }
-#endif /* HAVE_VFS_ITERATE */
+#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
 
-int
-zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry,
-    struct inode *tdip, struct dentry *tdentry)
+static int
+zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
+    struct inode *tdip, struct dentry *tdentry, unsigned int flags)
 {
        cred_t *cr = CRED();
        int error;
 
+       /* We probably don't want to support renameat2(2) in ctldir */
+       if (flags)
+               return (-EINVAL);
+
        crhold(cr);
        error = -zfsctl_snapdir_rename(sdip, dname(sdentry),
            tdip, dname(tdentry), cr, 0);
@@ -309,6 +324,15 @@ zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry,
        return (error);
 }
 
+#ifndef HAVE_RENAME_WANTS_FLAGS
+static int
+zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry,
+    struct inode *tdip, struct dentry *tdentry)
+{
+       return (zpl_snapdir_rename2(sdip, sdentry, tdip, tdentry, 0));
+}
+#endif
+
 static int
 zpl_snapdir_rmdir(struct inode *dip, struct dentry *dentry)
 {
@@ -332,7 +356,7 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, zpl_umode_t mode)
        int error;
 
        crhold(cr);
-       vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+       vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
        zpl_vap_init(vap, dip, mode | S_IFDIR, cr);
 
        error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0);
@@ -342,7 +366,7 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, zpl_umode_t mode)
                d_instantiate(dentry, ip);
        }
 
-       kmem_free(vap, sizeof(vattr_t));
+       kmem_free(vap, sizeof (vattr_t));
        ASSERT3S(error, <=, 0);
        crfree(cr);
 
@@ -354,21 +378,23 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, zpl_umode_t mode)
  */
 /* ARGSUSED */
 static int
-zpl_snapdir_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
+    u32 request_mask, unsigned int query_flags)
 {
-       zfs_sb_t *zsb = ITOZSB(dentry->d_inode);
-       int error;
+       struct inode *ip = path->dentry->d_inode;
+       zfsvfs_t *zfsvfs = ITOZSB(ip);
 
-       ZFS_ENTER(zsb);
-       error = simple_getattr(mnt, dentry, stat);
-       stat->nlink = stat->size = avl_numnodes(&zsb->z_ctldir_snaps) + 2;
-       stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zsb->z_os);
-       stat->atime = CURRENT_TIME;
-       ZFS_EXIT(zsb);
+       ZFS_ENTER(zfsvfs);
+       generic_fillattr(ip, stat);
 
-       return (error);
+       stat->nlink = stat->size = 2;
+       stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os);
+       stat->atime = current_time(ip);
+       ZFS_EXIT(zfsvfs);
+
+       return (0);
 }
+ZPL_GETATTR_WRAPPER(zpl_snapdir_getattr);
 
 /*
  * The '.zfs/snapshot' directory file operations.  These mainly control
@@ -379,7 +405,9 @@ const struct file_operations zpl_fops_snapdir = {
        .open           = zpl_common_open,
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-#ifdef HAVE_VFS_ITERATE
+#ifdef HAVE_VFS_ITERATE_SHARED
+       .iterate_shared = zpl_snapdir_iterate,
+#elif defined(HAVE_VFS_ITERATE)
        .iterate        = zpl_snapdir_iterate,
 #else
        .readdir        = zpl_snapdir_readdir,
@@ -395,7 +423,11 @@ const struct file_operations zpl_fops_snapdir = {
 const struct inode_operations zpl_ops_snapdir = {
        .lookup         = zpl_snapdir_lookup,
        .getattr        = zpl_snapdir_getattr,
+#ifdef HAVE_RENAME_WANTS_FLAGS
+       .rename         = zpl_snapdir_rename2,
+#else
        .rename         = zpl_snapdir_rename,
+#endif
        .rmdir          = zpl_snapdir_rmdir,
        .mkdir          = zpl_snapdir_mkdir,
 };
@@ -409,42 +441,47 @@ zpl_shares_lookup(struct inode *dip, struct dentry *dentry,
     unsigned int flags)
 #endif
 {
+       fstrans_cookie_t cookie;
        cred_t *cr = CRED();
        struct inode *ip = NULL;
        int error;
 
        crhold(cr);
+       cookie = spl_fstrans_mark();
        error = -zfsctl_shares_lookup(dip, dname(dentry), &ip,
            0, cr, NULL, NULL);
        ASSERT3S(error, <=, 0);
+       spl_fstrans_unmark(cookie);
        crfree(cr);
 
        if (error) {
                if (error == -ENOENT)
-                       return d_splice_alias(NULL, dentry);
+                       return (d_splice_alias(NULL, dentry));
                else
-                       return ERR_PTR(error);
+                       return (ERR_PTR(error));
        }
 
-       return d_splice_alias(ip, dentry);
+       return (d_splice_alias(ip, dentry));
 }
 
 static int
-zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
+zpl_shares_iterate(struct file *filp, zpl_dir_context_t *ctx)
 {
+       fstrans_cookie_t cookie;
        cred_t *cr = CRED();
-       zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode);
+       zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
        znode_t *dzp;
        int error = 0;
 
-       ZFS_ENTER(zsb);
+       ZFS_ENTER(zfsvfs);
+       cookie = spl_fstrans_mark();
 
-       if (zsb->z_shares_dir == 0) {
-               dir_emit_dots(filp, ctx);
+       if (zfsvfs->z_shares_dir == 0) {
+               zpl_dir_emit_dots(filp, ctx);
                goto out;
        }
 
-       error = -zfs_zget(zsb, zsb->z_shares_dir, &dzp);
+       error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
        if (error)
                goto out;
 
@@ -454,17 +491,19 @@ zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
 
        iput(ZTOI(dzp));
 out:
-       ZFS_EXIT(zsb);
+       spl_fstrans_unmark(cookie);
+       ZFS_EXIT(zfsvfs);
        ASSERT3S(error, <=, 0);
 
        return (error);
 }
 
-#if !defined(HAVE_VFS_ITERATE)
+#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
 static int
 zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dir_context ctx = DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
+       zpl_dir_context_t ctx =
+           ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
        int error;
 
        error = zpl_shares_iterate(filp, &ctx);
@@ -472,38 +511,40 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        return (error);
 }
-#endif /* HAVE_VFS_ITERATE */
+#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
 
 /* ARGSUSED */
 static int
-zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
+    u32 request_mask, unsigned int query_flags)
 {
-       struct inode *ip = dentry->d_inode;
-       zfs_sb_t *zsb = ITOZSB(ip);
+       struct inode *ip = path->dentry->d_inode;
+       zfsvfs_t *zfsvfs = ITOZSB(ip);
        znode_t *dzp;
        int error;
 
-       ZFS_ENTER(zsb);
+       ZFS_ENTER(zfsvfs);
 
-       if (zsb->z_shares_dir == 0) {
-               error = simple_getattr(mnt, dentry, stat);
+       if (zfsvfs->z_shares_dir == 0) {
+               generic_fillattr(path->dentry->d_inode, stat);
                stat->nlink = stat->size = 2;
-               stat->atime = CURRENT_TIME;
-               ZFS_EXIT(zsb);
-               return (error);
+               stat->atime = current_time(ip);
+               ZFS_EXIT(zfsvfs);
+               return (0);
        }
 
-       error = -zfs_zget(zsb, zsb->z_shares_dir, &dzp);
-       if (error == 0)
-               error = -zfs_getattr_fast(dentry->d_inode, stat);
+       error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
+       if (error == 0) {
+               error = -zfs_getattr_fast(ZTOI(dzp), stat);
+               iput(ZTOI(dzp));
+       }
 
-       iput(ZTOI(dzp));
-       ZFS_EXIT(zsb);
+       ZFS_EXIT(zfsvfs);
        ASSERT3S(error, <=, 0);
 
        return (error);
 }
+ZPL_GETATTR_WRAPPER(zpl_shares_getattr);
 
 /*
  * The '.zfs/shares' directory file operations.
@@ -512,7 +553,9 @@ const struct file_operations zpl_fops_shares = {
        .open           = zpl_common_open,
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-#ifdef HAVE_VFS_ITERATE
+#ifdef HAVE_VFS_ITERATE_SHARED
+       .iterate_shared = zpl_shares_iterate,
+#elif defined(HAVE_VFS_ITERATE)
        .iterate        = zpl_shares_iterate,
 #else
        .readdir        = zpl_shares_readdir,