mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-18 10:21:01 +03:00
58bc86c5cb
As of the 5.10 kernel the generic splice compatibility code has been removed. All filesystems are now responsible for registering a ->splice_read and ->splice_write callback to support this operation. The good news is the VFS provided generic_file_splice_read() and iter_file_splice_write() callbacks can be used provided the ->iter_read and ->iter_write callback support pipes. However, this is currently not the case and only iovecs and bvecs (not pipes) are ever attached to the uio structure. This commit changes that by allowing full iov_iter structures to be attached to uios. Ever since the 4.9 kernel the iov_iter structure has supported iovecs, kvecs, bvevs, and pipes so it's desirable to pass the entire thing when possible. In conjunction with this the uio helper functions (i.e uiomove(), uiocopy(), etc) have been updated to understand the new UIO_ITER type. Note that using the kernel provided uio_iter interfaces allowed the existing Linux specific uio handling code to be simplified. When there's no longer a need to support kernel's older than 4.9, then it will be possible to remove the iovec and bvec members from the uio structure and always use a uio_iter. Until then we need to maintain all of the existing types for older kernels. Some additional refactoring and cleanup was included in this change: - Added checks to configure to detect available iov_iter interfaces. Some are available all the way back to the 3.10 kernel and are used when available. In particular, uio_prefaultpages() now always uses iov_iter_fault_in_readable() which is available for all supported kernels. - The unused UIO_USERISPACE type has been removed. It is no longer needed now that the uio_seg enum is platform specific. - Moved zfs_uio.c from the zcommon.ko module to the Linux specific platform code for the zfs.ko module. This gets it out of libzfs where it was never needed and keeps this Linux specific code out of the common sources. - Removed unnecessary O_APPEND handling from zfs_iter_write(), this is redundant and O_APPEND is already handled in zfs_write(); NOTE: Cleanly applying this kernel compatibility change required applying the following commits. This makes the change larger than it absolutely needs to be, but the resulting code matches what's in the branch branch. This is both more tested and makes it easier to apply any future backports in this area.7cf4cd824
Remove incorrect assertion783be694f
Reduce confusion in zfs_writeaf5626ac2
Return EFAULT at the end of zfs_write() when setcc1f85be8
Simplify offset and length limit in zfs_write9585538d0
Const some unchanging variables in zfs_write86e74dc16
Remove redundant oid parameter to update_pagesb3d723fb0
Factor uid, gid, and projid out of loop in zfs_write3d40b6554
Share zfs_fsync, zfs_read, zfs_write, et al between Linux and FreeBSD Reviewed-by: Colin Ian King <colin.king@canonical.com> Reviewed-by: Tony Hutter <hutter2@llnl.gov> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #11351
175 lines
5.0 KiB
C
175 lines
5.0 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
*
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
* or http://www.opensolaris.org/os/licensing.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
/*
|
|
* Copyright (c) 2011, Lawrence Livermore National Security, LLC.
|
|
*/
|
|
|
|
#ifndef _SYS_ZPL_H
|
|
#define _SYS_ZPL_H
|
|
|
|
#include <sys/mntent.h>
|
|
#include <sys/vfs.h>
|
|
#include <linux/aio.h>
|
|
#include <linux/dcache_compat.h>
|
|
#include <linux/exportfs.h>
|
|
#include <linux/falloc.h>
|
|
#include <linux/parser.h>
|
|
#include <linux/task_io_accounting_ops.h>
|
|
#include <linux/vfs_compat.h>
|
|
#include <linux/writeback.h>
|
|
#include <linux/xattr_compat.h>
|
|
|
|
/* zpl_inode.c */
|
|
extern void zpl_vap_init(vattr_t *vap, struct inode *dir,
|
|
umode_t mode, cred_t *cr);
|
|
|
|
extern const struct inode_operations zpl_inode_operations;
|
|
extern const struct inode_operations zpl_dir_inode_operations;
|
|
extern const struct inode_operations zpl_symlink_inode_operations;
|
|
extern const struct inode_operations zpl_special_inode_operations;
|
|
extern dentry_operations_t zpl_dentry_operations;
|
|
extern const struct address_space_operations zpl_address_space_operations;
|
|
extern const struct file_operations zpl_file_operations;
|
|
extern const struct file_operations zpl_dir_file_operations;
|
|
|
|
/* zpl_super.c */
|
|
extern void zpl_prune_sb(int64_t nr_to_scan, void *arg);
|
|
|
|
extern const struct super_operations zpl_super_operations;
|
|
extern const struct export_operations zpl_export_operations;
|
|
extern struct file_system_type zpl_fs_type;
|
|
|
|
/* zpl_xattr.c */
|
|
extern ssize_t zpl_xattr_list(struct dentry *dentry, char *buf, size_t size);
|
|
extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip,
|
|
const struct qstr *qstr);
|
|
#if defined(CONFIG_FS_POSIX_ACL)
|
|
#if defined(HAVE_SET_ACL)
|
|
extern int zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type);
|
|
#endif /* HAVE_SET_ACL */
|
|
extern struct posix_acl *zpl_get_acl(struct inode *ip, int type);
|
|
extern int zpl_init_acl(struct inode *ip, struct inode *dir);
|
|
extern int zpl_chmod_acl(struct inode *ip);
|
|
#else
|
|
static inline int
|
|
zpl_init_acl(struct inode *ip, struct inode *dir)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
static inline int
|
|
zpl_chmod_acl(struct inode *ip)
|
|
{
|
|
return (0);
|
|
}
|
|
#endif /* CONFIG_FS_POSIX_ACL */
|
|
|
|
extern xattr_handler_t *zpl_xattr_handlers[];
|
|
|
|
/* zpl_ctldir.c */
|
|
extern const struct file_operations zpl_fops_root;
|
|
extern const struct inode_operations zpl_ops_root;
|
|
|
|
extern const struct file_operations zpl_fops_snapdir;
|
|
extern const struct inode_operations zpl_ops_snapdir;
|
|
extern const struct dentry_operations zpl_dops_snapdirs;
|
|
|
|
extern const struct file_operations zpl_fops_shares;
|
|
extern const struct inode_operations zpl_ops_shares;
|
|
|
|
#if defined(HAVE_VFS_ITERATE) || defined(HAVE_VFS_ITERATE_SHARED)
|
|
|
|
#define ZPL_DIR_CONTEXT_INIT(_dirent, _actor, _pos) { \
|
|
.actor = _actor, \
|
|
.pos = _pos, \
|
|
}
|
|
|
|
typedef struct dir_context zpl_dir_context_t;
|
|
|
|
#define zpl_dir_emit dir_emit
|
|
#define zpl_dir_emit_dot dir_emit_dot
|
|
#define zpl_dir_emit_dotdot dir_emit_dotdot
|
|
#define zpl_dir_emit_dots dir_emit_dots
|
|
|
|
#else
|
|
|
|
typedef struct zpl_dir_context {
|
|
void *dirent;
|
|
const filldir_t actor;
|
|
loff_t pos;
|
|
} zpl_dir_context_t;
|
|
|
|
#define ZPL_DIR_CONTEXT_INIT(_dirent, _actor, _pos) { \
|
|
.dirent = _dirent, \
|
|
.actor = _actor, \
|
|
.pos = _pos, \
|
|
}
|
|
|
|
static inline bool
|
|
zpl_dir_emit(zpl_dir_context_t *ctx, const char *name, int namelen,
|
|
uint64_t ino, unsigned type)
|
|
{
|
|
return (!ctx->actor(ctx->dirent, name, namelen, ctx->pos, ino, type));
|
|
}
|
|
|
|
static inline bool
|
|
zpl_dir_emit_dot(struct file *file, zpl_dir_context_t *ctx)
|
|
{
|
|
return (ctx->actor(ctx->dirent, ".", 1, ctx->pos,
|
|
file_inode(file)->i_ino, DT_DIR) == 0);
|
|
}
|
|
|
|
static inline bool
|
|
zpl_dir_emit_dotdot(struct file *file, zpl_dir_context_t *ctx)
|
|
{
|
|
return (ctx->actor(ctx->dirent, "..", 2, ctx->pos,
|
|
parent_ino(file_dentry(file)), DT_DIR) == 0);
|
|
}
|
|
|
|
static inline bool
|
|
zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
|
|
{
|
|
if (ctx->pos == 0) {
|
|
if (!zpl_dir_emit_dot(file, ctx))
|
|
return (false);
|
|
ctx->pos = 1;
|
|
}
|
|
if (ctx->pos == 1) {
|
|
if (!zpl_dir_emit_dotdot(file, ctx))
|
|
return (false);
|
|
ctx->pos = 2;
|
|
}
|
|
return (true);
|
|
}
|
|
#endif /* HAVE_VFS_ITERATE */
|
|
|
|
#if defined(HAVE_INODE_TIMESTAMP_TRUNCATE)
|
|
#define zpl_inode_timestamp_truncate(ts, ip) timestamp_truncate(ts, ip)
|
|
#elif defined(HAVE_INODE_TIMESPEC64_TIMES)
|
|
#define zpl_inode_timestamp_truncate(ts, ip) \
|
|
timespec64_trunc(ts, (ip)->i_sb->s_time_gran)
|
|
#else
|
|
#define zpl_inode_timestamp_truncate(ts, ip) \
|
|
timespec_trunc(ts, (ip)->i_sb->s_time_gran)
|
|
#endif
|
|
|
|
#endif /* _SYS_ZPL_H */
|