Commit a2308b7f authored by Linus Torvalds's avatar Linus Torvalds

Merge git://oss.sgi.com:8090/oss/git/xfs-2.6

* git://oss.sgi.com:8090/oss/git/xfs-2.6:
  [XFS] Provide XFS support for the splice syscall.
  [XFS] Reenable write barriers by default.
  [XFS] Make project quota enforcement return an error code consistent with
  [XFS] Implement the silent parameter to fill_super, previously ignored.
  [XFS] Cleanup comment to remove reference to obsoleted function
parents f27f0a04 1b895840
...@@ -69,7 +69,6 @@ __xfs_file_read( ...@@ -69,7 +69,6 @@ __xfs_file_read(
return rval; return rval;
} }
STATIC ssize_t STATIC ssize_t
xfs_file_aio_read( xfs_file_aio_read(
struct kiocb *iocb, struct kiocb *iocb,
...@@ -90,7 +89,6 @@ xfs_file_aio_read_invis( ...@@ -90,7 +89,6 @@ xfs_file_aio_read_invis(
return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
} }
STATIC inline ssize_t STATIC inline ssize_t
__xfs_file_write( __xfs_file_write(
struct kiocb *iocb, struct kiocb *iocb,
...@@ -113,7 +111,6 @@ __xfs_file_write( ...@@ -113,7 +111,6 @@ __xfs_file_write(
return rval; return rval;
} }
STATIC ssize_t STATIC ssize_t
xfs_file_aio_write( xfs_file_aio_write(
struct kiocb *iocb, struct kiocb *iocb,
...@@ -134,7 +131,6 @@ xfs_file_aio_write_invis( ...@@ -134,7 +131,6 @@ xfs_file_aio_write_invis(
return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
} }
STATIC inline ssize_t STATIC inline ssize_t
__xfs_file_readv( __xfs_file_readv(
struct file *file, struct file *file,
...@@ -179,7 +175,6 @@ xfs_file_readv_invis( ...@@ -179,7 +175,6 @@ xfs_file_readv_invis(
return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos); return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
} }
STATIC inline ssize_t STATIC inline ssize_t
__xfs_file_writev( __xfs_file_writev(
struct file *file, struct file *file,
...@@ -204,7 +199,6 @@ __xfs_file_writev( ...@@ -204,7 +199,6 @@ __xfs_file_writev(
return rval; return rval;
} }
STATIC ssize_t STATIC ssize_t
xfs_file_writev( xfs_file_writev(
struct file *file, struct file *file,
...@@ -228,7 +222,7 @@ xfs_file_writev_invis( ...@@ -228,7 +222,7 @@ xfs_file_writev_invis(
STATIC ssize_t STATIC ssize_t
xfs_file_sendfile( xfs_file_sendfile(
struct file *filp, struct file *filp,
loff_t *ppos, loff_t *pos,
size_t count, size_t count,
read_actor_t actor, read_actor_t actor,
void *target) void *target)
...@@ -236,10 +230,80 @@ xfs_file_sendfile( ...@@ -236,10 +230,80 @@ xfs_file_sendfile(
vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
ssize_t rval; ssize_t rval;
VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval); VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
return rval; return rval;
} }
STATIC ssize_t
xfs_file_sendfile_invis(
struct file *filp,
loff_t *pos,
size_t count,
read_actor_t actor,
void *target)
{
vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
ssize_t rval;
VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
return rval;
}
STATIC ssize_t
xfs_file_splice_read(
struct file *infilp,
struct inode *pipe,
size_t len,
unsigned int flags)
{
vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode);
ssize_t rval;
VOP_SPLICE_READ(vp, infilp, pipe, len, flags, 0, NULL, rval);
return rval;
}
STATIC ssize_t
xfs_file_splice_read_invis(
struct file *infilp,
struct inode *pipe,
size_t len,
unsigned int flags)
{
vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode);
ssize_t rval;
VOP_SPLICE_READ(vp, infilp, pipe, len, flags, IO_INVIS, NULL, rval);
return rval;
}
STATIC ssize_t
xfs_file_splice_write(
struct inode *pipe,
struct file *outfilp,
size_t len,
unsigned int flags)
{
vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode);
ssize_t rval;
VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, 0, NULL, rval);
return rval;
}
STATIC ssize_t
xfs_file_splice_write_invis(
struct inode *pipe,
struct file *outfilp,
size_t len,
unsigned int flags)
{
vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode);
ssize_t rval;
VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, IO_INVIS, NULL, rval);
return rval;
}
STATIC int STATIC int
xfs_file_open( xfs_file_open(
...@@ -251,13 +315,10 @@ xfs_file_open( ...@@ -251,13 +315,10 @@ xfs_file_open(
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
return -EFBIG; return -EFBIG;
ASSERT(vp);
VOP_OPEN(vp, NULL, error); VOP_OPEN(vp, NULL, error);
return -error; return -error;
} }
STATIC int STATIC int
xfs_file_release( xfs_file_release(
struct inode *inode, struct inode *inode,
...@@ -271,7 +332,6 @@ xfs_file_release( ...@@ -271,7 +332,6 @@ xfs_file_release(
return -error; return -error;
} }
STATIC int STATIC int
xfs_file_fsync( xfs_file_fsync(
struct file *filp, struct file *filp,
...@@ -285,21 +345,11 @@ xfs_file_fsync( ...@@ -285,21 +345,11 @@ xfs_file_fsync(
if (datasync) if (datasync)
flags |= FSYNC_DATA; flags |= FSYNC_DATA;
ASSERT(vp);
VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
return -error; return -error;
} }
/*
* xfs_file_readdir maps to VOP_READDIR().
* We need to build a uio, cred, ...
*/
#define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
#ifdef CONFIG_XFS_DMAPI #ifdef CONFIG_XFS_DMAPI
STATIC struct page * STATIC struct page *
xfs_vm_nopage( xfs_vm_nopage(
struct vm_area_struct *area, struct vm_area_struct *area,
...@@ -319,10 +369,8 @@ xfs_vm_nopage( ...@@ -319,10 +369,8 @@ xfs_vm_nopage(
return filemap_nopage(area, address, type); return filemap_nopage(area, address, type);
} }
#endif /* CONFIG_XFS_DMAPI */ #endif /* CONFIG_XFS_DMAPI */
STATIC int STATIC int
xfs_file_readdir( xfs_file_readdir(
struct file *filp, struct file *filp,
...@@ -330,7 +378,7 @@ xfs_file_readdir( ...@@ -330,7 +378,7 @@ xfs_file_readdir(
filldir_t filldir) filldir_t filldir)
{ {
int error = 0; int error = 0;
vnode_t *vp; vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
uio_t uio; uio_t uio;
iovec_t iov; iovec_t iov;
int eof = 0; int eof = 0;
...@@ -340,9 +388,6 @@ xfs_file_readdir( ...@@ -340,9 +388,6 @@ xfs_file_readdir(
xfs_off_t start_offset, curr_offset; xfs_off_t start_offset, curr_offset;
xfs_dirent_t *dbp = NULL; xfs_dirent_t *dbp = NULL;
vp = vn_from_inode(filp->f_dentry->d_inode);
ASSERT(vp);
/* Try fairly hard to get memory */ /* Try fairly hard to get memory */
do { do {
if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL))) if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
...@@ -387,7 +432,7 @@ xfs_file_readdir( ...@@ -387,7 +432,7 @@ xfs_file_readdir(
} }
size -= dbp->d_reclen; size -= dbp->d_reclen;
curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */; curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
dbp = nextdp(dbp); dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
} }
} }
done: done:
...@@ -402,7 +447,6 @@ xfs_file_readdir( ...@@ -402,7 +447,6 @@ xfs_file_readdir(
return -error; return -error;
} }
STATIC int STATIC int
xfs_file_mmap( xfs_file_mmap(
struct file *filp, struct file *filp,
...@@ -457,11 +501,10 @@ xfs_file_ioctl_invis( ...@@ -457,11 +501,10 @@ xfs_file_ioctl_invis(
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int error;
struct inode *inode = filp->f_dentry->d_inode; struct inode *inode = filp->f_dentry->d_inode;
vnode_t *vp = vn_from_inode(inode); vnode_t *vp = vn_from_inode(inode);
int error;
ASSERT(vp);
VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
VMODIFY(vp); VMODIFY(vp);
...@@ -537,6 +580,8 @@ const struct file_operations xfs_file_operations = { ...@@ -537,6 +580,8 @@ const struct file_operations xfs_file_operations = {
.aio_read = xfs_file_aio_read, .aio_read = xfs_file_aio_read,
.aio_write = xfs_file_aio_write, .aio_write = xfs_file_aio_write,
.sendfile = xfs_file_sendfile, .sendfile = xfs_file_sendfile,
.splice_read = xfs_file_splice_read,
.splice_write = xfs_file_splice_write,
.unlocked_ioctl = xfs_file_ioctl, .unlocked_ioctl = xfs_file_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = xfs_file_compat_ioctl, .compat_ioctl = xfs_file_compat_ioctl,
...@@ -558,7 +603,9 @@ const struct file_operations xfs_invis_file_operations = { ...@@ -558,7 +603,9 @@ const struct file_operations xfs_invis_file_operations = {
.writev = xfs_file_writev_invis, .writev = xfs_file_writev_invis,
.aio_read = xfs_file_aio_read_invis, .aio_read = xfs_file_aio_read_invis,
.aio_write = xfs_file_aio_write_invis, .aio_write = xfs_file_aio_write_invis,
.sendfile = xfs_file_sendfile, .sendfile = xfs_file_sendfile_invis,
.splice_read = xfs_file_splice_read_invis,
.splice_write = xfs_file_splice_write_invis,
.unlocked_ioctl = xfs_file_ioctl_invis, .unlocked_ioctl = xfs_file_ioctl_invis,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = xfs_file_compat_invis_ioctl, .compat_ioctl = xfs_file_compat_invis_ioctl,
......
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
*/ */
#undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */
#define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */ #define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */
#define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
#else #else
......
...@@ -301,36 +301,23 @@ xfs_sendfile( ...@@ -301,36 +301,23 @@ xfs_sendfile(
void *target, void *target,
cred_t *credp) cred_t *credp)
{ {
xfs_inode_t *ip = XFS_BHVTOI(bdp);
xfs_mount_t *mp = ip->i_mount;
ssize_t ret; ssize_t ret;
xfs_fsize_t n;
xfs_inode_t *ip;
xfs_mount_t *mp;
vnode_t *vp;
ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount;
XFS_STATS_INC(xs_read_calls); XFS_STATS_INC(xs_read_calls);
if (XFS_FORCED_SHUTDOWN(mp))
n = XFS_MAXIOFFSET(mp) - *offset;
if ((n <= 0) || (count == 0))
return 0;
if (n < count)
count = n;
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
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) && if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
(!(ioflags & IO_INVIS))) { (!(ioflags & IO_INVIS))) {
vrwlock_t locktype = VRWLOCK_READ; vrwlock_t locktype = VRWLOCK_READ;
int error; int error;
error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count, error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
*offset, count,
FILP_DELAY_FLAG(filp), &locktype); FILP_DELAY_FLAG(filp), &locktype);
if (error) { if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
...@@ -340,12 +327,96 @@ xfs_sendfile( ...@@ -340,12 +327,96 @@ xfs_sendfile(
xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore, xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
(void *)(unsigned long)target, count, *offset, ioflags); (void *)(unsigned long)target, count, *offset, ioflags);
ret = generic_file_sendfile(filp, offset, count, actor, target); ret = generic_file_sendfile(filp, offset, count, actor, target);
if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret);
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return ret;
}
ssize_t
xfs_splice_read(
bhv_desc_t *bdp,
struct file *infilp,
struct inode *pipe,
size_t count,
int flags,
int ioflags,
cred_t *credp)
{
xfs_inode_t *ip = XFS_BHVTOI(bdp);
xfs_mount_t *mp = ip->i_mount;
ssize_t ret;
XFS_STATS_INC(xs_read_calls);
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return -EIO;
xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
(!(ioflags & IO_INVIS))) {
vrwlock_t locktype = VRWLOCK_READ;
int error;
error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
infilp->f_pos, count,
FILP_DELAY_FLAG(infilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return -error;
}
}
xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
pipe, count, infilp->f_pos, ioflags);
ret = generic_file_splice_read(infilp, pipe, count, flags);
if (ret > 0) if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret); XFS_STATS_ADD(xs_read_bytes, ret);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return ret;
}
ssize_t
xfs_splice_write(
bhv_desc_t *bdp,
struct inode *pipe,
struct file *outfilp,
size_t count,
int flags,
int ioflags,
cred_t *credp)
{
xfs_inode_t *ip = XFS_BHVTOI(bdp);
xfs_mount_t *mp = ip->i_mount;
ssize_t ret;
XFS_STATS_INC(xs_write_calls);
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return -EIO;
xfs_ilock(ip, XFS_IOLOCK_EXCL);
if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
(!(ioflags & IO_INVIS))) {
vrwlock_t locktype = VRWLOCK_WRITE;
int error;
error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
outfilp->f_pos, count,
FILP_DELAY_FLAG(outfilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return -error;
}
}
xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
pipe, count, outfilp->f_pos, ioflags);
ret = generic_file_splice_write(pipe, outfilp, count, flags);
if (ret > 0)
XFS_STATS_ADD(xs_write_bytes, ret);
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return ret; return ret;
} }
...@@ -363,7 +434,7 @@ xfs_zero_last_block( ...@@ -363,7 +434,7 @@ xfs_zero_last_block(
xfs_fsize_t end_size) xfs_fsize_t end_size)
{ {
xfs_fileoff_t last_fsb; xfs_fileoff_t last_fsb;
xfs_mount_t *mp; xfs_mount_t *mp = io->io_mount;
int nimaps; int nimaps;
int zero_offset; int zero_offset;
int zero_len; int zero_len;
...@@ -373,8 +444,6 @@ xfs_zero_last_block( ...@@ -373,8 +444,6 @@ xfs_zero_last_block(
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
mp = io->io_mount;
zero_offset = XFS_B_FSB_OFFSET(mp, isize); zero_offset = XFS_B_FSB_OFFSET(mp, isize);
if (zero_offset == 0) { if (zero_offset == 0) {
/* /*
...@@ -405,10 +474,9 @@ xfs_zero_last_block( ...@@ -405,10 +474,9 @@ xfs_zero_last_block(
* don't deadlock when the buffer cache calls back to us. * don't deadlock when the buffer cache calls back to us.
*/ */
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
loff = XFS_FSB_TO_B(mp, last_fsb);
loff = XFS_FSB_TO_B(mp, last_fsb);
zero_len = mp->m_sb.sb_blocksize - zero_offset; zero_len = mp->m_sb.sb_blocksize - zero_offset;
error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
...@@ -441,7 +509,7 @@ xfs_zero_eof( ...@@ -441,7 +509,7 @@ xfs_zero_eof(
xfs_fileoff_t zero_count_fsb; xfs_fileoff_t zero_count_fsb;
xfs_fileoff_t last_fsb; xfs_fileoff_t last_fsb;
xfs_extlen_t buf_len_fsb; xfs_extlen_t buf_len_fsb;
xfs_mount_t *mp; xfs_mount_t *mp = io->io_mount;
int nimaps; int nimaps;
int error = 0; int error = 0;
xfs_bmbt_irec_t imap; xfs_bmbt_irec_t imap;
...@@ -450,8 +518,6 @@ xfs_zero_eof( ...@@ -450,8 +518,6 @@ xfs_zero_eof(
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
ASSERT(offset > isize); ASSERT(offset > isize);
mp = io->io_mount;
/* /*
* First handle zeroing the block on which isize resides. * First handle zeroing the block on which isize resides.
* We only zero a part of that block so it is handled specially. * We only zero a part of that block so it is handled specially.
......
...@@ -60,6 +60,8 @@ struct xfs_iomap; ...@@ -60,6 +60,8 @@ struct xfs_iomap;
#define XFS_IOMAP_ALLOC_ENTER 25 #define XFS_IOMAP_ALLOC_ENTER 25
#define XFS_IOMAP_ALLOC_MAP 26 #define XFS_IOMAP_ALLOC_MAP 26
#define XFS_IOMAP_UNWRITTEN 27 #define XFS_IOMAP_UNWRITTEN 27
#define XFS_SPLICE_READ_ENTER 28
#define XFS_SPLICE_WRITE_ENTER 29
extern void xfs_rw_enter_trace(int, struct xfs_iocore *, extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
void *, size_t, loff_t, int); void *, size_t, loff_t, int);
extern void xfs_inval_cached_trace(struct xfs_iocore *, extern void xfs_inval_cached_trace(struct xfs_iocore *,
...@@ -78,6 +80,7 @@ extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int, ...@@ -78,6 +80,7 @@ extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *); struct xfs_iomap *, int *);
extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *); extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
extern int xfs_bdstrat_cb(struct xfs_buf *); extern int xfs_bdstrat_cb(struct xfs_buf *);
extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, 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);
...@@ -90,7 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *, ...@@ -90,7 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
loff_t *, int, size_t, read_actor_t, loff_t *, int, size_t, read_actor_t,
void *, struct cred *); void *, struct cred *);
extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *,
extern int xfs_dev_is_read_only(struct xfs_mount *, char *); struct inode *, size_t, int, int,
struct cred *);
extern ssize_t xfs_splice_write(struct bhv_desc *, struct inode *,
struct file *, size_t, int, int,
struct cred *);
#endif /* __XFS_LRW_H__ */ #endif /* __XFS_LRW_H__ */
...@@ -67,7 +67,8 @@ mempool_t *xfs_ioend_pool; ...@@ -67,7 +67,8 @@ mempool_t *xfs_ioend_pool;
STATIC struct xfs_mount_args * STATIC struct xfs_mount_args *
xfs_args_allocate( xfs_args_allocate(
struct super_block *sb) struct super_block *sb,
int silent)
{ {
struct xfs_mount_args *args; struct xfs_mount_args *args;
...@@ -80,8 +81,8 @@ xfs_args_allocate( ...@@ -80,8 +81,8 @@ xfs_args_allocate(
args->flags |= XFSMNT_DIRSYNC; args->flags |= XFSMNT_DIRSYNC;
if (sb->s_flags & MS_SYNCHRONOUS) if (sb->s_flags & MS_SYNCHRONOUS)
args->flags |= XFSMNT_WSYNC; args->flags |= XFSMNT_WSYNC;
if (silent)
/* Default to 32 bit inodes on Linux all the time */ args->flags |= XFSMNT_QUIET;
args->flags |= XFSMNT_32BITINODES; args->flags |= XFSMNT_32BITINODES;
return args; return args;
...@@ -719,7 +720,7 @@ xfs_fs_remount( ...@@ -719,7 +720,7 @@ xfs_fs_remount(
char *options) char *options)
{ {
vfs_t *vfsp = vfs_from_sb(sb); vfs_t *vfsp = vfs_from_sb(sb);
struct xfs_mount_args *args = xfs_args_allocate(sb); struct xfs_mount_args *args = xfs_args_allocate(sb, 0);
int error; int error;
VFS_PARSEARGS(vfsp, options, args, 1, error); VFS_PARSEARGS(vfsp, options, args, 1, error);
...@@ -825,7 +826,7 @@ xfs_fs_fill_super( ...@@ -825,7 +826,7 @@ xfs_fs_fill_super(
{ {
vnode_t *rootvp; vnode_t *rootvp;
struct vfs *vfsp = vfs_allocate(sb); struct vfs *vfsp = vfs_allocate(sb);
struct xfs_mount_args *args = xfs_args_allocate(sb); struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
struct kstatfs statvfs; struct kstatfs statvfs;
int error, error2; int error, error2;
......
...@@ -173,6 +173,12 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *, ...@@ -173,6 +173,12 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
loff_t *, int, size_t, read_actor_t, loff_t *, int, size_t, read_actor_t,
void *, struct cred *); void *, struct cred *);
typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *,
struct inode *, size_t, int, int,
struct cred *);
typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct inode *,
struct file *, size_t, int, int,
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 *,
int, unsigned int, void __user *); int, unsigned int, void __user *);
typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
...@@ -231,6 +237,8 @@ typedef struct vnodeops { ...@@ -231,6 +237,8 @@ typedef struct vnodeops {
vop_read_t vop_read; vop_read_t vop_read;
vop_write_t vop_write; vop_write_t vop_write;
vop_sendfile_t vop_sendfile; vop_sendfile_t vop_sendfile;
vop_splice_read_t vop_splice_read;
vop_splice_write_t vop_splice_write;
vop_ioctl_t vop_ioctl; vop_ioctl_t vop_ioctl;
vop_getattr_t vop_getattr; vop_getattr_t vop_getattr;
vop_setattr_t vop_setattr; vop_setattr_t vop_setattr;
...@@ -276,6 +284,10 @@ typedef struct vnodeops { ...@@ -276,6 +284,10 @@ typedef struct vnodeops {
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
#define VOP_SENDFILE(vp,f,off,ioflags,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,ioflags,cnt,act,targ,cr) rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
#define VOP_SPLICE_READ(vp,f,pipe,cnt,fl,iofl,cr,rv) \
rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr)
#define VOP_SPLICE_WRITE(vp,f,pipe,cnt,fl,iofl,cr,rv) \
rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,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) \
......
...@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve( ...@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve(
{ {
int error; int error;
xfs_mount_t *mp; xfs_mount_t *mp;
uint delblks, blkflags; uint delblks, blkflags, prjflags = 0;
xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
ASSERT(XFS_ISLOCKED_INODE(ip)); ASSERT(XFS_ISLOCKED_INODE(ip));
...@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve( ...@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve(
} }
} }
if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
if ((XFS_IS_GQUOTA_ON(ip->i_mount) && if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) || ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
(XFS_IS_PQUOTA_ON(ip->i_mount) && prjflags = XFS_QMOPT_ENOSPC;
ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
if (prjflags ||
(XFS_IS_GQUOTA_ON(ip->i_mount) &&
ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
delblksgdq = gdqp; delblksgdq = gdqp;
if (delblks) { if (delblks) {
ASSERT(ip->i_gdquot); ASSERT(ip->i_gdquot);
...@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve( ...@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve(
if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
flags | blkflags))) flags | blkflags | prjflags)))
return (error); return (error);
/* /*
...@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve( ...@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve(
ASSERT(unresudq || unresgdq); ASSERT(unresudq || unresgdq);
if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
flags | blkflags))) flags | blkflags | prjflags)))
return (error); return (error);
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
......
...@@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots( ...@@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots(
} }
} }
STATIC int
xfs_quota_error(uint flags)
{
if (flags & XFS_QMOPT_ENOSPC)
return ENOSPC;
return EDQUOT;
}
/* /*
* This reserves disk blocks and inodes against a dquot. * This reserves disk blocks and inodes against a dquot.
* Flags indicate if the dquot is to be locked here and also * Flags indicate if the dquot is to be locked here and also
* if the blk reservation is for RT or regular blocks. * if the blk reservation is for RT or regular blocks.
* Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
* Returns EDQUOT if quota is exceeded.
*/ */
STATIC int STATIC int
xfs_trans_dqresv( xfs_trans_dqresv(
...@@ -666,19 +673,15 @@ xfs_trans_dqresv( ...@@ -666,19 +673,15 @@ xfs_trans_dqresv(
*/ */
if (hardlimit > 0ULL && if (hardlimit > 0ULL &&
(hardlimit <= nblks + *resbcountp)) { (hardlimit <= nblks + *resbcountp)) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} }
if (softlimit > 0ULL && if (softlimit > 0ULL &&
(softlimit <= nblks + *resbcountp)) { (softlimit <= nblks + *resbcountp)) {
/*
* If timer or warnings has expired,
* return EDQUOT
*/
if ((timer != 0 && get_seconds() > timer) || if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) { (warns != 0 && warns >= warnlimit)) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} }
} }
...@@ -695,16 +698,12 @@ xfs_trans_dqresv( ...@@ -695,16 +698,12 @@ xfs_trans_dqresv(
if (!softlimit) if (!softlimit)
softlimit = q->qi_isoftlimit; softlimit = q->qi_isoftlimit;
if (hardlimit > 0ULL && count >= hardlimit) { if (hardlimit > 0ULL && count >= hardlimit) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} else if (softlimit > 0ULL && count >= softlimit) { } else if (softlimit > 0ULL && count >= softlimit) {
/*
* If timer or warnings has expired,
* return EDQUOT
*/
if ((timer != 0 && get_seconds() > timer) || if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) { (warns != 0 && warns >= warnlimit)) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} }
} }
...@@ -751,13 +750,14 @@ xfs_trans_dqresv( ...@@ -751,13 +750,14 @@ xfs_trans_dqresv(
/* /*
* Given a dquot(s), make disk block and/or inode reservations against them. * Given dquot(s), make disk block and/or inode reservations against them.
* The fact that this does the reservation against both the usr and * The fact that this does the reservation against both the usr and
* grp quotas is important, because this follows a both-or-nothing * grp/prj quotas is important, because this follows a both-or-nothing
* approach. * approach.
* *
* flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
* XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
* XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota.
* XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
* XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
* dquots are unlocked on return, if they were not locked by caller. * dquots are unlocked on return, if they were not locked by caller.
...@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots( ...@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots(
long ninos, long ninos,
uint flags) uint flags)
{ {
int resvd; int resvd = 0, error;
if (! XFS_IS_QUOTA_ON(mp)) if (!XFS_IS_QUOTA_ON(mp))
return (0); return 0;
if (tp && tp->t_dqinfo == NULL) if (tp && tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp); xfs_trans_alloc_dqinfo(tp);
ASSERT(flags & XFS_QMOPT_RESBLK_MASK); ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
resvd = 0;
if (udqp) { if (udqp) {
if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags)) error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,
return (EDQUOT); (flags & ~XFS_QMOPT_ENOSPC));
if (error)
return error;
resvd = 1; resvd = 1;
} }
if (gdqp) { if (gdqp) {
if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) { error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
if (error) {
/* /*
* can't do it, so backout previous reservation * can't do it, so backout previous reservation
*/ */
...@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots( ...@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots(
xfs_trans_dqresv(tp, mp, udqp, xfs_trans_dqresv(tp, mp, udqp,
-nblks, -ninos, flags); -nblks, -ninos, flags);
} }
return (EDQUOT); return error;
} }
} }
/* /*
* Didn't change anything critical, so, no need to log * Didn't change anything critical, so, no need to log
*/ */
return (0); return 0;
} }
...@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots( ...@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots(
* Lock the dquot and change the reservation if we can. * Lock the dquot and change the reservation if we can.
* This doesn't change the actual usage, just the reservation. * This doesn't change the actual usage, just the reservation.
* The inode sent in is locked. * The inode sent in is locked.
*
* Returns 0 on success, EDQUOT or other errors otherwise
*/ */
STATIC int STATIC int
xfs_trans_reserve_quota_nblks( xfs_trans_reserve_quota_nblks(
...@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks( ...@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks(
xfs_inode_t *ip, xfs_inode_t *ip,
long nblks, long nblks,
long ninos, long ninos,
uint type) uint flags)
{ {
int error; int error;
if (!XFS_IS_QUOTA_ON(mp)) if (!XFS_IS_QUOTA_ON(mp))
return (0); return 0;
if (XFS_IS_PQUOTA_ON(mp))
flags |= XFS_QMOPT_ENOSPC;
ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS || ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
(type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS); XFS_TRANS_DQ_RES_RTBLKS ||
(flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
XFS_TRANS_DQ_RES_BLKS);
/* /*
* Reserve nblks against these dquots, with trans as the mediator. * Reserve nblks against these dquots, with trans as the mediator.
...@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks( ...@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks(
error = xfs_trans_reserve_quota_bydquots(tp, mp, error = xfs_trans_reserve_quota_bydquots(tp, mp,
ip->i_udquot, ip->i_gdquot, ip->i_udquot, ip->i_gdquot,
nblks, ninos, nblks, ninos,
type); flags);
return (error); return error;
} }
/* /*
......
...@@ -4719,18 +4719,17 @@ xfs_bmapi( ...@@ -4719,18 +4719,17 @@ xfs_bmapi(
/* /*
* Make a transaction-less quota reservation for * Make a transaction-less quota reservation for
* delayed allocation blocks. This number gets * delayed allocation blocks. This number gets
* adjusted later. * adjusted later. We return if we haven't
* We return EDQUOT if we haven't allocated * allocated blocks already inside this loop.
* blks already inside this loop;
*/ */
if (XFS_TRANS_RESERVE_QUOTA_NBLKS( if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
mp, NULL, ip, (long)alen, 0, mp, NULL, ip, (long)alen, 0,
rt ? XFS_QMOPT_RES_RTBLKS : rt ? XFS_QMOPT_RES_RTBLKS :
XFS_QMOPT_RES_REGBLKS)) { XFS_QMOPT_RES_REGBLKS))) {
if (n == 0) { if (n == 0) {
*nmap = 0; *nmap = 0;
ASSERT(cur == NULL); ASSERT(cur == NULL);
return XFS_ERROR(EDQUOT); return error;
} }
break; break;
} }
......
...@@ -353,10 +353,11 @@ xfs_check_nostate_extents( ...@@ -353,10 +353,11 @@ xfs_check_nostate_extents(
xfs_extnum_t num); xfs_extnum_t num);
/* /*
* Call xfs_bmap_do_search_extents() to search for the extent * Search the extent records for the entry containing block bno.
* record containing block bno. If in multi-level in-core extent * If bno lies in a hole, point to the next entry. If bno lies
* allocation mode, find and extract the target extent buffer, * past eof, *eofp will be set, and *prevp will contain the last
* otherwise just use the direct extent list. * entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/ */
xfs_bmbt_rec_t * xfs_bmbt_rec_t *
xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *, xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
......
...@@ -68,6 +68,7 @@ struct xfs_mount_args { ...@@ -68,6 +68,7 @@ struct xfs_mount_args {
* enforcement */ * enforcement */
#define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit #define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit
* enforcement */ * enforcement */
#define XFSMNT_QUIET 0x00000080 /* don't report mount errors */
#define XFSMNT_NOALIGN 0x00000200 /* don't allocate at #define XFSMNT_NOALIGN 0x00000200 /* don't allocate at
* stripe boundaries*/ * stripe boundaries*/
#define XFSMNT_RETERR 0x00000400 /* return error to user */ #define XFSMNT_RETERR 0x00000400 /* return error to user */
......
...@@ -186,4 +186,7 @@ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...); ...@@ -186,4 +186,7 @@ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...);
#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \ #define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args)
#define xfs_fs_mount_cmn_err(f, fmt, args...) \
((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0)
#endif /* __XFS_ERROR_H__ */ #endif /* __XFS_ERROR_H__ */
...@@ -213,7 +213,8 @@ xfs_mount_free( ...@@ -213,7 +213,8 @@ xfs_mount_free(
STATIC int STATIC int
xfs_mount_validate_sb( xfs_mount_validate_sb(
xfs_mount_t *mp, xfs_mount_t *mp,
xfs_sb_t *sbp) xfs_sb_t *sbp,
int flags)
{ {
/* /*
* If the log device and data device have the * If the log device and data device have the
...@@ -223,33 +224,29 @@ xfs_mount_validate_sb( ...@@ -223,33 +224,29 @@ xfs_mount_validate_sb(
* a volume filesystem in a non-volume manner. * a volume filesystem in a non-volume manner.
*/ */
if (sbp->sb_magicnum != XFS_SB_MAGIC) { if (sbp->sb_magicnum != XFS_SB_MAGIC) {
cmn_err(CE_WARN, "XFS: bad magic number"); xfs_fs_mount_cmn_err(flags, "bad magic number");
return XFS_ERROR(EWRONGFS); return XFS_ERROR(EWRONGFS);
} }
if (!XFS_SB_GOOD_VERSION(sbp)) { if (!XFS_SB_GOOD_VERSION(sbp)) {
cmn_err(CE_WARN, "XFS: bad version"); xfs_fs_mount_cmn_err(flags, "bad version");
return XFS_ERROR(EWRONGFS); return XFS_ERROR(EWRONGFS);
} }
if (unlikely( if (unlikely(
sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
cmn_err(CE_WARN, xfs_fs_mount_cmn_err(flags,
"XFS: filesystem is marked as having an external log; " "filesystem is marked as having an external log; "
"specify logdev on the\nmount command line."); "specify logdev on the\nmount command line.");
XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)", return XFS_ERROR(EINVAL);
XFS_ERRLEVEL_HIGH, mp, sbp);
return XFS_ERROR(EFSCORRUPTED);
} }
if (unlikely( if (unlikely(
sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
cmn_err(CE_WARN, xfs_fs_mount_cmn_err(flags,
"XFS: filesystem is marked as having an internal log; " "filesystem is marked as having an internal log; "
"don't specify logdev on\nthe mount command line."); "do not specify logdev on\nthe mount command line.");
XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)", return XFS_ERROR(EINVAL);
XFS_ERRLEVEL_HIGH, mp, sbp);
return XFS_ERROR(EFSCORRUPTED);
} }
/* /*
...@@ -274,9 +271,7 @@ xfs_mount_validate_sb( ...@@ -274,9 +271,7 @@ xfs_mount_validate_sb(
(sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) ||
(sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) ||
(sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) { (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) {
cmn_err(CE_WARN, "XFS: SB sanity check 1 failed"); xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)",
XFS_ERRLEVEL_LOW, mp, sbp);
return XFS_ERROR(EFSCORRUPTED); return XFS_ERROR(EFSCORRUPTED);
} }
...@@ -289,9 +284,7 @@ xfs_mount_validate_sb( ...@@ -289,9 +284,7 @@ xfs_mount_validate_sb(
(xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
cmn_err(CE_WARN, "XFS: SB sanity check 2 failed"); xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
XFS_ERROR_REPORT("xfs_mount_validate_sb(4)",
XFS_ERRLEVEL_LOW, mp);
return XFS_ERROR(EFSCORRUPTED); return XFS_ERROR(EFSCORRUPTED);
} }
...@@ -307,15 +300,13 @@ xfs_mount_validate_sb( ...@@ -307,15 +300,13 @@ xfs_mount_validate_sb(
(sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX || (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
(sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) { (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
#endif #endif
cmn_err(CE_WARN, xfs_fs_mount_cmn_err(flags,
"XFS: File system is too large to be mounted on this system."); "file system too large to be mounted on this system.");
return XFS_ERROR(E2BIG); return XFS_ERROR(E2BIG);
} }
if (unlikely(sbp->sb_inprogress)) { if (unlikely(sbp->sb_inprogress)) {
cmn_err(CE_WARN, "XFS: file system busy"); xfs_fs_mount_cmn_err(flags, "file system busy");
XFS_ERROR_REPORT("xfs_mount_validate_sb(5)",
XFS_ERRLEVEL_LOW, mp);
return XFS_ERROR(EFSCORRUPTED); return XFS_ERROR(EFSCORRUPTED);
} }
...@@ -323,8 +314,8 @@ xfs_mount_validate_sb( ...@@ -323,8 +314,8 @@ xfs_mount_validate_sb(
* Version 1 directory format has never worked on Linux. * Version 1 directory format has never worked on Linux.
*/ */
if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) { if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
cmn_err(CE_WARN, xfs_fs_mount_cmn_err(flags,
"XFS: Attempted to mount file system using version 1 directory format"); "file system using version 1 directory format");
return XFS_ERROR(ENOSYS); return XFS_ERROR(ENOSYS);
} }
...@@ -332,11 +323,11 @@ xfs_mount_validate_sb( ...@@ -332,11 +323,11 @@ xfs_mount_validate_sb(
* Until this is fixed only page-sized or smaller data blocks work. * Until this is fixed only page-sized or smaller data blocks work.
*/ */
if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
cmn_err(CE_WARN, xfs_fs_mount_cmn_err(flags,
"XFS: Attempted to mount file system with blocksize %d bytes", "file system with blocksize %d bytes",
sbp->sb_blocksize); sbp->sb_blocksize);
cmn_err(CE_WARN, xfs_fs_mount_cmn_err(flags,
"XFS: Only page-sized (%ld) or less blocksizes currently work.", "only pagesize (%ld) or less will currently work.",
PAGE_SIZE); PAGE_SIZE);
return XFS_ERROR(ENOSYS); return XFS_ERROR(ENOSYS);
} }
...@@ -484,7 +475,7 @@ xfs_xlatesb( ...@@ -484,7 +475,7 @@ xfs_xlatesb(
* Does the initial read of the superblock. * Does the initial read of the superblock.
*/ */
int int
xfs_readsb(xfs_mount_t *mp) xfs_readsb(xfs_mount_t *mp, int flags)
{ {
unsigned int sector_size; unsigned int sector_size;
unsigned int extra_flags; unsigned int extra_flags;
...@@ -506,7 +497,7 @@ xfs_readsb(xfs_mount_t *mp) ...@@ -506,7 +497,7 @@ xfs_readsb(xfs_mount_t *mp)
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags); BTOBB(sector_size), extra_flags);
if (!bp || XFS_BUF_ISERROR(bp)) { if (!bp || XFS_BUF_ISERROR(bp)) {
cmn_err(CE_WARN, "XFS: SB read failed"); xfs_fs_mount_cmn_err(flags, "SB read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail; goto fail;
} }
...@@ -520,9 +511,9 @@ xfs_readsb(xfs_mount_t *mp) ...@@ -520,9 +511,9 @@ xfs_readsb(xfs_mount_t *mp)
sbp = XFS_BUF_TO_SBP(bp); sbp = XFS_BUF_TO_SBP(bp);
xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS); xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
error = xfs_mount_validate_sb(mp, &(mp->m_sb)); error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
if (error) { if (error) {
cmn_err(CE_WARN, "XFS: SB validate failed"); xfs_fs_mount_cmn_err(flags, "SB validate failed");
goto fail; goto fail;
} }
...@@ -530,8 +521,8 @@ xfs_readsb(xfs_mount_t *mp) ...@@ -530,8 +521,8 @@ xfs_readsb(xfs_mount_t *mp)
* We must be able to do sector-sized and sector-aligned IO. * We must be able to do sector-sized and sector-aligned IO.
*/ */
if (sector_size > mp->m_sb.sb_sectsize) { if (sector_size > mp->m_sb.sb_sectsize) {
cmn_err(CE_WARN, xfs_fs_mount_cmn_err(flags,
"XFS: device supports only %u byte sectors (not %u)", "device supports only %u byte sectors (not %u)",
sector_size, mp->m_sb.sb_sectsize); sector_size, mp->m_sb.sb_sectsize);
error = ENOSYS; error = ENOSYS;
goto fail; goto fail;
...@@ -548,7 +539,7 @@ xfs_readsb(xfs_mount_t *mp) ...@@ -548,7 +539,7 @@ xfs_readsb(xfs_mount_t *mp)
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags); BTOBB(sector_size), extra_flags);
if (!bp || XFS_BUF_ISERROR(bp)) { if (!bp || XFS_BUF_ISERROR(bp)) {
cmn_err(CE_WARN, "XFS: SB re-read failed"); xfs_fs_mount_cmn_err(flags, "SB re-read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail; goto fail;
} }
...@@ -678,7 +669,7 @@ xfs_mountfs( ...@@ -678,7 +669,7 @@ xfs_mountfs(
int error = 0; int error = 0;
if (mp->m_sb_bp == NULL) { if (mp->m_sb_bp == NULL) {
if ((error = xfs_readsb(mp))) { if ((error = xfs_readsb(mp, mfsi_flags))) {
return error; return error;
} }
} }
......
...@@ -510,9 +510,12 @@ xfs_preferred_iosize(xfs_mount_t *mp) ...@@ -510,9 +510,12 @@ xfs_preferred_iosize(xfs_mount_t *mp)
*/ */
#define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */ #define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */
#define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */ #define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */
/* XFS_MFSI_RRINODES */
#define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */ #define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */
/* log recovery */ /* log recovery */
#define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */ #define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */
/* XFS_MFSI_CONVERT_SUNIT */
#define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */
/* /*
* Macros for getting from mount to vfs and back. * Macros for getting from mount to vfs and back.
...@@ -581,7 +584,7 @@ extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t, ...@@ -581,7 +584,7 @@ extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t,
extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
uint, int); uint, int);
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int xfs_readsb(xfs_mount_t *mp); extern int xfs_readsb(xfs_mount_t *, int);
extern void xfs_freesb(xfs_mount_t *); extern void xfs_freesb(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int, int *); extern int xfs_syncsub(xfs_mount_t *, int, int, int *);
......
...@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat { ...@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */ #define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */
#define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */ #define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */
#define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */ #define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */
#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */ #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */
#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */ #define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */
#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */ #define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */
#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */ #define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */
#define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */
/* /*
* flags to xfs_trans_mod_dquot to indicate which field needs to be * flags to xfs_trans_mod_dquot to indicate which field needs to be
......
...@@ -442,6 +442,9 @@ xfs_mount( ...@@ -442,6 +442,9 @@ xfs_mount(
p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
if (args->flags & XFSMNT_QUIET)
flags |= XFS_MFSI_QUIET;
/* /*
* Open real time and log devices - order is important. * Open real time and log devices - order is important.
*/ */
...@@ -492,7 +495,7 @@ xfs_mount( ...@@ -492,7 +495,7 @@ xfs_mount(
error = xfs_start_flags(vfsp, args, mp); error = xfs_start_flags(vfsp, args, mp);
if (error) if (error)
goto error1; goto error1;
error = xfs_readsb(mp); error = xfs_readsb(mp, flags);
if (error) if (error)
goto error1; goto error1;
error = xfs_finish_flags(vfsp, args, mp); error = xfs_finish_flags(vfsp, args, mp);
...@@ -1697,8 +1700,9 @@ xfs_parseargs( ...@@ -1697,8 +1700,9 @@ xfs_parseargs(
int dsunit, dswidth, vol_dsunit, vol_dswidth; int dsunit, dswidth, vol_dsunit, vol_dswidth;
int iosize; int iosize;
args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
args->flags |= XFSMNT_IDELETE; args->flags |= XFSMNT_IDELETE;
args->flags |= XFSMNT_BARRIER;
args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
if (!options) if (!options)
goto done; goto done;
...@@ -1947,8 +1951,6 @@ xfs_showargs( ...@@ -1947,8 +1951,6 @@ xfs_showargs(
seq_printf(m, "," MNTOPT_IKEEP); seq_printf(m, "," MNTOPT_IKEEP);
if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE)) if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
seq_printf(m, "," MNTOPT_LARGEIO); seq_printf(m, "," MNTOPT_LARGEIO);
if (mp->m_flags & XFS_MOUNT_BARRIER)
seq_printf(m, "," MNTOPT_BARRIER);
if (!(vfsp->vfs_flag & VFS_32BITINODES)) if (!(vfsp->vfs_flag & VFS_32BITINODES))
seq_printf(m, "," MNTOPT_64BITINODE); seq_printf(m, "," MNTOPT_64BITINODE);
......
...@@ -4648,6 +4648,10 @@ vnodeops_t xfs_vnodeops = { ...@@ -4648,6 +4648,10 @@ vnodeops_t xfs_vnodeops = {
.vop_read = xfs_read, .vop_read = xfs_read,
#ifdef HAVE_SENDFILE #ifdef HAVE_SENDFILE
.vop_sendfile = xfs_sendfile, .vop_sendfile = xfs_sendfile,
#endif
#ifdef HAVE_SPLICE
.vop_splice_read = xfs_splice_read,
.vop_splice_write = xfs_splice_write,
#endif #endif
.vop_write = xfs_write, .vop_write = xfs_write,
.vop_ioctl = xfs_ioctl, .vop_ioctl = xfs_ioctl,
......
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