aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_iops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c170
1 files changed, 136 insertions, 34 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 5e8bb7f71b5a..cc4abd3daa49 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -52,6 +52,7 @@
52#include <linux/xattr.h> 52#include <linux/xattr.h>
53#include <linux/namei.h> 53#include <linux/namei.h>
54#include <linux/security.h> 54#include <linux/security.h>
55#include <linux/falloc.h>
55 56
56/* 57/*
57 * Bring the atime in the XFS inode uptodate. 58 * Bring the atime in the XFS inode uptodate.
@@ -71,6 +72,22 @@ xfs_synchronize_atime(
71} 72}
72 73
73/* 74/*
75 * If the linux inode exists, mark it dirty.
76 * Used when commiting a dirty inode into a transaction so that
77 * the inode will get written back by the linux code
78 */
79void
80xfs_mark_inode_dirty_sync(
81 xfs_inode_t *ip)
82{
83 bhv_vnode_t *vp;
84
85 vp = XFS_ITOV_NULL(ip);
86 if (vp)
87 mark_inode_dirty_sync(vn_to_inode(vp));
88}
89
90/*
74 * Change the requested timestamp in the given inode. 91 * Change the requested timestamp in the given inode.
75 * We don't lock across timestamp updates, and we don't log them but 92 * We don't lock across timestamp updates, and we don't log them but
76 * we do record the fact that there is dirty information in core. 93 * we do record the fact that there is dirty information in core.
@@ -184,10 +201,6 @@ xfs_validate_fields(
184 struct xfs_inode *ip = XFS_I(inode); 201 struct xfs_inode *ip = XFS_I(inode);
185 loff_t size; 202 loff_t size;
186 203
187 inode->i_nlink = ip->i_d.di_nlink;
188 inode->i_blocks =
189 XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks +
190 ip->i_delayed_blks);
191 /* we're under i_sem so i_size can't change under us */ 204 /* we're under i_sem so i_size can't change under us */
192 size = XFS_ISIZE(ip); 205 size = XFS_ISIZE(ip);
193 if (i_size_read(inode) != size) 206 if (i_size_read(inode) != size)
@@ -542,12 +555,31 @@ xfs_vn_put_link(
542 555
543#ifdef CONFIG_XFS_POSIX_ACL 556#ifdef CONFIG_XFS_POSIX_ACL
544STATIC int 557STATIC int
558xfs_check_acl(
559 struct inode *inode,
560 int mask)
561{
562 struct xfs_inode *ip = XFS_I(inode);
563 int error;
564
565 xfs_itrace_entry(ip);
566
567 if (XFS_IFORK_Q(ip)) {
568 error = xfs_acl_iaccess(ip, mask, NULL);
569 if (error != -1)
570 return -error;
571 }
572
573 return -EAGAIN;
574}
575
576STATIC int
545xfs_vn_permission( 577xfs_vn_permission(
546 struct inode *inode, 578 struct inode *inode,
547 int mode, 579 int mask,
548 struct nameidata *nd) 580 struct nameidata *nd)
549{ 581{
550 return -xfs_access(XFS_I(inode), mode << 6, NULL); 582 return generic_permission(inode, mask, xfs_check_acl);
551} 583}
552#else 584#else
553#define xfs_vn_permission NULL 585#define xfs_vn_permission NULL
@@ -555,33 +587,61 @@ xfs_vn_permission(
555 587
556STATIC int 588STATIC int
557xfs_vn_getattr( 589xfs_vn_getattr(
558 struct vfsmount *mnt, 590 struct vfsmount *mnt,
559 struct dentry *dentry, 591 struct dentry *dentry,
560 struct kstat *stat) 592 struct kstat *stat)
561{ 593{
562 struct inode *inode = dentry->d_inode; 594 struct inode *inode = dentry->d_inode;
563 bhv_vattr_t vattr = { .va_mask = XFS_AT_STAT }; 595 struct xfs_inode *ip = XFS_I(inode);
564 int error; 596 struct xfs_mount *mp = ip->i_mount;
565 597
566 error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY); 598 xfs_itrace_entry(ip);
567 if (likely(!error)) { 599
568 stat->size = i_size_read(inode); 600 if (XFS_FORCED_SHUTDOWN(mp))
569 stat->dev = inode->i_sb->s_dev; 601 return XFS_ERROR(EIO);
570 stat->rdev = (vattr.va_rdev == 0) ? 0 : 602
571 MKDEV(sysv_major(vattr.va_rdev) & 0x1ff, 603 stat->size = XFS_ISIZE(ip);
572 sysv_minor(vattr.va_rdev)); 604 stat->dev = inode->i_sb->s_dev;
573 stat->mode = vattr.va_mode; 605 stat->mode = ip->i_d.di_mode;
574 stat->nlink = vattr.va_nlink; 606 stat->nlink = ip->i_d.di_nlink;
575 stat->uid = vattr.va_uid; 607 stat->uid = ip->i_d.di_uid;
576 stat->gid = vattr.va_gid; 608 stat->gid = ip->i_d.di_gid;
577 stat->ino = vattr.va_nodeid; 609 stat->ino = ip->i_ino;
578 stat->atime = vattr.va_atime; 610#if XFS_BIG_INUMS
579 stat->mtime = vattr.va_mtime; 611 stat->ino += mp->m_inoadd;
580 stat->ctime = vattr.va_ctime; 612#endif
581 stat->blocks = vattr.va_nblocks; 613 stat->atime = inode->i_atime;
582 stat->blksize = vattr.va_blocksize; 614 stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec;
615 stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
616 stat->ctime.tv_sec = ip->i_d.di_ctime.t_sec;
617 stat->ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
618 stat->blocks =
619 XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
620
621
622 switch (inode->i_mode & S_IFMT) {
623 case S_IFBLK:
624 case S_IFCHR:
625 stat->blksize = BLKDEV_IOSIZE;
626 stat->rdev = MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff,
627 sysv_minor(ip->i_df.if_u2.if_rdev));
628 break;
629 default:
630 if (XFS_IS_REALTIME_INODE(ip)) {
631 /*
632 * If the file blocks are being allocated from a
633 * realtime volume, then return the inode's realtime
634 * extent size or the realtime volume's extent size.
635 */
636 stat->blksize =
637 xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
638 } else
639 stat->blksize = xfs_preferred_iosize(mp);
640 stat->rdev = 0;
641 break;
583 } 642 }
584 return -error; 643
644 return 0;
585} 645}
586 646
587STATIC int 647STATIC int
@@ -636,7 +696,7 @@ xfs_vn_setattr(
636 696
637 error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL); 697 error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
638 if (likely(!error)) 698 if (likely(!error))
639 __vn_revalidate(vn_from_inode(inode), &vattr); 699 vn_revalidate(vn_from_inode(inode));
640 return -error; 700 return -error;
641} 701}
642 702
@@ -750,6 +810,47 @@ xfs_vn_removexattr(
750 return namesp->attr_remove(vp, attr, xflags); 810 return namesp->attr_remove(vp, attr, xflags);
751} 811}
752 812
813STATIC long
814xfs_vn_fallocate(
815 struct inode *inode,
816 int mode,
817 loff_t offset,
818 loff_t len)
819{
820 long error;
821 loff_t new_size = 0;
822 xfs_flock64_t bf;
823 xfs_inode_t *ip = XFS_I(inode);
824
825 /* preallocation on directories not yet supported */
826 error = -ENODEV;
827 if (S_ISDIR(inode->i_mode))
828 goto out_error;
829
830 bf.l_whence = 0;
831 bf.l_start = offset;
832 bf.l_len = len;
833
834 xfs_ilock(ip, XFS_IOLOCK_EXCL);
835 error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
836 0, NULL, ATTR_NOLOCK);
837 if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
838 offset + len > i_size_read(inode))
839 new_size = offset + len;
840
841 /* Change file size if needed */
842 if (new_size) {
843 bhv_vattr_t va;
844
845 va.va_mask = XFS_AT_SIZE;
846 va.va_size = new_size;
847 error = xfs_setattr(ip, &va, ATTR_NOLOCK, NULL);
848 }
849
850 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
851out_error:
852 return error;
853}
753 854
754const struct inode_operations xfs_inode_operations = { 855const struct inode_operations xfs_inode_operations = {
755 .permission = xfs_vn_permission, 856 .permission = xfs_vn_permission,
@@ -760,6 +861,7 @@ const struct inode_operations xfs_inode_operations = {
760 .getxattr = xfs_vn_getxattr, 861 .getxattr = xfs_vn_getxattr,
761 .listxattr = xfs_vn_listxattr, 862 .listxattr = xfs_vn_listxattr,
762 .removexattr = xfs_vn_removexattr, 863 .removexattr = xfs_vn_removexattr,
864 .fallocate = xfs_vn_fallocate,
763}; 865};
764 866
765const struct inode_operations xfs_dir_inode_operations = { 867const struct inode_operations xfs_dir_inode_operations = {