aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iops.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-14 03:16:35 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-14 03:16:35 -0500
commit7e1a1e9378018aeea2c7e8a3dd2ceb1db1523b0b (patch)
treee322fc5b10e2252f974cec0216f31356719a0a53 /fs/xfs/xfs_iops.c
parentfcd7476f9e03a36e709e0807198d47a826cc4e3a (diff)
parent359d992bcd398273637cd9edde10afca953783c4 (diff)
Merge tag 'xfs-for-linus-v3.13-rc1' of git://oss.sgi.com/xfs/xfs
Pull xfs update from Ben Myers: "For 3.13-rc1 we have an eclectic assortment of bugfixes, cleanups, and refactoring. Bugfixes that stand out are the fix for the AGF/AGI deadlock, incore extent list fixes, verifier fixes for v4 superblocks and growfs, and memory leaks. There are some asserts, warnings, and strings that were cleaned up. There was further rearrangement of code to make libxfs and the kernel sync up more easily, differences between v2 and v3 directory code were abstracted using an ops vector, xfs_inactive was reworked, and the preallocation/hole punching code was refactored. - simplify kmem_zone_zalloc - add traces for AGF/AGI read ops - add additional AIL traces - fix xfs_remove AGF vs AGI deadlock - fix the extent count of new incore extent page in the indirection array - don't fail bad secondary superblocks verification on v4 filesystems due to unzeroed bits after v4 fields - fix possible NULL dereference in xlog_verify_iclog - remove redundant assert in xfs_dir2_leafn_split - prevent stack overflows from page cache allocation - fix some sparse warnings - fix directory block format verifier to check the leaf entry count - abstract the differences in dir2/dir3 via an ops vector - continue process of reorganization to make libxfs/kernel code merges easier - refactor the preallocation and hole punching code - fix for growfs and verifiers - remove unnecessary scary corruption error when probing non-xfs filesystems - remove extra newlines from strings passed to printk - prevent deadlock trying to cover an active log - rework xfs_inactive() - add the inode directory type support to XFS_IOC_FSGEOM - cleanup (remove) usage of is_bad_inode - fix miscalculation in xfs_iext_realloc_direct which results in oversized direct extent list - remove unnecessary count arg to xfs_iomap_write_allocate - fix memory leak in xlog_recover_add_to_trans - check superblock instead of block magic to determine if dtype field is present - fix lockdep annotation due to project quotas - fix regression in xfs_node_toosmall which can lead to incorrect directory btree node collapse - make log recovery verify filesystem uuid of recovering blocks - fix XFS_IOC_FREE_EOFBLOCKS definition - remove invalid assert in xfs_inode_free - fix for AIL lock regression" * tag 'xfs-for-linus-v3.13-rc1' of git://oss.sgi.com/xfs/xfs: (49 commits) xfs: simplify kmem_{zone_}zalloc xfs: add tracepoints to AGF/AGI read operations xfs: trace AIL manipulations xfs: xfs_remove deadlocks due to inverted AGF vs AGI lock ordering xfs: fix the extent count when allocating an new indirection array entry xfs: be more forgiving of a v4 secondary sb w/ junk in v5 fields xfs: fix possible NULL dereference in xlog_verify_iclog xfs:xfs_dir2_node.c: pointer use before check for null xfs: prevent stack overflows from page cache allocation xfs: fix static and extern sparse warnings xfs: validity check the directory block leaf entry count xfs: make dir2 ftype offset pointers explicit xfs: convert directory vector functions to constants xfs: convert directory vector functions to constants xfs: vectorise encoding/decoding directory headers xfs: vectorise DA btree operations xfs: vectorise directory leaf operations xfs: vectorise directory data operations part 2 xfs: vectorise directory data operations xfs: vectorise remaining shortform dir2 ops ...
Diffstat (limited to 'fs/xfs/xfs_iops.c')
-rw-r--r--fs/xfs/xfs_iops.c70
1 files changed, 40 insertions, 30 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 2b8952d9199b..27e0e544e963 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -17,32 +17,28 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_shared.h"
20#include "xfs_format.h" 21#include "xfs_format.h"
21#include "xfs_acl.h" 22#include "xfs_log_format.h"
22#include "xfs_log.h" 23#include "xfs_trans_resv.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_alloc.h"
27#include "xfs_quota.h"
28#include "xfs_mount.h" 26#include "xfs_mount.h"
29#include "xfs_bmap_btree.h" 27#include "xfs_da_format.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 28#include "xfs_inode.h"
32#include "xfs_bmap.h" 29#include "xfs_bmap.h"
33#include "xfs_bmap_util.h" 30#include "xfs_bmap_util.h"
34#include "xfs_rtalloc.h" 31#include "xfs_acl.h"
32#include "xfs_quota.h"
35#include "xfs_error.h" 33#include "xfs_error.h"
36#include "xfs_itable.h"
37#include "xfs_attr.h" 34#include "xfs_attr.h"
38#include "xfs_buf_item.h" 35#include "xfs_trans.h"
39#include "xfs_inode_item.h"
40#include "xfs_trace.h" 36#include "xfs_trace.h"
41#include "xfs_icache.h" 37#include "xfs_icache.h"
42#include "xfs_symlink.h" 38#include "xfs_symlink.h"
43#include "xfs_da_btree.h" 39#include "xfs_da_btree.h"
44#include "xfs_dir2_format.h"
45#include "xfs_dir2_priv.h" 40#include "xfs_dir2_priv.h"
41#include "xfs_dinode.h"
46 42
47#include <linux/capability.h> 43#include <linux/capability.h>
48#include <linux/xattr.h> 44#include <linux/xattr.h>
@@ -709,8 +705,7 @@ out_dqrele:
709int 705int
710xfs_setattr_size( 706xfs_setattr_size(
711 struct xfs_inode *ip, 707 struct xfs_inode *ip,
712 struct iattr *iattr, 708 struct iattr *iattr)
713 int flags)
714{ 709{
715 struct xfs_mount *mp = ip->i_mount; 710 struct xfs_mount *mp = ip->i_mount;
716 struct inode *inode = VFS_I(ip); 711 struct inode *inode = VFS_I(ip);
@@ -733,15 +728,11 @@ xfs_setattr_size(
733 if (error) 728 if (error)
734 return XFS_ERROR(error); 729 return XFS_ERROR(error);
735 730
731 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
736 ASSERT(S_ISREG(ip->i_d.di_mode)); 732 ASSERT(S_ISREG(ip->i_d.di_mode));
737 ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| 733 ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
738 ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); 734 ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
739 735
740 if (!(flags & XFS_ATTR_NOLOCK)) {
741 lock_flags |= XFS_IOLOCK_EXCL;
742 xfs_ilock(ip, lock_flags);
743 }
744
745 oldsize = inode->i_size; 736 oldsize = inode->i_size;
746 newsize = iattr->ia_size; 737 newsize = iattr->ia_size;
747 738
@@ -750,12 +741,11 @@ xfs_setattr_size(
750 */ 741 */
751 if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) { 742 if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
752 if (!(mask & (ATTR_CTIME|ATTR_MTIME))) 743 if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
753 goto out_unlock; 744 return 0;
754 745
755 /* 746 /*
756 * Use the regular setattr path to update the timestamps. 747 * Use the regular setattr path to update the timestamps.
757 */ 748 */
758 xfs_iunlock(ip, lock_flags);
759 iattr->ia_valid &= ~ATTR_SIZE; 749 iattr->ia_valid &= ~ATTR_SIZE;
760 return xfs_setattr_nonsize(ip, iattr, 0); 750 return xfs_setattr_nonsize(ip, iattr, 0);
761 } 751 }
@@ -765,7 +755,7 @@ xfs_setattr_size(
765 */ 755 */
766 error = xfs_qm_dqattach(ip, 0); 756 error = xfs_qm_dqattach(ip, 0);
767 if (error) 757 if (error)
768 goto out_unlock; 758 return error;
769 759
770 /* 760 /*
771 * Now we can make the changes. Before we join the inode to the 761 * Now we can make the changes. Before we join the inode to the
@@ -783,7 +773,7 @@ xfs_setattr_size(
783 */ 773 */
784 error = xfs_zero_eof(ip, newsize, oldsize); 774 error = xfs_zero_eof(ip, newsize, oldsize);
785 if (error) 775 if (error)
786 goto out_unlock; 776 return error;
787 } 777 }
788 778
789 /* 779 /*
@@ -802,7 +792,7 @@ xfs_setattr_size(
802 error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping, 792 error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
803 ip->i_d.di_size, newsize); 793 ip->i_d.di_size, newsize);
804 if (error) 794 if (error)
805 goto out_unlock; 795 return error;
806 } 796 }
807 797
808 /* 798 /*
@@ -812,7 +802,7 @@ xfs_setattr_size(
812 802
813 error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks); 803 error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks);
814 if (error) 804 if (error)
815 goto out_unlock; 805 return error;
816 806
817 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); 807 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
818 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); 808 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
@@ -916,12 +906,21 @@ out_trans_cancel:
916 906
917STATIC int 907STATIC int
918xfs_vn_setattr( 908xfs_vn_setattr(
919 struct dentry *dentry, 909 struct dentry *dentry,
920 struct iattr *iattr) 910 struct iattr *iattr)
921{ 911{
922 if (iattr->ia_valid & ATTR_SIZE) 912 struct xfs_inode *ip = XFS_I(dentry->d_inode);
923 return -xfs_setattr_size(XFS_I(dentry->d_inode), iattr, 0); 913 int error;
924 return -xfs_setattr_nonsize(XFS_I(dentry->d_inode), iattr, 0); 914
915 if (iattr->ia_valid & ATTR_SIZE) {
916 xfs_ilock(ip, XFS_IOLOCK_EXCL);
917 error = xfs_setattr_size(ip, iattr);
918 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
919 } else {
920 error = xfs_setattr_nonsize(ip, iattr, 0);
921 }
922
923 return -error;
925} 924}
926 925
927STATIC int 926STATIC int
@@ -1169,6 +1168,7 @@ xfs_setup_inode(
1169 struct xfs_inode *ip) 1168 struct xfs_inode *ip)
1170{ 1169{
1171 struct inode *inode = &ip->i_vnode; 1170 struct inode *inode = &ip->i_vnode;
1171 gfp_t gfp_mask;
1172 1172
1173 inode->i_ino = ip->i_ino; 1173 inode->i_ino = ip->i_ino;
1174 inode->i_state = I_NEW; 1174 inode->i_state = I_NEW;
@@ -1204,6 +1204,7 @@ xfs_setup_inode(
1204 inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; 1204 inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
1205 xfs_diflags_to_iflags(inode, ip); 1205 xfs_diflags_to_iflags(inode, ip);
1206 1206
1207 ip->d_ops = ip->i_mount->m_nondir_inode_ops;
1207 switch (inode->i_mode & S_IFMT) { 1208 switch (inode->i_mode & S_IFMT) {
1208 case S_IFREG: 1209 case S_IFREG:
1209 inode->i_op = &xfs_inode_operations; 1210 inode->i_op = &xfs_inode_operations;
@@ -1216,6 +1217,7 @@ xfs_setup_inode(
1216 else 1217 else
1217 inode->i_op = &xfs_dir_inode_operations; 1218 inode->i_op = &xfs_dir_inode_operations;
1218 inode->i_fop = &xfs_dir_file_operations; 1219 inode->i_fop = &xfs_dir_file_operations;
1220 ip->d_ops = ip->i_mount->m_dir_inode_ops;
1219 break; 1221 break;
1220 case S_IFLNK: 1222 case S_IFLNK:
1221 inode->i_op = &xfs_symlink_inode_operations; 1223 inode->i_op = &xfs_symlink_inode_operations;
@@ -1229,6 +1231,14 @@ xfs_setup_inode(
1229 } 1231 }
1230 1232
1231 /* 1233 /*
1234 * Ensure all page cache allocations are done from GFP_NOFS context to
1235 * prevent direct reclaim recursion back into the filesystem and blowing
1236 * stacks or deadlocking.
1237 */
1238 gfp_mask = mapping_gfp_mask(inode->i_mapping);
1239 mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS)));
1240
1241 /*
1232 * If there is no attribute fork no ACL can exist on this inode, 1242 * If there is no attribute fork no ACL can exist on this inode,
1233 * and it can't have any file capabilities attached to it either. 1243 * and it can't have any file capabilities attached to it either.
1234 */ 1244 */