diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 170 |
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 | */ | ||
79 | void | ||
80 | xfs_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 |
544 | STATIC int | 557 | STATIC int |
558 | xfs_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 | |||
576 | STATIC int | ||
545 | xfs_vn_permission( | 577 | xfs_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 | ||
556 | STATIC int | 588 | STATIC int |
557 | xfs_vn_getattr( | 589 | xfs_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 | ||
587 | STATIC int | 647 | STATIC 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 | ||
813 | STATIC long | ||
814 | xfs_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); | ||
851 | out_error: | ||
852 | return error; | ||
853 | } | ||
753 | 854 | ||
754 | const struct inode_operations xfs_inode_operations = { | 855 | const 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 | ||
765 | const struct inode_operations xfs_dir_inode_operations = { | 867 | const struct inode_operations xfs_dir_inode_operations = { |