Commit 36a49183 authored by Stephen Lord's avatar Stephen Lord Committed by Stephen Lord

Change the way XFS implements the invisible I/O mechanism used by

the online backup tools.
parent 79bfe848
...@@ -58,29 +58,55 @@ ...@@ -58,29 +58,55 @@
static struct vm_operations_struct linvfs_file_vm_ops; static struct vm_operations_struct linvfs_file_vm_ops;
STATIC ssize_t STATIC inline ssize_t
linvfs_read( __linvfs_read(
struct kiocb *iocb, struct kiocb *iocb,
char __user *buf, char __user *buf,
int ioflags,
size_t count, size_t count,
loff_t pos) loff_t pos)
{ {
struct iovec iov = {buf, count}; struct iovec iov = {buf, count};
struct file *file = iocb->ki_filp;
vnode_t *vp; vnode_t *vp;
int error; int error;
BUG_ON(iocb->ki_pos != pos); BUG_ON(iocb->ki_pos != pos);
vp = LINVFS_GET_VP(iocb->ki_filp->f_dentry->d_inode);
VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, NULL, error);
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
vp = LINVFS_GET_VP(file->f_dentry->d_inode);
VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, error);
return error; return error;
} }
STATIC ssize_t STATIC ssize_t
linvfs_write( linvfs_read(
struct kiocb *iocb,
char __user *buf,
size_t count,
loff_t pos)
{
return __linvfs_read(iocb, buf, 0, count, pos);
}
STATIC ssize_t
linvfs_read_invis(
struct kiocb *iocb,
char __user *buf,
size_t count,
loff_t pos)
{
return __linvfs_read(iocb, buf, IO_INVIS, count, pos);
}
STATIC inline ssize_t
__linvfs_write(
struct kiocb *iocb, struct kiocb *iocb,
const char *buf, const char *buf,
int ioflags,
size_t count, size_t count,
loff_t pos) loff_t pos)
{ {
...@@ -89,25 +115,48 @@ linvfs_write( ...@@ -89,25 +115,48 @@ linvfs_write(
struct inode *inode = file->f_dentry->d_inode->i_mapping->host; struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
vnode_t *vp = LINVFS_GET_VP(inode); vnode_t *vp = LINVFS_GET_VP(inode);
int error; int error;
int direct = file->f_flags & O_DIRECT;
BUG_ON(iocb->ki_pos != pos); BUG_ON(iocb->ki_pos != pos);
if (unlikely(file->f_flags & O_DIRECT)) {
if (direct) { ioflags |= IO_ISDIRECT;
VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, NULL, error); VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
ioflags, NULL, error);
} else { } else {
down(&inode->i_sem); down(&inode->i_sem);
VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, NULL, error); VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
ioflags, NULL, error);
up(&inode->i_sem); up(&inode->i_sem);
} }
return error; return error;
} }
STATIC ssize_t STATIC ssize_t
linvfs_readv( linvfs_write(
struct kiocb *iocb,
const char __user *buf,
size_t count,
loff_t pos)
{
return __linvfs_write(iocb, buf, 0, count, pos);
}
STATIC ssize_t
linvfs_write_invis(
struct kiocb *iocb,
const char __user *buf,
size_t count,
loff_t pos)
{
return __linvfs_write(iocb, buf, IO_INVIS, count, pos);
}
STATIC inline ssize_t
__linvfs_readv(
struct file *file, struct file *file,
const struct iovec *iov, const struct iovec *iov,
int ioflags,
unsigned long nr_segs, unsigned long nr_segs,
loff_t *ppos) loff_t *ppos)
{ {
...@@ -118,7 +167,10 @@ linvfs_readv( ...@@ -118,7 +167,10 @@ linvfs_readv(
init_sync_kiocb(&kiocb, file); init_sync_kiocb(&kiocb, file);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, NULL, error);
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, error);
if (-EIOCBQUEUED == error) if (-EIOCBQUEUED == error)
error = wait_on_sync_kiocb(&kiocb); error = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
...@@ -127,25 +179,49 @@ linvfs_readv( ...@@ -127,25 +179,49 @@ linvfs_readv(
} }
STATIC ssize_t STATIC ssize_t
linvfs_writev( linvfs_readv(
struct file *file, struct file *file,
const struct iovec *iov, const struct iovec *iov,
unsigned long nr_segs, unsigned long nr_segs,
loff_t *ppos) loff_t *ppos)
{
return __linvfs_readv(file, iov, 0, nr_segs, ppos);
}
STATIC ssize_t
linvfs_readv_invis(
struct file *file,
const struct iovec *iov,
unsigned long nr_segs,
loff_t *ppos)
{
return __linvfs_readv(file, iov, IO_INVIS, nr_segs, ppos);
}
STATIC inline ssize_t
__linvfs_writev(
struct file *file,
const struct iovec *iov,
int ioflags,
unsigned long nr_segs,
loff_t *ppos)
{ {
struct inode *inode = file->f_dentry->d_inode->i_mapping->host; struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
vnode_t *vp = LINVFS_GET_VP(inode); vnode_t *vp = LINVFS_GET_VP(inode);
struct kiocb kiocb; struct kiocb kiocb;
int error; int error;
int direct = file->f_flags & O_DIRECT;
init_sync_kiocb(&kiocb, file); init_sync_kiocb(&kiocb, file);
kiocb.ki_pos = *ppos; kiocb.ki_pos = *ppos;
if (direct) { if (unlikely(file->f_flags & O_DIRECT)) {
VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, NULL, error); ioflags |= IO_ISDIRECT;
VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
ioflags, NULL, error);
} else { } else {
down(&inode->i_sem); down(&inode->i_sem);
VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, NULL, error); VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
ioflags, NULL, error);
up(&inode->i_sem); up(&inode->i_sem);
} }
if (-EIOCBQUEUED == error) if (-EIOCBQUEUED == error)
...@@ -155,6 +231,27 @@ linvfs_writev( ...@@ -155,6 +231,27 @@ linvfs_writev(
return error; return error;
} }
STATIC ssize_t
linvfs_writev(
struct file *file,
const struct iovec *iov,
unsigned long nr_segs,
loff_t *ppos)
{
return __linvfs_writev(file, iov, 0, nr_segs, ppos);
}
STATIC ssize_t
linvfs_writev_invis(
struct file *file,
const struct iovec *iov,
unsigned long nr_segs,
loff_t *ppos)
{
return __linvfs_writev(file, iov, IO_INVIS, nr_segs, ppos);
}
STATIC ssize_t STATIC ssize_t
linvfs_sendfile( linvfs_sendfile(
struct file *filp, struct file *filp,
...@@ -166,8 +263,7 @@ linvfs_sendfile( ...@@ -166,8 +263,7 @@ linvfs_sendfile(
vnode_t *vp = LINVFS_GET_VP(filp->f_dentry->d_inode); vnode_t *vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
int error; int error;
VOP_SENDFILE(vp, filp, ppos, count, actor, target, NULL, error); VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, error);
return error; return error;
} }
...@@ -260,7 +356,6 @@ linvfs_readdir( ...@@ -260,7 +356,6 @@ linvfs_readdir(
return -ENOMEM; return -ENOMEM;
uio.uio_iov = &iov; uio.uio_iov = &iov;
uio.uio_fmode = filp->f_mode;
uio.uio_segflg = UIO_SYSSPACE; uio.uio_segflg = UIO_SYSSPACE;
curr_offset = filp->f_pos; curr_offset = filp->f_pos;
if (filp->f_pos != 0x7fffffff) if (filp->f_pos != 0x7fffffff)
...@@ -346,7 +441,30 @@ linvfs_ioctl( ...@@ -346,7 +441,30 @@ linvfs_ioctl(
vnode_t *vp = LINVFS_GET_VP(inode); vnode_t *vp = LINVFS_GET_VP(inode);
ASSERT(vp); ASSERT(vp);
VOP_IOCTL(vp, inode, filp, cmd, arg, error); VOP_IOCTL(vp, inode, filp, 0, cmd, arg, error);
VMODIFY(vp);
/* NOTE: some of the ioctl's return positive #'s as a
* byte count indicating success, such as
* readlink_by_handle. So we don't "sign flip"
* like most other routines. This means true
* errors need to be returned as a negative value.
*/
return error;
}
STATIC int
linvfs_ioctl_invis(
struct inode *inode,
struct file *filp,
unsigned int cmd,
unsigned long arg)
{
int error;
vnode_t *vp = LINVFS_GET_VP(inode);
ASSERT(vp);
VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, arg, error);
VMODIFY(vp); VMODIFY(vp);
/* NOTE: some of the ioctl's return positive #'s as a /* NOTE: some of the ioctl's return positive #'s as a
...@@ -396,6 +514,23 @@ struct file_operations linvfs_file_operations = { ...@@ -396,6 +514,23 @@ struct file_operations linvfs_file_operations = {
.fsync = linvfs_fsync, .fsync = linvfs_fsync,
}; };
struct file_operations linvfs_invis_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.readv = linvfs_readv_invis,
.writev = linvfs_writev_invis,
.aio_read = linvfs_read_invis,
.aio_write = linvfs_write_invis,
.sendfile = linvfs_sendfile,
.ioctl = linvfs_ioctl_invis,
.mmap = linvfs_file_mmap,
.open = linvfs_open,
.release = linvfs_release,
.fsync = linvfs_fsync,
};
struct file_operations linvfs_dir_operations = { struct file_operations linvfs_dir_operations = {
.read = generic_read_dir, .read = generic_read_dir,
.readdir = linvfs_readdir, .readdir = linvfs_readdir,
......
...@@ -373,7 +373,8 @@ xfs_open_by_handle( ...@@ -373,7 +373,8 @@ xfs_open_by_handle(
put_unused_fd(new_fd); put_unused_fd(new_fd);
return -XFS_ERROR(-PTR_ERR(filp)); return -XFS_ERROR(-PTR_ERR(filp));
} }
filp->f_mode |= FINVIS; if (inode->i_mode & S_IFREG)
filp->f_op = &linvfs_invis_file_operations;
fd_install(new_fd, filp); fd_install(new_fd, filp);
return new_fd; return new_fd;
...@@ -415,12 +416,11 @@ xfs_readlink_by_handle( ...@@ -415,12 +416,11 @@ xfs_readlink_by_handle(
auio.uio_iov = &aiov; auio.uio_iov = &aiov;
auio.uio_iovcnt = 1; auio.uio_iovcnt = 1;
auio.uio_fmode = FINVIS;
auio.uio_offset = 0; auio.uio_offset = 0;
auio.uio_segflg = UIO_USERSPACE; auio.uio_segflg = UIO_USERSPACE;
auio.uio_resid = olen; auio.uio_resid = olen;
VOP_READLINK(vp, &auio, NULL, error); VOP_READLINK(vp, &auio, IO_INVIS, NULL, error);
VN_RELE(vp); VN_RELE(vp);
return (olen - auio.uio_resid); return (olen - auio.uio_resid);
...@@ -575,6 +575,7 @@ xfs_ioc_space( ...@@ -575,6 +575,7 @@ xfs_ioc_space(
bhv_desc_t *bdp, bhv_desc_t *bdp,
vnode_t *vp, vnode_t *vp,
struct file *filp, struct file *filp,
int flags,
unsigned int cmd, unsigned int cmd,
unsigned long arg); unsigned long arg);
...@@ -606,6 +607,7 @@ STATIC int ...@@ -606,6 +607,7 @@ STATIC int
xfs_ioc_getbmap( xfs_ioc_getbmap(
bhv_desc_t *bdp, bhv_desc_t *bdp,
struct file *filp, struct file *filp,
int flags,
unsigned int cmd, unsigned int cmd,
unsigned long arg); unsigned long arg);
...@@ -619,6 +621,7 @@ xfs_ioctl( ...@@ -619,6 +621,7 @@ xfs_ioctl(
bhv_desc_t *bdp, bhv_desc_t *bdp,
struct inode *inode, struct inode *inode,
struct file *filp, struct file *filp,
int ioflags,
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
...@@ -652,7 +655,7 @@ xfs_ioctl( ...@@ -652,7 +655,7 @@ xfs_ioctl(
!capable(CAP_SYS_ADMIN)) !capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
return xfs_ioc_space(bdp, vp, filp, cmd, arg); return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg);
case XFS_IOC_DIOINFO: { case XFS_IOC_DIOINFO: {
struct dioattr da; struct dioattr da;
...@@ -703,7 +706,7 @@ xfs_ioctl( ...@@ -703,7 +706,7 @@ xfs_ioctl(
case XFS_IOC_GETBMAP: case XFS_IOC_GETBMAP:
case XFS_IOC_GETBMAPA: case XFS_IOC_GETBMAPA:
return xfs_ioc_getbmap(bdp, filp, cmd, arg); return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg);
case XFS_IOC_GETBMAPX: case XFS_IOC_GETBMAPX:
return xfs_ioc_getbmapx(bdp, arg); return xfs_ioc_getbmapx(bdp, arg);
...@@ -865,6 +868,7 @@ xfs_ioc_space( ...@@ -865,6 +868,7 @@ xfs_ioc_space(
bhv_desc_t *bdp, bhv_desc_t *bdp,
vnode_t *vp, vnode_t *vp,
struct file *filp, struct file *filp,
int ioflags,
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
...@@ -886,7 +890,7 @@ xfs_ioc_space( ...@@ -886,7 +890,7 @@ xfs_ioc_space(
if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
attr_flags |= ATTR_NONBLOCK; attr_flags |= ATTR_NONBLOCK;
if (filp->f_mode & FINVIS) if (ioflags & IO_INVIS)
attr_flags |= ATTR_DMI; attr_flags |= ATTR_DMI;
error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos, error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos,
...@@ -1153,6 +1157,7 @@ STATIC int ...@@ -1153,6 +1157,7 @@ STATIC int
xfs_ioc_getbmap( xfs_ioc_getbmap(
bhv_desc_t *bdp, bhv_desc_t *bdp,
struct file *filp, struct file *filp,
int ioflags,
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
...@@ -1167,7 +1172,7 @@ xfs_ioc_getbmap( ...@@ -1167,7 +1172,7 @@ xfs_ioc_getbmap(
return -XFS_ERROR(EINVAL); return -XFS_ERROR(EINVAL);
iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
if (filp->f_mode & FINVIS) if (ioflags & IO_INVIS)
iflags |= BMV_IF_NO_DMAPI_READ; iflags |= BMV_IF_NO_DMAPI_READ;
error = xfs_getbmap(bdp, &bm, (struct getbmap *)arg+1, iflags); error = xfs_getbmap(bdp, &bm, (struct getbmap *)arg+1, iflags);
......
...@@ -386,9 +386,8 @@ linvfs_readlink( ...@@ -386,9 +386,8 @@ linvfs_readlink(
uio.uio_segflg = UIO_USERSPACE; uio.uio_segflg = UIO_USERSPACE;
uio.uio_resid = size; uio.uio_resid = size;
uio.uio_iovcnt = 1; uio.uio_iovcnt = 1;
uio.uio_fmode = 0;
VOP_READLINK(vp, &uio, NULL, error); VOP_READLINK(vp, &uio, 0, NULL, error);
if (error) if (error)
return -error; return -error;
...@@ -433,10 +432,9 @@ linvfs_follow_link( ...@@ -433,10 +432,9 @@ linvfs_follow_link(
uio->uio_offset = 0; uio->uio_offset = 0;
uio->uio_segflg = UIO_SYSSPACE; uio->uio_segflg = UIO_SYSSPACE;
uio->uio_resid = MAXNAMELEN; uio->uio_resid = MAXNAMELEN;
uio->uio_fmode = 0;
uio->uio_iovcnt = 1; uio->uio_iovcnt = 1;
VOP_READLINK(vp, uio, NULL, error); VOP_READLINK(vp, uio, 0, NULL, error);
if (error) { if (error) {
kfree(uio); kfree(uio);
kfree(link); kfree(link);
......
...@@ -61,6 +61,7 @@ extern struct inode_operations linvfs_dir_inode_operations; ...@@ -61,6 +61,7 @@ extern struct inode_operations linvfs_dir_inode_operations;
extern struct inode_operations linvfs_symlink_inode_operations; extern struct inode_operations linvfs_symlink_inode_operations;
extern struct file_operations linvfs_file_operations; extern struct file_operations linvfs_file_operations;
extern struct file_operations linvfs_invis_file_operations;
extern struct file_operations linvfs_dir_operations; extern struct file_operations linvfs_dir_operations;
extern struct address_space_operations linvfs_aops; extern struct address_space_operations linvfs_aops;
......
...@@ -195,8 +195,6 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh) ...@@ -195,8 +195,6 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
#define MAXPATHLEN 1024 #define MAXPATHLEN 1024
#define FINVIS 0x0100 /* don't update timestamps - XFS */
#define MIN(a,b) (min(a,b)) #define MIN(a,b) (min(a,b))
#define MAX(a,b) (max(a,b)) #define MAX(a,b) (max(a,b))
#define howmany(x, y) (((x)+((y)-1))/(y)) #define howmany(x, y) (((x)+((y)-1))/(y))
......
...@@ -149,6 +149,7 @@ xfs_read( ...@@ -149,6 +149,7 @@ xfs_read(
const struct iovec *iovp, const struct iovec *iovp,
unsigned int segs, unsigned int segs,
loff_t *offset, loff_t *offset,
int ioflags,
cred_t *credp) cred_t *credp)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
...@@ -159,8 +160,6 @@ xfs_read( ...@@ -159,8 +160,6 @@ xfs_read(
xfs_mount_t *mp; xfs_mount_t *mp;
vnode_t *vp; vnode_t *vp;
unsigned long seg; unsigned long seg;
int direct = (file->f_flags & O_DIRECT);
int invisible = (file->f_mode & FINVIS);
ip = XFS_BHVTOI(bdp); ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp); vp = BHV_TO_VNODE(bdp);
...@@ -183,7 +182,7 @@ xfs_read( ...@@ -183,7 +182,7 @@ xfs_read(
} }
/* END copy & waste from filemap.c */ /* END copy & waste from filemap.c */
if (direct) { if (ioflags & IO_ISDIRECT) {
pb_target_t *target = pb_target_t *target =
(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp; mp->m_rtdev_targp : mp->m_ddev_targp;
...@@ -214,7 +213,8 @@ xfs_read( ...@@ -214,7 +213,8 @@ xfs_read(
*/ */
xfs_ilock(ip, XFS_IOLOCK_SHARED); xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && !invisible) { if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
!(ioflags & IO_INVIS)) {
int error; int error;
vrwlock_t locktype = VRWLOCK_READ; vrwlock_t locktype = VRWLOCK_READ;
...@@ -226,14 +226,13 @@ xfs_read( ...@@ -226,14 +226,13 @@ xfs_read(
} }
} }
/* We need to deal with the iovec case seperately here */
ret = __generic_file_aio_read(iocb, iovp, segs, offset); ret = __generic_file_aio_read(iocb, iovp, segs, offset);
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
if (ret > 0) if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret); XFS_STATS_ADD(xs_read_bytes, ret);
if (!invisible) if (likely(!(ioflags & IO_INVIS)))
xfs_ichgtime(ip, XFS_ICHGTIME_ACC); xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
return ret; return ret;
...@@ -244,6 +243,7 @@ xfs_sendfile( ...@@ -244,6 +243,7 @@ xfs_sendfile(
bhv_desc_t *bdp, bhv_desc_t *bdp,
struct file *filp, struct file *filp,
loff_t *offset, loff_t *offset,
int ioflags,
size_t count, size_t count,
read_actor_t actor, read_actor_t actor,
void *target, void *target,
...@@ -254,7 +254,6 @@ xfs_sendfile( ...@@ -254,7 +254,6 @@ xfs_sendfile(
xfs_inode_t *ip; xfs_inode_t *ip;
xfs_mount_t *mp; xfs_mount_t *mp;
vnode_t *vp; vnode_t *vp;
int invisible = (filp->f_mode & FINVIS);
ip = XFS_BHVTOI(bdp); ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp); vp = BHV_TO_VNODE(bdp);
...@@ -274,7 +273,9 @@ xfs_sendfile( ...@@ -274,7 +273,9 @@ xfs_sendfile(
return -EIO; return -EIO;
xfs_ilock(ip, XFS_IOLOCK_SHARED); xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && !invisible) {
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
(!(ioflags & IO_INVIS))) {
vrwlock_t locktype = VRWLOCK_READ; vrwlock_t locktype = VRWLOCK_READ;
int error; int error;
...@@ -289,8 +290,7 @@ xfs_sendfile( ...@@ -289,8 +290,7 @@ xfs_sendfile(
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
XFS_STATS_ADD(xs_read_bytes, ret); XFS_STATS_ADD(xs_read_bytes, ret);
if (!invisible) xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
return ret; return ret;
} }
...@@ -518,6 +518,7 @@ xfs_write( ...@@ -518,6 +518,7 @@ xfs_write(
const struct iovec *iovp, const struct iovec *iovp,
unsigned int segs, unsigned int segs,
loff_t *offset, loff_t *offset,
int ioflags,
cred_t *credp) cred_t *credp)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
...@@ -532,8 +533,6 @@ xfs_write( ...@@ -532,8 +533,6 @@ xfs_write(
vnode_t *vp; vnode_t *vp;
unsigned long seg; unsigned long seg;
int iolock; int iolock;
int direct = (file->f_flags & O_DIRECT);
int invisible = (file->f_mode & FINVIS);
int eventsent = 0; int eventsent = 0;
vrwlock_t locktype; vrwlock_t locktype;
...@@ -569,7 +568,7 @@ xfs_write( ...@@ -569,7 +568,7 @@ xfs_write(
return -EIO; return -EIO;
} }
if (direct) { if (ioflags & IO_ISDIRECT) {
pb_target_t *target = pb_target_t *target =
(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp; mp->m_rtdev_targp : mp->m_ddev_targp;
...@@ -586,6 +585,7 @@ xfs_write( ...@@ -586,6 +585,7 @@ xfs_write(
} }
xfs_ilock(xip, XFS_ILOCK_EXCL|iolock); xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
isize = xip->i_d.di_size; isize = xip->i_d.di_size;
limit = XFS_MAXIOFFSET(mp); limit = XFS_MAXIOFFSET(mp);
...@@ -608,7 +608,7 @@ xfs_write( ...@@ -608,7 +608,7 @@ xfs_write(
} }
if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) && if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
!invisible && !eventsent)) { !(ioflags & IO_INVIS) && !eventsent)) {
loff_t savedsize = *offset; loff_t savedsize = *offset;
xfs_iunlock(xip, XFS_ILOCK_EXCL); xfs_iunlock(xip, XFS_ILOCK_EXCL);
...@@ -642,7 +642,7 @@ xfs_write( ...@@ -642,7 +642,7 @@ xfs_write(
* *
* We must update xfs' times since revalidate will overcopy xfs. * We must update xfs' times since revalidate will overcopy xfs.
*/ */
if (size && !invisible) if (size && !(ioflags & IO_INVIS))
xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
/* /*
...@@ -654,7 +654,7 @@ xfs_write( ...@@ -654,7 +654,7 @@ xfs_write(
* to zero it out up to the new size. * to zero it out up to the new size.
*/ */
if (!direct && (*offset > isize && isize)) { if (!(ioflags & IO_ISDIRECT) && (*offset > isize && isize)) {
error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, *offset, error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, *offset,
isize, *offset + size); isize, *offset + size);
if (error) { if (error) {
...@@ -683,14 +683,15 @@ xfs_write( ...@@ -683,14 +683,15 @@ xfs_write(
} }
retry: retry:
if (direct) { if (ioflags & IO_ISDIRECT) {
xfs_inval_cached_pages(vp, &xip->i_iocore, *offset, 1, 1); xfs_inval_cached_pages(vp, &xip->i_iocore, *offset, 1, 1);
} }
ret = generic_file_aio_write_nolock(iocb, iovp, segs, offset); ret = generic_file_aio_write_nolock(iocb, iovp, segs, offset);
if ((ret == -ENOSPC) && if ((ret == -ENOSPC) &&
DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) && !invisible) { DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
!(ioflags & IO_INVIS)) {
xfs_rwunlock(bdp, locktype); xfs_rwunlock(bdp, locktype);
error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp, error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
......
...@@ -56,12 +56,12 @@ extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, ...@@ -56,12 +56,12 @@ extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
xfs_fsize_t, xfs_fsize_t); xfs_fsize_t, xfs_fsize_t);
extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int, const struct iovec *, unsigned int,
loff_t *, struct cred *); loff_t *, int, struct cred *);
extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *, extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int, const struct iovec *, unsigned int,
loff_t *, struct cred *); loff_t *, int, struct cred *);
extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
loff_t *, size_t, read_actor_t, loff_t *, int, size_t, read_actor_t,
void *, struct cred *); void *, struct cred *);
extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int, extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
......
...@@ -373,7 +373,7 @@ STATIC int ...@@ -373,7 +373,7 @@ STATIC int
init_inodecache( void ) init_inodecache( void )
{ {
linvfs_inode_cachep = kmem_cache_create("linvfs_icache", linvfs_inode_cachep = kmem_cache_create("linvfs_icache",
sizeof(vnode_t), 0, sizeof(vnode_t), 0,
SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
init_once, NULL); init_once, NULL);
...@@ -579,7 +579,7 @@ linvfs_freeze_fs( ...@@ -579,7 +579,7 @@ linvfs_freeze_fs(
if (sb->s_flags & MS_RDONLY) if (sb->s_flags & MS_RDONLY)
return; return;
VFS_ROOT(vfsp, &vp, error); VFS_ROOT(vfsp, &vp, error);
VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, XFS_IOC_FREEZE, 0, error); VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_FREEZE, 0, error);
VN_RELE(vp); VN_RELE(vp);
} }
...@@ -592,7 +592,7 @@ linvfs_unfreeze_fs( ...@@ -592,7 +592,7 @@ linvfs_unfreeze_fs(
int error; int error;
VFS_ROOT(vfsp, &vp, error); VFS_ROOT(vfsp, &vp, error);
VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, XFS_IOC_THAW, 0, error); VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_THAW, 0, error);
VN_RELE(vp); VN_RELE(vp);
} }
......
...@@ -155,9 +155,17 @@ extern u_short vttoif_tab[]; ...@@ -155,9 +155,17 @@ extern u_short vttoif_tab[];
#define VMODIFIED 0x8 /* XFS inode state possibly differs */ #define VMODIFIED 0x8 /* XFS inode state possibly differs */
/* to the Linux inode state. */ /* to the Linux inode state. */
typedef enum vrwlock { VRWLOCK_NONE, VRWLOCK_READ, /*
VRWLOCK_WRITE, VRWLOCK_WRITE_DIRECT, * Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter.
VRWLOCK_TRY_READ, VRWLOCK_TRY_WRITE } vrwlock_t; */
typedef enum vrwlock {
VRWLOCK_NONE,
VRWLOCK_READ,
VRWLOCK_WRITE,
VRWLOCK_WRITE_DIRECT,
VRWLOCK_TRY_READ,
VRWLOCK_TRY_WRITE
} vrwlock_t;
/* /*
* Return values for VOP_INACTIVE. A return value of * Return values for VOP_INACTIVE. A return value of
...@@ -182,15 +190,15 @@ typedef enum vchange { ...@@ -182,15 +190,15 @@ typedef enum vchange {
typedef int (*vop_open_t)(bhv_desc_t *, struct cred *); typedef int (*vop_open_t)(bhv_desc_t *, struct cred *);
typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *, typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
const struct iovec *, unsigned int, const struct iovec *, unsigned int,
loff_t *, struct cred *); loff_t *, int, struct cred *);
typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *, typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
const struct iovec *, unsigned int, const struct iovec *, unsigned int,
loff_t *, struct cred *); loff_t *, int, struct cred *);
typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
loff_t *, size_t, read_actor_t, loff_t *, int, size_t, read_actor_t,
void *, struct cred *); void *, struct cred *);
typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
unsigned int, unsigned long); int, unsigned int, unsigned long);
typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
struct cred *); struct cred *);
typedef int (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int, typedef int (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int,
...@@ -212,7 +220,8 @@ typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, ...@@ -212,7 +220,8 @@ typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
int *); int *);
typedef int (*vop_symlink_t)(bhv_desc_t *, vname_t *, struct vattr *, typedef int (*vop_symlink_t)(bhv_desc_t *, vname_t *, struct vattr *,
char *, vnode_t **, struct cred *); char *, vnode_t **, struct cred *);
typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, struct cred *); typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
struct cred *);
typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
xfs_off_t, xfs_off_t); xfs_off_t, xfs_off_t);
typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *);
...@@ -284,12 +293,12 @@ typedef struct vnodeops { ...@@ -284,12 +293,12 @@ typedef struct vnodeops {
*/ */
#define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op) #define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op)
#define VOP_READ(vp,file,iov,segs,offset,cr,rv) \ #define VOP_READ(vp,file,iov,segs,offset,ioflags,cr,rv) \
rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,cr) rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
#define VOP_WRITE(vp,file,iov,segs,offset,cr,rv) \ #define VOP_WRITE(vp,file,iov,segs,offset,ioflags,cr,rv) \
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,cr) rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
#define VOP_SENDFILE(vp,f,off,cnt,act,targ,cr,rv) \ #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \
rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,cnt,act,targ,cr) rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
#define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \
rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
#define VOP_OPEN(vp, cr, rv) \ #define VOP_OPEN(vp, cr, rv) \
...@@ -318,8 +327,8 @@ typedef struct vnodeops { ...@@ -318,8 +327,8 @@ typedef struct vnodeops {
rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp) rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp)
#define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \ #define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \
rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr) rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr)
#define VOP_READLINK(vp,uiop,cr,rv) \ #define VOP_READLINK(vp,uiop,fl,cr,rv) \
rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr) rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,fl,cr)
#define VOP_FSYNC(vp,f,cr,b,e,rv) \ #define VOP_FSYNC(vp,f,cr,b,e,rv) \
rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e) rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e)
#define VOP_INACTIVE(vp, cr, rv) \ #define VOP_INACTIVE(vp, cr, rv) \
...@@ -366,15 +375,20 @@ typedef struct vnodeops { ...@@ -366,15 +375,20 @@ typedef struct vnodeops {
*/ */
#define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \ #define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \
rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt) rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt)
#define VOP_IOCTL(vp, inode, filp, cmd, arg, rv) \ #define VOP_IOCTL(vp, inode, filp, fl, cmd, arg, rv) \
rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,cmd,arg) rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg)
#define VOP_IFLUSH(vp, flags, rv) \ #define VOP_IFLUSH(vp, flags, rv) \
rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags) rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags)
/* /*
* Flags for VOP_IFLUSH call * Flags for read/write calls - same values as IRIX
*/ */
#define IO_ISDIRECT 0x00004 /* bypass page cache */
#define IO_INVIS 0x00020 /* don't update inode timestamps */
/*
* Flags for VOP_IFLUSH call
*/
#define FLUSH_SYNC 1 /* wait for flush to complete */ #define FLUSH_SYNC 1 /* wait for flush to complete */
#define FLUSH_INODE 2 /* flush the inode itself */ #define FLUSH_INODE 2 /* flush the inode itself */
#define FLUSH_LOG 4 /* force the last log entry for #define FLUSH_LOG 4 /* force the last log entry for
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
#define SYMLINK_MAPS 2 #define SYMLINK_MAPS 2
extern int xfs_ioctl(bhv_desc_t *, struct inode *, struct file *, extern int xfs_ioctl(bhv_desc_t *, struct inode *, struct file *,
unsigned int, unsigned long); int, unsigned int, unsigned long);
/* /*
...@@ -992,6 +992,7 @@ STATIC int ...@@ -992,6 +992,7 @@ STATIC int
xfs_readlink( xfs_readlink(
bhv_desc_t *bdp, bhv_desc_t *bdp,
uio_t *uiop, uio_t *uiop,
int ioflags,
cred_t *credp) cred_t *credp)
{ {
xfs_inode_t *ip; xfs_inode_t *ip;
...@@ -1033,7 +1034,7 @@ xfs_readlink( ...@@ -1033,7 +1034,7 @@ xfs_readlink(
goto error_return; goto error_return;
} }
if (!(uiop->uio_fmode & FINVIS)) { if (!(ioflags & IO_INVIS)) {
xfs_ichgtime(ip, XFS_ICHGTIME_ACC); xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment