#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_iomap.h"
+ #include "xfs_vnodeops.h"
#include <linux/mpage.h>
#include <linux/pagevec.h>
#include <linux/writeback.h>
next = bh->b_private;
bh->b_end_io(bh, !ioend->io_error);
}
- if (unlikely(ioend->io_error))
- vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
- vn_iowake(ioend->io_vnode);
+ if (unlikely(ioend->io_error)) {
+ vn_ioerror(XFS_I(ioend->io_inode), ioend->io_error,
+ __FILE__,__LINE__);
+ }
+ vn_iowake(XFS_I(ioend->io_inode));
mempool_free(ioend, xfs_ioend_pool);
}
xfs_setfilesize(
xfs_ioend_t *ioend)
{
- xfs_inode_t *ip;
+ xfs_inode_t *ip = XFS_I(ioend->io_inode);
xfs_fsize_t isize;
xfs_fsize_t bsize;
- ip = xfs_vtoi(ioend->io_vnode);
- if (!ip)
- return;
-
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
ASSERT(ioend->io_type != IOMAP_READ);
ip->i_d.di_size = isize;
ip->i_update_core = 1;
ip->i_update_size = 1;
- mark_inode_dirty_sync(vn_to_inode(ioend->io_vnode));
+ mark_inode_dirty_sync(ioend->io_inode);
}
xfs_iunlock(ip, XFS_ILOCK_EXCL);
{
xfs_ioend_t *ioend =
container_of(work, xfs_ioend_t, io_work);
- bhv_vnode_t *vp = ioend->io_vnode;
xfs_off_t offset = ioend->io_offset;
size_t size = ioend->io_size;
if (likely(!ioend->io_error)) {
- bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
+ xfs_bmap(XFS_I(ioend->io_inode), offset, size,
+ BMAPI_UNWRITTEN, NULL, NULL);
xfs_setfilesize(ioend);
}
xfs_destroy_ioend(ioend);
ioend->io_error = 0;
ioend->io_list = NULL;
ioend->io_type = type;
- ioend->io_vnode = vn_from_inode(inode);
+ ioend->io_inode = inode;
ioend->io_buffer_head = NULL;
ioend->io_buffer_tail = NULL;
- atomic_inc(&ioend->io_vnode->v_iocount);
+ atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
ioend->io_offset = 0;
ioend->io_size = 0;
xfs_iomap_t *mapp,
int flags)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
+ xfs_inode_t *ip = XFS_I(inode);
int error, nmaps = 1;
- error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps);
+ error = xfs_bmap(ip, offset, count,
+ flags, mapp, &nmaps);
if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
- VMODIFY(vp);
+ xfs_iflags_set(ip, XFS_IMODIFIED);
return -error;
}
/*
* BIO completion handler for buffered IO.
*/
-STATIC int
+STATIC void
xfs_end_bio(
struct bio *bio,
- unsigned int bytes_done,
int error)
{
xfs_ioend_t *ioend = bio->bi_private;
- if (bio->bi_size)
- return 1;
-
ASSERT(atomic_read(&bio->bi_cnt) >= 1);
ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
bio_put(bio);
xfs_finish_ioend(ioend, 0);
- return 0;
}
STATIC void
clear_page_dirty_for_io(page);
set_page_writeback(page);
unlock_page(page);
- if (!buffers) {
+ /* If no buffers on the page are to be written, finish it here */
+ if (!buffers)
end_page_writeback(page);
- wbc->pages_skipped++; /* We didn't write this page */
- }
}
static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
unlock_buffer(bh);
} while ((bh = next_bh) != NULL);
- vn_iowake(ioend->io_vnode);
+ vn_iowake(XFS_I(ioend->io_inode));
mempool_free(ioend, xfs_ioend_pool);
} while ((ioend = next) != NULL);
}
struct address_space *mapping,
struct writeback_control *wbc)
{
- struct bhv_vnode *vp = vn_from_inode(mapping->host);
-
- if (VN_TRUNC(vp))
- VUNTRUNCATE(vp);
+ xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
return generic_writepages(mapping, wbc);
}
int direct,
bmapi_flags_t flags)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
xfs_iomap_t iomap;
xfs_off_t offset;
ssize_t size;
offset = (xfs_off_t)iblock << inode->i_blkbits;
ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
size = bh_result->b_size;
- error = bhv_vop_bmap(vp, offset, size,
+ error = xfs_bmap(XFS_I(inode), offset, size,
create ? flags : BMAPI_READ, &iomap, &niomap);
if (error)
return -error;
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
- bhv_vnode_t *vp = vn_from_inode(inode);
xfs_iomap_t iomap;
int maps = 1;
int error;
ssize_t ret;
- error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps);
+ error = xfs_bmap(XFS_I(inode), offset, 0,
+ BMAPI_DEVICE, &iomap, &maps);
if (error)
return -error;
}
STATIC int
-xfs_vm_prepare_write(
+xfs_vm_write_begin(
struct file *file,
- struct page *page,
- unsigned int from,
- unsigned int to)
+ struct address_space *mapping,
+ loff_t pos,
+ unsigned len,
+ unsigned flags,
+ struct page **pagep,
+ void **fsdata)
{
- return block_prepare_write(page, from, to, xfs_get_blocks);
+ *pagep = NULL;
+ return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+ xfs_get_blocks);
}
STATIC sector_t
sector_t block)
{
struct inode *inode = (struct inode *)mapping->host;
- bhv_vnode_t *vp = vn_from_inode(inode);
+ struct xfs_inode *ip = XFS_I(inode);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
- bhv_vop_rwlock(vp, VRWLOCK_READ);
- bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
- bhv_vop_rwunlock(vp, VRWLOCK_READ);
+ vn_trace_entry(XFS_I(inode), __FUNCTION__,
+ (inst_t *)__return_address);
+ xfs_rwlock(ip, VRWLOCK_READ);
+ xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
+ xfs_rwunlock(ip, VRWLOCK_READ);
return generic_block_bmap(mapping, block, xfs_get_blocks);
}
.sync_page = block_sync_page,
.releasepage = xfs_vm_releasepage,
.invalidatepage = xfs_vm_invalidatepage,
- .prepare_write = xfs_vm_prepare_write,
- .commit_write = generic_commit_write,
+ .write_begin = xfs_vm_write_begin,
+ .write_end = generic_write_end,
.bmap = xfs_vm_bmap,
.direct_IO = xfs_vm_direct_IO,
.migratepage = buffer_migrate_page,
{
a_list_t *aentry;
+ #ifdef CONFIG_XEN
+ /*
+ * Xen needs to be able to make sure it can get an exclusive
+ * RO mapping of pages it wants to turn into a pagetable. If
+ * a newly allocated page is also still being vmap()ed by xfs,
+ * it will cause pagetable construction to fail. This is a
+ * quick workaround to always eagerly unmap pages so that Xen
+ * is happy.
+ */
+ vunmap(addr);
+ return;
+ #endif
+
aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
if (likely(aentry)) {
spin_lock(&as_lock);
xfs_buf_t *bp =
container_of(work, xfs_buf_t, b_iodone_work);
- if (bp->b_iodone)
+ /*
+ * We can get an EOPNOTSUPP to ordered writes. Here we clear the
+ * ordered flag and reissue them. Because we can't tell the higher
+ * layers directly that they should not issue ordered I/O anymore, they
+ * need to check if the ordered flag was cleared during I/O completion.
+ */
+ if ((bp->b_error == EOPNOTSUPP) &&
+ (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) {
+ XB_TRACE(bp, "ordered_retry", bp->b_iodone);
+ bp->b_flags &= ~XBF_ORDERED;
+ xfs_buf_iorequest(bp);
+ } else if (bp->b_iodone)
(*(bp->b_iodone))(bp);
else if (bp->b_flags & XBF_ASYNC)
xfs_buf_relse(bp);
}
}
-STATIC int
+STATIC void
xfs_buf_bio_end_io(
struct bio *bio,
- unsigned int bytes_done,
int error)
{
xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private;
unsigned int blocksize = bp->b_target->bt_bsize;
struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
- if (bio->bi_size)
- return 1;
-
if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
bp->b_error = EIO;
_xfs_buf_ioend(bp, 1);
bio_put(bio);
- return 0;
}
STATIC void
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
+ #include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/xattr.h>
#include <linux/security.h>
/*
- * Get a XFS inode from a given vnode.
- */
- xfs_inode_t *
- xfs_vtoi(
- bhv_vnode_t *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.
*/
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;
+ ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
+ ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
}
}
*/
SYNCHRONIZE();
ip->i_update_core = 1;
- if (!(inode->i_state & I_LOCK))
+ if (!(inode->i_state & I_SYNC))
mark_inode_dirty_sync(inode);
}
*/
SYNCHRONIZE();
ip->i_update_core = 1;
- if (!(inode->i_state & I_LOCK))
+ if (!(inode->i_state & I_SYNC))
mark_inode_dirty_sync(inode);
}
*/
STATIC void
xfs_validate_fields(
- struct inode *ip,
- bhv_vattr_t *vattr)
+ struct inode *inode)
{
- vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
- if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) {
- ip->i_nlink = vattr->va_nlink;
- ip->i_blocks = vattr->va_nblocks;
-
- /* we're under i_sem so i_size can't change under us */
- if (i_size_read(ip) != vattr->va_size)
- i_size_write(ip, vattr->va_size);
- }
+ struct xfs_inode *ip = XFS_I(inode);
+ loff_t size;
+
+ inode->i_nlink = ip->i_d.di_nlink;
+ inode->i_blocks =
+ XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks +
+ ip->i_delayed_blks);
+ /* we're under i_sem so i_size can't change under us */
+ size = XFS_ISIZE(ip);
+ if (i_size_read(inode) != size)
+ i_size_write(inode, size);
}
/*
return -error;
}
- error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL);
+ error = xfs_attr_set(XFS_I(ip), name, value,
+ length, ATTR_SECURE);
if (!error)
- VMODIFY(vp);
+ xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED);
kfree(name);
kfree(value);
STATIC void
xfs_cleanup_inode(
- bhv_vnode_t *dvp,
+ struct inode *dir,
bhv_vnode_t *vp,
struct dentry *dentry,
int mode)
teardown.d_name = dentry->d_name;
if (S_ISDIR(mode))
- bhv_vop_rmdir(dvp, &teardown, NULL);
+ xfs_rmdir(XFS_I(dir), &teardown);
else
- bhv_vop_remove(dvp, &teardown, NULL);
+ xfs_remove(XFS_I(dir), &teardown);
VN_RELE(vp);
}
dev_t rdev)
{
struct inode *ip;
- bhv_vattr_t vattr = { 0 };
bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir);
xfs_acl_t *default_acl = NULL;
attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current))
mode &= ~current->fs->umask;
- vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
- vattr.va_mode = mode;
-
switch (mode & S_IFMT) {
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
- vattr.va_rdev = sysv_encode_dev(rdev);
- vattr.va_mask |= XFS_AT_RDEV;
- /*FALLTHROUGH*/
+ rdev = sysv_encode_dev(rdev);
case S_IFREG:
- error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL);
+ error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL);
break;
case S_IFDIR:
- error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL);
+ error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL);
break;
default:
error = EINVAL;
if (unlikely(!error)) {
error = xfs_init_security(vp, dir);
if (error)
- xfs_cleanup_inode(dvp, vp, dentry, mode);
+ xfs_cleanup_inode(dir, vp, dentry, mode);
}
if (unlikely(default_acl)) {
if (!error) {
- error = _ACL_INHERIT(vp, &vattr, default_acl);
+ error = _ACL_INHERIT(vp, mode, default_acl);
if (!error)
- VMODIFY(vp);
+ xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED);
else
- xfs_cleanup_inode(dvp, vp, dentry, mode);
+ xfs_cleanup_inode(dir, vp, dentry, mode);
}
_ACL_FREE(default_acl);
}
if (S_ISCHR(mode) || S_ISBLK(mode))
ip->i_rdev = rdev;
else if (S_ISDIR(mode))
- xfs_validate_fields(ip, &vattr);
+ xfs_validate_fields(ip);
d_instantiate(dentry, ip);
- xfs_validate_fields(dir, &vattr);
+ xfs_validate_fields(dir);
}
return -error;
}
struct dentry *dentry,
struct nameidata *nd)
{
- bhv_vnode_t *vp = vn_from_inode(dir), *cvp;
+ bhv_vnode_t *cvp;
int error;
if (dentry->d_name.len >= MAXNAMELEN)
return ERR_PTR(-ENAMETOOLONG);
- error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL);
+ error = xfs_lookup(XFS_I(dir), dentry, &cvp);
if (unlikely(error)) {
if (unlikely(error != ENOENT))
return ERR_PTR(-error);
struct dentry *dentry)
{
struct inode *ip; /* inode of guy being linked to */
- bhv_vnode_t *tdvp; /* target directory for new name/link */
bhv_vnode_t *vp; /* vp of name being linked */
- bhv_vattr_t vattr;
int error;
ip = old_dentry->d_inode; /* inode being linked to */
- tdvp = vn_from_inode(dir);
vp = vn_from_inode(ip);
VN_HOLD(vp);
- error = bhv_vop_link(tdvp, vp, dentry, NULL);
+ error = xfs_link(XFS_I(dir), vp, dentry);
if (unlikely(error)) {
VN_RELE(vp);
} else {
- VMODIFY(tdvp);
- xfs_validate_fields(ip, &vattr);
+ xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
+ xfs_validate_fields(ip);
d_instantiate(dentry, ip);
}
return -error;
struct dentry *dentry)
{
struct inode *inode;
- bhv_vnode_t *dvp; /* directory containing name to remove */
- bhv_vattr_t vattr;
int error;
inode = dentry->d_inode;
- dvp = vn_from_inode(dir);
- error = bhv_vop_remove(dvp, dentry, NULL);
+ error = xfs_remove(XFS_I(dir), dentry);
if (likely(!error)) {
- xfs_validate_fields(dir, &vattr); /* size needs update */
- xfs_validate_fields(inode, &vattr);
+ xfs_validate_fields(dir); /* size needs update */
+ xfs_validate_fields(inode);
}
return -error;
}
const char *symname)
{
struct inode *ip;
- bhv_vattr_t va = { 0 };
- bhv_vnode_t *dvp; /* directory containing name of symlink */
bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */
int error;
+ mode_t mode;
- dvp = vn_from_inode(dir);
cvp = NULL;
- va.va_mode = S_IFLNK |
+ mode = S_IFLNK |
(irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
- va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
- error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL);
+ error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode,
+ &cvp, NULL);
if (likely(!error && cvp)) {
error = xfs_init_security(cvp, dir);
if (likely(!error)) {
ip = vn_to_inode(cvp);
d_instantiate(dentry, ip);
- xfs_validate_fields(dir, &va);
- xfs_validate_fields(ip, &va);
+ xfs_validate_fields(dir);
+ xfs_validate_fields(ip);
} else {
- xfs_cleanup_inode(dvp, cvp, dentry, 0);
+ xfs_cleanup_inode(dir, cvp, dentry, 0);
}
}
return -error;
struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- bhv_vnode_t *dvp = vn_from_inode(dir);
- bhv_vattr_t vattr;
int error;
- error = bhv_vop_rmdir(dvp, dentry, NULL);
+ error = xfs_rmdir(XFS_I(dir), dentry);
if (likely(!error)) {
- xfs_validate_fields(inode, &vattr);
- xfs_validate_fields(dir, &vattr);
+ xfs_validate_fields(inode);
+ xfs_validate_fields(dir);
}
return -error;
}
struct dentry *ndentry)
{
struct inode *new_inode = ndentry->d_inode;
- bhv_vnode_t *fvp; /* from directory */
bhv_vnode_t *tvp; /* target directory */
- bhv_vattr_t vattr;
int error;
- fvp = vn_from_inode(odir);
tvp = vn_from_inode(ndir);
- error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL);
+ error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry);
if (likely(!error)) {
if (new_inode)
- xfs_validate_fields(new_inode, &vattr);
- xfs_validate_fields(odir, &vattr);
+ xfs_validate_fields(new_inode);
+ xfs_validate_fields(odir);
if (ndir != odir)
- xfs_validate_fields(ndir, &vattr);
+ xfs_validate_fields(ndir);
}
return -error;
}
struct dentry *dentry,
struct nameidata *nd)
{
- bhv_vnode_t *vp;
- uio_t *uio;
- iovec_t iov;
- int error;
char *link;
-
- ASSERT(dentry);
- ASSERT(nd);
+ int error = -ENOMEM;
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
- if (!link) {
- nd_set_link(nd, ERR_PTR(-ENOMEM));
- return NULL;
- }
-
- uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
- if (!uio) {
- kfree(link);
- nd_set_link(nd, ERR_PTR(-ENOMEM));
- return NULL;
- }
-
- vp = vn_from_inode(dentry->d_inode);
-
- iov.iov_base = link;
- iov.iov_len = MAXPATHLEN;
+ if (!link)
+ goto out_err;
- uio->uio_iov = &iov;
- uio->uio_offset = 0;
- uio->uio_segflg = UIO_SYSSPACE;
- uio->uio_resid = MAXPATHLEN;
- uio->uio_iovcnt = 1;
-
- error = bhv_vop_readlink(vp, uio, 0, NULL);
- if (unlikely(error)) {
- kfree(link);
- link = ERR_PTR(-error);
- } else {
- link[MAXPATHLEN - uio->uio_resid] = '\0';
- }
- kfree(uio);
+ error = -xfs_readlink(XFS_I(dentry->d_inode), link);
+ if (unlikely(error))
+ goto out_kfree;
nd_set_link(nd, link);
return NULL;
+
+ out_kfree:
+ kfree(link);
+ out_err:
+ nd_set_link(nd, ERR_PTR(error));
+ return NULL;
}
STATIC void
int mode,
struct nameidata *nd)
{
- return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL);
+ return -xfs_access(XFS_I(inode), mode << 6, NULL);
}
#else
#define xfs_vn_permission NULL
struct kstat *stat)
{
struct inode *inode = dentry->d_inode;
- bhv_vnode_t *vp = vn_from_inode(inode);
bhv_vattr_t vattr = { .va_mask = XFS_AT_STAT };
int error;
- error = bhv_vop_getattr(vp, &vattr, ATTR_LAZY, NULL);
+ error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY);
if (likely(!error)) {
stat->size = i_size_read(inode);
stat->dev = inode->i_sb->s_dev;
{
struct inode *inode = dentry->d_inode;
unsigned int ia_valid = attr->ia_valid;
- bhv_vnode_t *vp = vn_from_inode(inode);
bhv_vattr_t vattr = { 0 };
int flags = 0;
int error;
flags |= ATTR_NONBLOCK;
#endif
- error = bhv_vop_setattr(vp, &vattr, flags, NULL);
+ error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
if (likely(!error))
- __vn_revalidate(vp, &vattr);
+ __vn_revalidate(vn_from_inode(inode), &vattr);
return -error;
}
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_iomap.h"
+ #include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/writeback.h>
loff_t pos, /* offset in file */
size_t count) /* size of data to zero */
{
- unsigned bytes;
struct page *page;
struct address_space *mapping;
int status;
mapping = ip->i_mapping;
do {
- unsigned long index, offset;
+ unsigned offset, bytes;
+ void *fsdata;
offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
- index = pos >> PAGE_CACHE_SHIFT;
bytes = PAGE_CACHE_SIZE - offset;
if (bytes > count)
bytes = count;
- status = -ENOMEM;
- page = grab_cache_page(mapping, index);
- if (!page)
- break;
-
- status = mapping->a_ops->prepare_write(NULL, page, offset,
- offset + bytes);
+ status = pagecache_write_begin(NULL, mapping, pos, bytes,
+ AOP_FLAG_UNINTERRUPTIBLE,
+ &page, &fsdata);
if (status)
- goto unlock;
+ break;
zero_user_page(page, offset, bytes, KM_USER0);
- status = mapping->a_ops->commit_write(NULL, page, offset,
- offset + bytes);
- if (!status) {
- pos += bytes;
- count -= bytes;
- }
-
-unlock:
- unlock_page(page);
- page_cache_release(page);
- if (status)
- break;
+ status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
+ page, fsdata);
+ WARN_ON(status <= 0); /* can't return less than zero! */
+ pos += bytes;
+ count -= bytes;
+ status = 0;
} while (count);
return (-status);
ssize_t /* bytes read, or (-) error */
xfs_read(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
struct kiocb *iocb,
const struct iovec *iovp,
unsigned int segs,
loff_t *offset,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
+ bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
size_t size = 0;
ssize_t ret = 0;
xfs_fsize_t n;
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- bhv_vnode_t *vp;
unsigned long seg;
- ip = XFS_BHVTOI(bdp);
- vp = BHV_TO_VNODE(bdp);
- mp = ip->i_mount;
XFS_STATS_INC(xs_read_calls);
mutex_lock(&inode->i_mutex);
xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
- !(ioflags & IO_INVIS)) {
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_READ;
int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
- ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
- BHV_TO_VNODE(bdp), *offset, size,
+ ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *offset, size,
dmflags, &locktype);
if (ret) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
if (unlikely(ioflags & IO_ISDIRECT)) {
if (VN_CACHED(vp))
- ret = bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
- -1, FI_REMAPF_LOCKED);
+ ret = xfs_flushinval_pages(ip,
+ ctooff(offtoct(*offset)),
+ -1, FI_REMAPF_LOCKED);
mutex_unlock(&inode->i_mutex);
if (ret) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
ssize_t
xfs_splice_read(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
struct file *infilp,
loff_t *ppos,
struct pipe_inode_info *pipe,
size_t count,
int flags,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
ssize_t ret;
xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
- (!(ioflags & IO_INVIS))) {
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_READ;
int error;
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
- *ppos, count,
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *ppos, count,
FILP_DELAY_FLAG(infilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
ssize_t
xfs_splice_write(
- bhv_desc_t *bdp,
+ xfs_inode_t *ip,
struct pipe_inode_info *pipe,
struct file *outfilp,
loff_t *ppos,
size_t count,
int flags,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
xfs_iocore_t *io = &ip->i_iocore;
ssize_t ret;
xfs_ilock(ip, XFS_IOLOCK_EXCL);
- if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
- (!(ioflags & IO_INVIS))) {
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_WRITE;
int error;
- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
- *ppos, count,
+ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, *ppos, count,
FILP_DELAY_FLAG(outfilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
ssize_t /* bytes written, or (-) error */
xfs_write(
- bhv_desc_t *bdp,
+ struct xfs_inode *xip,
struct kiocb *iocb,
const struct iovec *iovp,
unsigned int nsegs,
loff_t *offset,
- int ioflags,
- cred_t *credp)
+ int ioflags)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
+ bhv_vnode_t *vp = XFS_ITOV(xip);
unsigned long segs = nsegs;
- xfs_inode_t *xip;
xfs_mount_t *mp;
ssize_t ret = 0, error = 0;
xfs_fsize_t isize, new_size;
xfs_iocore_t *io;
- bhv_vnode_t *vp;
int iolock;
int eventsent = 0;
bhv_vrwlock_t locktype;
XFS_STATS_INC(xs_write_calls);
- vp = BHV_TO_VNODE(bdp);
- xip = XFS_BHVTOI(bdp);
-
error = generic_segment_checks(iovp, &segs, &ocount, VERIFY_READ);
if (error)
return error;
io = &xip->i_iocore;
mp = io->io_mount;
- vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE);
+ xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
goto out_unlock_mutex;
}
- if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
+ if ((DM_EVENT_ENABLED(xip, DM_EVENT_WRITE) &&
!(ioflags & IO_INVIS) && !eventsent)) {
int dmflags = FILP_DELAY_FLAG(file);
*/
if (pos > xip->i_size) {
- error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
+ error = xfs_zero_eof(vp, io, pos, xip->i_size);
if (error) {
xfs_iunlock(xip, XFS_ILOCK_EXCL);
goto out_unlock_internal;
WARN_ON(need_i_mutex == 0);
xfs_inval_cached_trace(io, pos, -1,
ctooff(offtoct(pos)), -1);
- error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
+ error = xfs_flushinval_pages(xip,
+ ctooff(offtoct(pos)),
-1, FI_REMAPF_LOCKED);
if (error)
goto out_unlock_internal;
if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO))
ret = wait_on_sync_kiocb(iocb);
- if ((ret == -ENOSPC) &&
- DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
- !(ioflags & IO_INVIS)) {
-
- xfs_rwunlock(bdp, locktype);
+ if (ret == -ENOSPC &&
+ DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
+ xfs_rwunlock(xip, locktype);
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
0, 0, 0); /* Delay flag intentionally unused */
if (need_i_mutex)
mutex_lock(&inode->i_mutex);
- xfs_rwlock(bdp, locktype);
+ xfs_rwlock(xip, locktype);
if (error)
goto out_unlock_internal;
pos = xip->i_size;
/* Handle various SYNC-type writes */
if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
- error = xfs_write_sync_logforce(mp, xip);
- if (error)
- goto out_unlock_internal;
-
- xfs_rwunlock(bdp, locktype);
+ int error2;
+ xfs_rwunlock(xip, locktype);
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
-
- error = sync_page_range(inode, mapping, pos, ret);
+ error2 = sync_page_range(inode, mapping, pos, ret);
if (!error)
- error = -ret;
+ error = error2;
if (need_i_mutex)
mutex_lock(&inode->i_mutex);
- xfs_rwlock(bdp, locktype);
+ xfs_rwlock(xip, locktype);
+ error2 = xfs_write_sync_logforce(mp, xip);
+ if (!error)
+ error = error2;
}
out_unlock_internal:
xip->i_d.di_size = xip->i_size;
xfs_iunlock(xip, XFS_ILOCK_EXCL);
}
- xfs_rwunlock(bdp, locktype);
+ xfs_rwunlock(xip, locktype);
out_unlock_mutex:
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
int
- xfs_bmap(bhv_desc_t *bdp,
+ xfs_bmap(
+ xfs_inode_t *ip,
xfs_off_t offset,
ssize_t count,
int flags,
xfs_iomap_t *iomapp,
int *niomaps)
{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
xfs_iocore_t *io = &ip->i_iocore;
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
+ #include "xfs_vnodeops.h"
+ #include "xfs_vfsops.h"
#include "xfs_version.h"
#include <linux/namei.h>
inode->i_flags |= S_NOATIME;
else
inode->i_flags &= ~S_NOATIME;
- vp->v_flag &= ~VMODIFIED;
+ xfs_iflags_clear(ip, XFS_IMODIFIED);
}
void
xfs_initialize_vnode(
- bhv_desc_t *bdp,
+ struct xfs_mount *mp,
bhv_vnode_t *vp,
- bhv_desc_t *inode_bhv,
- int unlock)
+ struct xfs_inode *ip)
{
- xfs_inode_t *ip = XFS_BHVTOI(inode_bhv);
struct inode *inode = vn_to_inode(vp);
- if (!inode_bhv->bd_vobj) {
- vp->v_vfsp = bhvtovfs(bdp);
- bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops);
- bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
+ if (!ip->i_vnode) {
+ ip->i_vnode = vp;
+ inode->i_private = ip;
}
/*
* second time once the inode is properly set up, and then we can
* finish our work.
*/
- if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
- xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
+ if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) {
+ xfs_revalidate_inode(mp, vp, ip);
xfs_set_inodeops(inode);
xfs_iflags_clear(ip, XFS_INEW);
STATIC void
xfs_fs_inode_init_once(
- void *vnode,
kmem_zone_t *zonep,
- unsigned long flags)
+ void *vnode)
{
inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
}
struct inode *inode,
int sync)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
int error = 0, flags = FLUSH_INODE;
- if (vp) {
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
- if (sync) {
- filemap_fdatawait(inode->i_mapping);
- flags |= FLUSH_SYNC;
- }
- error = bhv_vop_iflush(vp, flags);
- if (error == EAGAIN)
- error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
+ vn_trace_entry(XFS_I(inode), __FUNCTION__,
+ (inst_t *)__return_address);
+ if (sync) {
+ filemap_fdatawait(inode->i_mapping);
+ flags |= FLUSH_SYNC;
}
+ error = xfs_inode_flush(XFS_I(inode), flags);
+ /*
+ * if we failed to write out the inode then mark
+ * it dirty again so we'll try again later.
+ */
+ if (error)
+ mark_inode_dirty_sync(inode);
+
return -error;
}
xfs_fs_clear_inode(
struct inode *inode)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
-
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-
- XFS_STATS_INC(vn_rele);
- XFS_STATS_INC(vn_remove);
- XFS_STATS_INC(vn_reclaim);
- XFS_STATS_DEC(vn_active);
+ xfs_inode_t *ip = XFS_I(inode);
/*
- * This can happen because xfs_iget_core calls xfs_idestroy if we
+ * ip can be null when xfs_iget_core calls xfs_idestroy if we
* find an inode with di_mode == 0 but without IGET_CREATE set.
*/
- if (VNHEAD(vp))
- bhv_vop_inactive(vp, NULL);
-
- VN_LOCK(vp);
- vp->v_flag &= ~VMODIFIED;
- VN_UNLOCK(vp, 0);
-
- if (VNHEAD(vp))
- if (bhv_vop_reclaim(vp))
- panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp);
-
- ASSERT(VNHEAD(vp) == NULL);
+ if (ip) {
+ vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+
+ XFS_STATS_INC(vn_rele);
+ XFS_STATS_INC(vn_remove);
+ XFS_STATS_INC(vn_reclaim);
+ XFS_STATS_DEC(vn_active);
+
+ xfs_inactive(ip);
+ xfs_iflags_clear(ip, XFS_IMODIFIED);
+ if (xfs_reclaim(ip))
+ panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode);
+ }
- #ifdef XFS_VNODE_TRACE
- ktrace_free(vp->v_trace);
- #endif
+ ASSERT(XFS_I(inode) == NULL);
}
/*
*/
STATIC void
xfs_syncd_queue_work(
- struct bhv_vfs *vfs,
+ struct xfs_mount *mp,
void *data,
- void (*syncer)(bhv_vfs_t *, void *))
+ void (*syncer)(struct xfs_mount *, void *))
{
struct bhv_vfs_sync_work *work;
INIT_LIST_HEAD(&work->w_list);
work->w_syncer = syncer;
work->w_data = data;
- work->w_vfs = vfs;
- spin_lock(&vfs->vfs_sync_lock);
- list_add_tail(&work->w_list, &vfs->vfs_sync_list);
- spin_unlock(&vfs->vfs_sync_lock);
- wake_up_process(vfs->vfs_sync_task);
+ work->w_mount = mp;
+ spin_lock(&mp->m_sync_lock);
+ list_add_tail(&work->w_list, &mp->m_sync_list);
+ spin_unlock(&mp->m_sync_lock);
+ wake_up_process(mp->m_sync_task);
}
/*
*/
STATIC void
xfs_flush_inode_work(
- bhv_vfs_t *vfs,
- void *inode)
+ struct xfs_mount *mp,
+ void *arg)
{
- filemap_flush(((struct inode *)inode)->i_mapping);
- iput((struct inode *)inode);
+ struct inode *inode = arg;
+ filemap_flush(inode->i_mapping);
+ iput(inode);
}
void
xfs_flush_inode(
xfs_inode_t *ip)
{
- struct inode *inode = vn_to_inode(XFS_ITOV(ip));
- struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
+ struct inode *inode = ip->i_vnode;
igrab(inode);
- xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
+ xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
delay(msecs_to_jiffies(500));
}
*/
STATIC void
xfs_flush_device_work(
- bhv_vfs_t *vfs,
- void *inode)
+ struct xfs_mount *mp,
+ void *arg)
{
- sync_blockdev(vfs->vfs_super->s_bdev);
- iput((struct inode *)inode);
+ struct inode *inode = arg;
+ sync_blockdev(mp->m_super->s_bdev);
+ iput(inode);
}
void
xfs_inode_t *ip)
{
struct inode *inode = vn_to_inode(XFS_ITOV(ip));
- struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
igrab(inode);
- xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
+ xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
delay(msecs_to_jiffies(500));
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
}
STATIC void
- vfs_sync_worker(
- bhv_vfs_t *vfsp,
+ xfs_sync_worker(
+ struct xfs_mount *mp,
void *unused)
{
int error;
- if (!(vfsp->vfs_flag & VFS_RDONLY))
- error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
- SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER,
- NULL);
- vfsp->vfs_sync_seq++;
- wake_up(&vfsp->vfs_wait_single_sync_task);
+ if (!(mp->m_flags & XFS_MOUNT_RDONLY))
+ error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR |
+ SYNC_REFCACHE | SYNC_SUPER);
+ mp->m_sync_seq++;
+ wake_up(&mp->m_wait_single_sync_task);
}
STATIC int
xfssyncd(
void *arg)
{
+ struct xfs_mount *mp = arg;
long timeleft;
- bhv_vfs_t *vfsp = (bhv_vfs_t *) arg;
bhv_vfs_sync_work_t *work, *n;
LIST_HEAD (tmp);
timeleft = schedule_timeout_interruptible(timeleft);
/* swsusp */
try_to_freeze();
- if (kthread_should_stop() && list_empty(&vfsp->vfs_sync_list))
+ if (kthread_should_stop() && list_empty(&mp->m_sync_list))
break;
- spin_lock(&vfsp->vfs_sync_lock);
+ spin_lock(&mp->m_sync_lock);
/*
* We can get woken by laptop mode, to do a sync -
* that's the (only!) case where the list would be
* empty with time remaining.
*/
- if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
+ if (!timeleft || list_empty(&mp->m_sync_list)) {
if (!timeleft)
timeleft = xfs_syncd_centisecs *
msecs_to_jiffies(10);
- INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
- list_add_tail(&vfsp->vfs_sync_work.w_list,
- &vfsp->vfs_sync_list);
+ INIT_LIST_HEAD(&mp->m_sync_work.w_list);
+ list_add_tail(&mp->m_sync_work.w_list,
+ &mp->m_sync_list);
}
- list_for_each_entry_safe(work, n, &vfsp->vfs_sync_list, w_list)
+ list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
list_move(&work->w_list, &tmp);
- spin_unlock(&vfsp->vfs_sync_lock);
+ spin_unlock(&mp->m_sync_lock);
list_for_each_entry_safe(work, n, &tmp, w_list) {
- (*work->w_syncer)(vfsp, work->w_data);
+ (*work->w_syncer)(mp, work->w_data);
list_del(&work->w_list);
- if (work == &vfsp->vfs_sync_work)
+ if (work == &mp->m_sync_work)
continue;
kmem_free(work, sizeof(struct bhv_vfs_sync_work));
}
return 0;
}
- STATIC int
- xfs_fs_start_syncd(
- bhv_vfs_t *vfsp)
- {
- vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
- vfsp->vfs_sync_work.w_vfs = vfsp;
- vfsp->vfs_sync_task = kthread_run(xfssyncd, vfsp, "xfssyncd");
- if (IS_ERR(vfsp->vfs_sync_task))
- return -PTR_ERR(vfsp->vfs_sync_task);
- return 0;
- }
-
- STATIC void
- xfs_fs_stop_syncd(
- bhv_vfs_t *vfsp)
- {
- kthread_stop(vfsp->vfs_sync_task);
- }
-
STATIC void
xfs_fs_put_super(
struct super_block *sb)
{
- bhv_vfs_t *vfsp = vfs_from_sb(sb);
+ struct xfs_mount *mp = XFS_M(sb);
int error;
- xfs_fs_stop_syncd(vfsp);
- bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL);
- error = bhv_vfs_unmount(vfsp, 0, NULL);
- if (error) {
+ kthread_stop(mp->m_sync_task);
+
+ xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI);
+ error = xfs_unmount(mp, 0, NULL);
+ if (error)
printk("XFS: unmount got error=%d\n", error);
- printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp);
- } else {
- vfs_deallocate(vfsp);
- }
}
STATIC void
struct super_block *sb)
{
if (!(sb->s_flags & MS_RDONLY))
- bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL);
+ xfs_sync(XFS_M(sb), SYNC_FSDATA);
sb->s_dirt = 0;
}
struct super_block *sb,
int wait)
{
- bhv_vfs_t *vfsp = vfs_from_sb(sb);
+ struct xfs_mount *mp = XFS_M(sb);
int error;
int flags;
- if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
+ /*
+ * Treat a sync operation like a freeze. This is to work
+ * around a race in sync_inodes() which works in two phases
+ * - an asynchronous flush, which can write out an inode
+ * without waiting for file size updates to complete, and a
+ * synchronous flush, which wont do anything because the
+ * async flush removed the inode's dirty flag. Also
+ * sync_inodes() will not see any files that just have
+ * outstanding transactions to be flushed because we don't
+ * dirty the Linux inode until after the transaction I/O
+ * completes.
+ */
+ if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
/*
* First stage of freeze - no more writers will make progress
* now we are here, so we flush delwri and delalloc buffers
*/
flags = SYNC_DATA_QUIESCE;
} else
- flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
+ flags = SYNC_FSDATA;
- error = bhv_vfs_sync(vfsp, flags, NULL);
+ error = xfs_sync(mp, flags);
sb->s_dirt = 0;
if (unlikely(laptop_mode)) {
- int prev_sync_seq = vfsp->vfs_sync_seq;
+ int prev_sync_seq = mp->m_sync_seq;
/*
* The disk must be active because we're syncing.
* We schedule xfssyncd now (now that the disk is
* active) instead of later (when it might not be).
*/
- wake_up_process(vfsp->vfs_sync_task);
+ wake_up_process(mp->m_sync_task);
/*
* We have to wait for the sync iteration to complete.
* If we don't, the disk activity caused by the sync
* will come after the sync is completed, and that
* triggers another sync from laptop mode.
*/
- wait_event(vfsp->vfs_wait_single_sync_task,
- vfsp->vfs_sync_seq != prev_sync_seq);
+ wait_event(mp->m_wait_single_sync_task,
+ mp->m_sync_seq != prev_sync_seq);
}
return -error;
struct dentry *dentry,
struct kstatfs *statp)
{
- return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp,
+ return -xfs_statvfs(XFS_M(dentry->d_sb), statp,
vn_from_inode(dentry->d_inode));
}
int *flags,
char *options)
{
- bhv_vfs_t *vfsp = vfs_from_sb(sb);
+ struct xfs_mount *mp = XFS_M(sb);
struct xfs_mount_args *args = xfs_args_allocate(sb, 0);
int error;
- error = bhv_vfs_parseargs(vfsp, options, args, 1);
+ error = xfs_parseargs(mp, options, args, 1);
if (!error)
- error = bhv_vfs_mntupdate(vfsp, flags, args);
+ error = xfs_mntupdate(mp, flags, args);
kmem_free(args, sizeof(*args));
return -error;
}
xfs_fs_lockfs(
struct super_block *sb)
{
- bhv_vfs_freeze(vfs_from_sb(sb));
+ xfs_freeze(XFS_M(sb));
}
STATIC int
struct seq_file *m,
struct vfsmount *mnt)
{
- return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m);
+ return -xfs_showargs(XFS_M(mnt->mnt_sb), m);
}
STATIC int
struct super_block *sb,
int type)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL);
+ return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL);
}
STATIC int
struct super_block *sb,
struct fs_quota_stat *fqs)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
+ return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
}
STATIC int
unsigned int flags,
int op)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags);
+ return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags);
}
STATIC int
qid_t id,
struct fs_disk_quota *fdq)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb),
+ return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XGETQUOTA :
((type == GRPQUOTA) ? Q_XGETGQUOTA :
Q_XGETPQUOTA), id, (caddr_t)fdq);
qid_t id,
struct fs_disk_quota *fdq)
{
- return -bhv_vfs_quotactl(vfs_from_sb(sb),
+ return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XSETQLIM :
((type == GRPQUOTA) ? Q_XSETGQLIM :
Q_XSETPQLIM), id, (caddr_t)fdq);
void *data,
int silent)
{
- struct bhv_vnode *rootvp;
- struct bhv_vfs *vfsp = vfs_allocate(sb);
+ struct inode *rootvp;
+ struct xfs_mount *mp = NULL;
struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
struct kstatfs statvfs;
int error;
- bhv_insert_all_vfsops(vfsp);
+ mp = xfs_mount_init();
- error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0);
- if (error) {
- bhv_remove_all_vfsops(vfsp, 1);
+ INIT_LIST_HEAD(&mp->m_sync_list);
+ spin_lock_init(&mp->m_sync_lock);
+ init_waitqueue_head(&mp->m_wait_single_sync_task);
+
+ mp->m_super = sb;
+ sb->s_fs_info = mp;
+
+ if (sb->s_flags & MS_RDONLY)
+ mp->m_flags |= XFS_MOUNT_RDONLY;
+
+ error = xfs_parseargs(mp, (char *)data, args, 0);
+ if (error)
goto fail_vfsop;
- }
sb_min_blocksize(sb, BBSIZE);
sb->s_export_op = &xfs_export_operations;
sb->s_qcop = &xfs_quotactl_operations;
sb->s_op = &xfs_super_operations;
- error = bhv_vfs_mount(vfsp, args, NULL);
- if (error) {
- bhv_remove_all_vfsops(vfsp, 1);
+ error = xfs_mount(mp, args, NULL);
+ if (error)
goto fail_vfsop;
- }
- error = bhv_vfs_statvfs(vfsp, &statvfs, NULL);
+ error = xfs_statvfs(mp, &statvfs, NULL);
if (error)
goto fail_unmount;
sb->s_time_gran = 1;
set_posix_acl_flag(sb);
- error = bhv_vfs_root(vfsp, &rootvp);
+ error = xfs_root(mp, &rootvp);
if (error)
goto fail_unmount;
error = EINVAL;
goto fail_vnrele;
}
- if ((error = xfs_fs_start_syncd(vfsp)))
+
+ mp->m_sync_work.w_syncer = xfs_sync_worker;
+ mp->m_sync_work.w_mount = mp;
+ mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
+ if (IS_ERR(mp->m_sync_task)) {
+ error = -PTR_ERR(mp->m_sync_task);
goto fail_vnrele;
- vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address);
+ }
+
+ vn_trace_exit(XFS_I(sb->s_root->d_inode), __FUNCTION__,
+ (inst_t *)__return_address);
kmem_free(args, sizeof(*args));
return 0;
}
fail_unmount:
- bhv_vfs_unmount(vfsp, 0, NULL);
+ xfs_unmount(mp, 0, NULL);
fail_vfsop:
- vfs_deallocate(vfsp);
kmem_free(args, sizeof(*args));
return -error;
}
init_xfs_fs( void )
{
int error;
- struct sysinfo si;
static char message[] __initdata = KERN_INFO \
XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n";
printk(message);
- si_meminfo(&si);
- xfs_physmem = si.totalram;
-
ktrace_init(64);
error = xfs_init_zones();