Commit 9f5974c8 authored by Linus Torvalds's avatar Linus Torvalds
parents a2d823bf ddae9c2e
This diff is collapsed.
......@@ -23,14 +23,24 @@ extern mempool_t *xfs_ioend_pool;
typedef void (*xfs_ioend_func_t)(void *);
/*
* xfs_ioend struct manages large extent writes for XFS.
* It can manage several multi-page bio's at once.
*/
typedef struct xfs_ioend {
struct xfs_ioend *io_list; /* next ioend in chain */
unsigned int io_type; /* delalloc / unwritten */
unsigned int io_uptodate; /* I/O status register */
atomic_t io_remaining; /* hold count */
struct vnode *io_vnode; /* file being written to */
struct buffer_head *io_buffer_head;/* buffer linked list head */
struct buffer_head *io_buffer_tail;/* buffer linked list tail */
size_t io_size; /* size of the extent */
xfs_off_t io_offset; /* offset in the file */
struct work_struct io_work; /* xfsdatad work queue */
} xfs_ioend_t;
extern struct address_space_operations linvfs_aops;
extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
#endif /* __XFS_IOPS_H__ */
This diff is collapsed.
This diff is collapsed.
......@@ -509,16 +509,14 @@ linvfs_open_exec(
vnode_t *vp = LINVFS_GET_VP(inode);
xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
int error = 0;
bhv_desc_t *bdp;
xfs_inode_t *ip;
if (vp->v_vfsp->vfs_flag & VFS_DMI) {
bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
if (!bdp) {
ip = xfs_vtoi(vp);
if (!ip) {
error = -EINVAL;
goto open_exec_out;
}
ip = XFS_BHVTOI(bdp);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) {
error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
0, 0, 0, NULL);
......
......@@ -146,13 +146,10 @@ xfs_find_handle(
if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
xfs_inode_t *ip;
bhv_desc_t *bhv;
int lock_mode;
/* need to get access to the xfs_inode to read the generation */
bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops);
ASSERT(bhv);
ip = XFS_BHVTOI(bhv);
ip = xfs_vtoi(vp);
ASSERT(ip);
lock_mode = xfs_ilock_map_shared(ip);
......@@ -751,9 +748,8 @@ xfs_ioctl(
(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
da.d_mem = da.d_miniosz = 1 << target->pbr_sshift;
/* The size dio will do in one go */
da.d_maxiosz = 64 * PAGE_CACHE_SIZE;
da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
if (copy_to_user(arg, &da, sizeof(da)))
return -XFS_ERROR(EFAULT);
......
......@@ -54,10 +54,45 @@
#include <linux/capability.h>
#include <linux/xattr.h>
#include <linux/namei.h>
#include <linux/security.h>
#define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) || \
(S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME))
/*
* Get a XFS inode from a given vnode.
*/
xfs_inode_t *
xfs_vtoi(
struct vnode *vp)
{
bhv_desc_t *bdp;
bdp = bhv_lookup_range(VN_BHV_HEAD(vp),
VNODE_POSITION_XFS, VNODE_POSITION_XFS);
if (unlikely(bdp == NULL))
return NULL;
return XFS_BHVTOI(bdp);
}
/*
* Bring the atime in the XFS inode uptodate.
* Used before logging the inode to disk or when the Linux inode goes away.
*/
void
xfs_synchronize_atime(
xfs_inode_t *ip)
{
vnode_t *vp;
vp = XFS_ITOV_NULL(ip);
if (vp) {
struct inode *inode = &vp->v_inode;
ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
}
}
/*
* Change the requested timestamp in the given inode.
* We don't lock across timestamp updates, and we don't log them but
......@@ -77,23 +112,6 @@ xfs_ichgtime(
struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip));
timespec_t tv;
/*
* We're not supposed to change timestamps in readonly-mounted
* filesystems. Throw it away if anyone asks us.
*/
if (unlikely(IS_RDONLY(inode)))
return;
/*
* Don't update access timestamps on reads if mounted "noatime".
* Throw it away if anyone asks us.
*/
if (unlikely(
(ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) &&
(flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) ==
XFS_ICHGTIME_ACC))
return;
nanotime(&tv);
if (flags & XFS_ICHGTIME_MOD) {
inode->i_mtime = tv;
......@@ -130,8 +148,6 @@ xfs_ichgtime(
* Variant on the above which avoids querying the system clock
* in situations where we know the Linux inode timestamps have
* just been updated (and so we can update our inode cheaply).
* We also skip the readonly and noatime checks here, they are
* also catered for already.
*/
void
xfs_ichgtime_fast(
......@@ -142,20 +158,16 @@ xfs_ichgtime_fast(
timespec_t *tvp;
/*
* We're not supposed to change timestamps in readonly-mounted
* filesystems. Throw it away if anyone asks us.
* Atime updates for read() & friends are handled lazily now, and
* explicit updates must go through xfs_ichgtime()
*/
if (unlikely(IS_RDONLY(inode)))
return;
ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
/*
* Don't update access timestamps on reads if mounted "noatime".
* Throw it away if anyone asks us.
* We're not supposed to change timestamps in readonly-mounted
* filesystems. Throw it away if anyone asks us.
*/
if (unlikely(
(ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) &&
((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) ==
XFS_ICHGTIME_ACC)))
if (unlikely(IS_RDONLY(inode)))
return;
if (flags & XFS_ICHGTIME_MOD) {
......@@ -163,11 +175,6 @@ xfs_ichgtime_fast(
ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec;
ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec;
}
if (flags & XFS_ICHGTIME_ACC) {
tvp = &inode->i_atime;
ip->i_d.di_atime.t_sec = (__int32_t)tvp->tv_sec;
ip->i_d.di_atime.t_nsec = (__int32_t)tvp->tv_nsec;
}
if (flags & XFS_ICHGTIME_CHG) {
tvp = &inode->i_ctime;
ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec;
......@@ -213,6 +220,39 @@ validate_fields(
}
}
/*
* Hook in SELinux. This is not quite correct yet, what we really need
* here (as we do for default ACLs) is a mechanism by which creation of
* these attrs can be journalled at inode creation time (along with the
* inode, of course, such that log replay can't cause these to be lost).
*/
STATIC int
linvfs_init_security(
struct vnode *vp,
struct inode *dir)
{
struct inode *ip = LINVFS_GET_IP(vp);
size_t length;
void *value;
char *name;
int error;
error = security_inode_init_security(ip, dir, &name, &value, &length);
if (error) {
if (error == -EOPNOTSUPP)
return 0;
return -error;
}
VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error);
if (!error)
VMODIFY(vp);
kfree(name);
kfree(value);
return error;
}
/*
* Determine whether a process has a valid fs_struct (kernel daemons
* like knfsd don't have an fs_struct).
......@@ -278,6 +318,9 @@ linvfs_mknod(
break;
}
if (!error)
error = linvfs_init_security(vp, dir);
if (default_acl) {
if (!error) {
error = _ACL_INHERIT(vp, &va, default_acl);
......@@ -294,8 +337,6 @@ linvfs_mknod(
teardown.d_inode = ip = LINVFS_GET_IP(vp);
teardown.d_name = dentry->d_name;
vn_mark_bad(vp);
if (S_ISDIR(mode))
VOP_RMDIR(dvp, &teardown, NULL, err2);
else
......@@ -506,7 +547,7 @@ linvfs_follow_link(
ASSERT(dentry);
ASSERT(nd);
link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL);
link = (char *)kmalloc(MAXPATHLEN+1, GFP_KERNEL);
if (!link) {
nd_set_link(nd, ERR_PTR(-ENOMEM));
return NULL;
......@@ -522,12 +563,12 @@ linvfs_follow_link(
vp = LINVFS_GET_VP(dentry->d_inode);
iov.iov_base = link;
iov.iov_len = MAXNAMELEN;
iov.iov_len = MAXPATHLEN;
uio->uio_iov = &iov;
uio->uio_offset = 0;
uio->uio_segflg = UIO_SYSSPACE;
uio->uio_resid = MAXNAMELEN;
uio->uio_resid = MAXPATHLEN;
uio->uio_iovcnt = 1;
VOP_READLINK(vp, uio, 0, NULL, error);
......@@ -535,7 +576,7 @@ linvfs_follow_link(
kfree(link);
link = ERR_PTR(-error);
} else {
link[MAXNAMELEN - uio->uio_resid] = '\0';
link[MAXPATHLEN - uio->uio_resid] = '\0';
}
kfree(uio);
......
......@@ -26,11 +26,6 @@ extern struct file_operations linvfs_file_operations;
extern struct file_operations linvfs_invis_file_operations;
extern struct file_operations linvfs_dir_operations;
extern struct address_space_operations linvfs_aops;
extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern void linvfs_unwritten_done(struct buffer_head *, int);
extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
int, unsigned int, void __user *);
......
......@@ -110,10 +110,6 @@
* delalloc and these ondisk-uninitialised buffers.
*/
BUFFER_FNS(PrivateStart, unwritten);
static inline void set_buffer_unwritten_io(struct buffer_head *bh)
{
bh->b_end_io = linvfs_unwritten_done;
}
#define restricted_chown xfs_params.restrict_chown.val
#define irix_sgid_inherit xfs_params.sgid_inherit.val
......@@ -232,7 +228,7 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
#define xfs_itruncate_data(ip, off) \
(-vmtruncate(LINVFS_GET_IP(XFS_ITOV(ip)), (off)))
#define xfs_statvfs_fsid(statp, mp) \
({ u64 id = huge_encode_dev((mp)->m_dev); \
({ u64 id = huge_encode_dev((mp)->m_ddev_targp->bt_dev); \
__kernel_fsid_t *fsid = &(statp)->f_fsid; \
(fsid->val[0] = (u32)id, fsid->val[1] = (u32)(id >> 32)); })
......
......@@ -233,8 +233,8 @@ xfs_read(
xfs_buftarg_t *target =
(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
if ((*offset & target->pbr_smask) ||
(size & target->pbr_smask)) {
if ((*offset & target->bt_smask) ||
(size & target->bt_smask)) {
if (*offset == ip->i_d.di_size) {
return (0);
}
......@@ -281,9 +281,6 @@ xfs_read(
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
if (likely(!(ioflags & IO_INVIS)))
xfs_ichgtime_fast(ip, inode, XFS_ICHGTIME_ACC);
unlock_isem:
if (unlikely(ioflags & IO_ISDIRECT))
mutex_unlock(&inode->i_mutex);
......@@ -346,9 +343,6 @@ xfs_sendfile(
if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret);
if (likely(!(ioflags & IO_INVIS)))
xfs_ichgtime_fast(ip, LINVFS_GET_IP(vp), XFS_ICHGTIME_ACC);
return ret;
}
......@@ -362,7 +356,6 @@ STATIC int /* error (positive) */
xfs_zero_last_block(
struct inode *ip,
xfs_iocore_t *io,
xfs_off_t offset,
xfs_fsize_t isize,
xfs_fsize_t end_size)
{
......@@ -371,19 +364,16 @@ xfs_zero_last_block(
int nimaps;
int zero_offset;
int zero_len;
int isize_fsb_offset;
int error = 0;
xfs_bmbt_irec_t imap;
loff_t loff;
size_t lsize;
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
ASSERT(offset > isize);
mp = io->io_mount;
isize_fsb_offset = XFS_B_FSB_OFFSET(mp, isize);
if (isize_fsb_offset == 0) {
zero_offset = XFS_B_FSB_OFFSET(mp, isize);
if (zero_offset == 0) {
/*
* There are no extra bytes in the last block on disk to
* zero, so return.
......@@ -413,10 +403,8 @@ xfs_zero_last_block(
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
loff = XFS_FSB_TO_B(mp, last_fsb);
lsize = XFS_FSB_TO_B(mp, 1);
zero_offset = isize_fsb_offset;
zero_len = mp->m_sb.sb_blocksize - isize_fsb_offset;
zero_len = mp->m_sb.sb_blocksize - zero_offset;
error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
......@@ -447,20 +435,17 @@ xfs_zero_eof(
struct inode *ip = LINVFS_GET_IP(vp);
xfs_fileoff_t start_zero_fsb;
xfs_fileoff_t end_zero_fsb;
xfs_fileoff_t prev_zero_fsb;
xfs_fileoff_t zero_count_fsb;
xfs_fileoff_t last_fsb;
xfs_extlen_t buf_len_fsb;
xfs_extlen_t prev_zero_count;
xfs_mount_t *mp;
int nimaps;
int error = 0;
xfs_bmbt_irec_t imap;
loff_t loff;
size_t lsize;
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
ASSERT(offset > isize);
mp = io->io_mount;
......@@ -468,7 +453,7 @@ xfs_zero_eof(
* First handle zeroing the block on which isize resides.
* We only zero a part of that block so it is handled specially.
*/
error = xfs_zero_last_block(ip, io, offset, isize, end_size);
error = xfs_zero_last_block(ip, io, isize, end_size);
if (error) {
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
......@@ -496,8 +481,6 @@ xfs_zero_eof(
}
ASSERT(start_zero_fsb <= end_zero_fsb);
prev_zero_fsb = NULLFILEOFF;
prev_zero_count = 0;
while (start_zero_fsb <= end_zero_fsb) {
nimaps = 1;
zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
......@@ -519,10 +502,7 @@ xfs_zero_eof(
* that sits on a hole and sets the page as P_HOLE
* and calls remapf if it is a mapped file.
*/
prev_zero_fsb = NULLFILEOFF;
prev_zero_count = 0;
start_zero_fsb = imap.br_startoff +
imap.br_blockcount;
start_zero_fsb = imap.br_startoff + imap.br_blockcount;
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
continue;
}
......@@ -543,17 +523,15 @@ xfs_zero_eof(
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
loff = XFS_FSB_TO_B(mp, start_zero_fsb);
lsize = XFS_FSB_TO_B(mp, buf_len_fsb);
error = xfs_iozero(ip, loff, lsize, end_size);
error = xfs_iozero(ip,
XFS_FSB_TO_B(mp, start_zero_fsb),
XFS_FSB_TO_B(mp, buf_len_fsb),
end_size);
if (error) {
goto out_lock;
}
prev_zero_fsb = start_zero_fsb;
prev_zero_count = buf_len_fsb;
start_zero_fsb = imap.br_startoff + buf_len_fsb;
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
......@@ -640,7 +618,7 @@ xfs_write(
(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
if ((pos & target->pbr_smask) || (count & target->pbr_smask))
if ((pos & target->bt_smask) || (count & target->bt_smask))
return XFS_ERROR(-EINVAL);
if (!VN_CACHED(vp) && pos < i_size_read(inode))
......@@ -831,6 +809,10 @@ xfs_write(
goto retry;
}
isize = i_size_read(inode);
if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
*offset = isize;
if (*offset > xip->i_d.di_size) {
xfs_ilock(xip, XFS_ILOCK_EXCL);
if (*offset > xip->i_d.di_size) {
......@@ -956,7 +938,7 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
if (!XFS_FORCED_SHUTDOWN(mp)) {
pagebuf_iorequest(bp);
xfs_buf_iorequest(bp);
return 0;
} else {
xfs_buftrace("XFS__BDSTRAT IOERROR", bp);
......@@ -1009,7 +991,7 @@ xfsbdstrat(
* if (XFS_BUF_IS_GRIO(bp)) {
*/
pagebuf_iorequest(bp);
xfs_buf_iorequest(bp);
return 0;
}
......
......@@ -34,7 +34,7 @@ xfs_read_xfsstats(
__uint64_t xs_write_bytes = 0;
__uint64_t xs_read_bytes = 0;
static struct xstats_entry {
static const struct xstats_entry {
char *desc;
int endpoint;
} xstats[] = {
......
......@@ -109,15 +109,15 @@ struct xfsstats {
__uint32_t vn_remove; /* # times vn_remove called */
__uint32_t vn_free; /* # times vn_free called */
#define XFSSTAT_END_BUF (XFSSTAT_END_VNODE_OPS+9)
__uint32_t pb_get;
__uint32_t pb_create;
__uint32_t pb_get_locked;
__uint32_t pb_get_locked_waited;
__uint32_t pb_busy_locked;
__uint32_t pb_miss_locked;
__uint32_t pb_page_retries;
__uint32_t pb_page_found;
__uint32_t pb_get_read;
__uint32_t xb_get;
__uint32_t xb_create;
__uint32_t xb_get_locked;
__uint32_t xb_get_locked_waited;
__uint32_t xb_busy_locked;
__uint32_t xb_miss_locked;
__uint32_t xb_page_retries;
__uint32_t xb_page_found;
__uint32_t xb_get_read;
/* Extra precision counters */
__uint64_t xs_xstrat_bytes;
__uint64_t xs_write_bytes;
......
This diff is collapsed.
......@@ -106,7 +106,6 @@ vn_revalidate_core(
inode->i_blocks = vap->va_nblocks;
inode->i_mtime = vap->va_mtime;
inode->i_ctime = vap->va_ctime;
inode->i_atime = vap->va_atime;
inode->i_blksize = vap->va_blocksize;
if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
inode->i_flags |= S_IMMUTABLE;
......
......@@ -565,6 +565,25 @@ static inline int VN_BAD(struct vnode *vp)
return is_bad_inode(LINVFS_GET_IP(vp));
}
/*
* Extracting atime values in various formats
*/
static inline void vn_atime_to_bstime(struct vnode *vp, xfs_bstime_t *bs_atime)
{
bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
}
static inline void vn_atime_to_timespec(struct vnode *vp, struct timespec *ts)
{
*ts = vp->v_inode.i_atime;
}
static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt)
{
*tt = vp->v_inode.i_atime.tv_sec;
}
/*
* Some useful predicates.
*/
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -57,7 +57,7 @@ struct xfs_mount_args {
/*
* XFS mount option flags -- args->flags1
*/
#define XFSMNT_COMPAT_ATTR 0x00000001 /* do not use ATTR2 format */
#define XFSMNT_ATTR2 0x00000001 /* allow ATTR2 EA format */
#define XFSMNT_WSYNC 0x00000002 /* safe mode nfs mount
* compatible */
#define XFSMNT_INO64 0x00000004 /* move inode numbers up
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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