aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/xfs/Makefile8
-rw-r--r--fs/xfs/kmem.c22
-rw-r--r--fs/xfs/kmem.h21
-rw-r--r--fs/xfs/xfs_acl.c8
-rw-r--r--fs/xfs/xfs_ag.h4
-rw-r--r--fs/xfs/xfs_alloc.c19
-rw-r--r--fs/xfs/xfs_alloc.h3
-rw-r--r--fs/xfs/xfs_alloc_btree.c14
-rw-r--r--fs/xfs/xfs_alloc_btree.h35
-rw-r--r--fs/xfs/xfs_aops.c16
-rw-r--r--fs/xfs/xfs_attr.c12
-rw-r--r--fs/xfs/xfs_attr_inactive.c21
-rw-r--r--fs/xfs/xfs_attr_leaf.c29
-rw-r--r--fs/xfs/xfs_attr_leaf.h232
-rw-r--r--fs/xfs/xfs_attr_list.c32
-rw-r--r--fs/xfs/xfs_attr_remote.c14
-rw-r--r--fs/xfs/xfs_attr_remote.h29
-rw-r--r--fs/xfs/xfs_bit.c4
-rw-r--r--fs/xfs/xfs_bmap.c22
-rw-r--r--fs/xfs/xfs_bmap_btree.c13
-rw-r--r--fs/xfs/xfs_bmap_btree.h105
-rw-r--r--fs/xfs/xfs_bmap_util.c293
-rw-r--r--fs/xfs/xfs_bmap_util.h9
-rw-r--r--fs/xfs/xfs_btree.c12
-rw-r--r--fs/xfs/xfs_btree.h79
-rw-r--r--fs/xfs/xfs_buf.c11
-rw-r--r--fs/xfs/xfs_buf_item.c9
-rw-r--r--fs/xfs/xfs_buf_item.h4
-rw-r--r--fs/xfs/xfs_da_btree.c264
-rw-r--r--fs/xfs/xfs_da_btree.h143
-rw-r--r--fs/xfs/xfs_da_format.c907
-rw-r--r--fs/xfs/xfs_da_format.h (renamed from fs/xfs/xfs_dir2_format.h)681
-rw-r--r--fs/xfs/xfs_dir2.c20
-rw-r--r--fs/xfs/xfs_dir2.h106
-rw-r--r--fs/xfs/xfs_dir2_block.c109
-rw-r--r--fs/xfs/xfs_dir2_data.c161
-rw-r--r--fs/xfs/xfs_dir2_leaf.c243
-rw-r--r--fs/xfs/xfs_dir2_node.c351
-rw-r--r--fs/xfs/xfs_dir2_priv.h20
-rw-r--r--fs/xfs/xfs_dir2_readdir.c42
-rw-r--r--fs/xfs/xfs_dir2_sf.c216
-rw-r--r--fs/xfs/xfs_discard.c11
-rw-r--r--fs/xfs/xfs_dquot.c133
-rw-r--r--fs/xfs/xfs_dquot.h2
-rw-r--r--fs/xfs/xfs_dquot_buf.c288
-rw-r--r--fs/xfs/xfs_dquot_item.c14
-rw-r--r--fs/xfs/xfs_error.c11
-rw-r--r--fs/xfs/xfs_export.c12
-rw-r--r--fs/xfs/xfs_extent_busy.c11
-rw-r--r--fs/xfs/xfs_extent_busy.h4
-rw-r--r--fs/xfs/xfs_extfree_item.c8
-rw-r--r--fs/xfs/xfs_file.c92
-rw-r--r--fs/xfs/xfs_filestream.c12
-rw-r--r--fs/xfs/xfs_format.h263
-rw-r--r--fs/xfs/xfs_fs.h4
-rw-r--r--fs/xfs/xfs_fsops.c45
-rw-r--r--fs/xfs/xfs_ialloc.c20
-rw-r--r--fs/xfs/xfs_ialloc.h5
-rw-r--r--fs/xfs/xfs_ialloc_btree.c13
-rw-r--r--fs/xfs/xfs_ialloc_btree.h51
-rw-r--r--fs/xfs/xfs_icache.c20
-rw-r--r--fs/xfs/xfs_icreate_item.c7
-rw-r--r--fs/xfs/xfs_inode.c338
-rw-r--r--fs/xfs/xfs_inode.h6
-rw-r--r--fs/xfs/xfs_inode_buf.c10
-rw-r--r--fs/xfs/xfs_inode_buf.h3
-rw-r--r--fs/xfs/xfs_inode_fork.c40
-rw-r--r--fs/xfs/xfs_inode_fork.h1
-rw-r--r--fs/xfs/xfs_inode_item.c12
-rw-r--r--fs/xfs/xfs_ioctl.c146
-rw-r--r--fs/xfs/xfs_ioctl32.c7
-rw-r--r--fs/xfs/xfs_iomap.c23
-rw-r--r--fs/xfs/xfs_iomap.h8
-rw-r--r--fs/xfs/xfs_iops.c70
-rw-r--r--fs/xfs/xfs_iops.h8
-rw-r--r--fs/xfs/xfs_itable.c15
-rw-r--r--fs/xfs/xfs_log.c75
-rw-r--r--fs/xfs/xfs_log.h10
-rw-r--r--fs/xfs/xfs_log_cil.c26
-rw-r--r--fs/xfs/xfs_log_format.h177
-rw-r--r--fs/xfs/xfs_log_priv.h17
-rw-r--r--fs/xfs/xfs_log_recover.c171
-rw-r--r--fs/xfs/xfs_log_rlimit.c9
-rw-r--r--fs/xfs/xfs_message.c5
-rw-r--r--fs/xfs/xfs_mount.c21
-rw-r--r--fs/xfs/xfs_mount.h3
-rw-r--r--fs/xfs/xfs_qm.c39
-rw-r--r--fs/xfs/xfs_qm.h2
-rw-r--r--fs/xfs/xfs_qm_bhv.c12
-rw-r--r--fs/xfs/xfs_qm_syscalls.c28
-rw-r--r--fs/xfs/xfs_quota.h4
-rw-r--r--fs/xfs/xfs_quota_defs.h4
-rw-r--r--fs/xfs/xfs_quotaops.c5
-rw-r--r--fs/xfs/xfs_rtalloc.c1552
-rw-r--r--fs/xfs/xfs_rtalloc.h24
-rw-r--r--fs/xfs/xfs_rtbitmap.c974
-rw-r--r--fs/xfs/xfs_sb.c46
-rw-r--r--fs/xfs/xfs_sb.h3
-rw-r--r--fs/xfs/xfs_shared.h244
-rw-r--r--fs/xfs/xfs_super.c38
-rw-r--r--fs/xfs/xfs_symlink.c102
-rw-r--r--fs/xfs/xfs_symlink.h2
-rw-r--r--fs/xfs/xfs_symlink_remote.c6
-rw-r--r--fs/xfs/xfs_trace.c16
-rw-r--r--fs/xfs/xfs_trace.h84
-rw-r--r--fs/xfs/xfs_trans.c23
-rw-r--r--fs/xfs/xfs_trans.h20
-rw-r--r--fs/xfs/xfs_trans_ail.c10
-rw-r--r--fs/xfs/xfs_trans_buf.c12
-rw-r--r--fs/xfs/xfs_trans_dquot.c15
-rw-r--r--fs/xfs/xfs_trans_extfree.c7
-rw-r--r--fs/xfs/xfs_trans_inode.c13
-rw-r--r--fs/xfs/xfs_trans_priv.h1
-rw-r--r--fs/xfs/xfs_trans_resv.c18
-rw-r--r--fs/xfs/xfs_vnode.h8
-rw-r--r--fs/xfs/xfs_xattr.c8
116 files changed, 5209 insertions, 4681 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 0719e4db93f2..c21f43506661 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -66,12 +66,14 @@ xfs-y += xfs_alloc.o \
66 xfs_bmap_btree.o \ 66 xfs_bmap_btree.o \
67 xfs_btree.o \ 67 xfs_btree.o \
68 xfs_da_btree.o \ 68 xfs_da_btree.o \
69 xfs_da_format.o \
69 xfs_dir2.o \ 70 xfs_dir2.o \
70 xfs_dir2_block.o \ 71 xfs_dir2_block.o \
71 xfs_dir2_data.o \ 72 xfs_dir2_data.o \
72 xfs_dir2_leaf.o \ 73 xfs_dir2_leaf.o \
73 xfs_dir2_node.o \ 74 xfs_dir2_node.o \
74 xfs_dir2_sf.o \ 75 xfs_dir2_sf.o \
76 xfs_dquot_buf.o \
75 xfs_ialloc.o \ 77 xfs_ialloc.o \
76 xfs_ialloc_btree.o \ 78 xfs_ialloc_btree.o \
77 xfs_icreate_item.o \ 79 xfs_icreate_item.o \
@@ -103,7 +105,11 @@ xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \
103 xfs_qm_bhv.o \ 105 xfs_qm_bhv.o \
104 xfs_qm.o \ 106 xfs_qm.o \
105 xfs_quotaops.o 107 xfs_quotaops.o
106xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o 108
109# xfs_rtbitmap is shared with libxfs
110xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o \
111 xfs_rtbitmap.o
112
107xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o 113xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
108xfs-$(CONFIG_PROC_FS) += xfs_stats.o 114xfs-$(CONFIG_PROC_FS) += xfs_stats.o
109xfs-$(CONFIG_SYSCTL) += xfs_sysctl.o 115xfs-$(CONFIG_SYSCTL) += xfs_sysctl.o
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c
index a02cfb9e3bce..66a36befc5c0 100644
--- a/fs/xfs/kmem.c
+++ b/fs/xfs/kmem.c
@@ -63,17 +63,6 @@ kmem_alloc(size_t size, xfs_km_flags_t flags)
63} 63}
64 64
65void * 65void *
66kmem_zalloc(size_t size, xfs_km_flags_t flags)
67{
68 void *ptr;
69
70 ptr = kmem_alloc(size, flags);
71 if (ptr)
72 memset((char *)ptr, 0, (int)size);
73 return ptr;
74}
75
76void *
77kmem_zalloc_large(size_t size, xfs_km_flags_t flags) 66kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
78{ 67{
79 void *ptr; 68 void *ptr;
@@ -128,14 +117,3 @@ kmem_zone_alloc(kmem_zone_t *zone, xfs_km_flags_t flags)
128 congestion_wait(BLK_RW_ASYNC, HZ/50); 117 congestion_wait(BLK_RW_ASYNC, HZ/50);
129 } while (1); 118 } while (1);
130} 119}
131
132void *
133kmem_zone_zalloc(kmem_zone_t *zone, xfs_km_flags_t flags)
134{
135 void *ptr;
136
137 ptr = kmem_zone_alloc(zone, flags);
138 if (ptr)
139 memset((char *)ptr, 0, kmem_cache_size(zone));
140 return ptr;
141}
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
index 3a7371cab508..64db0e53edea 100644
--- a/fs/xfs/kmem.h
+++ b/fs/xfs/kmem.h
@@ -32,6 +32,7 @@ typedef unsigned __bitwise xfs_km_flags_t;
32#define KM_NOSLEEP ((__force xfs_km_flags_t)0x0002u) 32#define KM_NOSLEEP ((__force xfs_km_flags_t)0x0002u)
33#define KM_NOFS ((__force xfs_km_flags_t)0x0004u) 33#define KM_NOFS ((__force xfs_km_flags_t)0x0004u)
34#define KM_MAYFAIL ((__force xfs_km_flags_t)0x0008u) 34#define KM_MAYFAIL ((__force xfs_km_flags_t)0x0008u)
35#define KM_ZERO ((__force xfs_km_flags_t)0x0010u)
35 36
36/* 37/*
37 * We use a special process flag to avoid recursive callbacks into 38 * We use a special process flag to avoid recursive callbacks into
@@ -43,7 +44,7 @@ kmem_flags_convert(xfs_km_flags_t flags)
43{ 44{
44 gfp_t lflags; 45 gfp_t lflags;
45 46
46 BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL)); 47 BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL|KM_ZERO));
47 48
48 if (flags & KM_NOSLEEP) { 49 if (flags & KM_NOSLEEP) {
49 lflags = GFP_ATOMIC | __GFP_NOWARN; 50 lflags = GFP_ATOMIC | __GFP_NOWARN;
@@ -52,11 +53,14 @@ kmem_flags_convert(xfs_km_flags_t flags)
52 if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS)) 53 if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
53 lflags &= ~__GFP_FS; 54 lflags &= ~__GFP_FS;
54 } 55 }
56
57 if (flags & KM_ZERO)
58 lflags |= __GFP_ZERO;
59
55 return lflags; 60 return lflags;
56} 61}
57 62
58extern void *kmem_alloc(size_t, xfs_km_flags_t); 63extern void *kmem_alloc(size_t, xfs_km_flags_t);
59extern void *kmem_zalloc(size_t, xfs_km_flags_t);
60extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t); 64extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t);
61extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); 65extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t);
62extern void kmem_free(const void *); 66extern void kmem_free(const void *);
@@ -64,6 +68,12 @@ extern void kmem_free(const void *);
64 68
65extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); 69extern void *kmem_zalloc_greedy(size_t *, size_t, size_t);
66 70
71static inline void *
72kmem_zalloc(size_t size, xfs_km_flags_t flags)
73{
74 return kmem_alloc(size, flags | KM_ZERO);
75}
76
67/* 77/*
68 * Zone interfaces 78 * Zone interfaces
69 */ 79 */
@@ -102,6 +112,11 @@ kmem_zone_destroy(kmem_zone_t *zone)
102} 112}
103 113
104extern void *kmem_zone_alloc(kmem_zone_t *, xfs_km_flags_t); 114extern void *kmem_zone_alloc(kmem_zone_t *, xfs_km_flags_t);
105extern void *kmem_zone_zalloc(kmem_zone_t *, xfs_km_flags_t); 115
116static inline void *
117kmem_zone_zalloc(kmem_zone_t *zone, xfs_km_flags_t flags)
118{
119 return kmem_zone_alloc(zone, flags | KM_ZERO);
120}
106 121
107#endif /* __XFS_SUPPORT_KMEM_H__ */ 122#endif /* __XFS_SUPPORT_KMEM_H__ */
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 0e2f37efedd0..370eb3e121d1 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -16,15 +16,15 @@
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_format.h"
19#include "xfs_log_format.h" 20#include "xfs_log_format.h"
20#include "xfs_trans_resv.h" 21#include "xfs_trans_resv.h"
21#include "xfs_acl.h"
22#include "xfs_attr.h"
23#include "xfs_bmap_btree.h"
24#include "xfs_inode.h"
25#include "xfs_ag.h" 22#include "xfs_ag.h"
26#include "xfs_sb.h" 23#include "xfs_sb.h"
27#include "xfs_mount.h" 24#include "xfs_mount.h"
25#include "xfs_inode.h"
26#include "xfs_acl.h"
27#include "xfs_attr.h"
28#include "xfs_trace.h" 28#include "xfs_trace.h"
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/xattr.h> 30#include <linux/xattr.h>
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 1cb740afd674..3fc109819c34 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -128,8 +128,6 @@ typedef struct xfs_agf {
128extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, 128extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
129 xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); 129 xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
130 130
131extern const struct xfs_buf_ops xfs_agf_buf_ops;
132
133/* 131/*
134 * Size of the unlinked inode hash table in the agi. 132 * Size of the unlinked inode hash table in the agi.
135 */ 133 */
@@ -191,8 +189,6 @@ typedef struct xfs_agi {
191extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, 189extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
192 xfs_agnumber_t agno, struct xfs_buf **bpp); 190 xfs_agnumber_t agno, struct xfs_buf **bpp);
193 191
194extern const struct xfs_buf_ops xfs_agi_buf_ops;
195
196/* 192/*
197 * The third a.g. block contains the a.g. freelist, an array 193 * The third a.g. block contains the a.g. freelist, an array
198 * of block pointers to blocks owned by the allocation btree code. 194 * of block pointers to blocks owned by the allocation btree code.
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 5a1393f5e020..9eab2dfdcbb5 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -17,25 +17,25 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_format.h"
21#include "xfs_log_format.h"
22#include "xfs_shared.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_alloc_btree.h"
29#include "xfs_ialloc_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 28#include "xfs_inode.h"
32#include "xfs_btree.h" 29#include "xfs_btree.h"
30#include "xfs_alloc_btree.h"
33#include "xfs_alloc.h" 31#include "xfs_alloc.h"
34#include "xfs_extent_busy.h" 32#include "xfs_extent_busy.h"
35#include "xfs_error.h" 33#include "xfs_error.h"
36#include "xfs_cksum.h" 34#include "xfs_cksum.h"
37#include "xfs_trace.h" 35#include "xfs_trace.h"
36#include "xfs_trans.h"
38#include "xfs_buf_item.h" 37#include "xfs_buf_item.h"
38#include "xfs_log.h"
39 39
40struct workqueue_struct *xfs_alloc_wq; 40struct workqueue_struct *xfs_alloc_wq;
41 41
@@ -2294,6 +2294,8 @@ xfs_read_agf(
2294{ 2294{
2295 int error; 2295 int error;
2296 2296
2297 trace_xfs_read_agf(mp, agno);
2298
2297 ASSERT(agno != NULLAGNUMBER); 2299 ASSERT(agno != NULLAGNUMBER);
2298 error = xfs_trans_read_buf( 2300 error = xfs_trans_read_buf(
2299 mp, tp, mp->m_ddev_targp, 2301 mp, tp, mp->m_ddev_targp,
@@ -2324,8 +2326,9 @@ xfs_alloc_read_agf(
2324 struct xfs_perag *pag; /* per allocation group data */ 2326 struct xfs_perag *pag; /* per allocation group data */
2325 int error; 2327 int error;
2326 2328
2327 ASSERT(agno != NULLAGNUMBER); 2329 trace_xfs_alloc_read_agf(mp, agno);
2328 2330
2331 ASSERT(agno != NULLAGNUMBER);
2329 error = xfs_read_agf(mp, tp, agno, 2332 error = xfs_read_agf(mp, tp, agno,
2330 (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, 2333 (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0,
2331 bpp); 2334 bpp);
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index 99d0a6101558..feacb061bab7 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -231,7 +231,4 @@ xfs_alloc_get_rec(
231 xfs_extlen_t *len, /* output: length of extent */ 231 xfs_extlen_t *len, /* output: length of extent */
232 int *stat); /* output: success/failure */ 232 int *stat); /* output: success/failure */
233 233
234extern const struct xfs_buf_ops xfs_agf_buf_ops;
235extern const struct xfs_buf_ops xfs_agfl_buf_ops;
236
237#endif /* __XFS_ALLOC_H__ */ 234#endif /* __XFS_ALLOC_H__ */
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index cafc90251d19..13085429e523 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -17,23 +17,21 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log.h" 21#include "xfs_format.h"
22#include "xfs_trans.h" 22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_mount.h" 26#include "xfs_mount.h"
26#include "xfs_bmap_btree.h"
27#include "xfs_alloc_btree.h"
28#include "xfs_ialloc_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h"
31#include "xfs_btree.h" 27#include "xfs_btree.h"
28#include "xfs_alloc_btree.h"
32#include "xfs_alloc.h" 29#include "xfs_alloc.h"
33#include "xfs_extent_busy.h" 30#include "xfs_extent_busy.h"
34#include "xfs_error.h" 31#include "xfs_error.h"
35#include "xfs_trace.h" 32#include "xfs_trace.h"
36#include "xfs_cksum.h" 33#include "xfs_cksum.h"
34#include "xfs_trans.h"
37 35
38 36
39STATIC struct xfs_btree_cur * 37STATIC struct xfs_btree_cur *
diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h
index e3a3f7424192..45e189e7e81c 100644
--- a/fs/xfs/xfs_alloc_btree.h
+++ b/fs/xfs/xfs_alloc_btree.h
@@ -27,39 +27,6 @@ struct xfs_btree_cur;
27struct xfs_mount; 27struct xfs_mount;
28 28
29/* 29/*
30 * There are two on-disk btrees, one sorted by blockno and one sorted
31 * by blockcount and blockno. All blocks look the same to make the code
32 * simpler; if we have time later, we'll make the optimizations.
33 */
34#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */
35#define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */
36#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */
37#define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */
38
39/*
40 * Data record/key structure
41 */
42typedef struct xfs_alloc_rec {
43 __be32 ar_startblock; /* starting block number */
44 __be32 ar_blockcount; /* count of free blocks */
45} xfs_alloc_rec_t, xfs_alloc_key_t;
46
47typedef struct xfs_alloc_rec_incore {
48 xfs_agblock_t ar_startblock; /* starting block number */
49 xfs_extlen_t ar_blockcount; /* count of free blocks */
50} xfs_alloc_rec_incore_t;
51
52/* btree pointer type */
53typedef __be32 xfs_alloc_ptr_t;
54
55/*
56 * Block numbers in the AG:
57 * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
58 */
59#define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1))
60#define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1))
61
62/*
63 * Btree block header size depends on a superblock flag. 30 * Btree block header size depends on a superblock flag.
64 */ 31 */
65#define XFS_ALLOC_BLOCK_LEN(mp) \ 32#define XFS_ALLOC_BLOCK_LEN(mp) \
@@ -95,6 +62,4 @@ extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
95 xfs_agnumber_t, xfs_btnum_t); 62 xfs_agnumber_t, xfs_btnum_t);
96extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); 63extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int);
97 64
98extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
99
100#endif /* __XFS_ALLOC_BTREE_H__ */ 65#endif /* __XFS_ALLOC_BTREE_H__ */
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index e51e581454e9..71c8c9d2b882 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -16,14 +16,15 @@
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_log.h" 19#include "xfs_shared.h"
20#include "xfs_format.h"
21#include "xfs_log_format.h"
22#include "xfs_trans_resv.h"
20#include "xfs_sb.h" 23#include "xfs_sb.h"
21#include "xfs_ag.h" 24#include "xfs_ag.h"
22#include "xfs_trans.h"
23#include "xfs_mount.h" 25#include "xfs_mount.h"
24#include "xfs_bmap_btree.h"
25#include "xfs_dinode.h"
26#include "xfs_inode.h" 26#include "xfs_inode.h"
27#include "xfs_trans.h"
27#include "xfs_inode_item.h" 28#include "xfs_inode_item.h"
28#include "xfs_alloc.h" 29#include "xfs_alloc.h"
29#include "xfs_error.h" 30#include "xfs_error.h"
@@ -31,6 +32,8 @@
31#include "xfs_trace.h" 32#include "xfs_trace.h"
32#include "xfs_bmap.h" 33#include "xfs_bmap.h"
33#include "xfs_bmap_util.h" 34#include "xfs_bmap_util.h"
35#include "xfs_bmap_btree.h"
36#include "xfs_dinode.h"
34#include <linux/aio.h> 37#include <linux/aio.h>
35#include <linux/gfp.h> 38#include <linux/gfp.h>
36#include <linux/mpage.h> 39#include <linux/mpage.h>
@@ -333,7 +336,7 @@ xfs_map_blocks(
333 336
334 if (type == XFS_IO_DELALLOC && 337 if (type == XFS_IO_DELALLOC &&
335 (!nimaps || isnullstartblock(imap->br_startblock))) { 338 (!nimaps || isnullstartblock(imap->br_startblock))) {
336 error = xfs_iomap_write_allocate(ip, offset, count, imap); 339 error = xfs_iomap_write_allocate(ip, offset, imap);
337 if (!error) 340 if (!error)
338 trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); 341 trace_xfs_map_blocks_alloc(ip, offset, count, type, imap);
339 return -XFS_ERROR(error); 342 return -XFS_ERROR(error);
@@ -1569,8 +1572,7 @@ xfs_vm_write_begin(
1569 1572
1570 ASSERT(len <= PAGE_CACHE_SIZE); 1573 ASSERT(len <= PAGE_CACHE_SIZE);
1571 1574
1572 page = grab_cache_page_write_begin(mapping, index, 1575 page = grab_cache_page_write_begin(mapping, index, flags);
1573 flags | AOP_FLAG_NOFS);
1574 if (!page) 1576 if (!page)
1575 return -ENOMEM; 1577 return -ENOMEM;
1576 1578
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index ddcf2267ffa6..b86127072ac3 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -17,23 +17,24 @@
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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_trans_priv.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_mount.h" 27#include "xfs_mount.h"
28#include "xfs_da_format.h"
28#include "xfs_da_btree.h" 29#include "xfs_da_btree.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_attr_sf.h" 30#include "xfs_attr_sf.h"
31#include "xfs_dinode.h"
32#include "xfs_inode.h" 31#include "xfs_inode.h"
33#include "xfs_alloc.h" 32#include "xfs_alloc.h"
33#include "xfs_trans.h"
34#include "xfs_inode_item.h" 34#include "xfs_inode_item.h"
35#include "xfs_bmap.h" 35#include "xfs_bmap.h"
36#include "xfs_bmap_util.h" 36#include "xfs_bmap_util.h"
37#include "xfs_bmap_btree.h"
37#include "xfs_attr.h" 38#include "xfs_attr.h"
38#include "xfs_attr_leaf.h" 39#include "xfs_attr_leaf.h"
39#include "xfs_attr_remote.h" 40#include "xfs_attr_remote.h"
@@ -41,6 +42,7 @@
41#include "xfs_quota.h" 42#include "xfs_quota.h"
42#include "xfs_trans_space.h" 43#include "xfs_trans_space.h"
43#include "xfs_trace.h" 44#include "xfs_trace.h"
45#include "xfs_dinode.h"
44 46
45/* 47/*
46 * xfs_attr.c 48 * xfs_attr.c
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index bb24b07cbedb..09480c57f069 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -18,22 +18,20 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_shared.h"
21#include "xfs_format.h" 22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 25#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_da_format.h"
28#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
29#include "xfs_bmap_btree.h" 31#include "xfs_inode.h"
30#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_alloc.h" 32#include "xfs_alloc.h"
33#include "xfs_btree.h"
34#include "xfs_attr_remote.h" 33#include "xfs_attr_remote.h"
35#include "xfs_dinode.h" 34#include "xfs_trans.h"
36#include "xfs_inode.h"
37#include "xfs_inode_item.h" 35#include "xfs_inode_item.h"
38#include "xfs_bmap.h" 36#include "xfs_bmap.h"
39#include "xfs_attr.h" 37#include "xfs_attr.h"
@@ -41,7 +39,8 @@
41#include "xfs_error.h" 39#include "xfs_error.h"
42#include "xfs_quota.h" 40#include "xfs_quota.h"
43#include "xfs_trace.h" 41#include "xfs_trace.h"
44#include "xfs_trans_priv.h" 42#include "xfs_dinode.h"
43#include "xfs_dir2.h"
45 44
46/* 45/*
47 * Look at all the extents for this logical region, 46 * Look at all the extents for this logical region,
@@ -232,13 +231,13 @@ xfs_attr3_node_inactive(
232 } 231 }
233 232
234 node = bp->b_addr; 233 node = bp->b_addr;
235 xfs_da3_node_hdr_from_disk(&ichdr, node); 234 dp->d_ops->node_hdr_from_disk(&ichdr, node);
236 parent_blkno = bp->b_bn; 235 parent_blkno = bp->b_bn;
237 if (!ichdr.count) { 236 if (!ichdr.count) {
238 xfs_trans_brelse(*trans, bp); 237 xfs_trans_brelse(*trans, bp);
239 return 0; 238 return 0;
240 } 239 }
241 btree = xfs_da3_node_tree_p(node); 240 btree = dp->d_ops->node_tree_p(node);
242 child_fsb = be32_to_cpu(btree[0].before); 241 child_fsb = be32_to_cpu(btree[0].before);
243 xfs_trans_brelse(*trans, bp); /* no locks for later trans */ 242 xfs_trans_brelse(*trans, bp); /* no locks for later trans */
244 243
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 86db20a9cc02..7b126f46a2f9 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -18,32 +18,31 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_shared.h"
22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 25#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_trans_priv.h"
26#include "xfs_sb.h" 26#include "xfs_sb.h"
27#include "xfs_ag.h" 27#include "xfs_ag.h"
28#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_da_format.h"
29#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_alloc.h"
34#include "xfs_btree.h"
35#include "xfs_attr_sf.h"
36#include "xfs_attr_remote.h"
37#include "xfs_dinode.h"
38#include "xfs_inode.h" 31#include "xfs_inode.h"
32#include "xfs_trans.h"
39#include "xfs_inode_item.h" 33#include "xfs_inode_item.h"
34#include "xfs_bmap_btree.h"
40#include "xfs_bmap.h" 35#include "xfs_bmap.h"
36#include "xfs_attr_sf.h"
37#include "xfs_attr_remote.h"
41#include "xfs_attr.h" 38#include "xfs_attr.h"
42#include "xfs_attr_leaf.h" 39#include "xfs_attr_leaf.h"
43#include "xfs_error.h" 40#include "xfs_error.h"
44#include "xfs_trace.h" 41#include "xfs_trace.h"
45#include "xfs_buf_item.h" 42#include "xfs_buf_item.h"
46#include "xfs_cksum.h" 43#include "xfs_cksum.h"
44#include "xfs_dinode.h"
45#include "xfs_dir2.h"
47 46
48 47
49/* 48/*
@@ -918,8 +917,8 @@ xfs_attr3_leaf_to_node(
918 if (error) 917 if (error)
919 goto out; 918 goto out;
920 node = bp1->b_addr; 919 node = bp1->b_addr;
921 xfs_da3_node_hdr_from_disk(&icnodehdr, node); 920 dp->d_ops->node_hdr_from_disk(&icnodehdr, node);
922 btree = xfs_da3_node_tree_p(node); 921 btree = dp->d_ops->node_tree_p(node);
923 922
924 leaf = bp2->b_addr; 923 leaf = bp2->b_addr;
925 xfs_attr3_leaf_hdr_from_disk(&icleafhdr, leaf); 924 xfs_attr3_leaf_hdr_from_disk(&icleafhdr, leaf);
@@ -929,7 +928,7 @@ xfs_attr3_leaf_to_node(
929 btree[0].hashval = entries[icleafhdr.count - 1].hashval; 928 btree[0].hashval = entries[icleafhdr.count - 1].hashval;
930 btree[0].before = cpu_to_be32(blkno); 929 btree[0].before = cpu_to_be32(blkno);
931 icnodehdr.count = 1; 930 icnodehdr.count = 1;
932 xfs_da3_node_hdr_to_disk(node, &icnodehdr); 931 dp->d_ops->node_hdr_to_disk(node, &icnodehdr);
933 xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(mp) - 1); 932 xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(mp) - 1);
934 error = 0; 933 error = 0;
935out: 934out:
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index c1022138c7e6..3ec5ec0b8678 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -19,16 +19,6 @@
19#ifndef __XFS_ATTR_LEAF_H__ 19#ifndef __XFS_ATTR_LEAF_H__
20#define __XFS_ATTR_LEAF_H__ 20#define __XFS_ATTR_LEAF_H__
21 21
22/*
23 * Attribute storage layout, internal structure, access macros, etc.
24 *
25 * Attribute lists are structured around Btrees where all the data
26 * elements are in the leaf nodes. Attribute names are hashed into an int,
27 * then that int is used as the index into the Btree. Since the hashval
28 * of an attribute name may not be unique, we may have duplicate keys. The
29 * internal links in the Btree are logical block offsets into the file.
30 */
31
32struct attrlist; 22struct attrlist;
33struct attrlist_cursor_kern; 23struct attrlist_cursor_kern;
34struct xfs_attr_list_context; 24struct xfs_attr_list_context;
@@ -38,226 +28,6 @@ struct xfs_da_state_blk;
38struct xfs_inode; 28struct xfs_inode;
39struct xfs_trans; 29struct xfs_trans;
40 30
41/*========================================================================
42 * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
43 *========================================================================*/
44
45/*
46 * This is the structure of the leaf nodes in the Btree.
47 *
48 * Struct leaf_entry's are packed from the top. Name/values grow from the
49 * bottom but are not packed. The freemap contains run-length-encoded entries
50 * for the free bytes after the leaf_entry's, but only the N largest such,
51 * smaller runs are dropped. When the freemap doesn't show enough space
52 * for an allocation, we compact the name/value area and try again. If we
53 * still don't have enough space, then we have to split the block. The
54 * name/value structs (both local and remote versions) must be 32bit aligned.
55 *
56 * Since we have duplicate hash keys, for each key that matches, compare
57 * the actual name string. The root and intermediate node search always
58 * takes the first-in-the-block key match found, so we should only have
59 * to work "forw"ard. If none matches, continue with the "forw"ard leaf
60 * nodes until the hash key changes or the attribute name is found.
61 *
62 * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
63 * the leaf_entry. The namespaces are independent only because we also look
64 * at the namespace bit when we are looking for a matching attribute name.
65 *
66 * We also store an "incomplete" bit in the leaf_entry. It shows that an
67 * attribute is in the middle of being created and should not be shown to
68 * the user if we crash during the time that the bit is set. We clear the
69 * bit when we have finished setting up the attribute. We do this because
70 * we cannot create some large attributes inside a single transaction, and we
71 * need some indication that we weren't finished if we crash in the middle.
72 */
73#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
74
75typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
76 __be16 base; /* base of free region */
77 __be16 size; /* length of free region */
78} xfs_attr_leaf_map_t;
79
80typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
81 xfs_da_blkinfo_t info; /* block type, links, etc. */
82 __be16 count; /* count of active leaf_entry's */
83 __be16 usedbytes; /* num bytes of names/values stored */
84 __be16 firstused; /* first used byte in name area */
85 __u8 holes; /* != 0 if blk needs compaction */
86 __u8 pad1;
87 xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
88 /* N largest free regions */
89} xfs_attr_leaf_hdr_t;
90
91typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
92 __be32 hashval; /* hash value of name */
93 __be16 nameidx; /* index into buffer of name/value */
94 __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
95 __u8 pad2; /* unused pad byte */
96} xfs_attr_leaf_entry_t;
97
98typedef struct xfs_attr_leaf_name_local {
99 __be16 valuelen; /* number of bytes in value */
100 __u8 namelen; /* length of name bytes */
101 __u8 nameval[1]; /* name/value bytes */
102} xfs_attr_leaf_name_local_t;
103
104typedef struct xfs_attr_leaf_name_remote {
105 __be32 valueblk; /* block number of value bytes */
106 __be32 valuelen; /* number of bytes in value */
107 __u8 namelen; /* length of name bytes */
108 __u8 name[1]; /* name bytes */
109} xfs_attr_leaf_name_remote_t;
110
111typedef struct xfs_attr_leafblock {
112 xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
113 xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
114 xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
115 xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
116} xfs_attr_leafblock_t;
117
118/*
119 * CRC enabled leaf structures. Called "version 3" structures to match the
120 * version number of the directory and dablk structures for this feature, and
121 * attr2 is already taken by the variable inode attribute fork size feature.
122 */
123struct xfs_attr3_leaf_hdr {
124 struct xfs_da3_blkinfo info;
125 __be16 count;
126 __be16 usedbytes;
127 __be16 firstused;
128 __u8 holes;
129 __u8 pad1;
130 struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE];
131 __be32 pad2; /* 64 bit alignment */
132};
133
134#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc))
135
136struct xfs_attr3_leafblock {
137 struct xfs_attr3_leaf_hdr hdr;
138 struct xfs_attr_leaf_entry entries[1];
139
140 /*
141 * The rest of the block contains the following structures after the
142 * leaf entries, growing from the bottom up. The variables are never
143 * referenced, the locations accessed purely from helper functions.
144 *
145 * struct xfs_attr_leaf_name_local
146 * struct xfs_attr_leaf_name_remote
147 */
148};
149
150/*
151 * incore, neutral version of the attribute leaf header
152 */
153struct xfs_attr3_icleaf_hdr {
154 __uint32_t forw;
155 __uint32_t back;
156 __uint16_t magic;
157 __uint16_t count;
158 __uint16_t usedbytes;
159 __uint16_t firstused;
160 __u8 holes;
161 struct {
162 __uint16_t base;
163 __uint16_t size;
164 } freemap[XFS_ATTR_LEAF_MAPSIZE];
165};
166
167/*
168 * Flags used in the leaf_entry[i].flags field.
169 * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
170 * on the system call, they are "or"ed together for various operations.
171 */
172#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
173#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
174#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
175#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
176#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
177#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
178#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
179#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
180
181/*
182 * Conversion macros for converting namespace bits from argument flags
183 * to ondisk flags.
184 */
185#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
186#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
187#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
188#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
189#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
190 ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
191#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
192 ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
193
194/*
195 * Alignment for namelist and valuelist entries (since they are mixed
196 * there can be only one alignment value)
197 */
198#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))
199
200static inline int
201xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp)
202{
203 if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
204 return sizeof(struct xfs_attr3_leaf_hdr);
205 return sizeof(struct xfs_attr_leaf_hdr);
206}
207
208static inline struct xfs_attr_leaf_entry *
209xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp)
210{
211 if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
212 return &((struct xfs_attr3_leafblock *)leafp)->entries[0];
213 return &leafp->entries[0];
214}
215
216/*
217 * Cast typed pointers for "local" and "remote" name/value structs.
218 */
219static inline char *
220xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
221{
222 struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp);
223
224 return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)];
225}
226
227static inline xfs_attr_leaf_name_remote_t *
228xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
229{
230 return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx);
231}
232
233static inline xfs_attr_leaf_name_local_t *
234xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
235{
236 return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx);
237}
238
239/*
240 * Calculate total bytes used (including trailing pad for alignment) for
241 * a "local" name/value structure, a "remote" name/value structure, and
242 * a pointer which might be either.
243 */
244static inline int xfs_attr_leaf_entsize_remote(int nlen)
245{
246 return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
247 XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
248}
249
250static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
251{
252 return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
253 XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
254}
255
256static inline int xfs_attr_leaf_entsize_local_max(int bsize)
257{
258 return (((bsize) >> 1) + ((bsize) >> 2));
259}
260
261/* 31/*
262 * Used to keep a list of "remote value" extents when unlinking an inode. 32 * Used to keep a list of "remote value" extents when unlinking an inode.
263 */ 33 */
@@ -336,6 +106,4 @@ void xfs_attr3_leaf_hdr_from_disk(struct xfs_attr3_icleaf_hdr *to,
336void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to, 106void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to,
337 struct xfs_attr3_icleaf_hdr *from); 107 struct xfs_attr3_icleaf_hdr *from);
338 108
339extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
340
341#endif /* __XFS_ATTR_LEAF_H__ */ 109#endif /* __XFS_ATTR_LEAF_H__ */
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index cbc80d485177..2d174b128153 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -18,31 +18,29 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 24#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_mount.h" 27#include "xfs_mount.h"
28#include "xfs_da_format.h"
28#include "xfs_da_btree.h" 29#include "xfs_da_btree.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_alloc.h"
33#include "xfs_btree.h"
34#include "xfs_attr_sf.h"
35#include "xfs_attr_remote.h"
36#include "xfs_dinode.h"
37#include "xfs_inode.h" 30#include "xfs_inode.h"
31#include "xfs_trans.h"
38#include "xfs_inode_item.h" 32#include "xfs_inode_item.h"
39#include "xfs_bmap.h" 33#include "xfs_bmap.h"
40#include "xfs_attr.h" 34#include "xfs_attr.h"
35#include "xfs_attr_sf.h"
36#include "xfs_attr_remote.h"
41#include "xfs_attr_leaf.h" 37#include "xfs_attr_leaf.h"
42#include "xfs_error.h" 38#include "xfs_error.h"
43#include "xfs_trace.h" 39#include "xfs_trace.h"
44#include "xfs_buf_item.h" 40#include "xfs_buf_item.h"
45#include "xfs_cksum.h" 41#include "xfs_cksum.h"
42#include "xfs_dinode.h"
43#include "xfs_dir2.h"
46 44
47STATIC int 45STATIC int
48xfs_attr_shortform_compare(const void *a, const void *b) 46xfs_attr_shortform_compare(const void *a, const void *b)
@@ -229,6 +227,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
229 struct xfs_da_node_entry *btree; 227 struct xfs_da_node_entry *btree;
230 int error, i; 228 int error, i;
231 struct xfs_buf *bp; 229 struct xfs_buf *bp;
230 struct xfs_inode *dp = context->dp;
232 231
233 trace_xfs_attr_node_list(context); 232 trace_xfs_attr_node_list(context);
234 233
@@ -242,7 +241,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
242 */ 241 */
243 bp = NULL; 242 bp = NULL;
244 if (cursor->blkno > 0) { 243 if (cursor->blkno > 0) {
245 error = xfs_da3_node_read(NULL, context->dp, cursor->blkno, -1, 244 error = xfs_da3_node_read(NULL, dp, cursor->blkno, -1,
246 &bp, XFS_ATTR_FORK); 245 &bp, XFS_ATTR_FORK);
247 if ((error != 0) && (error != EFSCORRUPTED)) 246 if ((error != 0) && (error != EFSCORRUPTED))
248 return(error); 247 return(error);
@@ -292,7 +291,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
292 for (;;) { 291 for (;;) {
293 __uint16_t magic; 292 __uint16_t magic;
294 293
295 error = xfs_da3_node_read(NULL, context->dp, 294 error = xfs_da3_node_read(NULL, dp,
296 cursor->blkno, -1, &bp, 295 cursor->blkno, -1, &bp,
297 XFS_ATTR_FORK); 296 XFS_ATTR_FORK);
298 if (error) 297 if (error)
@@ -312,8 +311,8 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
312 return XFS_ERROR(EFSCORRUPTED); 311 return XFS_ERROR(EFSCORRUPTED);
313 } 312 }
314 313
315 xfs_da3_node_hdr_from_disk(&nodehdr, node); 314 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
316 btree = xfs_da3_node_tree_p(node); 315 btree = dp->d_ops->node_tree_p(node);
317 for (i = 0; i < nodehdr.count; btree++, i++) { 316 for (i = 0; i < nodehdr.count; btree++, i++) {
318 if (cursor->hashval 317 if (cursor->hashval
319 <= be32_to_cpu(btree->hashval)) { 318 <= be32_to_cpu(btree->hashval)) {
@@ -349,8 +348,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
349 break; 348 break;
350 cursor->blkno = leafhdr.forw; 349 cursor->blkno = leafhdr.forw;
351 xfs_trans_brelse(NULL, bp); 350 xfs_trans_brelse(NULL, bp);
352 error = xfs_attr3_leaf_read(NULL, context->dp, cursor->blkno, -1, 351 error = xfs_attr3_leaf_read(NULL, dp, cursor->blkno, -1, &bp);
353 &bp);
354 if (error) 352 if (error)
355 return error; 353 return error;
356 } 354 }
diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c
index 712a502de619..739e0a52deda 100644
--- a/fs/xfs/xfs_attr_remote.c
+++ b/fs/xfs/xfs_attr_remote.c
@@ -18,20 +18,19 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_shared.h"
22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 25#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_trans_priv.h"
26#include "xfs_sb.h" 26#include "xfs_sb.h"
27#include "xfs_ag.h" 27#include "xfs_ag.h"
28#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_error.h" 29#include "xfs_da_format.h"
30#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
31#include "xfs_bmap_btree.h"
32#include "xfs_dinode.h"
33#include "xfs_inode.h" 31#include "xfs_inode.h"
34#include "xfs_alloc.h" 32#include "xfs_alloc.h"
33#include "xfs_trans.h"
35#include "xfs_inode_item.h" 34#include "xfs_inode_item.h"
36#include "xfs_bmap.h" 35#include "xfs_bmap.h"
37#include "xfs_bmap_util.h" 36#include "xfs_bmap_util.h"
@@ -42,6 +41,7 @@
42#include "xfs_trace.h" 41#include "xfs_trace.h"
43#include "xfs_cksum.h" 42#include "xfs_cksum.h"
44#include "xfs_buf_item.h" 43#include "xfs_buf_item.h"
44#include "xfs_error.h"
45 45
46#define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ 46#define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */
47 47
diff --git a/fs/xfs/xfs_attr_remote.h b/fs/xfs/xfs_attr_remote.h
index 92a8fd7977cc..5a9acfa156d7 100644
--- a/fs/xfs/xfs_attr_remote.h
+++ b/fs/xfs/xfs_attr_remote.h
@@ -18,35 +18,6 @@
18#ifndef __XFS_ATTR_REMOTE_H__ 18#ifndef __XFS_ATTR_REMOTE_H__
19#define __XFS_ATTR_REMOTE_H__ 19#define __XFS_ATTR_REMOTE_H__
20 20
21#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */
22
23/*
24 * There is one of these headers per filesystem block in a remote attribute.
25 * This is done to ensure there is a 1:1 mapping between the attribute value
26 * length and the number of blocks needed to store the attribute. This makes the
27 * verification of a buffer a little more complex, but greatly simplifies the
28 * allocation, reading and writing of these attributes as we don't have to guess
29 * the number of blocks needed to store the attribute data.
30 */
31struct xfs_attr3_rmt_hdr {
32 __be32 rm_magic;
33 __be32 rm_offset;
34 __be32 rm_bytes;
35 __be32 rm_crc;
36 uuid_t rm_uuid;
37 __be64 rm_owner;
38 __be64 rm_blkno;
39 __be64 rm_lsn;
40};
41
42#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc)
43
44#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \
45 ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
46 sizeof(struct xfs_attr3_rmt_hdr) : 0))
47
48extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
49
50int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); 21int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
51 22
52int xfs_attr_rmtval_get(struct xfs_da_args *args); 23int xfs_attr_rmtval_get(struct xfs_da_args *args);
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index 48228848f5ae..0e8885a59646 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -16,10 +16,8 @@
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_log_format.h"
19#include "xfs_bit.h" 20#include "xfs_bit.h"
20#include "xfs_log.h"
21#include "xfs_trans.h"
22#include "xfs_buf_item.h"
23 21
24/* 22/*
25 * XFS bit manipulation routines, used in non-realtime code. 23 * XFS bit manipulation routines, used in non-realtime code.
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index f47e65c30be6..1c02da8bb7df 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -17,39 +17,37 @@
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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h" 25#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_da_format.h"
28#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
29#include "xfs_dir2_format.h"
30#include "xfs_dir2.h" 31#include "xfs_dir2.h"
31#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h"
34#include "xfs_dinode.h"
35#include "xfs_inode.h" 32#include "xfs_inode.h"
36#include "xfs_btree.h" 33#include "xfs_btree.h"
37#include "xfs_mount.h" 34#include "xfs_trans.h"
38#include "xfs_itable.h"
39#include "xfs_inode_item.h" 35#include "xfs_inode_item.h"
40#include "xfs_extfree_item.h" 36#include "xfs_extfree_item.h"
41#include "xfs_alloc.h" 37#include "xfs_alloc.h"
42#include "xfs_bmap.h" 38#include "xfs_bmap.h"
43#include "xfs_bmap_util.h" 39#include "xfs_bmap_util.h"
40#include "xfs_bmap_btree.h"
44#include "xfs_rtalloc.h" 41#include "xfs_rtalloc.h"
45#include "xfs_error.h" 42#include "xfs_error.h"
46#include "xfs_attr_leaf.h"
47#include "xfs_quota.h" 43#include "xfs_quota.h"
48#include "xfs_trans_space.h" 44#include "xfs_trans_space.h"
49#include "xfs_buf_item.h" 45#include "xfs_buf_item.h"
50#include "xfs_filestream.h"
51#include "xfs_trace.h" 46#include "xfs_trace.h"
52#include "xfs_symlink.h" 47#include "xfs_symlink.h"
48#include "xfs_attr_leaf.h"
49#include "xfs_dinode.h"
50#include "xfs_filestream.h"
53 51
54 52
55kmem_zone_t *xfs_bmap_free_item_zone; 53kmem_zone_t *xfs_bmap_free_item_zone;
@@ -1482,7 +1480,7 @@ xfs_bmap_search_extents(
1482 xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, 1480 xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
1483 "Access to block zero in inode %llu " 1481 "Access to block zero in inode %llu "
1484 "start_block: %llx start_off: %llx " 1482 "start_block: %llx start_off: %llx "
1485 "blkcnt: %llx extent-state: %x lastx: %x\n", 1483 "blkcnt: %llx extent-state: %x lastx: %x",
1486 (unsigned long long)ip->i_ino, 1484 (unsigned long long)ip->i_ino,
1487 (unsigned long long)gotp->br_startblock, 1485 (unsigned long long)gotp->br_startblock,
1488 (unsigned long long)gotp->br_startoff, 1486 (unsigned long long)gotp->br_startoff,
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index bb8de8e399c4..706bc3f777cb 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -17,27 +17,26 @@
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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_alloc_btree.h"
29#include "xfs_ialloc_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 28#include "xfs_inode.h"
29#include "xfs_trans.h"
32#include "xfs_inode_item.h" 30#include "xfs_inode_item.h"
33#include "xfs_alloc.h" 31#include "xfs_alloc.h"
34#include "xfs_btree.h" 32#include "xfs_btree.h"
35#include "xfs_itable.h" 33#include "xfs_bmap_btree.h"
36#include "xfs_bmap.h" 34#include "xfs_bmap.h"
37#include "xfs_error.h" 35#include "xfs_error.h"
38#include "xfs_quota.h" 36#include "xfs_quota.h"
39#include "xfs_trace.h" 37#include "xfs_trace.h"
40#include "xfs_cksum.h" 38#include "xfs_cksum.h"
39#include "xfs_dinode.h"
41 40
42/* 41/*
43 * Determine the extent state. 42 * Determine the extent state.
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index e367461a638e..6e42e1e50b89 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -18,9 +18,6 @@
18#ifndef __XFS_BMAP_BTREE_H__ 18#ifndef __XFS_BMAP_BTREE_H__
19#define __XFS_BMAP_BTREE_H__ 19#define __XFS_BMAP_BTREE_H__
20 20
21#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */
22#define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */
23
24struct xfs_btree_cur; 21struct xfs_btree_cur;
25struct xfs_btree_block; 22struct xfs_btree_block;
26struct xfs_mount; 23struct xfs_mount;
@@ -28,85 +25,6 @@ struct xfs_inode;
28struct xfs_trans; 25struct xfs_trans;
29 26
30/* 27/*
31 * Bmap root header, on-disk form only.
32 */
33typedef struct xfs_bmdr_block {
34 __be16 bb_level; /* 0 is a leaf */
35 __be16 bb_numrecs; /* current # of data records */
36} xfs_bmdr_block_t;
37
38/*
39 * Bmap btree record and extent descriptor.
40 * l0:63 is an extent flag (value 1 indicates non-normal).
41 * l0:9-62 are startoff.
42 * l0:0-8 and l1:21-63 are startblock.
43 * l1:0-20 are blockcount.
44 */
45#define BMBT_EXNTFLAG_BITLEN 1
46#define BMBT_STARTOFF_BITLEN 54
47#define BMBT_STARTBLOCK_BITLEN 52
48#define BMBT_BLOCKCOUNT_BITLEN 21
49
50typedef struct xfs_bmbt_rec {
51 __be64 l0, l1;
52} xfs_bmbt_rec_t;
53
54typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
55typedef xfs_bmbt_rec_t xfs_bmdr_rec_t;
56
57typedef struct xfs_bmbt_rec_host {
58 __uint64_t l0, l1;
59} xfs_bmbt_rec_host_t;
60
61/*
62 * Values and macros for delayed-allocation startblock fields.
63 */
64#define STARTBLOCKVALBITS 17
65#define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20)
66#define DSTARTBLOCKMASKBITS (15 + 20)
67#define STARTBLOCKMASK \
68 (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
69#define DSTARTBLOCKMASK \
70 (((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
71
72static inline int isnullstartblock(xfs_fsblock_t x)
73{
74 return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK;
75}
76
77static inline int isnulldstartblock(xfs_dfsbno_t x)
78{
79 return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK;
80}
81
82static inline xfs_fsblock_t nullstartblock(int k)
83{
84 ASSERT(k < (1 << STARTBLOCKVALBITS));
85 return STARTBLOCKMASK | (k);
86}
87
88static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
89{
90 return (xfs_filblks_t)((x) & ~STARTBLOCKMASK);
91}
92
93/*
94 * Possible extent formats.
95 */
96typedef enum {
97 XFS_EXTFMT_NOSTATE = 0,
98 XFS_EXTFMT_HASSTATE
99} xfs_exntfmt_t;
100
101/*
102 * Possible extent states.
103 */
104typedef enum {
105 XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
106 XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
107} xfs_exntst_t;
108
109/*
110 * Extent state and extent format macros. 28 * Extent state and extent format macros.
111 */ 29 */
112#define XFS_EXTFMT_INODE(x) \ 30#define XFS_EXTFMT_INODE(x) \
@@ -115,27 +33,6 @@ typedef enum {
115#define ISUNWRITTEN(x) ((x)->br_state == XFS_EXT_UNWRITTEN) 33#define ISUNWRITTEN(x) ((x)->br_state == XFS_EXT_UNWRITTEN)
116 34
117/* 35/*
118 * Incore version of above.
119 */
120typedef struct xfs_bmbt_irec
121{
122 xfs_fileoff_t br_startoff; /* starting file offset */
123 xfs_fsblock_t br_startblock; /* starting block number */
124 xfs_filblks_t br_blockcount; /* number of blocks */
125 xfs_exntst_t br_state; /* extent state */
126} xfs_bmbt_irec_t;
127
128/*
129 * Key structure for non-leaf levels of the tree.
130 */
131typedef struct xfs_bmbt_key {
132 __be64 br_startoff; /* starting file offset */
133} xfs_bmbt_key_t, xfs_bmdr_key_t;
134
135/* btree pointer type */
136typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
137
138/*
139 * Btree block header size depends on a superblock flag. 36 * Btree block header size depends on a superblock flag.
140 */ 37 */
141#define XFS_BMBT_BLOCK_LEN(mp) \ 38#define XFS_BMBT_BLOCK_LEN(mp) \
@@ -243,6 +140,4 @@ extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip,
243extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, 140extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
244 struct xfs_trans *, struct xfs_inode *, int); 141 struct xfs_trans *, struct xfs_inode *, int);
245 142
246extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
247
248#endif /* __XFS_BMAP_BTREE_H__ */ 143#endif /* __XFS_BMAP_BTREE_H__ */
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 97f952caea74..5887e41c0323 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -18,31 +18,31 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_shared.h"
21#include "xfs_format.h" 22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 25#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_inum.h"
25#include "xfs_trans.h"
26#include "xfs_sb.h" 26#include "xfs_sb.h"
27#include "xfs_ag.h" 27#include "xfs_ag.h"
28#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_da_btree.h" 29#include "xfs_da_format.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_dinode.h"
34#include "xfs_inode.h" 30#include "xfs_inode.h"
35#include "xfs_btree.h" 31#include "xfs_btree.h"
32#include "xfs_trans.h"
36#include "xfs_extfree_item.h" 33#include "xfs_extfree_item.h"
37#include "xfs_alloc.h" 34#include "xfs_alloc.h"
38#include "xfs_bmap.h" 35#include "xfs_bmap.h"
39#include "xfs_bmap_util.h" 36#include "xfs_bmap_util.h"
37#include "xfs_bmap_btree.h"
40#include "xfs_rtalloc.h" 38#include "xfs_rtalloc.h"
41#include "xfs_error.h" 39#include "xfs_error.h"
42#include "xfs_quota.h" 40#include "xfs_quota.h"
43#include "xfs_trans_space.h" 41#include "xfs_trans_space.h"
44#include "xfs_trace.h" 42#include "xfs_trace.h"
45#include "xfs_icache.h" 43#include "xfs_icache.h"
44#include "xfs_log.h"
45#include "xfs_dinode.h"
46 46
47/* Kernel only BMAP related definitions and functions */ 47/* Kernel only BMAP related definitions and functions */
48 48
@@ -965,32 +965,12 @@ xfs_free_eofblocks(
965 return error; 965 return error;
966} 966}
967 967
968/* 968int
969 * xfs_alloc_file_space()
970 * This routine allocates disk space for the given file.
971 *
972 * If alloc_type == 0, this request is for an ALLOCSP type
973 * request which will change the file size. In this case, no
974 * DMAPI event will be generated by the call. A TRUNCATE event
975 * will be generated later by xfs_setattr.
976 *
977 * If alloc_type != 0, this request is for a RESVSP type
978 * request, and a DMAPI DM_EVENT_WRITE will be generated if the
979 * lower block boundary byte address is less than the file's
980 * length.
981 *
982 * RETURNS:
983 * 0 on success
984 * errno on error
985 *
986 */
987STATIC int
988xfs_alloc_file_space( 969xfs_alloc_file_space(
989 xfs_inode_t *ip, 970 struct xfs_inode *ip,
990 xfs_off_t offset, 971 xfs_off_t offset,
991 xfs_off_t len, 972 xfs_off_t len,
992 int alloc_type, 973 int alloc_type)
993 int attr_flags)
994{ 974{
995 xfs_mount_t *mp = ip->i_mount; 975 xfs_mount_t *mp = ip->i_mount;
996 xfs_off_t count; 976 xfs_off_t count;
@@ -1232,24 +1212,11 @@ xfs_zero_remaining_bytes(
1232 return error; 1212 return error;
1233} 1213}
1234 1214
1235/* 1215int
1236 * xfs_free_file_space()
1237 * This routine frees disk space for the given file.
1238 *
1239 * This routine is only called by xfs_change_file_space
1240 * for an UNRESVSP type call.
1241 *
1242 * RETURNS:
1243 * 0 on success
1244 * errno on error
1245 *
1246 */
1247STATIC int
1248xfs_free_file_space( 1216xfs_free_file_space(
1249 xfs_inode_t *ip, 1217 struct xfs_inode *ip,
1250 xfs_off_t offset, 1218 xfs_off_t offset,
1251 xfs_off_t len, 1219 xfs_off_t len)
1252 int attr_flags)
1253{ 1220{
1254 int committed; 1221 int committed;
1255 int done; 1222 int done;
@@ -1267,7 +1234,6 @@ xfs_free_file_space(
1267 int rt; 1234 int rt;
1268 xfs_fileoff_t startoffset_fsb; 1235 xfs_fileoff_t startoffset_fsb;
1269 xfs_trans_t *tp; 1236 xfs_trans_t *tp;
1270 int need_iolock = 1;
1271 1237
1272 mp = ip->i_mount; 1238 mp = ip->i_mount;
1273 1239
@@ -1284,20 +1250,15 @@ xfs_free_file_space(
1284 startoffset_fsb = XFS_B_TO_FSB(mp, offset); 1250 startoffset_fsb = XFS_B_TO_FSB(mp, offset);
1285 endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len); 1251 endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len);
1286 1252
1287 if (attr_flags & XFS_ATTR_NOLOCK) 1253 /* wait for the completion of any pending DIOs */
1288 need_iolock = 0; 1254 inode_dio_wait(VFS_I(ip));
1289 if (need_iolock) {
1290 xfs_ilock(ip, XFS_IOLOCK_EXCL);
1291 /* wait for the completion of any pending DIOs */
1292 inode_dio_wait(VFS_I(ip));
1293 }
1294 1255
1295 rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); 1256 rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
1296 ioffset = offset & ~(rounding - 1); 1257 ioffset = offset & ~(rounding - 1);
1297 error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping, 1258 error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
1298 ioffset, -1); 1259 ioffset, -1);
1299 if (error) 1260 if (error)
1300 goto out_unlock_iolock; 1261 goto out;
1301 truncate_pagecache_range(VFS_I(ip), ioffset, -1); 1262 truncate_pagecache_range(VFS_I(ip), ioffset, -1);
1302 1263
1303 /* 1264 /*
@@ -1311,7 +1272,7 @@ xfs_free_file_space(
1311 error = xfs_bmapi_read(ip, startoffset_fsb, 1, 1272 error = xfs_bmapi_read(ip, startoffset_fsb, 1,
1312 &imap, &nimap, 0); 1273 &imap, &nimap, 0);
1313 if (error) 1274 if (error)
1314 goto out_unlock_iolock; 1275 goto out;
1315 ASSERT(nimap == 0 || nimap == 1); 1276 ASSERT(nimap == 0 || nimap == 1);
1316 if (nimap && imap.br_startblock != HOLESTARTBLOCK) { 1277 if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
1317 xfs_daddr_t block; 1278 xfs_daddr_t block;
@@ -1326,7 +1287,7 @@ xfs_free_file_space(
1326 error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1, 1287 error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1,
1327 &imap, &nimap, 0); 1288 &imap, &nimap, 0);
1328 if (error) 1289 if (error)
1329 goto out_unlock_iolock; 1290 goto out;
1330 ASSERT(nimap == 0 || nimap == 1); 1291 ASSERT(nimap == 0 || nimap == 1);
1331 if (nimap && imap.br_startblock != HOLESTARTBLOCK) { 1292 if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
1332 ASSERT(imap.br_startblock != DELAYSTARTBLOCK); 1293 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
@@ -1412,27 +1373,23 @@ xfs_free_file_space(
1412 xfs_iunlock(ip, XFS_ILOCK_EXCL); 1373 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1413 } 1374 }
1414 1375
1415 out_unlock_iolock: 1376 out:
1416 if (need_iolock)
1417 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1418 return error; 1377 return error;
1419 1378
1420 error0: 1379 error0:
1421 xfs_bmap_cancel(&free_list); 1380 xfs_bmap_cancel(&free_list);
1422 error1: 1381 error1:
1423 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 1382 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
1424 xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) : 1383 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1425 XFS_ILOCK_EXCL); 1384 goto out;
1426 return error;
1427} 1385}
1428 1386
1429 1387
1430STATIC int 1388int
1431xfs_zero_file_space( 1389xfs_zero_file_space(
1432 struct xfs_inode *ip, 1390 struct xfs_inode *ip,
1433 xfs_off_t offset, 1391 xfs_off_t offset,
1434 xfs_off_t len, 1392 xfs_off_t len)
1435 int attr_flags)
1436{ 1393{
1437 struct xfs_mount *mp = ip->i_mount; 1394 struct xfs_mount *mp = ip->i_mount;
1438 uint granularity; 1395 uint granularity;
@@ -1453,9 +1410,6 @@ xfs_zero_file_space(
1453 ASSERT(start_boundary >= offset); 1410 ASSERT(start_boundary >= offset);
1454 ASSERT(end_boundary <= offset + len); 1411 ASSERT(end_boundary <= offset + len);
1455 1412
1456 if (!(attr_flags & XFS_ATTR_NOLOCK))
1457 xfs_ilock(ip, XFS_IOLOCK_EXCL);
1458
1459 if (start_boundary < end_boundary - 1) { 1413 if (start_boundary < end_boundary - 1) {
1460 /* punch out the page cache over the conversion range */ 1414 /* punch out the page cache over the conversion range */
1461 truncate_pagecache_range(VFS_I(ip), start_boundary, 1415 truncate_pagecache_range(VFS_I(ip), start_boundary,
@@ -1463,16 +1417,16 @@ xfs_zero_file_space(
1463 /* convert the blocks */ 1417 /* convert the blocks */
1464 error = xfs_alloc_file_space(ip, start_boundary, 1418 error = xfs_alloc_file_space(ip, start_boundary,
1465 end_boundary - start_boundary - 1, 1419 end_boundary - start_boundary - 1,
1466 XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT, 1420 XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT);
1467 attr_flags);
1468 if (error) 1421 if (error)
1469 goto out_unlock; 1422 goto out;
1470 1423
1471 /* We've handled the interior of the range, now for the edges */ 1424 /* We've handled the interior of the range, now for the edges */
1472 if (start_boundary != offset) 1425 if (start_boundary != offset) {
1473 error = xfs_iozero(ip, offset, start_boundary - offset); 1426 error = xfs_iozero(ip, offset, start_boundary - offset);
1474 if (error) 1427 if (error)
1475 goto out_unlock; 1428 goto out;
1429 }
1476 1430
1477 if (end_boundary != offset + len) 1431 if (end_boundary != offset + len)
1478 error = xfs_iozero(ip, end_boundary, 1432 error = xfs_iozero(ip, end_boundary,
@@ -1486,197 +1440,12 @@ xfs_zero_file_space(
1486 error = xfs_iozero(ip, offset, len); 1440 error = xfs_iozero(ip, offset, len);
1487 } 1441 }
1488 1442
1489out_unlock: 1443out:
1490 if (!(attr_flags & XFS_ATTR_NOLOCK))
1491 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1492 return error; 1444 return error;
1493 1445
1494} 1446}
1495 1447
1496/* 1448/*
1497 * xfs_change_file_space()
1498 * This routine allocates or frees disk space for the given file.
1499 * The user specified parameters are checked for alignment and size
1500 * limitations.
1501 *
1502 * RETURNS:
1503 * 0 on success
1504 * errno on error
1505 *
1506 */
1507int
1508xfs_change_file_space(
1509 xfs_inode_t *ip,
1510 int cmd,
1511 xfs_flock64_t *bf,
1512 xfs_off_t offset,
1513 int attr_flags)
1514{
1515 xfs_mount_t *mp = ip->i_mount;
1516 int clrprealloc;
1517 int error;
1518 xfs_fsize_t fsize;
1519 int setprealloc;
1520 xfs_off_t startoffset;
1521 xfs_trans_t *tp;
1522 struct iattr iattr;
1523
1524 if (!S_ISREG(ip->i_d.di_mode))
1525 return XFS_ERROR(EINVAL);
1526
1527 switch (bf->l_whence) {
1528 case 0: /*SEEK_SET*/
1529 break;
1530 case 1: /*SEEK_CUR*/
1531 bf->l_start += offset;
1532 break;
1533 case 2: /*SEEK_END*/
1534 bf->l_start += XFS_ISIZE(ip);
1535 break;
1536 default:
1537 return XFS_ERROR(EINVAL);
1538 }
1539
1540 /*
1541 * length of <= 0 for resv/unresv/zero is invalid. length for
1542 * alloc/free is ignored completely and we have no idea what userspace
1543 * might have set it to, so set it to zero to allow range
1544 * checks to pass.
1545 */
1546 switch (cmd) {
1547 case XFS_IOC_ZERO_RANGE:
1548 case XFS_IOC_RESVSP:
1549 case XFS_IOC_RESVSP64:
1550 case XFS_IOC_UNRESVSP:
1551 case XFS_IOC_UNRESVSP64:
1552 if (bf->l_len <= 0)
1553 return XFS_ERROR(EINVAL);
1554 break;
1555 default:
1556 bf->l_len = 0;
1557 break;
1558 }
1559
1560 if (bf->l_start < 0 ||
1561 bf->l_start > mp->m_super->s_maxbytes ||
1562 bf->l_start + bf->l_len < 0 ||
1563 bf->l_start + bf->l_len >= mp->m_super->s_maxbytes)
1564 return XFS_ERROR(EINVAL);
1565
1566 bf->l_whence = 0;
1567
1568 startoffset = bf->l_start;
1569 fsize = XFS_ISIZE(ip);
1570
1571 setprealloc = clrprealloc = 0;
1572 switch (cmd) {
1573 case XFS_IOC_ZERO_RANGE:
1574 error = xfs_zero_file_space(ip, startoffset, bf->l_len,
1575 attr_flags);
1576 if (error)
1577 return error;
1578 setprealloc = 1;
1579 break;
1580
1581 case XFS_IOC_RESVSP:
1582 case XFS_IOC_RESVSP64:
1583 error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
1584 XFS_BMAPI_PREALLOC, attr_flags);
1585 if (error)
1586 return error;
1587 setprealloc = 1;
1588 break;
1589
1590 case XFS_IOC_UNRESVSP:
1591 case XFS_IOC_UNRESVSP64:
1592 if ((error = xfs_free_file_space(ip, startoffset, bf->l_len,
1593 attr_flags)))
1594 return error;
1595 break;
1596
1597 case XFS_IOC_ALLOCSP:
1598 case XFS_IOC_ALLOCSP64:
1599 case XFS_IOC_FREESP:
1600 case XFS_IOC_FREESP64:
1601 /*
1602 * These operations actually do IO when extending the file, but
1603 * the allocation is done seperately to the zeroing that is
1604 * done. This set of operations need to be serialised against
1605 * other IO operations, such as truncate and buffered IO. We
1606 * need to take the IOLOCK here to serialise the allocation and
1607 * zeroing IO to prevent other IOLOCK holders (e.g. getbmap,
1608 * truncate, direct IO) from racing against the transient
1609 * allocated but not written state we can have here.
1610 */
1611 xfs_ilock(ip, XFS_IOLOCK_EXCL);
1612 if (startoffset > fsize) {
1613 error = xfs_alloc_file_space(ip, fsize,
1614 startoffset - fsize, 0,
1615 attr_flags | XFS_ATTR_NOLOCK);
1616 if (error) {
1617 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1618 break;
1619 }
1620 }
1621
1622 iattr.ia_valid = ATTR_SIZE;
1623 iattr.ia_size = startoffset;
1624
1625 error = xfs_setattr_size(ip, &iattr,
1626 attr_flags | XFS_ATTR_NOLOCK);
1627 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1628
1629 if (error)
1630 return error;
1631
1632 clrprealloc = 1;
1633 break;
1634
1635 default:
1636 ASSERT(0);
1637 return XFS_ERROR(EINVAL);
1638 }
1639
1640 /*
1641 * update the inode timestamp, mode, and prealloc flag bits
1642 */
1643 tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
1644 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0);
1645 if (error) {
1646 xfs_trans_cancel(tp, 0);
1647 return error;
1648 }
1649
1650 xfs_ilock(ip, XFS_ILOCK_EXCL);
1651 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1652
1653 if ((attr_flags & XFS_ATTR_DMI) == 0) {
1654 ip->i_d.di_mode &= ~S_ISUID;
1655
1656 /*
1657 * Note that we don't have to worry about mandatory
1658 * file locking being disabled here because we only
1659 * clear the S_ISGID bit if the Group execute bit is
1660 * on, but if it was on then mandatory locking wouldn't
1661 * have been enabled.
1662 */
1663 if (ip->i_d.di_mode & S_IXGRP)
1664 ip->i_d.di_mode &= ~S_ISGID;
1665
1666 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
1667 }
1668 if (setprealloc)
1669 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
1670 else if (clrprealloc)
1671 ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
1672
1673 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1674 if (attr_flags & XFS_ATTR_SYNC)
1675 xfs_trans_set_sync(tp);
1676 return xfs_trans_commit(tp, 0);
1677}
1678
1679/*
1680 * We need to check that the format of the data fork in the temporary inode is 1449 * We need to check that the format of the data fork in the temporary inode is
1681 * valid for the target inode before doing the swap. This is not a problem with 1450 * valid for the target inode before doing the swap. This is not a problem with
1682 * attr1 because of the fixed fork offset, but attr2 has a dynamically sized 1451 * attr1 because of the fixed fork offset, but attr2 has a dynamically sized
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index 061260946f7a..900747b25772 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -93,9 +93,12 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,
93 int *is_empty); 93 int *is_empty);
94 94
95/* preallocation and hole punch interface */ 95/* preallocation and hole punch interface */
96int xfs_change_file_space(struct xfs_inode *ip, int cmd, 96int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset,
97 xfs_flock64_t *bf, xfs_off_t offset, 97 xfs_off_t len, int alloc_type);
98 int attr_flags); 98int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset,
99 xfs_off_t len);
100int xfs_zero_file_space(struct xfs_inode *ip, xfs_off_t offset,
101 xfs_off_t len);
99 102
100/* EOF block manipulation functions */ 103/* EOF block manipulation functions */
101bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); 104bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 5690e102243d..9adaae4f3e2f 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -17,18 +17,16 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_alloc_btree.h"
29#include "xfs_ialloc_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 28#include "xfs_inode.h"
29#include "xfs_trans.h"
32#include "xfs_inode_item.h" 30#include "xfs_inode_item.h"
33#include "xfs_buf_item.h" 31#include "xfs_buf_item.h"
34#include "xfs_btree.h" 32#include "xfs_btree.h"
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 06729b67ad58..91e34f21bace 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -27,73 +27,6 @@ struct xfs_trans;
27extern kmem_zone_t *xfs_btree_cur_zone; 27extern kmem_zone_t *xfs_btree_cur_zone;
28 28
29/* 29/*
30 * This nonsense is to make -wlint happy.
31 */
32#define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi)
33#define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi)
34#define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi)
35
36#define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi)
37#define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi)
38#define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi)
39#define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi)
40
41/*
42 * Generic btree header.
43 *
44 * This is a combination of the actual format used on disk for short and long
45 * format btrees. The first three fields are shared by both format, but the
46 * pointers are different and should be used with care.
47 *
48 * To get the size of the actual short or long form headers please use the size
49 * macros below. Never use sizeof(xfs_btree_block).
50 *
51 * The blkno, crc, lsn, owner and uuid fields are only available in filesystems
52 * with the crc feature bit, and all accesses to them must be conditional on
53 * that flag.
54 */
55struct xfs_btree_block {
56 __be32 bb_magic; /* magic number for block type */
57 __be16 bb_level; /* 0 is a leaf */
58 __be16 bb_numrecs; /* current # of data records */
59 union {
60 struct {
61 __be32 bb_leftsib;
62 __be32 bb_rightsib;
63
64 __be64 bb_blkno;
65 __be64 bb_lsn;
66 uuid_t bb_uuid;
67 __be32 bb_owner;
68 __le32 bb_crc;
69 } s; /* short form pointers */
70 struct {
71 __be64 bb_leftsib;
72 __be64 bb_rightsib;
73
74 __be64 bb_blkno;
75 __be64 bb_lsn;
76 uuid_t bb_uuid;
77 __be64 bb_owner;
78 __le32 bb_crc;
79 __be32 bb_pad; /* padding for alignment */
80 } l; /* long form pointers */
81 } bb_u; /* rest */
82};
83
84#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */
85#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */
86
87/* sizes of CRC enabled btree blocks */
88#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40)
89#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48)
90
91#define XFS_BTREE_SBLOCK_CRC_OFF \
92 offsetof(struct xfs_btree_block, bb_u.s.bb_crc)
93#define XFS_BTREE_LBLOCK_CRC_OFF \
94 offsetof(struct xfs_btree_block, bb_u.l.bb_crc)
95
96/*
97 * Generic key, ptr and record wrapper structures. 30 * Generic key, ptr and record wrapper structures.
98 * 31 *
99 * These are disk format structures, and are converted where necessary 32 * These are disk format structures, and are converted where necessary
@@ -119,6 +52,18 @@ union xfs_btree_rec {
119}; 52};
120 53
121/* 54/*
55 * This nonsense is to make -wlint happy.
56 */
57#define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi)
58#define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi)
59#define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi)
60
61#define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi)
62#define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi)
63#define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi)
64#define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi)
65
66/*
122 * For logging record fields. 67 * For logging record fields.
123 */ 68 */
124#define XFS_BB_MAGIC (1 << 0) 69#define XFS_BB_MAGIC (1 << 0)
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 263470075ea2..c7f0b77dcb00 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -34,12 +34,13 @@
34#include <linux/backing-dev.h> 34#include <linux/backing-dev.h>
35#include <linux/freezer.h> 35#include <linux/freezer.h>
36 36
37#include "xfs_sb.h" 37#include "xfs_log_format.h"
38#include "xfs_trans_resv.h" 38#include "xfs_trans_resv.h"
39#include "xfs_log.h" 39#include "xfs_sb.h"
40#include "xfs_ag.h" 40#include "xfs_ag.h"
41#include "xfs_mount.h" 41#include "xfs_mount.h"
42#include "xfs_trace.h" 42#include "xfs_trace.h"
43#include "xfs_log.h"
43 44
44static kmem_zone_t *xfs_buf_zone; 45static kmem_zone_t *xfs_buf_zone;
45 46
@@ -590,7 +591,7 @@ found:
590 error = _xfs_buf_map_pages(bp, flags); 591 error = _xfs_buf_map_pages(bp, flags);
591 if (unlikely(error)) { 592 if (unlikely(error)) {
592 xfs_warn(target->bt_mount, 593 xfs_warn(target->bt_mount,
593 "%s: failed to map pages\n", __func__); 594 "%s: failed to map pagesn", __func__);
594 xfs_buf_relse(bp); 595 xfs_buf_relse(bp);
595 return NULL; 596 return NULL;
596 } 597 }
@@ -809,7 +810,7 @@ xfs_buf_get_uncached(
809 error = _xfs_buf_map_pages(bp, 0); 810 error = _xfs_buf_map_pages(bp, 0);
810 if (unlikely(error)) { 811 if (unlikely(error)) {
811 xfs_warn(target->bt_mount, 812 xfs_warn(target->bt_mount,
812 "%s: failed to map pages\n", __func__); 813 "%s: failed to map pages", __func__);
813 goto fail_free_mem; 814 goto fail_free_mem;
814 } 815 }
815 816
@@ -1618,7 +1619,7 @@ xfs_setsize_buftarg_flags(
1618 bdevname(btp->bt_bdev, name); 1619 bdevname(btp->bt_bdev, name);
1619 1620
1620 xfs_warn(btp->bt_mount, 1621 xfs_warn(btp->bt_mount,
1621 "Cannot set_blocksize to %u on device %s\n", 1622 "Cannot set_blocksize to %u on device %s",
1622 sectorsize, name); 1623 sectorsize, name);
1623 return EINVAL; 1624 return EINVAL;
1624 } 1625 }
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index f1d85cfc0a54..a64f67ba25d3 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -17,17 +17,18 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_log_format.h"
21#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 22#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 23#include "xfs_sb.h"
25#include "xfs_ag.h" 24#include "xfs_ag.h"
26#include "xfs_mount.h" 25#include "xfs_mount.h"
26#include "xfs_trans.h"
27#include "xfs_buf_item.h" 27#include "xfs_buf_item.h"
28#include "xfs_trans_priv.h" 28#include "xfs_trans_priv.h"
29#include "xfs_error.h" 29#include "xfs_error.h"
30#include "xfs_trace.h" 30#include "xfs_trace.h"
31#include "xfs_log.h"
31 32
32 33
33kmem_zone_t *xfs_buf_item_zone; 34kmem_zone_t *xfs_buf_item_zone;
@@ -808,7 +809,7 @@ xfs_buf_item_init(
808 * Mark bytes first through last inclusive as dirty in the buf 809 * Mark bytes first through last inclusive as dirty in the buf
809 * item's bitmap. 810 * item's bitmap.
810 */ 811 */
811void 812static void
812xfs_buf_item_log_segment( 813xfs_buf_item_log_segment(
813 struct xfs_buf_log_item *bip, 814 struct xfs_buf_log_item *bip,
814 uint first, 815 uint first,
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index db6371087fe8..3f3455a41510 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -71,10 +71,6 @@ void xfs_buf_attach_iodone(struct xfs_buf *,
71void xfs_buf_iodone_callbacks(struct xfs_buf *); 71void xfs_buf_iodone_callbacks(struct xfs_buf *);
72void xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *); 72void xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *);
73 73
74void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *,
75 enum xfs_blft);
76void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp, struct xfs_buf *src_bp);
77
78extern kmem_zone_t *xfs_buf_item_zone; 74extern kmem_zone_t *xfs_buf_item_zone;
79 75
80#endif /* __XFS_BUF_ITEM_H__ */ 76#endif /* __XFS_BUF_ITEM_H__ */
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 20bf8e8002d6..796272a2e129 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -18,20 +18,20 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_shared.h"
22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 25#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_da_format.h"
28#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_dir2_format.h"
31#include "xfs_dir2.h" 31#include "xfs_dir2.h"
32#include "xfs_dir2_priv.h" 32#include "xfs_dir2_priv.h"
33#include "xfs_dinode.h"
34#include "xfs_inode.h" 33#include "xfs_inode.h"
34#include "xfs_trans.h"
35#include "xfs_inode_item.h" 35#include "xfs_inode_item.h"
36#include "xfs_alloc.h" 36#include "xfs_alloc.h"
37#include "xfs_bmap.h" 37#include "xfs_bmap.h"
@@ -129,56 +129,6 @@ xfs_da_state_free(xfs_da_state_t *state)
129 kmem_zone_free(xfs_da_state_zone, state); 129 kmem_zone_free(xfs_da_state_zone, state);
130} 130}
131 131
132void
133xfs_da3_node_hdr_from_disk(
134 struct xfs_da3_icnode_hdr *to,
135 struct xfs_da_intnode *from)
136{
137 ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC) ||
138 from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC));
139
140 if (from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
141 struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from;
142
143 to->forw = be32_to_cpu(hdr3->info.hdr.forw);
144 to->back = be32_to_cpu(hdr3->info.hdr.back);
145 to->magic = be16_to_cpu(hdr3->info.hdr.magic);
146 to->count = be16_to_cpu(hdr3->__count);
147 to->level = be16_to_cpu(hdr3->__level);
148 return;
149 }
150 to->forw = be32_to_cpu(from->hdr.info.forw);
151 to->back = be32_to_cpu(from->hdr.info.back);
152 to->magic = be16_to_cpu(from->hdr.info.magic);
153 to->count = be16_to_cpu(from->hdr.__count);
154 to->level = be16_to_cpu(from->hdr.__level);
155}
156
157void
158xfs_da3_node_hdr_to_disk(
159 struct xfs_da_intnode *to,
160 struct xfs_da3_icnode_hdr *from)
161{
162 ASSERT(from->magic == XFS_DA_NODE_MAGIC ||
163 from->magic == XFS_DA3_NODE_MAGIC);
164
165 if (from->magic == XFS_DA3_NODE_MAGIC) {
166 struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to;
167
168 hdr3->info.hdr.forw = cpu_to_be32(from->forw);
169 hdr3->info.hdr.back = cpu_to_be32(from->back);
170 hdr3->info.hdr.magic = cpu_to_be16(from->magic);
171 hdr3->__count = cpu_to_be16(from->count);
172 hdr3->__level = cpu_to_be16(from->level);
173 return;
174 }
175 to->hdr.info.forw = cpu_to_be32(from->forw);
176 to->hdr.info.back = cpu_to_be32(from->back);
177 to->hdr.info.magic = cpu_to_be16(from->magic);
178 to->hdr.__count = cpu_to_be16(from->count);
179 to->hdr.__level = cpu_to_be16(from->level);
180}
181
182static bool 132static bool
183xfs_da3_node_verify( 133xfs_da3_node_verify(
184 struct xfs_buf *bp) 134 struct xfs_buf *bp)
@@ -186,8 +136,11 @@ xfs_da3_node_verify(
186 struct xfs_mount *mp = bp->b_target->bt_mount; 136 struct xfs_mount *mp = bp->b_target->bt_mount;
187 struct xfs_da_intnode *hdr = bp->b_addr; 137 struct xfs_da_intnode *hdr = bp->b_addr;
188 struct xfs_da3_icnode_hdr ichdr; 138 struct xfs_da3_icnode_hdr ichdr;
139 const struct xfs_dir_ops *ops;
189 140
190 xfs_da3_node_hdr_from_disk(&ichdr, hdr); 141 ops = xfs_dir_get_ops(mp, NULL);
142
143 ops->node_hdr_from_disk(&ichdr, hdr);
191 144
192 if (xfs_sb_version_hascrc(&mp->m_sb)) { 145 if (xfs_sb_version_hascrc(&mp->m_sb)) {
193 struct xfs_da3_node_hdr *hdr3 = bp->b_addr; 146 struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
@@ -354,11 +307,12 @@ xfs_da3_node_create(
354 struct xfs_da3_icnode_hdr ichdr = {0}; 307 struct xfs_da3_icnode_hdr ichdr = {0};
355 struct xfs_buf *bp; 308 struct xfs_buf *bp;
356 int error; 309 int error;
310 struct xfs_inode *dp = args->dp;
357 311
358 trace_xfs_da_node_create(args); 312 trace_xfs_da_node_create(args);
359 ASSERT(level <= XFS_DA_NODE_MAXDEPTH); 313 ASSERT(level <= XFS_DA_NODE_MAXDEPTH);
360 314
361 error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork); 315 error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, whichfork);
362 if (error) 316 if (error)
363 return(error); 317 return(error);
364 bp->b_ops = &xfs_da3_node_buf_ops; 318 bp->b_ops = &xfs_da3_node_buf_ops;
@@ -377,9 +331,9 @@ xfs_da3_node_create(
377 } 331 }
378 ichdr.level = level; 332 ichdr.level = level;
379 333
380 xfs_da3_node_hdr_to_disk(node, &ichdr); 334 dp->d_ops->node_hdr_to_disk(node, &ichdr);
381 xfs_trans_log_buf(tp, bp, 335 xfs_trans_log_buf(tp, bp,
382 XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); 336 XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size));
383 337
384 *bpp = bp; 338 *bpp = bp;
385 return(0); 339 return(0);
@@ -589,8 +543,8 @@ xfs_da3_root_split(
589 oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { 543 oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
590 struct xfs_da3_icnode_hdr nodehdr; 544 struct xfs_da3_icnode_hdr nodehdr;
591 545
592 xfs_da3_node_hdr_from_disk(&nodehdr, oldroot); 546 dp->d_ops->node_hdr_from_disk(&nodehdr, oldroot);
593 btree = xfs_da3_node_tree_p(oldroot); 547 btree = dp->d_ops->node_tree_p(oldroot);
594 size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot); 548 size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot);
595 level = nodehdr.level; 549 level = nodehdr.level;
596 550
@@ -604,8 +558,8 @@ xfs_da3_root_split(
604 struct xfs_dir2_leaf_entry *ents; 558 struct xfs_dir2_leaf_entry *ents;
605 559
606 leaf = (xfs_dir2_leaf_t *)oldroot; 560 leaf = (xfs_dir2_leaf_t *)oldroot;
607 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 561 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
608 ents = xfs_dir3_leaf_ents_p(leaf); 562 ents = dp->d_ops->leaf_ents_p(leaf);
609 563
610 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || 564 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
611 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); 565 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
@@ -649,14 +603,14 @@ xfs_da3_root_split(
649 return error; 603 return error;
650 604
651 node = bp->b_addr; 605 node = bp->b_addr;
652 xfs_da3_node_hdr_from_disk(&nodehdr, node); 606 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
653 btree = xfs_da3_node_tree_p(node); 607 btree = dp->d_ops->node_tree_p(node);
654 btree[0].hashval = cpu_to_be32(blk1->hashval); 608 btree[0].hashval = cpu_to_be32(blk1->hashval);
655 btree[0].before = cpu_to_be32(blk1->blkno); 609 btree[0].before = cpu_to_be32(blk1->blkno);
656 btree[1].hashval = cpu_to_be32(blk2->hashval); 610 btree[1].hashval = cpu_to_be32(blk2->hashval);
657 btree[1].before = cpu_to_be32(blk2->blkno); 611 btree[1].before = cpu_to_be32(blk2->blkno);
658 nodehdr.count = 2; 612 nodehdr.count = 2;
659 xfs_da3_node_hdr_to_disk(node, &nodehdr); 613 dp->d_ops->node_hdr_to_disk(node, &nodehdr);
660 614
661#ifdef DEBUG 615#ifdef DEBUG
662 if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || 616 if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
@@ -693,11 +647,12 @@ xfs_da3_node_split(
693 int newcount; 647 int newcount;
694 int error; 648 int error;
695 int useextra; 649 int useextra;
650 struct xfs_inode *dp = state->args->dp;
696 651
697 trace_xfs_da_node_split(state->args); 652 trace_xfs_da_node_split(state->args);
698 653
699 node = oldblk->bp->b_addr; 654 node = oldblk->bp->b_addr;
700 xfs_da3_node_hdr_from_disk(&nodehdr, node); 655 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
701 656
702 /* 657 /*
703 * With V2 dirs the extra block is data or freespace. 658 * With V2 dirs the extra block is data or freespace.
@@ -744,7 +699,7 @@ xfs_da3_node_split(
744 * If we had double-split op below us, then add the extra block too. 699 * If we had double-split op below us, then add the extra block too.
745 */ 700 */
746 node = oldblk->bp->b_addr; 701 node = oldblk->bp->b_addr;
747 xfs_da3_node_hdr_from_disk(&nodehdr, node); 702 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
748 if (oldblk->index <= nodehdr.count) { 703 if (oldblk->index <= nodehdr.count) {
749 oldblk->index++; 704 oldblk->index++;
750 xfs_da3_node_add(state, oldblk, addblk); 705 xfs_da3_node_add(state, oldblk, addblk);
@@ -793,15 +748,16 @@ xfs_da3_node_rebalance(
793 int count; 748 int count;
794 int tmp; 749 int tmp;
795 int swap = 0; 750 int swap = 0;
751 struct xfs_inode *dp = state->args->dp;
796 752
797 trace_xfs_da_node_rebalance(state->args); 753 trace_xfs_da_node_rebalance(state->args);
798 754
799 node1 = blk1->bp->b_addr; 755 node1 = blk1->bp->b_addr;
800 node2 = blk2->bp->b_addr; 756 node2 = blk2->bp->b_addr;
801 xfs_da3_node_hdr_from_disk(&nodehdr1, node1); 757 dp->d_ops->node_hdr_from_disk(&nodehdr1, node1);
802 xfs_da3_node_hdr_from_disk(&nodehdr2, node2); 758 dp->d_ops->node_hdr_from_disk(&nodehdr2, node2);
803 btree1 = xfs_da3_node_tree_p(node1); 759 btree1 = dp->d_ops->node_tree_p(node1);
804 btree2 = xfs_da3_node_tree_p(node2); 760 btree2 = dp->d_ops->node_tree_p(node2);
805 761
806 /* 762 /*
807 * Figure out how many entries need to move, and in which direction. 763 * Figure out how many entries need to move, and in which direction.
@@ -814,10 +770,10 @@ xfs_da3_node_rebalance(
814 tmpnode = node1; 770 tmpnode = node1;
815 node1 = node2; 771 node1 = node2;
816 node2 = tmpnode; 772 node2 = tmpnode;
817 xfs_da3_node_hdr_from_disk(&nodehdr1, node1); 773 dp->d_ops->node_hdr_from_disk(&nodehdr1, node1);
818 xfs_da3_node_hdr_from_disk(&nodehdr2, node2); 774 dp->d_ops->node_hdr_from_disk(&nodehdr2, node2);
819 btree1 = xfs_da3_node_tree_p(node1); 775 btree1 = dp->d_ops->node_tree_p(node1);
820 btree2 = xfs_da3_node_tree_p(node2); 776 btree2 = dp->d_ops->node_tree_p(node2);
821 swap = 1; 777 swap = 1;
822 } 778 }
823 779
@@ -879,15 +835,14 @@ xfs_da3_node_rebalance(
879 /* 835 /*
880 * Log header of node 1 and all current bits of node 2. 836 * Log header of node 1 and all current bits of node 2.
881 */ 837 */
882 xfs_da3_node_hdr_to_disk(node1, &nodehdr1); 838 dp->d_ops->node_hdr_to_disk(node1, &nodehdr1);
883 xfs_trans_log_buf(tp, blk1->bp, 839 xfs_trans_log_buf(tp, blk1->bp,
884 XFS_DA_LOGRANGE(node1, &node1->hdr, 840 XFS_DA_LOGRANGE(node1, &node1->hdr, dp->d_ops->node_hdr_size));
885 xfs_da3_node_hdr_size(node1)));
886 841
887 xfs_da3_node_hdr_to_disk(node2, &nodehdr2); 842 dp->d_ops->node_hdr_to_disk(node2, &nodehdr2);
888 xfs_trans_log_buf(tp, blk2->bp, 843 xfs_trans_log_buf(tp, blk2->bp,
889 XFS_DA_LOGRANGE(node2, &node2->hdr, 844 XFS_DA_LOGRANGE(node2, &node2->hdr,
890 xfs_da3_node_hdr_size(node2) + 845 dp->d_ops->node_hdr_size +
891 (sizeof(btree2[0]) * nodehdr2.count))); 846 (sizeof(btree2[0]) * nodehdr2.count)));
892 847
893 /* 848 /*
@@ -897,10 +852,10 @@ xfs_da3_node_rebalance(
897 if (swap) { 852 if (swap) {
898 node1 = blk1->bp->b_addr; 853 node1 = blk1->bp->b_addr;
899 node2 = blk2->bp->b_addr; 854 node2 = blk2->bp->b_addr;
900 xfs_da3_node_hdr_from_disk(&nodehdr1, node1); 855 dp->d_ops->node_hdr_from_disk(&nodehdr1, node1);
901 xfs_da3_node_hdr_from_disk(&nodehdr2, node2); 856 dp->d_ops->node_hdr_from_disk(&nodehdr2, node2);
902 btree1 = xfs_da3_node_tree_p(node1); 857 btree1 = dp->d_ops->node_tree_p(node1);
903 btree2 = xfs_da3_node_tree_p(node2); 858 btree2 = dp->d_ops->node_tree_p(node2);
904 } 859 }
905 blk1->hashval = be32_to_cpu(btree1[nodehdr1.count - 1].hashval); 860 blk1->hashval = be32_to_cpu(btree1[nodehdr1.count - 1].hashval);
906 blk2->hashval = be32_to_cpu(btree2[nodehdr2.count - 1].hashval); 861 blk2->hashval = be32_to_cpu(btree2[nodehdr2.count - 1].hashval);
@@ -927,12 +882,13 @@ xfs_da3_node_add(
927 struct xfs_da3_icnode_hdr nodehdr; 882 struct xfs_da3_icnode_hdr nodehdr;
928 struct xfs_da_node_entry *btree; 883 struct xfs_da_node_entry *btree;
929 int tmp; 884 int tmp;
885 struct xfs_inode *dp = state->args->dp;
930 886
931 trace_xfs_da_node_add(state->args); 887 trace_xfs_da_node_add(state->args);
932 888
933 node = oldblk->bp->b_addr; 889 node = oldblk->bp->b_addr;
934 xfs_da3_node_hdr_from_disk(&nodehdr, node); 890 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
935 btree = xfs_da3_node_tree_p(node); 891 btree = dp->d_ops->node_tree_p(node);
936 892
937 ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); 893 ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count);
938 ASSERT(newblk->blkno != 0); 894 ASSERT(newblk->blkno != 0);
@@ -955,9 +911,9 @@ xfs_da3_node_add(
955 tmp + sizeof(*btree))); 911 tmp + sizeof(*btree)));
956 912
957 nodehdr.count += 1; 913 nodehdr.count += 1;
958 xfs_da3_node_hdr_to_disk(node, &nodehdr); 914 dp->d_ops->node_hdr_to_disk(node, &nodehdr);
959 xfs_trans_log_buf(state->args->trans, oldblk->bp, 915 xfs_trans_log_buf(state->args->trans, oldblk->bp,
960 XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); 916 XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size));
961 917
962 /* 918 /*
963 * Copy the last hash value from the oldblk to propagate upwards. 919 * Copy the last hash value from the oldblk to propagate upwards.
@@ -1094,6 +1050,7 @@ xfs_da3_root_join(
1094 struct xfs_da3_icnode_hdr oldroothdr; 1050 struct xfs_da3_icnode_hdr oldroothdr;
1095 struct xfs_da_node_entry *btree; 1051 struct xfs_da_node_entry *btree;
1096 int error; 1052 int error;
1053 struct xfs_inode *dp = state->args->dp;
1097 1054
1098 trace_xfs_da_root_join(state->args); 1055 trace_xfs_da_root_join(state->args);
1099 1056
@@ -1101,7 +1058,7 @@ xfs_da3_root_join(
1101 1058
1102 args = state->args; 1059 args = state->args;
1103 oldroot = root_blk->bp->b_addr; 1060 oldroot = root_blk->bp->b_addr;
1104 xfs_da3_node_hdr_from_disk(&oldroothdr, oldroot); 1061 dp->d_ops->node_hdr_from_disk(&oldroothdr, oldroot);
1105 ASSERT(oldroothdr.forw == 0); 1062 ASSERT(oldroothdr.forw == 0);
1106 ASSERT(oldroothdr.back == 0); 1063 ASSERT(oldroothdr.back == 0);
1107 1064
@@ -1115,10 +1072,10 @@ xfs_da3_root_join(
1115 * Read in the (only) child block, then copy those bytes into 1072 * Read in the (only) child block, then copy those bytes into
1116 * the root block's buffer and free the original child block. 1073 * the root block's buffer and free the original child block.
1117 */ 1074 */
1118 btree = xfs_da3_node_tree_p(oldroot); 1075 btree = dp->d_ops->node_tree_p(oldroot);
1119 child = be32_to_cpu(btree[0].before); 1076 child = be32_to_cpu(btree[0].before);
1120 ASSERT(child != 0); 1077 ASSERT(child != 0);
1121 error = xfs_da3_node_read(args->trans, args->dp, child, -1, &bp, 1078 error = xfs_da3_node_read(args->trans, dp, child, -1, &bp,
1122 args->whichfork); 1079 args->whichfork);
1123 if (error) 1080 if (error)
1124 return error; 1081 return error;
@@ -1168,6 +1125,7 @@ xfs_da3_node_toosmall(
1168 int error; 1125 int error;
1169 int retval; 1126 int retval;
1170 int i; 1127 int i;
1128 struct xfs_inode *dp = state->args->dp;
1171 1129
1172 trace_xfs_da_node_toosmall(state->args); 1130 trace_xfs_da_node_toosmall(state->args);
1173 1131
@@ -1179,7 +1137,7 @@ xfs_da3_node_toosmall(
1179 blk = &state->path.blk[ state->path.active-1 ]; 1137 blk = &state->path.blk[ state->path.active-1 ];
1180 info = blk->bp->b_addr; 1138 info = blk->bp->b_addr;
1181 node = (xfs_da_intnode_t *)info; 1139 node = (xfs_da_intnode_t *)info;
1182 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1140 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1183 if (nodehdr.count > (state->node_ents >> 1)) { 1141 if (nodehdr.count > (state->node_ents >> 1)) {
1184 *action = 0; /* blk over 50%, don't try to join */ 1142 *action = 0; /* blk over 50%, don't try to join */
1185 return(0); /* blk over 50%, don't try to join */ 1143 return(0); /* blk over 50%, don't try to join */
@@ -1231,13 +1189,13 @@ xfs_da3_node_toosmall(
1231 blkno = nodehdr.back; 1189 blkno = nodehdr.back;
1232 if (blkno == 0) 1190 if (blkno == 0)
1233 continue; 1191 continue;
1234 error = xfs_da3_node_read(state->args->trans, state->args->dp, 1192 error = xfs_da3_node_read(state->args->trans, dp,
1235 blkno, -1, &bp, state->args->whichfork); 1193 blkno, -1, &bp, state->args->whichfork);
1236 if (error) 1194 if (error)
1237 return(error); 1195 return(error);
1238 1196
1239 node = bp->b_addr; 1197 node = bp->b_addr;
1240 xfs_da3_node_hdr_from_disk(&thdr, node); 1198 dp->d_ops->node_hdr_from_disk(&thdr, node);
1241 xfs_trans_brelse(state->args->trans, bp); 1199 xfs_trans_brelse(state->args->trans, bp);
1242 1200
1243 if (count - thdr.count >= 0) 1201 if (count - thdr.count >= 0)
@@ -1275,6 +1233,7 @@ xfs_da3_node_toosmall(
1275 */ 1233 */
1276STATIC uint 1234STATIC uint
1277xfs_da3_node_lasthash( 1235xfs_da3_node_lasthash(
1236 struct xfs_inode *dp,
1278 struct xfs_buf *bp, 1237 struct xfs_buf *bp,
1279 int *count) 1238 int *count)
1280{ 1239{
@@ -1283,12 +1242,12 @@ xfs_da3_node_lasthash(
1283 struct xfs_da3_icnode_hdr nodehdr; 1242 struct xfs_da3_icnode_hdr nodehdr;
1284 1243
1285 node = bp->b_addr; 1244 node = bp->b_addr;
1286 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1245 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1287 if (count) 1246 if (count)
1288 *count = nodehdr.count; 1247 *count = nodehdr.count;
1289 if (!nodehdr.count) 1248 if (!nodehdr.count)
1290 return 0; 1249 return 0;
1291 btree = xfs_da3_node_tree_p(node); 1250 btree = dp->d_ops->node_tree_p(node);
1292 return be32_to_cpu(btree[nodehdr.count - 1].hashval); 1251 return be32_to_cpu(btree[nodehdr.count - 1].hashval);
1293} 1252}
1294 1253
@@ -1307,6 +1266,7 @@ xfs_da3_fixhashpath(
1307 xfs_dahash_t lasthash=0; 1266 xfs_dahash_t lasthash=0;
1308 int level; 1267 int level;
1309 int count; 1268 int count;
1269 struct xfs_inode *dp = state->args->dp;
1310 1270
1311 trace_xfs_da_fixhashpath(state->args); 1271 trace_xfs_da_fixhashpath(state->args);
1312 1272
@@ -1319,12 +1279,12 @@ xfs_da3_fixhashpath(
1319 return; 1279 return;
1320 break; 1280 break;
1321 case XFS_DIR2_LEAFN_MAGIC: 1281 case XFS_DIR2_LEAFN_MAGIC:
1322 lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); 1282 lasthash = xfs_dir2_leafn_lasthash(dp, blk->bp, &count);
1323 if (count == 0) 1283 if (count == 0)
1324 return; 1284 return;
1325 break; 1285 break;
1326 case XFS_DA_NODE_MAGIC: 1286 case XFS_DA_NODE_MAGIC:
1327 lasthash = xfs_da3_node_lasthash(blk->bp, &count); 1287 lasthash = xfs_da3_node_lasthash(dp, blk->bp, &count);
1328 if (count == 0) 1288 if (count == 0)
1329 return; 1289 return;
1330 break; 1290 break;
@@ -1333,8 +1293,8 @@ xfs_da3_fixhashpath(
1333 struct xfs_da3_icnode_hdr nodehdr; 1293 struct xfs_da3_icnode_hdr nodehdr;
1334 1294
1335 node = blk->bp->b_addr; 1295 node = blk->bp->b_addr;
1336 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1296 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1337 btree = xfs_da3_node_tree_p(node); 1297 btree = dp->d_ops->node_tree_p(node);
1338 if (be32_to_cpu(btree->hashval) == lasthash) 1298 if (be32_to_cpu(btree->hashval) == lasthash)
1339 break; 1299 break;
1340 blk->hashval = lasthash; 1300 blk->hashval = lasthash;
@@ -1360,11 +1320,12 @@ xfs_da3_node_remove(
1360 struct xfs_da_node_entry *btree; 1320 struct xfs_da_node_entry *btree;
1361 int index; 1321 int index;
1362 int tmp; 1322 int tmp;
1323 struct xfs_inode *dp = state->args->dp;
1363 1324
1364 trace_xfs_da_node_remove(state->args); 1325 trace_xfs_da_node_remove(state->args);
1365 1326
1366 node = drop_blk->bp->b_addr; 1327 node = drop_blk->bp->b_addr;
1367 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1328 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1368 ASSERT(drop_blk->index < nodehdr.count); 1329 ASSERT(drop_blk->index < nodehdr.count);
1369 ASSERT(drop_blk->index >= 0); 1330 ASSERT(drop_blk->index >= 0);
1370 1331
@@ -1372,7 +1333,7 @@ xfs_da3_node_remove(
1372 * Copy over the offending entry, or just zero it out. 1333 * Copy over the offending entry, or just zero it out.
1373 */ 1334 */
1374 index = drop_blk->index; 1335 index = drop_blk->index;
1375 btree = xfs_da3_node_tree_p(node); 1336 btree = dp->d_ops->node_tree_p(node);
1376 if (index < nodehdr.count - 1) { 1337 if (index < nodehdr.count - 1) {
1377 tmp = nodehdr.count - index - 1; 1338 tmp = nodehdr.count - index - 1;
1378 tmp *= (uint)sizeof(xfs_da_node_entry_t); 1339 tmp *= (uint)sizeof(xfs_da_node_entry_t);
@@ -1385,9 +1346,9 @@ xfs_da3_node_remove(
1385 xfs_trans_log_buf(state->args->trans, drop_blk->bp, 1346 xfs_trans_log_buf(state->args->trans, drop_blk->bp,
1386 XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index]))); 1347 XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index])));
1387 nodehdr.count -= 1; 1348 nodehdr.count -= 1;
1388 xfs_da3_node_hdr_to_disk(node, &nodehdr); 1349 dp->d_ops->node_hdr_to_disk(node, &nodehdr);
1389 xfs_trans_log_buf(state->args->trans, drop_blk->bp, 1350 xfs_trans_log_buf(state->args->trans, drop_blk->bp,
1390 XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); 1351 XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size));
1391 1352
1392 /* 1353 /*
1393 * Copy the last hash value from the block to propagate upwards. 1354 * Copy the last hash value from the block to propagate upwards.
@@ -1414,15 +1375,16 @@ xfs_da3_node_unbalance(
1414 struct xfs_trans *tp; 1375 struct xfs_trans *tp;
1415 int sindex; 1376 int sindex;
1416 int tmp; 1377 int tmp;
1378 struct xfs_inode *dp = state->args->dp;
1417 1379
1418 trace_xfs_da_node_unbalance(state->args); 1380 trace_xfs_da_node_unbalance(state->args);
1419 1381
1420 drop_node = drop_blk->bp->b_addr; 1382 drop_node = drop_blk->bp->b_addr;
1421 save_node = save_blk->bp->b_addr; 1383 save_node = save_blk->bp->b_addr;
1422 xfs_da3_node_hdr_from_disk(&drop_hdr, drop_node); 1384 dp->d_ops->node_hdr_from_disk(&drop_hdr, drop_node);
1423 xfs_da3_node_hdr_from_disk(&save_hdr, save_node); 1385 dp->d_ops->node_hdr_from_disk(&save_hdr, save_node);
1424 drop_btree = xfs_da3_node_tree_p(drop_node); 1386 drop_btree = dp->d_ops->node_tree_p(drop_node);
1425 save_btree = xfs_da3_node_tree_p(save_node); 1387 save_btree = dp->d_ops->node_tree_p(save_node);
1426 tp = state->args->trans; 1388 tp = state->args->trans;
1427 1389
1428 /* 1390 /*
@@ -1456,10 +1418,10 @@ xfs_da3_node_unbalance(
1456 memcpy(&save_btree[sindex], &drop_btree[0], tmp); 1418 memcpy(&save_btree[sindex], &drop_btree[0], tmp);
1457 save_hdr.count += drop_hdr.count; 1419 save_hdr.count += drop_hdr.count;
1458 1420
1459 xfs_da3_node_hdr_to_disk(save_node, &save_hdr); 1421 dp->d_ops->node_hdr_to_disk(save_node, &save_hdr);
1460 xfs_trans_log_buf(tp, save_blk->bp, 1422 xfs_trans_log_buf(tp, save_blk->bp,
1461 XFS_DA_LOGRANGE(save_node, &save_node->hdr, 1423 XFS_DA_LOGRANGE(save_node, &save_node->hdr,
1462 xfs_da3_node_hdr_size(save_node))); 1424 dp->d_ops->node_hdr_size));
1463 1425
1464 /* 1426 /*
1465 * Save the last hashval in the remaining block for upward propagation. 1427 * Save the last hashval in the remaining block for upward propagation.
@@ -1501,6 +1463,7 @@ xfs_da3_node_lookup_int(
1501 int max; 1463 int max;
1502 int error; 1464 int error;
1503 int retval; 1465 int retval;
1466 struct xfs_inode *dp = state->args->dp;
1504 1467
1505 args = state->args; 1468 args = state->args;
1506 1469
@@ -1536,7 +1499,8 @@ xfs_da3_node_lookup_int(
1536 if (blk->magic == XFS_DIR2_LEAFN_MAGIC || 1499 if (blk->magic == XFS_DIR2_LEAFN_MAGIC ||
1537 blk->magic == XFS_DIR3_LEAFN_MAGIC) { 1500 blk->magic == XFS_DIR3_LEAFN_MAGIC) {
1538 blk->magic = XFS_DIR2_LEAFN_MAGIC; 1501 blk->magic = XFS_DIR2_LEAFN_MAGIC;
1539 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); 1502 blk->hashval = xfs_dir2_leafn_lasthash(args->dp,
1503 blk->bp, NULL);
1540 break; 1504 break;
1541 } 1505 }
1542 1506
@@ -1547,8 +1511,8 @@ xfs_da3_node_lookup_int(
1547 * Search an intermediate node for a match. 1511 * Search an intermediate node for a match.
1548 */ 1512 */
1549 node = blk->bp->b_addr; 1513 node = blk->bp->b_addr;
1550 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1514 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1551 btree = xfs_da3_node_tree_p(node); 1515 btree = dp->d_ops->node_tree_p(node);
1552 1516
1553 max = nodehdr.count; 1517 max = nodehdr.count;
1554 blk->hashval = be32_to_cpu(btree[max - 1].hashval); 1518 blk->hashval = be32_to_cpu(btree[max - 1].hashval);
@@ -1643,6 +1607,7 @@ xfs_da3_node_lookup_int(
1643 */ 1607 */
1644STATIC int 1608STATIC int
1645xfs_da3_node_order( 1609xfs_da3_node_order(
1610 struct xfs_inode *dp,
1646 struct xfs_buf *node1_bp, 1611 struct xfs_buf *node1_bp,
1647 struct xfs_buf *node2_bp) 1612 struct xfs_buf *node2_bp)
1648{ 1613{
@@ -1655,10 +1620,10 @@ xfs_da3_node_order(
1655 1620
1656 node1 = node1_bp->b_addr; 1621 node1 = node1_bp->b_addr;
1657 node2 = node2_bp->b_addr; 1622 node2 = node2_bp->b_addr;
1658 xfs_da3_node_hdr_from_disk(&node1hdr, node1); 1623 dp->d_ops->node_hdr_from_disk(&node1hdr, node1);
1659 xfs_da3_node_hdr_from_disk(&node2hdr, node2); 1624 dp->d_ops->node_hdr_from_disk(&node2hdr, node2);
1660 btree1 = xfs_da3_node_tree_p(node1); 1625 btree1 = dp->d_ops->node_tree_p(node1);
1661 btree2 = xfs_da3_node_tree_p(node2); 1626 btree2 = dp->d_ops->node_tree_p(node2);
1662 1627
1663 if (node1hdr.count > 0 && node2hdr.count > 0 && 1628 if (node1hdr.count > 0 && node2hdr.count > 0 &&
1664 ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) || 1629 ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) ||
@@ -1685,6 +1650,7 @@ xfs_da3_blk_link(
1685 struct xfs_buf *bp; 1650 struct xfs_buf *bp;
1686 int before = 0; 1651 int before = 0;
1687 int error; 1652 int error;
1653 struct xfs_inode *dp = state->args->dp;
1688 1654
1689 /* 1655 /*
1690 * Set up environment. 1656 * Set up environment.
@@ -1702,10 +1668,10 @@ xfs_da3_blk_link(
1702 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); 1668 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
1703 break; 1669 break;
1704 case XFS_DIR2_LEAFN_MAGIC: 1670 case XFS_DIR2_LEAFN_MAGIC:
1705 before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); 1671 before = xfs_dir2_leafn_order(dp, old_blk->bp, new_blk->bp);
1706 break; 1672 break;
1707 case XFS_DA_NODE_MAGIC: 1673 case XFS_DA_NODE_MAGIC:
1708 before = xfs_da3_node_order(old_blk->bp, new_blk->bp); 1674 before = xfs_da3_node_order(dp, old_blk->bp, new_blk->bp);
1709 break; 1675 break;
1710 } 1676 }
1711 1677
@@ -1720,7 +1686,7 @@ xfs_da3_blk_link(
1720 new_info->forw = cpu_to_be32(old_blk->blkno); 1686 new_info->forw = cpu_to_be32(old_blk->blkno);
1721 new_info->back = old_info->back; 1687 new_info->back = old_info->back;
1722 if (old_info->back) { 1688 if (old_info->back) {
1723 error = xfs_da3_node_read(args->trans, args->dp, 1689 error = xfs_da3_node_read(args->trans, dp,
1724 be32_to_cpu(old_info->back), 1690 be32_to_cpu(old_info->back),
1725 -1, &bp, args->whichfork); 1691 -1, &bp, args->whichfork);
1726 if (error) 1692 if (error)
@@ -1741,7 +1707,7 @@ xfs_da3_blk_link(
1741 new_info->forw = old_info->forw; 1707 new_info->forw = old_info->forw;
1742 new_info->back = cpu_to_be32(old_blk->blkno); 1708 new_info->back = cpu_to_be32(old_blk->blkno);
1743 if (old_info->forw) { 1709 if (old_info->forw) {
1744 error = xfs_da3_node_read(args->trans, args->dp, 1710 error = xfs_da3_node_read(args->trans, dp,
1745 be32_to_cpu(old_info->forw), 1711 be32_to_cpu(old_info->forw),
1746 -1, &bp, args->whichfork); 1712 -1, &bp, args->whichfork);
1747 if (error) 1713 if (error)
@@ -1861,6 +1827,7 @@ xfs_da3_path_shift(
1861 xfs_dablk_t blkno = 0; 1827 xfs_dablk_t blkno = 0;
1862 int level; 1828 int level;
1863 int error; 1829 int error;
1830 struct xfs_inode *dp = state->args->dp;
1864 1831
1865 trace_xfs_da_path_shift(state->args); 1832 trace_xfs_da_path_shift(state->args);
1866 1833
@@ -1876,8 +1843,8 @@ xfs_da3_path_shift(
1876 level = (path->active-1) - 1; /* skip bottom layer in path */ 1843 level = (path->active-1) - 1; /* skip bottom layer in path */
1877 for (blk = &path->blk[level]; level >= 0; blk--, level--) { 1844 for (blk = &path->blk[level]; level >= 0; blk--, level--) {
1878 node = blk->bp->b_addr; 1845 node = blk->bp->b_addr;
1879 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1846 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1880 btree = xfs_da3_node_tree_p(node); 1847 btree = dp->d_ops->node_tree_p(node);
1881 1848
1882 if (forward && (blk->index < nodehdr.count - 1)) { 1849 if (forward && (blk->index < nodehdr.count - 1)) {
1883 blk->index++; 1850 blk->index++;
@@ -1911,7 +1878,7 @@ xfs_da3_path_shift(
1911 * Read the next child block. 1878 * Read the next child block.
1912 */ 1879 */
1913 blk->blkno = blkno; 1880 blk->blkno = blkno;
1914 error = xfs_da3_node_read(args->trans, args->dp, blkno, -1, 1881 error = xfs_da3_node_read(args->trans, dp, blkno, -1,
1915 &blk->bp, args->whichfork); 1882 &blk->bp, args->whichfork);
1916 if (error) 1883 if (error)
1917 return(error); 1884 return(error);
@@ -1933,8 +1900,8 @@ xfs_da3_path_shift(
1933 case XFS_DA3_NODE_MAGIC: 1900 case XFS_DA3_NODE_MAGIC:
1934 blk->magic = XFS_DA_NODE_MAGIC; 1901 blk->magic = XFS_DA_NODE_MAGIC;
1935 node = (xfs_da_intnode_t *)info; 1902 node = (xfs_da_intnode_t *)info;
1936 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1903 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1937 btree = xfs_da3_node_tree_p(node); 1904 btree = dp->d_ops->node_tree_p(node);
1938 blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); 1905 blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval);
1939 if (forward) 1906 if (forward)
1940 blk->index = 0; 1907 blk->index = 0;
@@ -1947,16 +1914,15 @@ xfs_da3_path_shift(
1947 blk->magic = XFS_ATTR_LEAF_MAGIC; 1914 blk->magic = XFS_ATTR_LEAF_MAGIC;
1948 ASSERT(level == path->active-1); 1915 ASSERT(level == path->active-1);
1949 blk->index = 0; 1916 blk->index = 0;
1950 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, 1917 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
1951 NULL);
1952 break; 1918 break;
1953 case XFS_DIR2_LEAFN_MAGIC: 1919 case XFS_DIR2_LEAFN_MAGIC:
1954 case XFS_DIR3_LEAFN_MAGIC: 1920 case XFS_DIR3_LEAFN_MAGIC:
1955 blk->magic = XFS_DIR2_LEAFN_MAGIC; 1921 blk->magic = XFS_DIR2_LEAFN_MAGIC;
1956 ASSERT(level == path->active-1); 1922 ASSERT(level == path->active-1);
1957 blk->index = 0; 1923 blk->index = 0;
1958 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, 1924 blk->hashval = xfs_dir2_leafn_lasthash(args->dp,
1959 NULL); 1925 blk->bp, NULL);
1960 break; 1926 break;
1961 default: 1927 default:
1962 ASSERT(0); 1928 ASSERT(0);
@@ -2163,7 +2129,7 @@ xfs_da3_swap_lastblock(
2163 struct xfs_dir2_leaf *dead_leaf2; 2129 struct xfs_dir2_leaf *dead_leaf2;
2164 struct xfs_da_node_entry *btree; 2130 struct xfs_da_node_entry *btree;
2165 struct xfs_da3_icnode_hdr par_hdr; 2131 struct xfs_da3_icnode_hdr par_hdr;
2166 struct xfs_inode *ip; 2132 struct xfs_inode *dp;
2167 struct xfs_trans *tp; 2133 struct xfs_trans *tp;
2168 struct xfs_mount *mp; 2134 struct xfs_mount *mp;
2169 struct xfs_buf *dead_buf; 2135 struct xfs_buf *dead_buf;
@@ -2187,12 +2153,12 @@ xfs_da3_swap_lastblock(
2187 dead_buf = *dead_bufp; 2153 dead_buf = *dead_bufp;
2188 dead_blkno = *dead_blknop; 2154 dead_blkno = *dead_blknop;
2189 tp = args->trans; 2155 tp = args->trans;
2190 ip = args->dp; 2156 dp = args->dp;
2191 w = args->whichfork; 2157 w = args->whichfork;
2192 ASSERT(w == XFS_DATA_FORK); 2158 ASSERT(w == XFS_DATA_FORK);
2193 mp = ip->i_mount; 2159 mp = dp->i_mount;
2194 lastoff = mp->m_dirfreeblk; 2160 lastoff = mp->m_dirfreeblk;
2195 error = xfs_bmap_last_before(tp, ip, &lastoff, w); 2161 error = xfs_bmap_last_before(tp, dp, &lastoff, w);
2196 if (error) 2162 if (error)
2197 return error; 2163 return error;
2198 if (unlikely(lastoff == 0)) { 2164 if (unlikely(lastoff == 0)) {
@@ -2204,7 +2170,7 @@ xfs_da3_swap_lastblock(
2204 * Read the last block in the btree space. 2170 * Read the last block in the btree space.
2205 */ 2171 */
2206 last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs; 2172 last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs;
2207 error = xfs_da3_node_read(tp, ip, last_blkno, -1, &last_buf, w); 2173 error = xfs_da3_node_read(tp, dp, last_blkno, -1, &last_buf, w);
2208 if (error) 2174 if (error)
2209 return error; 2175 return error;
2210 /* 2176 /*
@@ -2222,16 +2188,16 @@ xfs_da3_swap_lastblock(
2222 struct xfs_dir2_leaf_entry *ents; 2188 struct xfs_dir2_leaf_entry *ents;
2223 2189
2224 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; 2190 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
2225 xfs_dir3_leaf_hdr_from_disk(&leafhdr, dead_leaf2); 2191 dp->d_ops->leaf_hdr_from_disk(&leafhdr, dead_leaf2);
2226 ents = xfs_dir3_leaf_ents_p(dead_leaf2); 2192 ents = dp->d_ops->leaf_ents_p(dead_leaf2);
2227 dead_level = 0; 2193 dead_level = 0;
2228 dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); 2194 dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval);
2229 } else { 2195 } else {
2230 struct xfs_da3_icnode_hdr deadhdr; 2196 struct xfs_da3_icnode_hdr deadhdr;
2231 2197
2232 dead_node = (xfs_da_intnode_t *)dead_info; 2198 dead_node = (xfs_da_intnode_t *)dead_info;
2233 xfs_da3_node_hdr_from_disk(&deadhdr, dead_node); 2199 dp->d_ops->node_hdr_from_disk(&deadhdr, dead_node);
2234 btree = xfs_da3_node_tree_p(dead_node); 2200 btree = dp->d_ops->node_tree_p(dead_node);
2235 dead_level = deadhdr.level; 2201 dead_level = deadhdr.level;
2236 dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval); 2202 dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval);
2237 } 2203 }
@@ -2240,7 +2206,7 @@ xfs_da3_swap_lastblock(
2240 * If the moved block has a left sibling, fix up the pointers. 2206 * If the moved block has a left sibling, fix up the pointers.
2241 */ 2207 */
2242 if ((sib_blkno = be32_to_cpu(dead_info->back))) { 2208 if ((sib_blkno = be32_to_cpu(dead_info->back))) {
2243 error = xfs_da3_node_read(tp, ip, sib_blkno, -1, &sib_buf, w); 2209 error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w);
2244 if (error) 2210 if (error)
2245 goto done; 2211 goto done;
2246 sib_info = sib_buf->b_addr; 2212 sib_info = sib_buf->b_addr;
@@ -2262,7 +2228,7 @@ xfs_da3_swap_lastblock(
2262 * If the moved block has a right sibling, fix up the pointers. 2228 * If the moved block has a right sibling, fix up the pointers.
2263 */ 2229 */
2264 if ((sib_blkno = be32_to_cpu(dead_info->forw))) { 2230 if ((sib_blkno = be32_to_cpu(dead_info->forw))) {
2265 error = xfs_da3_node_read(tp, ip, sib_blkno, -1, &sib_buf, w); 2231 error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w);
2266 if (error) 2232 if (error)
2267 goto done; 2233 goto done;
2268 sib_info = sib_buf->b_addr; 2234 sib_info = sib_buf->b_addr;
@@ -2286,11 +2252,11 @@ xfs_da3_swap_lastblock(
2286 * Walk down the tree looking for the parent of the moved block. 2252 * Walk down the tree looking for the parent of the moved block.
2287 */ 2253 */
2288 for (;;) { 2254 for (;;) {
2289 error = xfs_da3_node_read(tp, ip, par_blkno, -1, &par_buf, w); 2255 error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w);
2290 if (error) 2256 if (error)
2291 goto done; 2257 goto done;
2292 par_node = par_buf->b_addr; 2258 par_node = par_buf->b_addr;
2293 xfs_da3_node_hdr_from_disk(&par_hdr, par_node); 2259 dp->d_ops->node_hdr_from_disk(&par_hdr, par_node);
2294 if (level >= 0 && level != par_hdr.level + 1) { 2260 if (level >= 0 && level != par_hdr.level + 1) {
2295 XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", 2261 XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)",
2296 XFS_ERRLEVEL_LOW, mp); 2262 XFS_ERRLEVEL_LOW, mp);
@@ -2298,7 +2264,7 @@ xfs_da3_swap_lastblock(
2298 goto done; 2264 goto done;
2299 } 2265 }
2300 level = par_hdr.level; 2266 level = par_hdr.level;
2301 btree = xfs_da3_node_tree_p(par_node); 2267 btree = dp->d_ops->node_tree_p(par_node);
2302 for (entno = 0; 2268 for (entno = 0;
2303 entno < par_hdr.count && 2269 entno < par_hdr.count &&
2304 be32_to_cpu(btree[entno].hashval) < dead_hash; 2270 be32_to_cpu(btree[entno].hashval) < dead_hash;
@@ -2337,18 +2303,18 @@ xfs_da3_swap_lastblock(
2337 error = XFS_ERROR(EFSCORRUPTED); 2303 error = XFS_ERROR(EFSCORRUPTED);
2338 goto done; 2304 goto done;
2339 } 2305 }
2340 error = xfs_da3_node_read(tp, ip, par_blkno, -1, &par_buf, w); 2306 error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w);
2341 if (error) 2307 if (error)
2342 goto done; 2308 goto done;
2343 par_node = par_buf->b_addr; 2309 par_node = par_buf->b_addr;
2344 xfs_da3_node_hdr_from_disk(&par_hdr, par_node); 2310 dp->d_ops->node_hdr_from_disk(&par_hdr, par_node);
2345 if (par_hdr.level != level) { 2311 if (par_hdr.level != level) {
2346 XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", 2312 XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)",
2347 XFS_ERRLEVEL_LOW, mp); 2313 XFS_ERRLEVEL_LOW, mp);
2348 error = XFS_ERROR(EFSCORRUPTED); 2314 error = XFS_ERROR(EFSCORRUPTED);
2349 goto done; 2315 goto done;
2350 } 2316 }
2351 btree = xfs_da3_node_tree_p(par_node); 2317 btree = dp->d_ops->node_tree_p(par_node);
2352 entno = 0; 2318 entno = 0;
2353 } 2319 }
2354 /* 2320 /*
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index b1f267995dea..6e95ea79f5d7 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -23,146 +23,7 @@ struct xfs_bmap_free;
23struct xfs_inode; 23struct xfs_inode;
24struct xfs_trans; 24struct xfs_trans;
25struct zone; 25struct zone;
26 26struct xfs_dir_ops;
27/*========================================================================
28 * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
29 *========================================================================*/
30
31/*
32 * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
33 *
34 * It is used to manage a doubly linked list of all blocks at the same
35 * level in the Btree, and to identify which type of block this is.
36 */
37#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
38#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
39#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
40#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
41
42typedef struct xfs_da_blkinfo {
43 __be32 forw; /* previous block in list */
44 __be32 back; /* following block in list */
45 __be16 magic; /* validity check on block */
46 __be16 pad; /* unused */
47} xfs_da_blkinfo_t;
48
49/*
50 * CRC enabled directory structure types
51 *
52 * The headers change size for the additional verification information, but
53 * otherwise the tree layouts and contents are unchanged. Hence the da btree
54 * code can use the struct xfs_da_blkinfo for manipulating the tree links and
55 * magic numbers without modification for both v2 and v3 nodes.
56 */
57#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */
58#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */
59#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */
60#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */
61
62struct xfs_da3_blkinfo {
63 /*
64 * the node link manipulation code relies on the fact that the first
65 * element of this structure is the struct xfs_da_blkinfo so it can
66 * ignore the differences in the rest of the structures.
67 */
68 struct xfs_da_blkinfo hdr;
69 __be32 crc; /* CRC of block */
70 __be64 blkno; /* first block of the buffer */
71 __be64 lsn; /* sequence number of last write */
72 uuid_t uuid; /* filesystem we belong to */
73 __be64 owner; /* inode that owns the block */
74};
75
76/*
77 * This is the structure of the root and intermediate nodes in the Btree.
78 * The leaf nodes are defined above.
79 *
80 * Entries are not packed.
81 *
82 * Since we have duplicate keys, use a binary search but always follow
83 * all match in the block, not just the first match found.
84 */
85#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */
86
87typedef struct xfs_da_node_hdr {
88 struct xfs_da_blkinfo info; /* block type, links, etc. */
89 __be16 __count; /* count of active entries */
90 __be16 __level; /* level above leaves (leaf == 0) */
91} xfs_da_node_hdr_t;
92
93struct xfs_da3_node_hdr {
94 struct xfs_da3_blkinfo info; /* block type, links, etc. */
95 __be16 __count; /* count of active entries */
96 __be16 __level; /* level above leaves (leaf == 0) */
97 __be32 __pad32;
98};
99
100#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc))
101
102typedef struct xfs_da_node_entry {
103 __be32 hashval; /* hash value for this descendant */
104 __be32 before; /* Btree block before this key */
105} xfs_da_node_entry_t;
106
107typedef struct xfs_da_intnode {
108 struct xfs_da_node_hdr hdr;
109 struct xfs_da_node_entry __btree[];
110} xfs_da_intnode_t;
111
112struct xfs_da3_intnode {
113 struct xfs_da3_node_hdr hdr;
114 struct xfs_da_node_entry __btree[];
115};
116
117/*
118 * In-core version of the node header to abstract the differences in the v2 and
119 * v3 disk format of the headers. Callers need to convert to/from disk format as
120 * appropriate.
121 */
122struct xfs_da3_icnode_hdr {
123 __uint32_t forw;
124 __uint32_t back;
125 __uint16_t magic;
126 __uint16_t count;
127 __uint16_t level;
128};
129
130extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to,
131 struct xfs_da_intnode *from);
132extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to,
133 struct xfs_da3_icnode_hdr *from);
134
135static inline int
136__xfs_da3_node_hdr_size(bool v3)
137{
138 if (v3)
139 return sizeof(struct xfs_da3_node_hdr);
140 return sizeof(struct xfs_da_node_hdr);
141}
142static inline int
143xfs_da3_node_hdr_size(struct xfs_da_intnode *dap)
144{
145 bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC);
146
147 return __xfs_da3_node_hdr_size(v3);
148}
149
150static inline struct xfs_da_node_entry *
151xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
152{
153 if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
154 struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap;
155 return dap3->__btree;
156 }
157 return dap->__btree;
158}
159
160extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to,
161 struct xfs_da_intnode *from);
162extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to,
163 struct xfs_da3_icnode_hdr *from);
164
165#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize
166 27
167/*======================================================================== 28/*========================================================================
168 * Btree searching and modification structure definitions. 29 * Btree searching and modification structure definitions.
@@ -309,8 +170,6 @@ int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
309 xfs_dablk_t bno, xfs_daddr_t mappedbno, 170 xfs_dablk_t bno, xfs_daddr_t mappedbno,
310 struct xfs_buf **bpp, int which_fork); 171 struct xfs_buf **bpp, int which_fork);
311 172
312extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
313
314/* 173/*
315 * Utility routines. 174 * Utility routines.
316 */ 175 */
diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c
new file mode 100644
index 000000000000..e6c83e1fbc8a
--- /dev/null
+++ b/fs/xfs/xfs_da_format.c
@@ -0,0 +1,907 @@
1/*
2 * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
3 * Copyright (c) 2013 Red Hat, Inc.
4 * All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#include "xfs.h"
20#include "xfs_fs.h"
21#include "xfs_shared.h"
22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_mount.h"
28#include "xfs_da_format.h"
29#include "xfs_inode.h"
30#include "xfs_dir2.h"
31
32/*
33 * Shortform directory ops
34 */
35static int
36xfs_dir2_sf_entsize(
37 struct xfs_dir2_sf_hdr *hdr,
38 int len)
39{
40 int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
41
42 count += len; /* name */
43 count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
44 sizeof(xfs_dir2_ino4_t); /* ino # */
45 return count;
46}
47
48static int
49xfs_dir3_sf_entsize(
50 struct xfs_dir2_sf_hdr *hdr,
51 int len)
52{
53 return xfs_dir2_sf_entsize(hdr, len) + sizeof(__uint8_t);
54}
55
56static struct xfs_dir2_sf_entry *
57xfs_dir2_sf_nextentry(
58 struct xfs_dir2_sf_hdr *hdr,
59 struct xfs_dir2_sf_entry *sfep)
60{
61 return (struct xfs_dir2_sf_entry *)
62 ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen));
63}
64
65static struct xfs_dir2_sf_entry *
66xfs_dir3_sf_nextentry(
67 struct xfs_dir2_sf_hdr *hdr,
68 struct xfs_dir2_sf_entry *sfep)
69{
70 return (struct xfs_dir2_sf_entry *)
71 ((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen));
72}
73
74
75/*
76 * For filetype enabled shortform directories, the file type field is stored at
77 * the end of the name. Because it's only a single byte, endian conversion is
78 * not necessary. For non-filetype enable directories, the type is always
79 * unknown and we never store the value.
80 */
81static __uint8_t
82xfs_dir2_sfe_get_ftype(
83 struct xfs_dir2_sf_entry *sfep)
84{
85 return XFS_DIR3_FT_UNKNOWN;
86}
87
88static void
89xfs_dir2_sfe_put_ftype(
90 struct xfs_dir2_sf_entry *sfep,
91 __uint8_t ftype)
92{
93 ASSERT(ftype < XFS_DIR3_FT_MAX);
94}
95
96static __uint8_t
97xfs_dir3_sfe_get_ftype(
98 struct xfs_dir2_sf_entry *sfep)
99{
100 __uint8_t ftype;
101
102 ftype = sfep->name[sfep->namelen];
103 if (ftype >= XFS_DIR3_FT_MAX)
104 return XFS_DIR3_FT_UNKNOWN;
105 return ftype;
106}
107
108static void
109xfs_dir3_sfe_put_ftype(
110 struct xfs_dir2_sf_entry *sfep,
111 __uint8_t ftype)
112{
113 ASSERT(ftype < XFS_DIR3_FT_MAX);
114
115 sfep->name[sfep->namelen] = ftype;
116}
117
118/*
119 * Inode numbers in short-form directories can come in two versions,
120 * either 4 bytes or 8 bytes wide. These helpers deal with the
121 * two forms transparently by looking at the headers i8count field.
122 *
123 * For 64-bit inode number the most significant byte must be zero.
124 */
125static xfs_ino_t
126xfs_dir2_sf_get_ino(
127 struct xfs_dir2_sf_hdr *hdr,
128 xfs_dir2_inou_t *from)
129{
130 if (hdr->i8count)
131 return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
132 else
133 return get_unaligned_be32(&from->i4.i);
134}
135
136static void
137xfs_dir2_sf_put_ino(
138 struct xfs_dir2_sf_hdr *hdr,
139 xfs_dir2_inou_t *to,
140 xfs_ino_t ino)
141{
142 ASSERT((ino & 0xff00000000000000ULL) == 0);
143
144 if (hdr->i8count)
145 put_unaligned_be64(ino, &to->i8.i);
146 else
147 put_unaligned_be32(ino, &to->i4.i);
148}
149
150static xfs_ino_t
151xfs_dir2_sf_get_parent_ino(
152 struct xfs_dir2_sf_hdr *hdr)
153{
154 return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
155}
156
157static void
158xfs_dir2_sf_put_parent_ino(
159 struct xfs_dir2_sf_hdr *hdr,
160 xfs_ino_t ino)
161{
162 xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
163}
164
165/*
166 * In short-form directory entries the inode numbers are stored at variable
167 * offset behind the entry name. If the entry stores a filetype value, then it
168 * sits between the name and the inode number. Hence the inode numbers may only
169 * be accessed through the helpers below.
170 */
171static xfs_ino_t
172xfs_dir2_sfe_get_ino(
173 struct xfs_dir2_sf_hdr *hdr,
174 struct xfs_dir2_sf_entry *sfep)
175{
176 return xfs_dir2_sf_get_ino(hdr,
177 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen]);
178}
179
180static void
181xfs_dir2_sfe_put_ino(
182 struct xfs_dir2_sf_hdr *hdr,
183 struct xfs_dir2_sf_entry *sfep,
184 xfs_ino_t ino)
185{
186 xfs_dir2_sf_put_ino(hdr,
187 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen], ino);
188}
189
190static xfs_ino_t
191xfs_dir3_sfe_get_ino(
192 struct xfs_dir2_sf_hdr *hdr,
193 struct xfs_dir2_sf_entry *sfep)
194{
195 return xfs_dir2_sf_get_ino(hdr,
196 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1]);
197}
198
199static void
200xfs_dir3_sfe_put_ino(
201 struct xfs_dir2_sf_hdr *hdr,
202 struct xfs_dir2_sf_entry *sfep,
203 xfs_ino_t ino)
204{
205 xfs_dir2_sf_put_ino(hdr,
206 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino);
207}
208
209
210/*
211 * Directory data block operations
212 */
213
214/*
215 * For special situations, the dirent size ends up fixed because we always know
216 * what the size of the entry is. That's true for the "." and "..", and
217 * therefore we know that they are a fixed size and hence their offsets are
218 * constant, as is the first entry.
219 *
220 * Hence, this calculation is written as a macro to be able to be calculated at
221 * compile time and so certain offsets can be calculated directly in the
222 * structure initaliser via the macro. There are two macros - one for dirents
223 * with ftype and without so there are no unresolvable conditionals in the
224 * calculations. We also use round_up() as XFS_DIR2_DATA_ALIGN is always a power
225 * of 2 and the compiler doesn't reject it (unlike roundup()).
226 */
227#define XFS_DIR2_DATA_ENTSIZE(n) \
228 round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \
229 sizeof(xfs_dir2_data_off_t)), XFS_DIR2_DATA_ALIGN)
230
231#define XFS_DIR3_DATA_ENTSIZE(n) \
232 round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \
233 sizeof(xfs_dir2_data_off_t) + sizeof(__uint8_t)), \
234 XFS_DIR2_DATA_ALIGN)
235
236static int
237xfs_dir2_data_entsize(
238 int n)
239{
240 return XFS_DIR2_DATA_ENTSIZE(n);
241}
242
243static int
244xfs_dir3_data_entsize(
245 int n)
246{
247 return XFS_DIR3_DATA_ENTSIZE(n);
248}
249
250static __uint8_t
251xfs_dir2_data_get_ftype(
252 struct xfs_dir2_data_entry *dep)
253{
254 return XFS_DIR3_FT_UNKNOWN;
255}
256
257static void
258xfs_dir2_data_put_ftype(
259 struct xfs_dir2_data_entry *dep,
260 __uint8_t ftype)
261{
262 ASSERT(ftype < XFS_DIR3_FT_MAX);
263}
264
265static __uint8_t
266xfs_dir3_data_get_ftype(
267 struct xfs_dir2_data_entry *dep)
268{
269 __uint8_t ftype = dep->name[dep->namelen];
270
271 ASSERT(ftype < XFS_DIR3_FT_MAX);
272 if (ftype >= XFS_DIR3_FT_MAX)
273 return XFS_DIR3_FT_UNKNOWN;
274 return ftype;
275}
276
277static void
278xfs_dir3_data_put_ftype(
279 struct xfs_dir2_data_entry *dep,
280 __uint8_t type)
281{
282 ASSERT(type < XFS_DIR3_FT_MAX);
283 ASSERT(dep->namelen != 0);
284
285 dep->name[dep->namelen] = type;
286}
287
288/*
289 * Pointer to an entry's tag word.
290 */
291static __be16 *
292xfs_dir2_data_entry_tag_p(
293 struct xfs_dir2_data_entry *dep)
294{
295 return (__be16 *)((char *)dep +
296 xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
297}
298
299static __be16 *
300xfs_dir3_data_entry_tag_p(
301 struct xfs_dir2_data_entry *dep)
302{
303 return (__be16 *)((char *)dep +
304 xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16));
305}
306
307/*
308 * location of . and .. in data space (always block 0)
309 */
310static struct xfs_dir2_data_entry *
311xfs_dir2_data_dot_entry_p(
312 struct xfs_dir2_data_hdr *hdr)
313{
314 return (struct xfs_dir2_data_entry *)
315 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
316}
317
318static struct xfs_dir2_data_entry *
319xfs_dir2_data_dotdot_entry_p(
320 struct xfs_dir2_data_hdr *hdr)
321{
322 return (struct xfs_dir2_data_entry *)
323 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
324 XFS_DIR2_DATA_ENTSIZE(1));
325}
326
327static struct xfs_dir2_data_entry *
328xfs_dir2_data_first_entry_p(
329 struct xfs_dir2_data_hdr *hdr)
330{
331 return (struct xfs_dir2_data_entry *)
332 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
333 XFS_DIR2_DATA_ENTSIZE(1) +
334 XFS_DIR2_DATA_ENTSIZE(2));
335}
336
337static struct xfs_dir2_data_entry *
338xfs_dir2_ftype_data_dotdot_entry_p(
339 struct xfs_dir2_data_hdr *hdr)
340{
341 return (struct xfs_dir2_data_entry *)
342 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
343 XFS_DIR3_DATA_ENTSIZE(1));
344}
345
346static struct xfs_dir2_data_entry *
347xfs_dir2_ftype_data_first_entry_p(
348 struct xfs_dir2_data_hdr *hdr)
349{
350 return (struct xfs_dir2_data_entry *)
351 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
352 XFS_DIR3_DATA_ENTSIZE(1) +
353 XFS_DIR3_DATA_ENTSIZE(2));
354}
355
356static struct xfs_dir2_data_entry *
357xfs_dir3_data_dot_entry_p(
358 struct xfs_dir2_data_hdr *hdr)
359{
360 return (struct xfs_dir2_data_entry *)
361 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
362}
363
364static struct xfs_dir2_data_entry *
365xfs_dir3_data_dotdot_entry_p(
366 struct xfs_dir2_data_hdr *hdr)
367{
368 return (struct xfs_dir2_data_entry *)
369 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) +
370 XFS_DIR3_DATA_ENTSIZE(1));
371}
372
373static struct xfs_dir2_data_entry *
374xfs_dir3_data_first_entry_p(
375 struct xfs_dir2_data_hdr *hdr)
376{
377 return (struct xfs_dir2_data_entry *)
378 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) +
379 XFS_DIR3_DATA_ENTSIZE(1) +
380 XFS_DIR3_DATA_ENTSIZE(2));
381}
382
383static struct xfs_dir2_data_free *
384xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
385{
386 return hdr->bestfree;
387}
388
389static struct xfs_dir2_data_free *
390xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
391{
392 return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
393}
394
395static struct xfs_dir2_data_entry *
396xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr)
397{
398 return (struct xfs_dir2_data_entry *)
399 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
400}
401
402static struct xfs_dir2_data_unused *
403xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr)
404{
405 return (struct xfs_dir2_data_unused *)
406 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
407}
408
409static struct xfs_dir2_data_entry *
410xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
411{
412 return (struct xfs_dir2_data_entry *)
413 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
414}
415
416static struct xfs_dir2_data_unused *
417xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
418{
419 return (struct xfs_dir2_data_unused *)
420 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
421}
422
423
424/*
425 * Directory Leaf block operations
426 */
427static int
428xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
429{
430 return (mp->m_dirblksize - sizeof(struct xfs_dir2_leaf_hdr)) /
431 (uint)sizeof(struct xfs_dir2_leaf_entry);
432}
433
434static struct xfs_dir2_leaf_entry *
435xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp)
436{
437 return lp->__ents;
438}
439
440static int
441xfs_dir3_max_leaf_ents(struct xfs_mount *mp)
442{
443 return (mp->m_dirblksize - sizeof(struct xfs_dir3_leaf_hdr)) /
444 (uint)sizeof(struct xfs_dir2_leaf_entry);
445}
446
447static struct xfs_dir2_leaf_entry *
448xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
449{
450 return ((struct xfs_dir3_leaf *)lp)->__ents;
451}
452
453static void
454xfs_dir2_leaf_hdr_from_disk(
455 struct xfs_dir3_icleaf_hdr *to,
456 struct xfs_dir2_leaf *from)
457{
458 to->forw = be32_to_cpu(from->hdr.info.forw);
459 to->back = be32_to_cpu(from->hdr.info.back);
460 to->magic = be16_to_cpu(from->hdr.info.magic);
461 to->count = be16_to_cpu(from->hdr.count);
462 to->stale = be16_to_cpu(from->hdr.stale);
463
464 ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC ||
465 to->magic == XFS_DIR2_LEAFN_MAGIC);
466}
467
468static void
469xfs_dir2_leaf_hdr_to_disk(
470 struct xfs_dir2_leaf *to,
471 struct xfs_dir3_icleaf_hdr *from)
472{
473 ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC ||
474 from->magic == XFS_DIR2_LEAFN_MAGIC);
475
476 to->hdr.info.forw = cpu_to_be32(from->forw);
477 to->hdr.info.back = cpu_to_be32(from->back);
478 to->hdr.info.magic = cpu_to_be16(from->magic);
479 to->hdr.count = cpu_to_be16(from->count);
480 to->hdr.stale = cpu_to_be16(from->stale);
481}
482
483static void
484xfs_dir3_leaf_hdr_from_disk(
485 struct xfs_dir3_icleaf_hdr *to,
486 struct xfs_dir2_leaf *from)
487{
488 struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from;
489
490 to->forw = be32_to_cpu(hdr3->info.hdr.forw);
491 to->back = be32_to_cpu(hdr3->info.hdr.back);
492 to->magic = be16_to_cpu(hdr3->info.hdr.magic);
493 to->count = be16_to_cpu(hdr3->count);
494 to->stale = be16_to_cpu(hdr3->stale);
495
496 ASSERT(to->magic == XFS_DIR3_LEAF1_MAGIC ||
497 to->magic == XFS_DIR3_LEAFN_MAGIC);
498}
499
500static void
501xfs_dir3_leaf_hdr_to_disk(
502 struct xfs_dir2_leaf *to,
503 struct xfs_dir3_icleaf_hdr *from)
504{
505 struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to;
506
507 ASSERT(from->magic == XFS_DIR3_LEAF1_MAGIC ||
508 from->magic == XFS_DIR3_LEAFN_MAGIC);
509
510 hdr3->info.hdr.forw = cpu_to_be32(from->forw);
511 hdr3->info.hdr.back = cpu_to_be32(from->back);
512 hdr3->info.hdr.magic = cpu_to_be16(from->magic);
513 hdr3->count = cpu_to_be16(from->count);
514 hdr3->stale = cpu_to_be16(from->stale);
515}
516
517
518/*
519 * Directory/Attribute Node block operations
520 */
521static struct xfs_da_node_entry *
522xfs_da2_node_tree_p(struct xfs_da_intnode *dap)
523{
524 return dap->__btree;
525}
526
527static struct xfs_da_node_entry *
528xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
529{
530 return ((struct xfs_da3_intnode *)dap)->__btree;
531}
532
533static void
534xfs_da2_node_hdr_from_disk(
535 struct xfs_da3_icnode_hdr *to,
536 struct xfs_da_intnode *from)
537{
538 ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
539 to->forw = be32_to_cpu(from->hdr.info.forw);
540 to->back = be32_to_cpu(from->hdr.info.back);
541 to->magic = be16_to_cpu(from->hdr.info.magic);
542 to->count = be16_to_cpu(from->hdr.__count);
543 to->level = be16_to_cpu(from->hdr.__level);
544}
545
546static void
547xfs_da2_node_hdr_to_disk(
548 struct xfs_da_intnode *to,
549 struct xfs_da3_icnode_hdr *from)
550{
551 ASSERT(from->magic == XFS_DA_NODE_MAGIC);
552 to->hdr.info.forw = cpu_to_be32(from->forw);
553 to->hdr.info.back = cpu_to_be32(from->back);
554 to->hdr.info.magic = cpu_to_be16(from->magic);
555 to->hdr.__count = cpu_to_be16(from->count);
556 to->hdr.__level = cpu_to_be16(from->level);
557}
558
559static void
560xfs_da3_node_hdr_from_disk(
561 struct xfs_da3_icnode_hdr *to,
562 struct xfs_da_intnode *from)
563{
564 struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from;
565
566 ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC));
567 to->forw = be32_to_cpu(hdr3->info.hdr.forw);
568 to->back = be32_to_cpu(hdr3->info.hdr.back);
569 to->magic = be16_to_cpu(hdr3->info.hdr.magic);
570 to->count = be16_to_cpu(hdr3->__count);
571 to->level = be16_to_cpu(hdr3->__level);
572}
573
574static void
575xfs_da3_node_hdr_to_disk(
576 struct xfs_da_intnode *to,
577 struct xfs_da3_icnode_hdr *from)
578{
579 struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to;
580
581 ASSERT(from->magic == XFS_DA3_NODE_MAGIC);
582 hdr3->info.hdr.forw = cpu_to_be32(from->forw);
583 hdr3->info.hdr.back = cpu_to_be32(from->back);
584 hdr3->info.hdr.magic = cpu_to_be16(from->magic);
585 hdr3->__count = cpu_to_be16(from->count);
586 hdr3->__level = cpu_to_be16(from->level);
587}
588
589
590/*
591 * Directory free space block operations
592 */
593static int
594xfs_dir2_free_max_bests(struct xfs_mount *mp)
595{
596 return (mp->m_dirblksize - sizeof(struct xfs_dir2_free_hdr)) /
597 sizeof(xfs_dir2_data_off_t);
598}
599
600static __be16 *
601xfs_dir2_free_bests_p(struct xfs_dir2_free *free)
602{
603 return (__be16 *)((char *)free + sizeof(struct xfs_dir2_free_hdr));
604}
605
606/*
607 * Convert data space db to the corresponding free db.
608 */
609static xfs_dir2_db_t
610xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
611{
612 return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir2_free_max_bests(mp);
613}
614
615/*
616 * Convert data space db to the corresponding index in a free db.
617 */
618static int
619xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
620{
621 return db % xfs_dir2_free_max_bests(mp);
622}
623
624static int
625xfs_dir3_free_max_bests(struct xfs_mount *mp)
626{
627 return (mp->m_dirblksize - sizeof(struct xfs_dir3_free_hdr)) /
628 sizeof(xfs_dir2_data_off_t);
629}
630
631static __be16 *
632xfs_dir3_free_bests_p(struct xfs_dir2_free *free)
633{
634 return (__be16 *)((char *)free + sizeof(struct xfs_dir3_free_hdr));
635}
636
637/*
638 * Convert data space db to the corresponding free db.
639 */
640static xfs_dir2_db_t
641xfs_dir3_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
642{
643 return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
644}
645
646/*
647 * Convert data space db to the corresponding index in a free db.
648 */
649static int
650xfs_dir3_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
651{
652 return db % xfs_dir3_free_max_bests(mp);
653}
654
655static void
656xfs_dir2_free_hdr_from_disk(
657 struct xfs_dir3_icfree_hdr *to,
658 struct xfs_dir2_free *from)
659{
660 to->magic = be32_to_cpu(from->hdr.magic);
661 to->firstdb = be32_to_cpu(from->hdr.firstdb);
662 to->nvalid = be32_to_cpu(from->hdr.nvalid);
663 to->nused = be32_to_cpu(from->hdr.nused);
664 ASSERT(to->magic == XFS_DIR2_FREE_MAGIC);
665}
666
667static void
668xfs_dir2_free_hdr_to_disk(
669 struct xfs_dir2_free *to,
670 struct xfs_dir3_icfree_hdr *from)
671{
672 ASSERT(from->magic == XFS_DIR2_FREE_MAGIC);
673
674 to->hdr.magic = cpu_to_be32(from->magic);
675 to->hdr.firstdb = cpu_to_be32(from->firstdb);
676 to->hdr.nvalid = cpu_to_be32(from->nvalid);
677 to->hdr.nused = cpu_to_be32(from->nused);
678}
679
680static void
681xfs_dir3_free_hdr_from_disk(
682 struct xfs_dir3_icfree_hdr *to,
683 struct xfs_dir2_free *from)
684{
685 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from;
686
687 to->magic = be32_to_cpu(hdr3->hdr.magic);
688 to->firstdb = be32_to_cpu(hdr3->firstdb);
689 to->nvalid = be32_to_cpu(hdr3->nvalid);
690 to->nused = be32_to_cpu(hdr3->nused);
691
692 ASSERT(to->magic == XFS_DIR3_FREE_MAGIC);
693}
694
695static void
696xfs_dir3_free_hdr_to_disk(
697 struct xfs_dir2_free *to,
698 struct xfs_dir3_icfree_hdr *from)
699{
700 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to;
701
702 ASSERT(from->magic == XFS_DIR3_FREE_MAGIC);
703
704 hdr3->hdr.magic = cpu_to_be32(from->magic);
705 hdr3->firstdb = cpu_to_be32(from->firstdb);
706 hdr3->nvalid = cpu_to_be32(from->nvalid);
707 hdr3->nused = cpu_to_be32(from->nused);
708}
709
710static const struct xfs_dir_ops xfs_dir2_ops = {
711 .sf_entsize = xfs_dir2_sf_entsize,
712 .sf_nextentry = xfs_dir2_sf_nextentry,
713 .sf_get_ftype = xfs_dir2_sfe_get_ftype,
714 .sf_put_ftype = xfs_dir2_sfe_put_ftype,
715 .sf_get_ino = xfs_dir2_sfe_get_ino,
716 .sf_put_ino = xfs_dir2_sfe_put_ino,
717 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
718 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
719
720 .data_entsize = xfs_dir2_data_entsize,
721 .data_get_ftype = xfs_dir2_data_get_ftype,
722 .data_put_ftype = xfs_dir2_data_put_ftype,
723 .data_entry_tag_p = xfs_dir2_data_entry_tag_p,
724 .data_bestfree_p = xfs_dir2_data_bestfree_p,
725
726 .data_dot_offset = sizeof(struct xfs_dir2_data_hdr),
727 .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) +
728 XFS_DIR2_DATA_ENTSIZE(1),
729 .data_first_offset = sizeof(struct xfs_dir2_data_hdr) +
730 XFS_DIR2_DATA_ENTSIZE(1) +
731 XFS_DIR2_DATA_ENTSIZE(2),
732 .data_entry_offset = sizeof(struct xfs_dir2_data_hdr),
733
734 .data_dot_entry_p = xfs_dir2_data_dot_entry_p,
735 .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p,
736 .data_first_entry_p = xfs_dir2_data_first_entry_p,
737 .data_entry_p = xfs_dir2_data_entry_p,
738 .data_unused_p = xfs_dir2_data_unused_p,
739
740 .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr),
741 .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk,
742 .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk,
743 .leaf_max_ents = xfs_dir2_max_leaf_ents,
744 .leaf_ents_p = xfs_dir2_leaf_ents_p,
745
746 .node_hdr_size = sizeof(struct xfs_da_node_hdr),
747 .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
748 .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
749 .node_tree_p = xfs_da2_node_tree_p,
750
751 .free_hdr_size = sizeof(struct xfs_dir2_free_hdr),
752 .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk,
753 .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk,
754 .free_max_bests = xfs_dir2_free_max_bests,
755 .free_bests_p = xfs_dir2_free_bests_p,
756 .db_to_fdb = xfs_dir2_db_to_fdb,
757 .db_to_fdindex = xfs_dir2_db_to_fdindex,
758};
759
760static const struct xfs_dir_ops xfs_dir2_ftype_ops = {
761 .sf_entsize = xfs_dir3_sf_entsize,
762 .sf_nextentry = xfs_dir3_sf_nextentry,
763 .sf_get_ftype = xfs_dir3_sfe_get_ftype,
764 .sf_put_ftype = xfs_dir3_sfe_put_ftype,
765 .sf_get_ino = xfs_dir3_sfe_get_ino,
766 .sf_put_ino = xfs_dir3_sfe_put_ino,
767 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
768 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
769
770 .data_entsize = xfs_dir3_data_entsize,
771 .data_get_ftype = xfs_dir3_data_get_ftype,
772 .data_put_ftype = xfs_dir3_data_put_ftype,
773 .data_entry_tag_p = xfs_dir3_data_entry_tag_p,
774 .data_bestfree_p = xfs_dir2_data_bestfree_p,
775
776 .data_dot_offset = sizeof(struct xfs_dir2_data_hdr),
777 .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) +
778 XFS_DIR3_DATA_ENTSIZE(1),
779 .data_first_offset = sizeof(struct xfs_dir2_data_hdr) +
780 XFS_DIR3_DATA_ENTSIZE(1) +
781 XFS_DIR3_DATA_ENTSIZE(2),
782 .data_entry_offset = sizeof(struct xfs_dir2_data_hdr),
783
784 .data_dot_entry_p = xfs_dir2_data_dot_entry_p,
785 .data_dotdot_entry_p = xfs_dir2_ftype_data_dotdot_entry_p,
786 .data_first_entry_p = xfs_dir2_ftype_data_first_entry_p,
787 .data_entry_p = xfs_dir2_data_entry_p,
788 .data_unused_p = xfs_dir2_data_unused_p,
789
790 .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr),
791 .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk,
792 .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk,
793 .leaf_max_ents = xfs_dir2_max_leaf_ents,
794 .leaf_ents_p = xfs_dir2_leaf_ents_p,
795
796 .node_hdr_size = sizeof(struct xfs_da_node_hdr),
797 .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
798 .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
799 .node_tree_p = xfs_da2_node_tree_p,
800
801 .free_hdr_size = sizeof(struct xfs_dir2_free_hdr),
802 .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk,
803 .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk,
804 .free_max_bests = xfs_dir2_free_max_bests,
805 .free_bests_p = xfs_dir2_free_bests_p,
806 .db_to_fdb = xfs_dir2_db_to_fdb,
807 .db_to_fdindex = xfs_dir2_db_to_fdindex,
808};
809
810static const struct xfs_dir_ops xfs_dir3_ops = {
811 .sf_entsize = xfs_dir3_sf_entsize,
812 .sf_nextentry = xfs_dir3_sf_nextentry,
813 .sf_get_ftype = xfs_dir3_sfe_get_ftype,
814 .sf_put_ftype = xfs_dir3_sfe_put_ftype,
815 .sf_get_ino = xfs_dir3_sfe_get_ino,
816 .sf_put_ino = xfs_dir3_sfe_put_ino,
817 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
818 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
819
820 .data_entsize = xfs_dir3_data_entsize,
821 .data_get_ftype = xfs_dir3_data_get_ftype,
822 .data_put_ftype = xfs_dir3_data_put_ftype,
823 .data_entry_tag_p = xfs_dir3_data_entry_tag_p,
824 .data_bestfree_p = xfs_dir3_data_bestfree_p,
825
826 .data_dot_offset = sizeof(struct xfs_dir3_data_hdr),
827 .data_dotdot_offset = sizeof(struct xfs_dir3_data_hdr) +
828 XFS_DIR3_DATA_ENTSIZE(1),
829 .data_first_offset = sizeof(struct xfs_dir3_data_hdr) +
830 XFS_DIR3_DATA_ENTSIZE(1) +
831 XFS_DIR3_DATA_ENTSIZE(2),
832 .data_entry_offset = sizeof(struct xfs_dir3_data_hdr),
833
834 .data_dot_entry_p = xfs_dir3_data_dot_entry_p,
835 .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p,
836 .data_first_entry_p = xfs_dir3_data_first_entry_p,
837 .data_entry_p = xfs_dir3_data_entry_p,
838 .data_unused_p = xfs_dir3_data_unused_p,
839
840 .leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr),
841 .leaf_hdr_to_disk = xfs_dir3_leaf_hdr_to_disk,
842 .leaf_hdr_from_disk = xfs_dir3_leaf_hdr_from_disk,
843 .leaf_max_ents = xfs_dir3_max_leaf_ents,
844 .leaf_ents_p = xfs_dir3_leaf_ents_p,
845
846 .node_hdr_size = sizeof(struct xfs_da3_node_hdr),
847 .node_hdr_to_disk = xfs_da3_node_hdr_to_disk,
848 .node_hdr_from_disk = xfs_da3_node_hdr_from_disk,
849 .node_tree_p = xfs_da3_node_tree_p,
850
851 .free_hdr_size = sizeof(struct xfs_dir3_free_hdr),
852 .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk,
853 .free_hdr_from_disk = xfs_dir3_free_hdr_from_disk,
854 .free_max_bests = xfs_dir3_free_max_bests,
855 .free_bests_p = xfs_dir3_free_bests_p,
856 .db_to_fdb = xfs_dir3_db_to_fdb,
857 .db_to_fdindex = xfs_dir3_db_to_fdindex,
858};
859
860static const struct xfs_dir_ops xfs_dir2_nondir_ops = {
861 .node_hdr_size = sizeof(struct xfs_da_node_hdr),
862 .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
863 .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
864 .node_tree_p = xfs_da2_node_tree_p,
865};
866
867static const struct xfs_dir_ops xfs_dir3_nondir_ops = {
868 .node_hdr_size = sizeof(struct xfs_da3_node_hdr),
869 .node_hdr_to_disk = xfs_da3_node_hdr_to_disk,
870 .node_hdr_from_disk = xfs_da3_node_hdr_from_disk,
871 .node_tree_p = xfs_da3_node_tree_p,
872};
873
874/*
875 * Return the ops structure according to the current config. If we are passed
876 * an inode, then that overrides the default config we use which is based on
877 * feature bits.
878 */
879const struct xfs_dir_ops *
880xfs_dir_get_ops(
881 struct xfs_mount *mp,
882 struct xfs_inode *dp)
883{
884 if (dp)
885 return dp->d_ops;
886 if (mp->m_dir_inode_ops)
887 return mp->m_dir_inode_ops;
888 if (xfs_sb_version_hascrc(&mp->m_sb))
889 return &xfs_dir3_ops;
890 if (xfs_sb_version_hasftype(&mp->m_sb))
891 return &xfs_dir2_ftype_ops;
892 return &xfs_dir2_ops;
893}
894
895const struct xfs_dir_ops *
896xfs_nondir_get_ops(
897 struct xfs_mount *mp,
898 struct xfs_inode *dp)
899{
900 if (dp)
901 return dp->d_ops;
902 if (mp->m_nondir_inode_ops)
903 return mp->m_nondir_inode_ops;
904 if (xfs_sb_version_hascrc(&mp->m_sb))
905 return &xfs_dir3_nondir_ops;
906 return &xfs_dir2_nondir_ops;
907}
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_da_format.h
index 9cf67381adf6..a19d3f8f639c 100644
--- a/fs/xfs/xfs_dir2_format.h
+++ b/fs/xfs/xfs_da_format.h
@@ -16,8 +16,113 @@
16 * along with this program; if not, write the Free Software Foundation, 16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */ 18 */
19#ifndef __XFS_DIR2_FORMAT_H__ 19#ifndef __XFS_DA_FORMAT_H__
20#define __XFS_DIR2_FORMAT_H__ 20#define __XFS_DA_FORMAT_H__
21
22/*========================================================================
23 * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
24 *========================================================================*/
25
26/*
27 * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
28 *
29 * It is used to manage a doubly linked list of all blocks at the same
30 * level in the Btree, and to identify which type of block this is.
31 */
32#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
33#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
34#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
35#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
36
37typedef struct xfs_da_blkinfo {
38 __be32 forw; /* previous block in list */
39 __be32 back; /* following block in list */
40 __be16 magic; /* validity check on block */
41 __be16 pad; /* unused */
42} xfs_da_blkinfo_t;
43
44/*
45 * CRC enabled directory structure types
46 *
47 * The headers change size for the additional verification information, but
48 * otherwise the tree layouts and contents are unchanged. Hence the da btree
49 * code can use the struct xfs_da_blkinfo for manipulating the tree links and
50 * magic numbers without modification for both v2 and v3 nodes.
51 */
52#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */
53#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */
54#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */
55#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */
56
57struct xfs_da3_blkinfo {
58 /*
59 * the node link manipulation code relies on the fact that the first
60 * element of this structure is the struct xfs_da_blkinfo so it can
61 * ignore the differences in the rest of the structures.
62 */
63 struct xfs_da_blkinfo hdr;
64 __be32 crc; /* CRC of block */
65 __be64 blkno; /* first block of the buffer */
66 __be64 lsn; /* sequence number of last write */
67 uuid_t uuid; /* filesystem we belong to */
68 __be64 owner; /* inode that owns the block */
69};
70
71/*
72 * This is the structure of the root and intermediate nodes in the Btree.
73 * The leaf nodes are defined above.
74 *
75 * Entries are not packed.
76 *
77 * Since we have duplicate keys, use a binary search but always follow
78 * all match in the block, not just the first match found.
79 */
80#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */
81
82typedef struct xfs_da_node_hdr {
83 struct xfs_da_blkinfo info; /* block type, links, etc. */
84 __be16 __count; /* count of active entries */
85 __be16 __level; /* level above leaves (leaf == 0) */
86} xfs_da_node_hdr_t;
87
88struct xfs_da3_node_hdr {
89 struct xfs_da3_blkinfo info; /* block type, links, etc. */
90 __be16 __count; /* count of active entries */
91 __be16 __level; /* level above leaves (leaf == 0) */
92 __be32 __pad32;
93};
94
95#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc))
96
97typedef struct xfs_da_node_entry {
98 __be32 hashval; /* hash value for this descendant */
99 __be32 before; /* Btree block before this key */
100} xfs_da_node_entry_t;
101
102typedef struct xfs_da_intnode {
103 struct xfs_da_node_hdr hdr;
104 struct xfs_da_node_entry __btree[];
105} xfs_da_intnode_t;
106
107struct xfs_da3_intnode {
108 struct xfs_da3_node_hdr hdr;
109 struct xfs_da_node_entry __btree[];
110};
111
112/*
113 * In-core version of the node header to abstract the differences in the v2 and
114 * v3 disk format of the headers. Callers need to convert to/from disk format as
115 * appropriate.
116 */
117struct xfs_da3_icnode_hdr {
118 __uint32_t forw;
119 __uint32_t back;
120 __uint16_t magic;
121 __uint16_t count;
122 __uint16_t level;
123};
124
125#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize
21 126
22/* 127/*
23 * Directory version 2. 128 * Directory version 2.
@@ -189,79 +294,6 @@ xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
189 ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); 294 ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count));
190} 295}
191 296
192static inline int
193xfs_dir3_sf_entsize(
194 struct xfs_mount *mp,
195 struct xfs_dir2_sf_hdr *hdr,
196 int len)
197{
198 int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
199
200 count += len; /* name */
201 count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
202 sizeof(xfs_dir2_ino4_t); /* ino # */
203 if (xfs_sb_version_hasftype(&mp->m_sb))
204 count += sizeof(__uint8_t); /* file type */
205 return count;
206}
207
208static inline struct xfs_dir2_sf_entry *
209xfs_dir3_sf_nextentry(
210 struct xfs_mount *mp,
211 struct xfs_dir2_sf_hdr *hdr,
212 struct xfs_dir2_sf_entry *sfep)
213{
214 return (struct xfs_dir2_sf_entry *)
215 ((char *)sfep + xfs_dir3_sf_entsize(mp, hdr, sfep->namelen));
216}
217
218/*
219 * in dir3 shortform directories, the file type field is stored at a variable
220 * offset after the inode number. Because it's only a single byte, endian
221 * conversion is not necessary.
222 */
223static inline __uint8_t *
224xfs_dir3_sfe_ftypep(
225 struct xfs_dir2_sf_hdr *hdr,
226 struct xfs_dir2_sf_entry *sfep)
227{
228 return (__uint8_t *)&sfep->name[sfep->namelen];
229}
230
231static inline __uint8_t
232xfs_dir3_sfe_get_ftype(
233 struct xfs_mount *mp,
234 struct xfs_dir2_sf_hdr *hdr,
235 struct xfs_dir2_sf_entry *sfep)
236{
237 __uint8_t *ftp;
238
239 if (!xfs_sb_version_hasftype(&mp->m_sb))
240 return XFS_DIR3_FT_UNKNOWN;
241
242 ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
243 if (*ftp >= XFS_DIR3_FT_MAX)
244 return XFS_DIR3_FT_UNKNOWN;
245 return *ftp;
246}
247
248static inline void
249xfs_dir3_sfe_put_ftype(
250 struct xfs_mount *mp,
251 struct xfs_dir2_sf_hdr *hdr,
252 struct xfs_dir2_sf_entry *sfep,
253 __uint8_t ftype)
254{
255 __uint8_t *ftp;
256
257 ASSERT(ftype < XFS_DIR3_FT_MAX);
258
259 if (!xfs_sb_version_hasftype(&mp->m_sb))
260 return;
261 ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
262 *ftp = ftype;
263}
264
265/* 297/*
266 * Data block structures. 298 * Data block structures.
267 * 299 *
@@ -345,17 +377,6 @@ struct xfs_dir3_data_hdr {
345 377
346#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) 378#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc)
347 379
348static inline struct xfs_dir2_data_free *
349xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
350{
351 if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
352 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
353 struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
354 return hdr3->best_free;
355 }
356 return hdr->bestfree;
357}
358
359/* 380/*
360 * Active entry in a data block. 381 * Active entry in a data block.
361 * 382 *
@@ -389,72 +410,6 @@ typedef struct xfs_dir2_data_unused {
389} xfs_dir2_data_unused_t; 410} xfs_dir2_data_unused_t;
390 411
391/* 412/*
392 * Size of a data entry.
393 */
394static inline int
395__xfs_dir3_data_entsize(
396 bool ftype,
397 int n)
398{
399 int size = offsetof(struct xfs_dir2_data_entry, name[0]);
400
401 size += n;
402 size += sizeof(xfs_dir2_data_off_t);
403 if (ftype)
404 size += sizeof(__uint8_t);
405 return roundup(size, XFS_DIR2_DATA_ALIGN);
406}
407static inline int
408xfs_dir3_data_entsize(
409 struct xfs_mount *mp,
410 int n)
411{
412 bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
413 return __xfs_dir3_data_entsize(ftype, n);
414}
415
416static inline __uint8_t
417xfs_dir3_dirent_get_ftype(
418 struct xfs_mount *mp,
419 struct xfs_dir2_data_entry *dep)
420{
421 if (xfs_sb_version_hasftype(&mp->m_sb)) {
422 __uint8_t type = dep->name[dep->namelen];
423
424 ASSERT(type < XFS_DIR3_FT_MAX);
425 if (type < XFS_DIR3_FT_MAX)
426 return type;
427
428 }
429 return XFS_DIR3_FT_UNKNOWN;
430}
431
432static inline void
433xfs_dir3_dirent_put_ftype(
434 struct xfs_mount *mp,
435 struct xfs_dir2_data_entry *dep,
436 __uint8_t type)
437{
438 ASSERT(type < XFS_DIR3_FT_MAX);
439 ASSERT(dep->namelen != 0);
440
441 if (xfs_sb_version_hasftype(&mp->m_sb))
442 dep->name[dep->namelen] = type;
443}
444
445/*
446 * Pointer to an entry's tag word.
447 */
448static inline __be16 *
449xfs_dir3_data_entry_tag_p(
450 struct xfs_mount *mp,
451 struct xfs_dir2_data_entry *dep)
452{
453 return (__be16 *)((char *)dep +
454 xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
455}
456
457/*
458 * Pointer to a freespace's tag word. 413 * Pointer to a freespace's tag word.
459 */ 414 */
460static inline __be16 * 415static inline __be16 *
@@ -464,93 +419,6 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
464 be16_to_cpu(dup->length) - sizeof(__be16)); 419 be16_to_cpu(dup->length) - sizeof(__be16));
465} 420}
466 421
467static inline size_t
468xfs_dir3_data_hdr_size(bool dir3)
469{
470 if (dir3)
471 return sizeof(struct xfs_dir3_data_hdr);
472 return sizeof(struct xfs_dir2_data_hdr);
473}
474
475static inline size_t
476xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr)
477{
478 bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
479 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
480 return xfs_dir3_data_hdr_size(dir3);
481}
482
483static inline struct xfs_dir2_data_entry *
484xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
485{
486 return (struct xfs_dir2_data_entry *)
487 ((char *)hdr + xfs_dir3_data_entry_offset(hdr));
488}
489
490static inline struct xfs_dir2_data_unused *
491xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
492{
493 return (struct xfs_dir2_data_unused *)
494 ((char *)hdr + xfs_dir3_data_entry_offset(hdr));
495}
496
497/*
498 * Offsets of . and .. in data space (always block 0)
499 *
500 * XXX: there is scope for significant optimisation of the logic here. Right
501 * now we are checking for "dir3 format" over and over again. Ideally we should
502 * only do it once for each operation.
503 */
504static inline xfs_dir2_data_aoff_t
505xfs_dir3_data_dot_offset(struct xfs_mount *mp)
506{
507 return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
508}
509
510static inline xfs_dir2_data_aoff_t
511xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
512{
513 return xfs_dir3_data_dot_offset(mp) +
514 xfs_dir3_data_entsize(mp, 1);
515}
516
517static inline xfs_dir2_data_aoff_t
518xfs_dir3_data_first_offset(struct xfs_mount *mp)
519{
520 return xfs_dir3_data_dotdot_offset(mp) +
521 xfs_dir3_data_entsize(mp, 2);
522}
523
524/*
525 * location of . and .. in data space (always block 0)
526 */
527static inline struct xfs_dir2_data_entry *
528xfs_dir3_data_dot_entry_p(
529 struct xfs_mount *mp,
530 struct xfs_dir2_data_hdr *hdr)
531{
532 return (struct xfs_dir2_data_entry *)
533 ((char *)hdr + xfs_dir3_data_dot_offset(mp));
534}
535
536static inline struct xfs_dir2_data_entry *
537xfs_dir3_data_dotdot_entry_p(
538 struct xfs_mount *mp,
539 struct xfs_dir2_data_hdr *hdr)
540{
541 return (struct xfs_dir2_data_entry *)
542 ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
543}
544
545static inline struct xfs_dir2_data_entry *
546xfs_dir3_data_first_entry_p(
547 struct xfs_mount *mp,
548 struct xfs_dir2_data_hdr *hdr)
549{
550 return (struct xfs_dir2_data_entry *)
551 ((char *)hdr + xfs_dir3_data_first_offset(mp));
552}
553
554/* 422/*
555 * Leaf block structures. 423 * Leaf block structures.
556 * 424 *
@@ -645,39 +513,6 @@ struct xfs_dir3_leaf {
645 513
646#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) 514#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc)
647 515
648extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
649 struct xfs_dir2_leaf *from);
650
651static inline int
652xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp)
653{
654 if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
655 lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
656 return sizeof(struct xfs_dir3_leaf_hdr);
657 return sizeof(struct xfs_dir2_leaf_hdr);
658}
659
660static inline int
661xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
662{
663 return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) /
664 (uint)sizeof(struct xfs_dir2_leaf_entry);
665}
666
667/*
668 * Get address of the bestcount field in the single-leaf block.
669 */
670static inline struct xfs_dir2_leaf_entry *
671xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
672{
673 if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
674 lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
675 struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp;
676 return lp3->__ents;
677 }
678 return lp->__ents;
679}
680
681/* 516/*
682 * Get address of the bestcount field in the single-leaf block. 517 * Get address of the bestcount field in the single-leaf block.
683 */ 518 */
@@ -869,48 +704,6 @@ struct xfs_dir3_icfree_hdr {
869 704
870}; 705};
871 706
872void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
873 struct xfs_dir2_free *from);
874
875static inline int
876xfs_dir3_free_hdr_size(struct xfs_mount *mp)
877{
878 if (xfs_sb_version_hascrc(&mp->m_sb))
879 return sizeof(struct xfs_dir3_free_hdr);
880 return sizeof(struct xfs_dir2_free_hdr);
881}
882
883static inline int
884xfs_dir3_free_max_bests(struct xfs_mount *mp)
885{
886 return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
887 sizeof(xfs_dir2_data_off_t);
888}
889
890static inline __be16 *
891xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
892{
893 return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
894}
895
896/*
897 * Convert data space db to the corresponding free db.
898 */
899static inline xfs_dir2_db_t
900xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
901{
902 return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
903}
904
905/*
906 * Convert data space db to the corresponding index in a free db.
907 */
908static inline int
909xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
910{
911 return db % xfs_dir3_free_max_bests(mp);
912}
913
914/* 707/*
915 * Single block format. 708 * Single block format.
916 * 709 *
@@ -961,4 +754,262 @@ xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
961 return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); 754 return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
962} 755}
963 756
964#endif /* __XFS_DIR2_FORMAT_H__ */ 757
758/*
759 * Attribute storage layout
760 *
761 * Attribute lists are structured around Btrees where all the data
762 * elements are in the leaf nodes. Attribute names are hashed into an int,
763 * then that int is used as the index into the Btree. Since the hashval
764 * of an attribute name may not be unique, we may have duplicate keys. The
765 * internal links in the Btree are logical block offsets into the file.
766 *
767 *========================================================================
768 * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
769 *========================================================================
770 *
771 * Struct leaf_entry's are packed from the top. Name/values grow from the
772 * bottom but are not packed. The freemap contains run-length-encoded entries
773 * for the free bytes after the leaf_entry's, but only the N largest such,
774 * smaller runs are dropped. When the freemap doesn't show enough space
775 * for an allocation, we compact the name/value area and try again. If we
776 * still don't have enough space, then we have to split the block. The
777 * name/value structs (both local and remote versions) must be 32bit aligned.
778 *
779 * Since we have duplicate hash keys, for each key that matches, compare
780 * the actual name string. The root and intermediate node search always
781 * takes the first-in-the-block key match found, so we should only have
782 * to work "forw"ard. If none matches, continue with the "forw"ard leaf
783 * nodes until the hash key changes or the attribute name is found.
784 *
785 * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
786 * the leaf_entry. The namespaces are independent only because we also look
787 * at the namespace bit when we are looking for a matching attribute name.
788 *
789 * We also store an "incomplete" bit in the leaf_entry. It shows that an
790 * attribute is in the middle of being created and should not be shown to
791 * the user if we crash during the time that the bit is set. We clear the
792 * bit when we have finished setting up the attribute. We do this because
793 * we cannot create some large attributes inside a single transaction, and we
794 * need some indication that we weren't finished if we crash in the middle.
795 */
796#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
797
798typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
799 __be16 base; /* base of free region */
800 __be16 size; /* length of free region */
801} xfs_attr_leaf_map_t;
802
803typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
804 xfs_da_blkinfo_t info; /* block type, links, etc. */
805 __be16 count; /* count of active leaf_entry's */
806 __be16 usedbytes; /* num bytes of names/values stored */
807 __be16 firstused; /* first used byte in name area */
808 __u8 holes; /* != 0 if blk needs compaction */
809 __u8 pad1;
810 xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
811 /* N largest free regions */
812} xfs_attr_leaf_hdr_t;
813
814typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
815 __be32 hashval; /* hash value of name */
816 __be16 nameidx; /* index into buffer of name/value */
817 __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
818 __u8 pad2; /* unused pad byte */
819} xfs_attr_leaf_entry_t;
820
821typedef struct xfs_attr_leaf_name_local {
822 __be16 valuelen; /* number of bytes in value */
823 __u8 namelen; /* length of name bytes */
824 __u8 nameval[1]; /* name/value bytes */
825} xfs_attr_leaf_name_local_t;
826
827typedef struct xfs_attr_leaf_name_remote {
828 __be32 valueblk; /* block number of value bytes */
829 __be32 valuelen; /* number of bytes in value */
830 __u8 namelen; /* length of name bytes */
831 __u8 name[1]; /* name bytes */
832} xfs_attr_leaf_name_remote_t;
833
834typedef struct xfs_attr_leafblock {
835 xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
836 xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
837 xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
838 xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
839} xfs_attr_leafblock_t;
840
841/*
842 * CRC enabled leaf structures. Called "version 3" structures to match the
843 * version number of the directory and dablk structures for this feature, and
844 * attr2 is already taken by the variable inode attribute fork size feature.
845 */
846struct xfs_attr3_leaf_hdr {
847 struct xfs_da3_blkinfo info;
848 __be16 count;
849 __be16 usedbytes;
850 __be16 firstused;
851 __u8 holes;
852 __u8 pad1;
853 struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE];
854 __be32 pad2; /* 64 bit alignment */
855};
856
857#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc))
858
859struct xfs_attr3_leafblock {
860 struct xfs_attr3_leaf_hdr hdr;
861 struct xfs_attr_leaf_entry entries[1];
862
863 /*
864 * The rest of the block contains the following structures after the
865 * leaf entries, growing from the bottom up. The variables are never
866 * referenced, the locations accessed purely from helper functions.
867 *
868 * struct xfs_attr_leaf_name_local
869 * struct xfs_attr_leaf_name_remote
870 */
871};
872
873/*
874 * incore, neutral version of the attribute leaf header
875 */
876struct xfs_attr3_icleaf_hdr {
877 __uint32_t forw;
878 __uint32_t back;
879 __uint16_t magic;
880 __uint16_t count;
881 __uint16_t usedbytes;
882 __uint16_t firstused;
883 __u8 holes;
884 struct {
885 __uint16_t base;
886 __uint16_t size;
887 } freemap[XFS_ATTR_LEAF_MAPSIZE];
888};
889
890/*
891 * Flags used in the leaf_entry[i].flags field.
892 * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
893 * on the system call, they are "or"ed together for various operations.
894 */
895#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
896#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
897#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
898#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
899#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
900#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
901#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
902#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
903
904/*
905 * Conversion macros for converting namespace bits from argument flags
906 * to ondisk flags.
907 */
908#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
909#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
910#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
911#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
912#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
913 ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
914#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
915 ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
916
917/*
918 * Alignment for namelist and valuelist entries (since they are mixed
919 * there can be only one alignment value)
920 */
921#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))
922
923static inline int
924xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp)
925{
926 if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
927 return sizeof(struct xfs_attr3_leaf_hdr);
928 return sizeof(struct xfs_attr_leaf_hdr);
929}
930
931static inline struct xfs_attr_leaf_entry *
932xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp)
933{
934 if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
935 return &((struct xfs_attr3_leafblock *)leafp)->entries[0];
936 return &leafp->entries[0];
937}
938
939/*
940 * Cast typed pointers for "local" and "remote" name/value structs.
941 */
942static inline char *
943xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
944{
945 struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp);
946
947 return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)];
948}
949
950static inline xfs_attr_leaf_name_remote_t *
951xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
952{
953 return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx);
954}
955
956static inline xfs_attr_leaf_name_local_t *
957xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
958{
959 return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx);
960}
961
962/*
963 * Calculate total bytes used (including trailing pad for alignment) for
964 * a "local" name/value structure, a "remote" name/value structure, and
965 * a pointer which might be either.
966 */
967static inline int xfs_attr_leaf_entsize_remote(int nlen)
968{
969 return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
970 XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
971}
972
973static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
974{
975 return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
976 XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
977}
978
979static inline int xfs_attr_leaf_entsize_local_max(int bsize)
980{
981 return (((bsize) >> 1) + ((bsize) >> 2));
982}
983
984
985
986/*
987 * Remote attribute block format definition
988 *
989 * There is one of these headers per filesystem block in a remote attribute.
990 * This is done to ensure there is a 1:1 mapping between the attribute value
991 * length and the number of blocks needed to store the attribute. This makes the
992 * verification of a buffer a little more complex, but greatly simplifies the
993 * allocation, reading and writing of these attributes as we don't have to guess
994 * the number of blocks needed to store the attribute data.
995 */
996#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */
997
998struct xfs_attr3_rmt_hdr {
999 __be32 rm_magic;
1000 __be32 rm_offset;
1001 __be32 rm_bytes;
1002 __be32 rm_crc;
1003 uuid_t rm_uuid;
1004 __be64 rm_owner;
1005 __be64 rm_blkno;
1006 __be64 rm_lsn;
1007};
1008
1009#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc)
1010
1011#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \
1012 ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
1013 sizeof(struct xfs_attr3_rmt_hdr) : 0))
1014
1015#endif /* __XFS_DA_FORMAT_H__ */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index edf203ab50af..ce16ef02997a 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -17,25 +17,24 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_format.h"
21#include "xfs_log.h" 21#include "xfs_log_format.h"
22#include "xfs_trans_resv.h"
22#include "xfs_inum.h" 23#include "xfs_inum.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_mount.h" 26#include "xfs_mount.h"
27#include "xfs_da_format.h"
27#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_alloc_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 29#include "xfs_inode.h"
30#include "xfs_trans.h"
32#include "xfs_inode_item.h" 31#include "xfs_inode_item.h"
33#include "xfs_bmap.h" 32#include "xfs_bmap.h"
34#include "xfs_dir2_format.h"
35#include "xfs_dir2.h" 33#include "xfs_dir2.h"
36#include "xfs_dir2_priv.h" 34#include "xfs_dir2_priv.h"
37#include "xfs_error.h" 35#include "xfs_error.h"
38#include "xfs_trace.h" 36#include "xfs_trace.h"
37#include "xfs_dinode.h"
39 38
40struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; 39struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
41 40
@@ -96,13 +95,17 @@ xfs_dir_mount(
96 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); 95 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb));
97 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= 96 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
98 XFS_MAX_BLOCKSIZE); 97 XFS_MAX_BLOCKSIZE);
98
99 mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
100 mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
101
99 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); 102 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
100 mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog; 103 mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
101 mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp)); 104 mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp));
102 mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); 105 mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
103 mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); 106 mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp));
104 107
105 nodehdr_size = __xfs_da3_node_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); 108 nodehdr_size = mp->m_dir_inode_ops->node_hdr_size;
106 mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / 109 mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) /
107 (uint)sizeof(xfs_da_node_entry_t); 110 (uint)sizeof(xfs_da_node_entry_t);
108 mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / 111 mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) /
@@ -113,6 +116,7 @@ xfs_dir_mount(
113 mp->m_dirnameops = &xfs_ascii_ci_nameops; 116 mp->m_dirnameops = &xfs_ascii_ci_nameops;
114 else 117 else
115 mp->m_dirnameops = &xfs_default_nameops; 118 mp->m_dirnameops = &xfs_default_nameops;
119
116} 120}
117 121
118/* 122/*
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 9910401327d4..cec70e0781ab 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -32,6 +32,83 @@ struct xfs_dir2_data_unused;
32extern struct xfs_name xfs_name_dotdot; 32extern struct xfs_name xfs_name_dotdot;
33 33
34/* 34/*
35 * directory operations vector for encode/decode routines
36 */
37struct xfs_dir_ops {
38 int (*sf_entsize)(struct xfs_dir2_sf_hdr *hdr, int len);
39 struct xfs_dir2_sf_entry *
40 (*sf_nextentry)(struct xfs_dir2_sf_hdr *hdr,
41 struct xfs_dir2_sf_entry *sfep);
42 __uint8_t (*sf_get_ftype)(struct xfs_dir2_sf_entry *sfep);
43 void (*sf_put_ftype)(struct xfs_dir2_sf_entry *sfep,
44 __uint8_t ftype);
45 xfs_ino_t (*sf_get_ino)(struct xfs_dir2_sf_hdr *hdr,
46 struct xfs_dir2_sf_entry *sfep);
47 void (*sf_put_ino)(struct xfs_dir2_sf_hdr *hdr,
48 struct xfs_dir2_sf_entry *sfep,
49 xfs_ino_t ino);
50 xfs_ino_t (*sf_get_parent_ino)(struct xfs_dir2_sf_hdr *hdr);
51 void (*sf_put_parent_ino)(struct xfs_dir2_sf_hdr *hdr,
52 xfs_ino_t ino);
53
54 int (*data_entsize)(int len);
55 __uint8_t (*data_get_ftype)(struct xfs_dir2_data_entry *dep);
56 void (*data_put_ftype)(struct xfs_dir2_data_entry *dep,
57 __uint8_t ftype);
58 __be16 * (*data_entry_tag_p)(struct xfs_dir2_data_entry *dep);
59 struct xfs_dir2_data_free *
60 (*data_bestfree_p)(struct xfs_dir2_data_hdr *hdr);
61
62 xfs_dir2_data_aoff_t data_dot_offset;
63 xfs_dir2_data_aoff_t data_dotdot_offset;
64 xfs_dir2_data_aoff_t data_first_offset;
65 size_t data_entry_offset;
66
67 struct xfs_dir2_data_entry *
68 (*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr);
69 struct xfs_dir2_data_entry *
70 (*data_dotdot_entry_p)(struct xfs_dir2_data_hdr *hdr);
71 struct xfs_dir2_data_entry *
72 (*data_first_entry_p)(struct xfs_dir2_data_hdr *hdr);
73 struct xfs_dir2_data_entry *
74 (*data_entry_p)(struct xfs_dir2_data_hdr *hdr);
75 struct xfs_dir2_data_unused *
76 (*data_unused_p)(struct xfs_dir2_data_hdr *hdr);
77
78 int leaf_hdr_size;
79 void (*leaf_hdr_to_disk)(struct xfs_dir2_leaf *to,
80 struct xfs_dir3_icleaf_hdr *from);
81 void (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to,
82 struct xfs_dir2_leaf *from);
83 int (*leaf_max_ents)(struct xfs_mount *mp);
84 struct xfs_dir2_leaf_entry *
85 (*leaf_ents_p)(struct xfs_dir2_leaf *lp);
86
87 int node_hdr_size;
88 void (*node_hdr_to_disk)(struct xfs_da_intnode *to,
89 struct xfs_da3_icnode_hdr *from);
90 void (*node_hdr_from_disk)(struct xfs_da3_icnode_hdr *to,
91 struct xfs_da_intnode *from);
92 struct xfs_da_node_entry *
93 (*node_tree_p)(struct xfs_da_intnode *dap);
94
95 int free_hdr_size;
96 void (*free_hdr_to_disk)(struct xfs_dir2_free *to,
97 struct xfs_dir3_icfree_hdr *from);
98 void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to,
99 struct xfs_dir2_free *from);
100 int (*free_max_bests)(struct xfs_mount *mp);
101 __be16 * (*free_bests_p)(struct xfs_dir2_free *free);
102 xfs_dir2_db_t (*db_to_fdb)(struct xfs_mount *mp, xfs_dir2_db_t db);
103 int (*db_to_fdindex)(struct xfs_mount *mp, xfs_dir2_db_t db);
104};
105
106extern const struct xfs_dir_ops *
107 xfs_dir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp);
108extern const struct xfs_dir_ops *
109 xfs_nondir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp);
110
111/*
35 * Generic directory interface routines 112 * Generic directory interface routines
36 */ 113 */
37extern void xfs_dir_startup(void); 114extern void xfs_dir_startup(void);
@@ -65,37 +142,30 @@ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
65/* 142/*
66 * Interface routines used by userspace utilities 143 * Interface routines used by userspace utilities
67 */ 144 */
68extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp);
69extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp,
70 xfs_ino_t ino);
71extern xfs_ino_t xfs_dir3_sfe_get_ino(struct xfs_mount *mp,
72 struct xfs_dir2_sf_hdr *sfp, struct xfs_dir2_sf_entry *sfep);
73extern void xfs_dir3_sfe_put_ino(struct xfs_mount *mp,
74 struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep,
75 xfs_ino_t ino);
76
77extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r); 145extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
78extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r); 146extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
79extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, 147extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
80 struct xfs_buf *bp); 148 struct xfs_buf *bp);
81 149
82extern void xfs_dir2_data_freescan(struct xfs_mount *mp, 150extern void xfs_dir2_data_freescan(struct xfs_inode *dp,
83 struct xfs_dir2_data_hdr *hdr, int *loghead); 151 struct xfs_dir2_data_hdr *hdr, int *loghead);
84extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp, 152extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_inode *dp,
85 struct xfs_dir2_data_entry *dep); 153 struct xfs_buf *bp, struct xfs_dir2_data_entry *dep);
86extern void xfs_dir2_data_log_header(struct xfs_trans *tp, 154extern void xfs_dir2_data_log_header(struct xfs_trans *tp, struct xfs_inode *dp,
87 struct xfs_buf *bp); 155 struct xfs_buf *bp);
88extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp, 156extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp,
89 struct xfs_dir2_data_unused *dup); 157 struct xfs_dir2_data_unused *dup);
90extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_buf *bp, 158extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_inode *dp,
159 struct xfs_buf *bp, xfs_dir2_data_aoff_t offset,
160 xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
161extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_inode *dp,
162 struct xfs_buf *bp, struct xfs_dir2_data_unused *dup,
91 xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, 163 xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len,
92 int *needlogp, int *needscanp); 164 int *needlogp, int *needscanp);
93extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp,
94 struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset,
95 xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
96 165
97extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( 166extern struct xfs_dir2_data_free *xfs_dir2_data_freefind(
98 struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_unused *dup); 167 struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,
168 struct xfs_dir2_data_unused *dup);
99 169
100extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; 170extern const struct xfs_buf_ops xfs_dir3_block_buf_ops;
101extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; 171extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops;
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 12dad188939d..90cdbf4b5f19 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -18,25 +18,25 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_format.h"
22#include "xfs_log.h" 22#include "xfs_log_format.h"
23#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_mount.h" 26#include "xfs_mount.h"
27#include "xfs_da_format.h"
27#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h" 29#include "xfs_inode.h"
30#include "xfs_trans.h"
31#include "xfs_inode_item.h" 31#include "xfs_inode_item.h"
32#include "xfs_bmap.h" 32#include "xfs_bmap.h"
33#include "xfs_buf_item.h" 33#include "xfs_buf_item.h"
34#include "xfs_dir2_format.h"
35#include "xfs_dir2.h" 34#include "xfs_dir2.h"
36#include "xfs_dir2_priv.h" 35#include "xfs_dir2_priv.h"
37#include "xfs_error.h" 36#include "xfs_error.h"
38#include "xfs_trace.h" 37#include "xfs_trace.h"
39#include "xfs_cksum.h" 38#include "xfs_cksum.h"
39#include "xfs_dinode.h"
40 40
41/* 41/*
42 * Local function prototypes. 42 * Local function prototypes.
@@ -168,6 +168,7 @@ xfs_dir3_block_init(
168 168
169static void 169static void
170xfs_dir2_block_need_space( 170xfs_dir2_block_need_space(
171 struct xfs_inode *dp,
171 struct xfs_dir2_data_hdr *hdr, 172 struct xfs_dir2_data_hdr *hdr,
172 struct xfs_dir2_block_tail *btp, 173 struct xfs_dir2_block_tail *btp,
173 struct xfs_dir2_leaf_entry *blp, 174 struct xfs_dir2_leaf_entry *blp,
@@ -183,7 +184,7 @@ xfs_dir2_block_need_space(
183 struct xfs_dir2_data_unused *enddup = NULL; 184 struct xfs_dir2_data_unused *enddup = NULL;
184 185
185 *compact = 0; 186 *compact = 0;
186 bf = xfs_dir3_data_bestfree_p(hdr); 187 bf = dp->d_ops->data_bestfree_p(hdr);
187 188
188 /* 189 /*
189 * If there are stale entries we'll use one for the leaf. 190 * If there are stale entries we'll use one for the leaf.
@@ -280,6 +281,7 @@ out:
280static void 281static void
281xfs_dir2_block_compact( 282xfs_dir2_block_compact(
282 struct xfs_trans *tp, 283 struct xfs_trans *tp,
284 struct xfs_inode *dp,
283 struct xfs_buf *bp, 285 struct xfs_buf *bp,
284 struct xfs_dir2_data_hdr *hdr, 286 struct xfs_dir2_data_hdr *hdr,
285 struct xfs_dir2_block_tail *btp, 287 struct xfs_dir2_block_tail *btp,
@@ -312,7 +314,7 @@ xfs_dir2_block_compact(
312 *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1); 314 *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
313 *lfloghigh -= be32_to_cpu(btp->stale) - 1; 315 *lfloghigh -= be32_to_cpu(btp->stale) - 1;
314 be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1)); 316 be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
315 xfs_dir2_data_make_free(tp, bp, 317 xfs_dir2_data_make_free(tp, dp, bp,
316 (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), 318 (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
317 (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)), 319 (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
318 needlog, &needscan); 320 needlog, &needscan);
@@ -323,7 +325,7 @@ xfs_dir2_block_compact(
323 * This needs to happen before the next call to use_free. 325 * This needs to happen before the next call to use_free.
324 */ 326 */
325 if (needscan) 327 if (needscan)
326 xfs_dir2_data_freescan(tp->t_mountp, hdr, needlog); 328 xfs_dir2_data_freescan(dp, hdr, needlog);
327} 329}
328 330
329/* 331/*
@@ -369,7 +371,7 @@ xfs_dir2_block_addname(
369 if (error) 371 if (error)
370 return error; 372 return error;
371 373
372 len = xfs_dir3_data_entsize(mp, args->namelen); 374 len = dp->d_ops->data_entsize(args->namelen);
373 375
374 /* 376 /*
375 * Set up pointers to parts of the block. 377 * Set up pointers to parts of the block.
@@ -382,7 +384,7 @@ xfs_dir2_block_addname(
382 * Find out if we can reuse stale entries or whether we need extra 384 * Find out if we can reuse stale entries or whether we need extra
383 * space for entry and new leaf. 385 * space for entry and new leaf.
384 */ 386 */
385 xfs_dir2_block_need_space(hdr, btp, blp, &tagp, &dup, 387 xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup,
386 &enddup, &compact, len); 388 &enddup, &compact, len);
387 389
388 /* 390 /*
@@ -418,7 +420,7 @@ xfs_dir2_block_addname(
418 * If need to compact the leaf entries, do it now. 420 * If need to compact the leaf entries, do it now.
419 */ 421 */
420 if (compact) { 422 if (compact) {
421 xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog, 423 xfs_dir2_block_compact(tp, dp, bp, hdr, btp, blp, &needlog,
422 &lfloghigh, &lfloglow); 424 &lfloghigh, &lfloglow);
423 /* recalculate blp post-compaction */ 425 /* recalculate blp post-compaction */
424 blp = xfs_dir2_block_leaf_p(btp); 426 blp = xfs_dir2_block_leaf_p(btp);
@@ -453,7 +455,7 @@ xfs_dir2_block_addname(
453 /* 455 /*
454 * Mark the space needed for the new leaf entry, now in use. 456 * Mark the space needed for the new leaf entry, now in use.
455 */ 457 */
456 xfs_dir2_data_use_free(tp, bp, enddup, 458 xfs_dir2_data_use_free(tp, dp, bp, enddup,
457 (xfs_dir2_data_aoff_t) 459 (xfs_dir2_data_aoff_t)
458 ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) - 460 ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) -
459 sizeof(*blp)), 461 sizeof(*blp)),
@@ -468,7 +470,7 @@ xfs_dir2_block_addname(
468 * This needs to happen before the next call to use_free. 470 * This needs to happen before the next call to use_free.
469 */ 471 */
470 if (needscan) { 472 if (needscan) {
471 xfs_dir2_data_freescan(mp, hdr, &needlog); 473 xfs_dir2_data_freescan(dp, hdr, &needlog);
472 needscan = 0; 474 needscan = 0;
473 } 475 }
474 /* 476 /*
@@ -540,7 +542,7 @@ xfs_dir2_block_addname(
540 /* 542 /*
541 * Mark space for the data entry used. 543 * Mark space for the data entry used.
542 */ 544 */
543 xfs_dir2_data_use_free(tp, bp, dup, 545 xfs_dir2_data_use_free(tp, dp, bp, dup,
544 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), 546 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
545 (xfs_dir2_data_aoff_t)len, &needlog, &needscan); 547 (xfs_dir2_data_aoff_t)len, &needlog, &needscan);
546 /* 548 /*
@@ -549,18 +551,18 @@ xfs_dir2_block_addname(
549 dep->inumber = cpu_to_be64(args->inumber); 551 dep->inumber = cpu_to_be64(args->inumber);
550 dep->namelen = args->namelen; 552 dep->namelen = args->namelen;
551 memcpy(dep->name, args->name, args->namelen); 553 memcpy(dep->name, args->name, args->namelen);
552 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); 554 dp->d_ops->data_put_ftype(dep, args->filetype);
553 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 555 tagp = dp->d_ops->data_entry_tag_p(dep);
554 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 556 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
555 /* 557 /*
556 * Clean up the bestfree array and log the header, tail, and entry. 558 * Clean up the bestfree array and log the header, tail, and entry.
557 */ 559 */
558 if (needscan) 560 if (needscan)
559 xfs_dir2_data_freescan(mp, hdr, &needlog); 561 xfs_dir2_data_freescan(dp, hdr, &needlog);
560 if (needlog) 562 if (needlog)
561 xfs_dir2_data_log_header(tp, bp); 563 xfs_dir2_data_log_header(tp, dp, bp);
562 xfs_dir2_block_log_tail(tp, bp); 564 xfs_dir2_block_log_tail(tp, bp);
563 xfs_dir2_data_log_entry(tp, bp, dep); 565 xfs_dir2_data_log_entry(tp, dp, bp, dep);
564 xfs_dir3_data_check(dp, bp); 566 xfs_dir3_data_check(dp, bp);
565 return 0; 567 return 0;
566} 568}
@@ -642,7 +644,7 @@ xfs_dir2_block_lookup(
642 * Fill in inode number, CI name if appropriate, release the block. 644 * Fill in inode number, CI name if appropriate, release the block.
643 */ 645 */
644 args->inumber = be64_to_cpu(dep->inumber); 646 args->inumber = be64_to_cpu(dep->inumber);
645 args->filetype = xfs_dir3_dirent_get_ftype(mp, dep); 647 args->filetype = dp->d_ops->data_get_ftype(dep);
646 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); 648 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
647 xfs_trans_brelse(args->trans, bp); 649 xfs_trans_brelse(args->trans, bp);
648 return XFS_ERROR(error); 650 return XFS_ERROR(error);
@@ -799,9 +801,9 @@ xfs_dir2_block_removename(
799 * Mark the data entry's space free. 801 * Mark the data entry's space free.
800 */ 802 */
801 needlog = needscan = 0; 803 needlog = needscan = 0;
802 xfs_dir2_data_make_free(tp, bp, 804 xfs_dir2_data_make_free(tp, dp, bp,
803 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), 805 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
804 xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan); 806 dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
805 /* 807 /*
806 * Fix up the block tail. 808 * Fix up the block tail.
807 */ 809 */
@@ -816,9 +818,9 @@ xfs_dir2_block_removename(
816 * Fix up bestfree, log the header if necessary. 818 * Fix up bestfree, log the header if necessary.
817 */ 819 */
818 if (needscan) 820 if (needscan)
819 xfs_dir2_data_freescan(mp, hdr, &needlog); 821 xfs_dir2_data_freescan(dp, hdr, &needlog);
820 if (needlog) 822 if (needlog)
821 xfs_dir2_data_log_header(tp, bp); 823 xfs_dir2_data_log_header(tp, dp, bp);
822 xfs_dir3_data_check(dp, bp); 824 xfs_dir3_data_check(dp, bp);
823 /* 825 /*
824 * See if the size as a shortform is good enough. 826 * See if the size as a shortform is good enough.
@@ -875,8 +877,8 @@ xfs_dir2_block_replace(
875 * Change the inode number to the new value. 877 * Change the inode number to the new value.
876 */ 878 */
877 dep->inumber = cpu_to_be64(args->inumber); 879 dep->inumber = cpu_to_be64(args->inumber);
878 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); 880 dp->d_ops->data_put_ftype(dep, args->filetype);
879 xfs_dir2_data_log_entry(args->trans, bp, dep); 881 xfs_dir2_data_log_entry(args->trans, dp, bp, dep);
880 xfs_dir3_data_check(dp, bp); 882 xfs_dir3_data_check(dp, bp);
881 return 0; 883 return 0;
882} 884}
@@ -934,8 +936,8 @@ xfs_dir2_leaf_to_block(
934 tp = args->trans; 936 tp = args->trans;
935 mp = dp->i_mount; 937 mp = dp->i_mount;
936 leaf = lbp->b_addr; 938 leaf = lbp->b_addr;
937 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 939 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
938 ents = xfs_dir3_leaf_ents_p(leaf); 940 ents = dp->d_ops->leaf_ents_p(leaf);
939 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 941 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
940 942
941 ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || 943 ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
@@ -949,7 +951,7 @@ xfs_dir2_leaf_to_block(
949 while (dp->i_d.di_size > mp->m_dirblksize) { 951 while (dp->i_d.di_size > mp->m_dirblksize) {
950 int hdrsz; 952 int hdrsz;
951 953
952 hdrsz = xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); 954 hdrsz = dp->d_ops->data_entry_offset;
953 bestsp = xfs_dir2_leaf_bests_p(ltp); 955 bestsp = xfs_dir2_leaf_bests_p(ltp);
954 if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == 956 if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
955 mp->m_dirblksize - hdrsz) { 957 mp->m_dirblksize - hdrsz) {
@@ -999,7 +1001,7 @@ xfs_dir2_leaf_to_block(
999 /* 1001 /*
1000 * Use up the space at the end of the block (blp/btp). 1002 * Use up the space at the end of the block (blp/btp).
1001 */ 1003 */
1002 xfs_dir2_data_use_free(tp, dbp, dup, mp->m_dirblksize - size, size, 1004 xfs_dir2_data_use_free(tp, dp, dbp, dup, mp->m_dirblksize - size, size,
1003 &needlog, &needscan); 1005 &needlog, &needscan);
1004 /* 1006 /*
1005 * Initialize the block tail. 1007 * Initialize the block tail.
@@ -1023,9 +1025,9 @@ xfs_dir2_leaf_to_block(
1023 * Scan the bestfree if we need it and log the data block header. 1025 * Scan the bestfree if we need it and log the data block header.
1024 */ 1026 */
1025 if (needscan) 1027 if (needscan)
1026 xfs_dir2_data_freescan(mp, hdr, &needlog); 1028 xfs_dir2_data_freescan(dp, hdr, &needlog);
1027 if (needlog) 1029 if (needlog)
1028 xfs_dir2_data_log_header(tp, dbp); 1030 xfs_dir2_data_log_header(tp, dp, dbp);
1029 /* 1031 /*
1030 * Pitch the old leaf block. 1032 * Pitch the old leaf block.
1031 */ 1033 */
@@ -1136,9 +1138,9 @@ xfs_dir2_sf_to_block(
1136 * The whole thing is initialized to free by the init routine. 1138 * The whole thing is initialized to free by the init routine.
1137 * Say we're using the leaf and tail area. 1139 * Say we're using the leaf and tail area.
1138 */ 1140 */
1139 dup = xfs_dir3_data_unused_p(hdr); 1141 dup = dp->d_ops->data_unused_p(hdr);
1140 needlog = needscan = 0; 1142 needlog = needscan = 0;
1141 xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog, 1143 xfs_dir2_data_use_free(tp, dp, bp, dup, mp->m_dirblksize - i, i, &needlog,
1142 &needscan); 1144 &needscan);
1143 ASSERT(needscan == 0); 1145 ASSERT(needscan == 0);
1144 /* 1146 /*
@@ -1152,38 +1154,38 @@ xfs_dir2_sf_to_block(
1152 /* 1154 /*
1153 * Remove the freespace, we'll manage it. 1155 * Remove the freespace, we'll manage it.
1154 */ 1156 */
1155 xfs_dir2_data_use_free(tp, bp, dup, 1157 xfs_dir2_data_use_free(tp, dp, bp, dup,
1156 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), 1158 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
1157 be16_to_cpu(dup->length), &needlog, &needscan); 1159 be16_to_cpu(dup->length), &needlog, &needscan);
1158 /* 1160 /*
1159 * Create entry for . 1161 * Create entry for .
1160 */ 1162 */
1161 dep = xfs_dir3_data_dot_entry_p(mp, hdr); 1163 dep = dp->d_ops->data_dot_entry_p(hdr);
1162 dep->inumber = cpu_to_be64(dp->i_ino); 1164 dep->inumber = cpu_to_be64(dp->i_ino);
1163 dep->namelen = 1; 1165 dep->namelen = 1;
1164 dep->name[0] = '.'; 1166 dep->name[0] = '.';
1165 xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR); 1167 dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
1166 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 1168 tagp = dp->d_ops->data_entry_tag_p(dep);
1167 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1169 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1168 xfs_dir2_data_log_entry(tp, bp, dep); 1170 xfs_dir2_data_log_entry(tp, dp, bp, dep);
1169 blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); 1171 blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
1170 blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, 1172 blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
1171 (char *)dep - (char *)hdr)); 1173 (char *)dep - (char *)hdr));
1172 /* 1174 /*
1173 * Create entry for .. 1175 * Create entry for ..
1174 */ 1176 */
1175 dep = xfs_dir3_data_dotdot_entry_p(mp, hdr); 1177 dep = dp->d_ops->data_dotdot_entry_p(hdr);
1176 dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); 1178 dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp));
1177 dep->namelen = 2; 1179 dep->namelen = 2;
1178 dep->name[0] = dep->name[1] = '.'; 1180 dep->name[0] = dep->name[1] = '.';
1179 xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR); 1181 dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
1180 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 1182 tagp = dp->d_ops->data_entry_tag_p(dep);
1181 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1183 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1182 xfs_dir2_data_log_entry(tp, bp, dep); 1184 xfs_dir2_data_log_entry(tp, dp, bp, dep);
1183 blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); 1185 blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
1184 blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, 1186 blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
1185 (char *)dep - (char *)hdr)); 1187 (char *)dep - (char *)hdr));
1186 offset = xfs_dir3_data_first_offset(mp); 1188 offset = dp->d_ops->data_first_offset;
1187 /* 1189 /*
1188 * Loop over existing entries, stuff them in. 1190 * Loop over existing entries, stuff them in.
1189 */ 1191 */
@@ -1214,7 +1216,9 @@ xfs_dir2_sf_to_block(
1214 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16( 1216 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
1215 ((char *)dup - (char *)hdr)); 1217 ((char *)dup - (char *)hdr));
1216 xfs_dir2_data_log_unused(tp, bp, dup); 1218 xfs_dir2_data_log_unused(tp, bp, dup);
1217 xfs_dir2_data_freeinsert(hdr, dup, &dummy); 1219 xfs_dir2_data_freeinsert(hdr,
1220 dp->d_ops->data_bestfree_p(hdr),
1221 dup, &dummy);
1218 offset += be16_to_cpu(dup->length); 1222 offset += be16_to_cpu(dup->length);
1219 continue; 1223 continue;
1220 } 1224 }
@@ -1222,14 +1226,13 @@ xfs_dir2_sf_to_block(
1222 * Copy a real entry. 1226 * Copy a real entry.
1223 */ 1227 */
1224 dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset); 1228 dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
1225 dep->inumber = cpu_to_be64(xfs_dir3_sfe_get_ino(mp, sfp, sfep)); 1229 dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep));
1226 dep->namelen = sfep->namelen; 1230 dep->namelen = sfep->namelen;
1227 xfs_dir3_dirent_put_ftype(mp, dep, 1231 dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep));
1228 xfs_dir3_sfe_get_ftype(mp, sfp, sfep));
1229 memcpy(dep->name, sfep->name, dep->namelen); 1232 memcpy(dep->name, sfep->name, dep->namelen);
1230 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 1233 tagp = dp->d_ops->data_entry_tag_p(dep);
1231 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1234 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1232 xfs_dir2_data_log_entry(tp, bp, dep); 1235 xfs_dir2_data_log_entry(tp, dp, bp, dep);
1233 name.name = sfep->name; 1236 name.name = sfep->name;
1234 name.len = sfep->namelen; 1237 name.len = sfep->namelen;
1235 blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> 1238 blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
@@ -1240,7 +1243,7 @@ xfs_dir2_sf_to_block(
1240 if (++i == sfp->count) 1243 if (++i == sfp->count)
1241 sfep = NULL; 1244 sfep = NULL;
1242 else 1245 else
1243 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 1246 sfep = dp->d_ops->sf_nextentry(sfp, sfep);
1244 } 1247 }
1245 /* Done with the temporary buffer */ 1248 /* Done with the temporary buffer */
1246 kmem_free(sfp); 1249 kmem_free(sfp);
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 47e1326c169a..70acff4ee173 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -18,20 +18,19 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_format.h"
22#include "xfs_log.h" 22#include "xfs_log_format.h"
23#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_mount.h" 26#include "xfs_mount.h"
27#include "xfs_da_format.h"
27#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h" 29#include "xfs_inode.h"
31#include "xfs_dir2_format.h"
32#include "xfs_dir2.h" 30#include "xfs_dir2.h"
33#include "xfs_dir2_priv.h" 31#include "xfs_dir2_priv.h"
34#include "xfs_error.h" 32#include "xfs_error.h"
33#include "xfs_trans.h"
35#include "xfs_buf_item.h" 34#include "xfs_buf_item.h"
36#include "xfs_cksum.h" 35#include "xfs_cksum.h"
37 36
@@ -63,11 +62,18 @@ __xfs_dir3_data_check(
63 char *p; /* current data position */ 62 char *p; /* current data position */
64 int stale; /* count of stale leaves */ 63 int stale; /* count of stale leaves */
65 struct xfs_name name; 64 struct xfs_name name;
65 const struct xfs_dir_ops *ops;
66 66
67 mp = bp->b_target->bt_mount; 67 mp = bp->b_target->bt_mount;
68
69 /*
70 * We can be passed a null dp here from a verifier, so we need to go the
71 * hard way to get them.
72 */
73 ops = xfs_dir_get_ops(mp, dp);
74
68 hdr = bp->b_addr; 75 hdr = bp->b_addr;
69 bf = xfs_dir3_data_bestfree_p(hdr); 76 p = (char *)ops->data_entry_p(hdr);
70 p = (char *)xfs_dir3_data_entry_p(hdr);
71 77
72 switch (hdr->magic) { 78 switch (hdr->magic) {
73 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): 79 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
@@ -75,6 +81,16 @@ __xfs_dir3_data_check(
75 btp = xfs_dir2_block_tail_p(mp, hdr); 81 btp = xfs_dir2_block_tail_p(mp, hdr);
76 lep = xfs_dir2_block_leaf_p(btp); 82 lep = xfs_dir2_block_leaf_p(btp);
77 endp = (char *)lep; 83 endp = (char *)lep;
84
85 /*
86 * The number of leaf entries is limited by the size of the
87 * block and the amount of space used by the data entries.
88 * We don't know how much space is used by the data entries yet,
89 * so just ensure that the count falls somewhere inside the
90 * block right now.
91 */
92 XFS_WANT_CORRUPTED_RETURN(be32_to_cpu(btp->count) <
93 ((char *)btp - p) / sizeof(struct xfs_dir2_leaf_entry));
78 break; 94 break;
79 case cpu_to_be32(XFS_DIR3_DATA_MAGIC): 95 case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
80 case cpu_to_be32(XFS_DIR2_DATA_MAGIC): 96 case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
@@ -85,10 +101,11 @@ __xfs_dir3_data_check(
85 return EFSCORRUPTED; 101 return EFSCORRUPTED;
86 } 102 }
87 103
88 count = lastfree = freeseen = 0;
89 /* 104 /*
90 * Account for zero bestfree entries. 105 * Account for zero bestfree entries.
91 */ 106 */
107 bf = ops->data_bestfree_p(hdr);
108 count = lastfree = freeseen = 0;
92 if (!bf[0].length) { 109 if (!bf[0].length) {
93 XFS_WANT_CORRUPTED_RETURN(!bf[0].offset); 110 XFS_WANT_CORRUPTED_RETURN(!bf[0].offset);
94 freeseen |= 1 << 0; 111 freeseen |= 1 << 0;
@@ -121,7 +138,7 @@ __xfs_dir3_data_check(
121 XFS_WANT_CORRUPTED_RETURN( 138 XFS_WANT_CORRUPTED_RETURN(
122 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) == 139 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
123 (char *)dup - (char *)hdr); 140 (char *)dup - (char *)hdr);
124 dfp = xfs_dir2_data_freefind(hdr, dup); 141 dfp = xfs_dir2_data_freefind(hdr, bf, dup);
125 if (dfp) { 142 if (dfp) {
126 i = (int)(dfp - bf); 143 i = (int)(dfp - bf);
127 XFS_WANT_CORRUPTED_RETURN( 144 XFS_WANT_CORRUPTED_RETURN(
@@ -147,10 +164,10 @@ __xfs_dir3_data_check(
147 XFS_WANT_CORRUPTED_RETURN( 164 XFS_WANT_CORRUPTED_RETURN(
148 !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber))); 165 !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)));
149 XFS_WANT_CORRUPTED_RETURN( 166 XFS_WANT_CORRUPTED_RETURN(
150 be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) == 167 be16_to_cpu(*ops->data_entry_tag_p(dep)) ==
151 (char *)dep - (char *)hdr); 168 (char *)dep - (char *)hdr);
152 XFS_WANT_CORRUPTED_RETURN( 169 XFS_WANT_CORRUPTED_RETURN(
153 xfs_dir3_dirent_get_ftype(mp, dep) < XFS_DIR3_FT_MAX); 170 ops->data_get_ftype(dep) < XFS_DIR3_FT_MAX);
154 count++; 171 count++;
155 lastfree = 0; 172 lastfree = 0;
156 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 173 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
@@ -168,7 +185,7 @@ __xfs_dir3_data_check(
168 } 185 }
169 XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count)); 186 XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count));
170 } 187 }
171 p += xfs_dir3_data_entsize(mp, dep->namelen); 188 p += ops->data_entsize(dep->namelen);
172 } 189 }
173 /* 190 /*
174 * Need to have seen all the entries and all the bestfree slots. 191 * Need to have seen all the entries and all the bestfree slots.
@@ -327,19 +344,18 @@ xfs_dir3_data_readahead(
327 */ 344 */
328xfs_dir2_data_free_t * 345xfs_dir2_data_free_t *
329xfs_dir2_data_freefind( 346xfs_dir2_data_freefind(
330 xfs_dir2_data_hdr_t *hdr, /* data block */ 347 struct xfs_dir2_data_hdr *hdr, /* data block header */
331 xfs_dir2_data_unused_t *dup) /* data unused entry */ 348 struct xfs_dir2_data_free *bf, /* bestfree table pointer */
349 struct xfs_dir2_data_unused *dup) /* unused space */
332{ 350{
333 xfs_dir2_data_free_t *dfp; /* bestfree entry */ 351 xfs_dir2_data_free_t *dfp; /* bestfree entry */
334 xfs_dir2_data_aoff_t off; /* offset value needed */ 352 xfs_dir2_data_aoff_t off; /* offset value needed */
335 struct xfs_dir2_data_free *bf;
336#ifdef DEBUG 353#ifdef DEBUG
337 int matched; /* matched the value */ 354 int matched; /* matched the value */
338 int seenzero; /* saw a 0 bestfree entry */ 355 int seenzero; /* saw a 0 bestfree entry */
339#endif 356#endif
340 357
341 off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); 358 off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
342 bf = xfs_dir3_data_bestfree_p(hdr);
343 359
344#ifdef DEBUG 360#ifdef DEBUG
345 /* 361 /*
@@ -399,11 +415,11 @@ xfs_dir2_data_freefind(
399 */ 415 */
400xfs_dir2_data_free_t * /* entry inserted */ 416xfs_dir2_data_free_t * /* entry inserted */
401xfs_dir2_data_freeinsert( 417xfs_dir2_data_freeinsert(
402 xfs_dir2_data_hdr_t *hdr, /* data block pointer */ 418 struct xfs_dir2_data_hdr *hdr, /* data block pointer */
403 xfs_dir2_data_unused_t *dup, /* unused space */ 419 struct xfs_dir2_data_free *dfp, /* bestfree table pointer */
420 struct xfs_dir2_data_unused *dup, /* unused space */
404 int *loghead) /* log the data header (out) */ 421 int *loghead) /* log the data header (out) */
405{ 422{
406 xfs_dir2_data_free_t *dfp; /* bestfree table pointer */
407 xfs_dir2_data_free_t new; /* new bestfree entry */ 423 xfs_dir2_data_free_t new; /* new bestfree entry */
408 424
409 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 425 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
@@ -411,7 +427,6 @@ xfs_dir2_data_freeinsert(
411 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 427 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
412 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 428 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
413 429
414 dfp = xfs_dir3_data_bestfree_p(hdr);
415 new.length = dup->length; 430 new.length = dup->length;
416 new.offset = cpu_to_be16((char *)dup - (char *)hdr); 431 new.offset = cpu_to_be16((char *)dup - (char *)hdr);
417 432
@@ -444,11 +459,11 @@ xfs_dir2_data_freeinsert(
444 */ 459 */
445STATIC void 460STATIC void
446xfs_dir2_data_freeremove( 461xfs_dir2_data_freeremove(
447 xfs_dir2_data_hdr_t *hdr, /* data block header */ 462 struct xfs_dir2_data_hdr *hdr, /* data block header */
448 xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */ 463 struct xfs_dir2_data_free *bf, /* bestfree table pointer */
464 struct xfs_dir2_data_free *dfp, /* bestfree entry pointer */
449 int *loghead) /* out: log data header */ 465 int *loghead) /* out: log data header */
450{ 466{
451 struct xfs_dir2_data_free *bf;
452 467
453 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 468 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
454 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 469 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
@@ -458,7 +473,6 @@ xfs_dir2_data_freeremove(
458 /* 473 /*
459 * It's the first entry, slide the next 2 up. 474 * It's the first entry, slide the next 2 up.
460 */ 475 */
461 bf = xfs_dir3_data_bestfree_p(hdr);
462 if (dfp == &bf[0]) { 476 if (dfp == &bf[0]) {
463 bf[0] = bf[1]; 477 bf[0] = bf[1];
464 bf[1] = bf[2]; 478 bf[1] = bf[2];
@@ -486,9 +500,9 @@ xfs_dir2_data_freeremove(
486 */ 500 */
487void 501void
488xfs_dir2_data_freescan( 502xfs_dir2_data_freescan(
489 xfs_mount_t *mp, /* filesystem mount point */ 503 struct xfs_inode *dp,
490 xfs_dir2_data_hdr_t *hdr, /* data block header */ 504 struct xfs_dir2_data_hdr *hdr,
491 int *loghead) /* out: log data header */ 505 int *loghead)
492{ 506{
493 xfs_dir2_block_tail_t *btp; /* block tail */ 507 xfs_dir2_block_tail_t *btp; /* block tail */
494 xfs_dir2_data_entry_t *dep; /* active data entry */ 508 xfs_dir2_data_entry_t *dep; /* active data entry */
@@ -505,19 +519,19 @@ xfs_dir2_data_freescan(
505 /* 519 /*
506 * Start by clearing the table. 520 * Start by clearing the table.
507 */ 521 */
508 bf = xfs_dir3_data_bestfree_p(hdr); 522 bf = dp->d_ops->data_bestfree_p(hdr);
509 memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT); 523 memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT);
510 *loghead = 1; 524 *loghead = 1;
511 /* 525 /*
512 * Set up pointers. 526 * Set up pointers.
513 */ 527 */
514 p = (char *)xfs_dir3_data_entry_p(hdr); 528 p = (char *)dp->d_ops->data_entry_p(hdr);
515 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 529 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
516 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { 530 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
517 btp = xfs_dir2_block_tail_p(mp, hdr); 531 btp = xfs_dir2_block_tail_p(dp->i_mount, hdr);
518 endp = (char *)xfs_dir2_block_leaf_p(btp); 532 endp = (char *)xfs_dir2_block_leaf_p(btp);
519 } else 533 } else
520 endp = (char *)hdr + mp->m_dirblksize; 534 endp = (char *)hdr + dp->i_mount->m_dirblksize;
521 /* 535 /*
522 * Loop over the block's entries. 536 * Loop over the block's entries.
523 */ 537 */
@@ -529,7 +543,7 @@ xfs_dir2_data_freescan(
529 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 543 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
530 ASSERT((char *)dup - (char *)hdr == 544 ASSERT((char *)dup - (char *)hdr ==
531 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup))); 545 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
532 xfs_dir2_data_freeinsert(hdr, dup, loghead); 546 xfs_dir2_data_freeinsert(hdr, bf, dup, loghead);
533 p += be16_to_cpu(dup->length); 547 p += be16_to_cpu(dup->length);
534 } 548 }
535 /* 549 /*
@@ -538,8 +552,8 @@ xfs_dir2_data_freescan(
538 else { 552 else {
539 dep = (xfs_dir2_data_entry_t *)p; 553 dep = (xfs_dir2_data_entry_t *)p;
540 ASSERT((char *)dep - (char *)hdr == 554 ASSERT((char *)dep - (char *)hdr ==
541 be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep))); 555 be16_to_cpu(*dp->d_ops->data_entry_tag_p(dep)));
542 p += xfs_dir3_data_entsize(mp, dep->namelen); 556 p += dp->d_ops->data_entsize(dep->namelen);
543 } 557 }
544 } 558 }
545} 559}
@@ -594,8 +608,8 @@ xfs_dir3_data_init(
594 } else 608 } else
595 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); 609 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
596 610
597 bf = xfs_dir3_data_bestfree_p(hdr); 611 bf = dp->d_ops->data_bestfree_p(hdr);
598 bf[0].offset = cpu_to_be16(xfs_dir3_data_entry_offset(hdr)); 612 bf[0].offset = cpu_to_be16(dp->d_ops->data_entry_offset);
599 for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { 613 for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
600 bf[i].length = 0; 614 bf[i].length = 0;
601 bf[i].offset = 0; 615 bf[i].offset = 0;
@@ -604,17 +618,17 @@ xfs_dir3_data_init(
604 /* 618 /*
605 * Set up an unused entry for the block's body. 619 * Set up an unused entry for the block's body.
606 */ 620 */
607 dup = xfs_dir3_data_unused_p(hdr); 621 dup = dp->d_ops->data_unused_p(hdr);
608 dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 622 dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
609 623
610 t = mp->m_dirblksize - (uint)xfs_dir3_data_entry_offset(hdr); 624 t = mp->m_dirblksize - (uint)dp->d_ops->data_entry_offset;
611 bf[0].length = cpu_to_be16(t); 625 bf[0].length = cpu_to_be16(t);
612 dup->length = cpu_to_be16(t); 626 dup->length = cpu_to_be16(t);
613 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); 627 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
614 /* 628 /*
615 * Log it and return it. 629 * Log it and return it.
616 */ 630 */
617 xfs_dir2_data_log_header(tp, bp); 631 xfs_dir2_data_log_header(tp, dp, bp);
618 xfs_dir2_data_log_unused(tp, bp, dup); 632 xfs_dir2_data_log_unused(tp, bp, dup);
619 *bpp = bp; 633 *bpp = bp;
620 return 0; 634 return 0;
@@ -626,11 +640,11 @@ xfs_dir3_data_init(
626void 640void
627xfs_dir2_data_log_entry( 641xfs_dir2_data_log_entry(
628 struct xfs_trans *tp, 642 struct xfs_trans *tp,
643 struct xfs_inode *dp,
629 struct xfs_buf *bp, 644 struct xfs_buf *bp,
630 xfs_dir2_data_entry_t *dep) /* data entry pointer */ 645 xfs_dir2_data_entry_t *dep) /* data entry pointer */
631{ 646{
632 struct xfs_dir2_data_hdr *hdr = bp->b_addr; 647 struct xfs_dir2_data_hdr *hdr = bp->b_addr;
633 struct xfs_mount *mp = tp->t_mountp;
634 648
635 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 649 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
636 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 650 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
@@ -638,7 +652,7 @@ xfs_dir2_data_log_entry(
638 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 652 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
639 653
640 xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), 654 xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
641 (uint)((char *)(xfs_dir3_data_entry_tag_p(mp, dep) + 1) - 655 (uint)((char *)(dp->d_ops->data_entry_tag_p(dep) + 1) -
642 (char *)hdr - 1)); 656 (char *)hdr - 1));
643} 657}
644 658
@@ -648,16 +662,19 @@ xfs_dir2_data_log_entry(
648void 662void
649xfs_dir2_data_log_header( 663xfs_dir2_data_log_header(
650 struct xfs_trans *tp, 664 struct xfs_trans *tp,
665 struct xfs_inode *dp,
651 struct xfs_buf *bp) 666 struct xfs_buf *bp)
652{ 667{
653 xfs_dir2_data_hdr_t *hdr = bp->b_addr; 668#ifdef DEBUG
669 struct xfs_dir2_data_hdr *hdr = bp->b_addr;
654 670
655 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 671 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
656 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 672 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
657 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 673 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
658 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 674 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
675#endif
659 676
660 xfs_trans_log_buf(tp, bp, 0, xfs_dir3_data_entry_offset(hdr) - 1); 677 xfs_trans_log_buf(tp, bp, 0, dp->d_ops->data_entry_offset - 1);
661} 678}
662 679
663/* 680/*
@@ -698,6 +715,7 @@ xfs_dir2_data_log_unused(
698void 715void
699xfs_dir2_data_make_free( 716xfs_dir2_data_make_free(
700 struct xfs_trans *tp, 717 struct xfs_trans *tp,
718 struct xfs_inode *dp,
701 struct xfs_buf *bp, 719 struct xfs_buf *bp,
702 xfs_dir2_data_aoff_t offset, /* starting byte offset */ 720 xfs_dir2_data_aoff_t offset, /* starting byte offset */
703 xfs_dir2_data_aoff_t len, /* length in bytes */ 721 xfs_dir2_data_aoff_t len, /* length in bytes */
@@ -735,7 +753,7 @@ xfs_dir2_data_make_free(
735 * If this isn't the start of the block, then back up to 753 * If this isn't the start of the block, then back up to
736 * the previous entry and see if it's free. 754 * the previous entry and see if it's free.
737 */ 755 */
738 if (offset > xfs_dir3_data_entry_offset(hdr)) { 756 if (offset > dp->d_ops->data_entry_offset) {
739 __be16 *tagp; /* tag just before us */ 757 __be16 *tagp; /* tag just before us */
740 758
741 tagp = (__be16 *)((char *)hdr + offset) - 1; 759 tagp = (__be16 *)((char *)hdr + offset) - 1;
@@ -761,15 +779,15 @@ xfs_dir2_data_make_free(
761 * Previous and following entries are both free, 779 * Previous and following entries are both free,
762 * merge everything into a single free entry. 780 * merge everything into a single free entry.
763 */ 781 */
764 bf = xfs_dir3_data_bestfree_p(hdr); 782 bf = dp->d_ops->data_bestfree_p(hdr);
765 if (prevdup && postdup) { 783 if (prevdup && postdup) {
766 xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */ 784 xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */
767 785
768 /* 786 /*
769 * See if prevdup and/or postdup are in bestfree table. 787 * See if prevdup and/or postdup are in bestfree table.
770 */ 788 */
771 dfp = xfs_dir2_data_freefind(hdr, prevdup); 789 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
772 dfp2 = xfs_dir2_data_freefind(hdr, postdup); 790 dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup);
773 /* 791 /*
774 * We need a rescan unless there are exactly 2 free entries 792 * We need a rescan unless there are exactly 2 free entries
775 * namely our two. Then we know what's happening, otherwise 793 * namely our two. Then we know what's happening, otherwise
@@ -797,12 +815,13 @@ xfs_dir2_data_make_free(
797 ASSERT(dfp2 == dfp); 815 ASSERT(dfp2 == dfp);
798 dfp2 = &bf[1]; 816 dfp2 = &bf[1];
799 } 817 }
800 xfs_dir2_data_freeremove(hdr, dfp2, needlogp); 818 xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp);
801 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 819 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
802 /* 820 /*
803 * Now insert the new entry. 821 * Now insert the new entry.
804 */ 822 */
805 dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp); 823 dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup,
824 needlogp);
806 ASSERT(dfp == &bf[0]); 825 ASSERT(dfp == &bf[0]);
807 ASSERT(dfp->length == prevdup->length); 826 ASSERT(dfp->length == prevdup->length);
808 ASSERT(!dfp[1].length); 827 ASSERT(!dfp[1].length);
@@ -813,7 +832,7 @@ xfs_dir2_data_make_free(
813 * The entry before us is free, merge with it. 832 * The entry before us is free, merge with it.
814 */ 833 */
815 else if (prevdup) { 834 else if (prevdup) {
816 dfp = xfs_dir2_data_freefind(hdr, prevdup); 835 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);
817 be16_add_cpu(&prevdup->length, len); 836 be16_add_cpu(&prevdup->length, len);
818 *xfs_dir2_data_unused_tag_p(prevdup) = 837 *xfs_dir2_data_unused_tag_p(prevdup) =
819 cpu_to_be16((char *)prevdup - (char *)hdr); 838 cpu_to_be16((char *)prevdup - (char *)hdr);
@@ -824,8 +843,8 @@ xfs_dir2_data_make_free(
824 * the old one and add the new one. 843 * the old one and add the new one.
825 */ 844 */
826 if (dfp) { 845 if (dfp) {
827 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 846 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
828 xfs_dir2_data_freeinsert(hdr, prevdup, needlogp); 847 xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp);
829 } 848 }
830 /* 849 /*
831 * Otherwise we need a scan if the new entry is big enough. 850 * Otherwise we need a scan if the new entry is big enough.
@@ -839,7 +858,7 @@ xfs_dir2_data_make_free(
839 * The following entry is free, merge with it. 858 * The following entry is free, merge with it.
840 */ 859 */
841 else if (postdup) { 860 else if (postdup) {
842 dfp = xfs_dir2_data_freefind(hdr, postdup); 861 dfp = xfs_dir2_data_freefind(hdr, bf, postdup);
843 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); 862 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
844 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 863 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
845 newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length)); 864 newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
@@ -852,8 +871,8 @@ xfs_dir2_data_make_free(
852 * the old one and add the new one. 871 * the old one and add the new one.
853 */ 872 */
854 if (dfp) { 873 if (dfp) {
855 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 874 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
856 xfs_dir2_data_freeinsert(hdr, newdup, needlogp); 875 xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
857 } 876 }
858 /* 877 /*
859 * Otherwise we need a scan if the new entry is big enough. 878 * Otherwise we need a scan if the new entry is big enough.
@@ -873,7 +892,7 @@ xfs_dir2_data_make_free(
873 *xfs_dir2_data_unused_tag_p(newdup) = 892 *xfs_dir2_data_unused_tag_p(newdup) =
874 cpu_to_be16((char *)newdup - (char *)hdr); 893 cpu_to_be16((char *)newdup - (char *)hdr);
875 xfs_dir2_data_log_unused(tp, bp, newdup); 894 xfs_dir2_data_log_unused(tp, bp, newdup);
876 xfs_dir2_data_freeinsert(hdr, newdup, needlogp); 895 xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);
877 } 896 }
878 *needscanp = needscan; 897 *needscanp = needscan;
879} 898}
@@ -884,6 +903,7 @@ xfs_dir2_data_make_free(
884void 903void
885xfs_dir2_data_use_free( 904xfs_dir2_data_use_free(
886 struct xfs_trans *tp, 905 struct xfs_trans *tp,
906 struct xfs_inode *dp,
887 struct xfs_buf *bp, 907 struct xfs_buf *bp,
888 xfs_dir2_data_unused_t *dup, /* unused entry */ 908 xfs_dir2_data_unused_t *dup, /* unused entry */
889 xfs_dir2_data_aoff_t offset, /* starting offset to use */ 909 xfs_dir2_data_aoff_t offset, /* starting offset to use */
@@ -913,9 +933,9 @@ xfs_dir2_data_use_free(
913 /* 933 /*
914 * Look up the entry in the bestfree table. 934 * Look up the entry in the bestfree table.
915 */ 935 */
916 dfp = xfs_dir2_data_freefind(hdr, dup);
917 oldlen = be16_to_cpu(dup->length); 936 oldlen = be16_to_cpu(dup->length);
918 bf = xfs_dir3_data_bestfree_p(hdr); 937 bf = dp->d_ops->data_bestfree_p(hdr);
938 dfp = xfs_dir2_data_freefind(hdr, bf, dup);
919 ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length)); 939 ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length));
920 /* 940 /*
921 * Check for alignment with front and back of the entry. 941 * Check for alignment with front and back of the entry.
@@ -932,7 +952,8 @@ xfs_dir2_data_use_free(
932 if (dfp) { 952 if (dfp) {
933 needscan = (bf[2].offset != 0); 953 needscan = (bf[2].offset != 0);
934 if (!needscan) 954 if (!needscan)
935 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 955 xfs_dir2_data_freeremove(hdr, bf, dfp,
956 needlogp);
936 } 957 }
937 } 958 }
938 /* 959 /*
@@ -950,8 +971,9 @@ xfs_dir2_data_use_free(
950 * If it was in the table, remove it and add the new one. 971 * If it was in the table, remove it and add the new one.
951 */ 972 */
952 if (dfp) { 973 if (dfp) {
953 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 974 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
954 dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp); 975 dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
976 needlogp);
955 ASSERT(dfp != NULL); 977 ASSERT(dfp != NULL);
956 ASSERT(dfp->length == newdup->length); 978 ASSERT(dfp->length == newdup->length);
957 ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr); 979 ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
@@ -977,8 +999,9 @@ xfs_dir2_data_use_free(
977 * If it was in the table, remove it and add the new one. 999 * If it was in the table, remove it and add the new one.
978 */ 1000 */
979 if (dfp) { 1001 if (dfp) {
980 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 1002 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);
981 dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp); 1003 dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,
1004 needlogp);
982 ASSERT(dfp != NULL); 1005 ASSERT(dfp != NULL);
983 ASSERT(dfp->length == newdup->length); 1006 ASSERT(dfp->length == newdup->length);
984 ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr); 1007 ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
@@ -1017,9 +1040,11 @@ xfs_dir2_data_use_free(
1017 if (dfp) { 1040 if (dfp) {
1018 needscan = (bf[2].length != 0); 1041 needscan = (bf[2].length != 0);
1019 if (!needscan) { 1042 if (!needscan) {
1020 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 1043 xfs_dir2_data_freeremove(hdr, bf, dfp,
1021 xfs_dir2_data_freeinsert(hdr, newdup, needlogp); 1044 needlogp);
1022 xfs_dir2_data_freeinsert(hdr, newdup2, 1045 xfs_dir2_data_freeinsert(hdr, bf, newdup,
1046 needlogp);
1047 xfs_dir2_data_freeinsert(hdr, bf, newdup2,
1023 needlogp); 1048 needlogp);
1024 } 1049 }
1025 } 1050 }
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 1021c8356d08..ae47ec6e16c4 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -18,23 +18,21 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_format.h"
22#include "xfs_bit.h" 22#include "xfs_log_format.h"
23#include "xfs_log.h" 23#include "xfs_trans_resv.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 24#include "xfs_sb.h"
26#include "xfs_ag.h" 25#include "xfs_ag.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
27#include "xfs_da_format.h"
28#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 29#include "xfs_inode.h"
32#include "xfs_bmap.h" 30#include "xfs_bmap.h"
33#include "xfs_dir2_format.h"
34#include "xfs_dir2.h" 31#include "xfs_dir2.h"
35#include "xfs_dir2_priv.h" 32#include "xfs_dir2_priv.h"
36#include "xfs_error.h" 33#include "xfs_error.h"
37#include "xfs_trace.h" 34#include "xfs_trace.h"
35#include "xfs_trans.h"
38#include "xfs_buf_item.h" 36#include "xfs_buf_item.h"
39#include "xfs_cksum.h" 37#include "xfs_cksum.h"
40 38
@@ -52,21 +50,21 @@ static void xfs_dir3_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp);
52 * Pop an assert if something is wrong. 50 * Pop an assert if something is wrong.
53 */ 51 */
54#ifdef DEBUG 52#ifdef DEBUG
55#define xfs_dir3_leaf_check(mp, bp) \ 53#define xfs_dir3_leaf_check(dp, bp) \
56do { \ 54do { \
57 if (!xfs_dir3_leaf1_check((mp), (bp))) \ 55 if (!xfs_dir3_leaf1_check((dp), (bp))) \
58 ASSERT(0); \ 56 ASSERT(0); \
59} while (0); 57} while (0);
60 58
61STATIC bool 59STATIC bool
62xfs_dir3_leaf1_check( 60xfs_dir3_leaf1_check(
63 struct xfs_mount *mp, 61 struct xfs_inode *dp,
64 struct xfs_buf *bp) 62 struct xfs_buf *bp)
65{ 63{
66 struct xfs_dir2_leaf *leaf = bp->b_addr; 64 struct xfs_dir2_leaf *leaf = bp->b_addr;
67 struct xfs_dir3_icleaf_hdr leafhdr; 65 struct xfs_dir3_icleaf_hdr leafhdr;
68 66
69 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 67 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
70 68
71 if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) { 69 if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) {
72 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; 70 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
@@ -75,71 +73,16 @@ xfs_dir3_leaf1_check(
75 } else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC) 73 } else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC)
76 return false; 74 return false;
77 75
78 return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); 76 return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf);
79} 77}
80#else 78#else
81#define xfs_dir3_leaf_check(mp, bp) 79#define xfs_dir3_leaf_check(dp, bp)
82#endif 80#endif
83 81
84void
85xfs_dir3_leaf_hdr_from_disk(
86 struct xfs_dir3_icleaf_hdr *to,
87 struct xfs_dir2_leaf *from)
88{
89 if (from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) ||
90 from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) {
91 to->forw = be32_to_cpu(from->hdr.info.forw);
92 to->back = be32_to_cpu(from->hdr.info.back);
93 to->magic = be16_to_cpu(from->hdr.info.magic);
94 to->count = be16_to_cpu(from->hdr.count);
95 to->stale = be16_to_cpu(from->hdr.stale);
96 } else {
97 struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from;
98
99 to->forw = be32_to_cpu(hdr3->info.hdr.forw);
100 to->back = be32_to_cpu(hdr3->info.hdr.back);
101 to->magic = be16_to_cpu(hdr3->info.hdr.magic);
102 to->count = be16_to_cpu(hdr3->count);
103 to->stale = be16_to_cpu(hdr3->stale);
104 }
105
106 ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC ||
107 to->magic == XFS_DIR3_LEAF1_MAGIC ||
108 to->magic == XFS_DIR2_LEAFN_MAGIC ||
109 to->magic == XFS_DIR3_LEAFN_MAGIC);
110}
111
112void
113xfs_dir3_leaf_hdr_to_disk(
114 struct xfs_dir2_leaf *to,
115 struct xfs_dir3_icleaf_hdr *from)
116{
117 ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC ||
118 from->magic == XFS_DIR3_LEAF1_MAGIC ||
119 from->magic == XFS_DIR2_LEAFN_MAGIC ||
120 from->magic == XFS_DIR3_LEAFN_MAGIC);
121
122 if (from->magic == XFS_DIR2_LEAF1_MAGIC ||
123 from->magic == XFS_DIR2_LEAFN_MAGIC) {
124 to->hdr.info.forw = cpu_to_be32(from->forw);
125 to->hdr.info.back = cpu_to_be32(from->back);
126 to->hdr.info.magic = cpu_to_be16(from->magic);
127 to->hdr.count = cpu_to_be16(from->count);
128 to->hdr.stale = cpu_to_be16(from->stale);
129 } else {
130 struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to;
131
132 hdr3->info.hdr.forw = cpu_to_be32(from->forw);
133 hdr3->info.hdr.back = cpu_to_be32(from->back);
134 hdr3->info.hdr.magic = cpu_to_be16(from->magic);
135 hdr3->count = cpu_to_be16(from->count);
136 hdr3->stale = cpu_to_be16(from->stale);
137 }
138}
139
140bool 82bool
141xfs_dir3_leaf_check_int( 83xfs_dir3_leaf_check_int(
142 struct xfs_mount *mp, 84 struct xfs_mount *mp,
85 struct xfs_inode *dp,
143 struct xfs_dir3_icleaf_hdr *hdr, 86 struct xfs_dir3_icleaf_hdr *hdr,
144 struct xfs_dir2_leaf *leaf) 87 struct xfs_dir2_leaf *leaf)
145{ 88{
@@ -147,8 +90,21 @@ xfs_dir3_leaf_check_int(
147 xfs_dir2_leaf_tail_t *ltp; 90 xfs_dir2_leaf_tail_t *ltp;
148 int stale; 91 int stale;
149 int i; 92 int i;
93 const struct xfs_dir_ops *ops;
94 struct xfs_dir3_icleaf_hdr leafhdr;
150 95
151 ents = xfs_dir3_leaf_ents_p(leaf); 96 /*
97 * we can be passed a null dp here from a verifier, so we need to go the
98 * hard way to get them.
99 */
100 ops = xfs_dir_get_ops(mp, dp);
101
102 if (!hdr) {
103 ops->leaf_hdr_from_disk(&leafhdr, leaf);
104 hdr = &leafhdr;
105 }
106
107 ents = ops->leaf_ents_p(leaf);
152 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 108 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
153 109
154 /* 110 /*
@@ -156,7 +112,7 @@ xfs_dir3_leaf_check_int(
156 * Should factor in the size of the bests table as well. 112 * Should factor in the size of the bests table as well.
157 * We can deduce a value for that from di_size. 113 * We can deduce a value for that from di_size.
158 */ 114 */
159 if (hdr->count > xfs_dir3_max_leaf_ents(mp, leaf)) 115 if (hdr->count > ops->leaf_max_ents(mp))
160 return false; 116 return false;
161 117
162 /* Leaves and bests don't overlap in leaf format. */ 118 /* Leaves and bests don't overlap in leaf format. */
@@ -192,7 +148,6 @@ xfs_dir3_leaf_verify(
192{ 148{
193 struct xfs_mount *mp = bp->b_target->bt_mount; 149 struct xfs_mount *mp = bp->b_target->bt_mount;
194 struct xfs_dir2_leaf *leaf = bp->b_addr; 150 struct xfs_dir2_leaf *leaf = bp->b_addr;
195 struct xfs_dir3_icleaf_hdr leafhdr;
196 151
197 ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); 152 ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC);
198 153
@@ -214,8 +169,7 @@ xfs_dir3_leaf_verify(
214 return false; 169 return false;
215 } 170 }
216 171
217 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 172 return xfs_dir3_leaf_check_int(mp, NULL, NULL, leaf);
218 return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf);
219} 173}
220 174
221static void 175static void
@@ -401,7 +355,7 @@ xfs_dir3_leaf_get_buf(
401 return error; 355 return error;
402 356
403 xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic); 357 xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic);
404 xfs_dir3_leaf_log_header(tp, bp); 358 xfs_dir3_leaf_log_header(tp, dp, bp);
405 if (magic == XFS_DIR2_LEAF1_MAGIC) 359 if (magic == XFS_DIR2_LEAF1_MAGIC)
406 xfs_dir3_leaf_log_tail(tp, bp); 360 xfs_dir3_leaf_log_tail(tp, bp);
407 *bpp = bp; 361 *bpp = bp;
@@ -462,31 +416,31 @@ xfs_dir2_block_to_leaf(
462 xfs_dir3_data_check(dp, dbp); 416 xfs_dir3_data_check(dp, dbp);
463 btp = xfs_dir2_block_tail_p(mp, hdr); 417 btp = xfs_dir2_block_tail_p(mp, hdr);
464 blp = xfs_dir2_block_leaf_p(btp); 418 blp = xfs_dir2_block_leaf_p(btp);
465 bf = xfs_dir3_data_bestfree_p(hdr); 419 bf = dp->d_ops->data_bestfree_p(hdr);
466 ents = xfs_dir3_leaf_ents_p(leaf); 420 ents = dp->d_ops->leaf_ents_p(leaf);
467 421
468 /* 422 /*
469 * Set the counts in the leaf header. 423 * Set the counts in the leaf header.
470 */ 424 */
471 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 425 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
472 leafhdr.count = be32_to_cpu(btp->count); 426 leafhdr.count = be32_to_cpu(btp->count);
473 leafhdr.stale = be32_to_cpu(btp->stale); 427 leafhdr.stale = be32_to_cpu(btp->stale);
474 xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); 428 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
475 xfs_dir3_leaf_log_header(tp, lbp); 429 xfs_dir3_leaf_log_header(tp, dp, lbp);
476 430
477 /* 431 /*
478 * Could compact these but I think we always do the conversion 432 * Could compact these but I think we always do the conversion
479 * after squeezing out stale entries. 433 * after squeezing out stale entries.
480 */ 434 */
481 memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); 435 memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t));
482 xfs_dir3_leaf_log_ents(tp, lbp, 0, leafhdr.count - 1); 436 xfs_dir3_leaf_log_ents(tp, dp, lbp, 0, leafhdr.count - 1);
483 needscan = 0; 437 needscan = 0;
484 needlog = 1; 438 needlog = 1;
485 /* 439 /*
486 * Make the space formerly occupied by the leaf entries and block 440 * Make the space formerly occupied by the leaf entries and block
487 * tail be free. 441 * tail be free.
488 */ 442 */
489 xfs_dir2_data_make_free(tp, dbp, 443 xfs_dir2_data_make_free(tp, dp, dbp,
490 (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), 444 (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
491 (xfs_dir2_data_aoff_t)((char *)hdr + mp->m_dirblksize - 445 (xfs_dir2_data_aoff_t)((char *)hdr + mp->m_dirblksize -
492 (char *)blp), 446 (char *)blp),
@@ -502,7 +456,7 @@ xfs_dir2_block_to_leaf(
502 hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); 456 hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
503 457
504 if (needscan) 458 if (needscan)
505 xfs_dir2_data_freescan(mp, hdr, &needlog); 459 xfs_dir2_data_freescan(dp, hdr, &needlog);
506 /* 460 /*
507 * Set up leaf tail and bests table. 461 * Set up leaf tail and bests table.
508 */ 462 */
@@ -514,8 +468,8 @@ xfs_dir2_block_to_leaf(
514 * Log the data header and leaf bests table. 468 * Log the data header and leaf bests table.
515 */ 469 */
516 if (needlog) 470 if (needlog)
517 xfs_dir2_data_log_header(tp, dbp); 471 xfs_dir2_data_log_header(tp, dp, dbp);
518 xfs_dir3_leaf_check(mp, lbp); 472 xfs_dir3_leaf_check(dp, lbp);
519 xfs_dir3_data_check(dp, dbp); 473 xfs_dir3_data_check(dp, dbp);
520 xfs_dir3_leaf_log_bests(tp, lbp, 0, 0); 474 xfs_dir3_leaf_log_bests(tp, lbp, 0, 0);
521 return 0; 475 return 0;
@@ -699,10 +653,10 @@ xfs_dir2_leaf_addname(
699 index = xfs_dir2_leaf_search_hash(args, lbp); 653 index = xfs_dir2_leaf_search_hash(args, lbp);
700 leaf = lbp->b_addr; 654 leaf = lbp->b_addr;
701 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 655 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
702 ents = xfs_dir3_leaf_ents_p(leaf); 656 ents = dp->d_ops->leaf_ents_p(leaf);
703 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 657 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
704 bestsp = xfs_dir2_leaf_bests_p(ltp); 658 bestsp = xfs_dir2_leaf_bests_p(ltp);
705 length = xfs_dir3_data_entsize(mp, args->namelen); 659 length = dp->d_ops->data_entsize(args->namelen);
706 660
707 /* 661 /*
708 * See if there are any entries with the same hash value 662 * See if there are any entries with the same hash value
@@ -864,7 +818,7 @@ xfs_dir2_leaf_addname(
864 else 818 else
865 xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); 819 xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block);
866 hdr = dbp->b_addr; 820 hdr = dbp->b_addr;
867 bf = xfs_dir3_data_bestfree_p(hdr); 821 bf = dp->d_ops->data_bestfree_p(hdr);
868 bestsp[use_block] = bf[0].length; 822 bestsp[use_block] = bf[0].length;
869 grown = 1; 823 grown = 1;
870 } else { 824 } else {
@@ -880,7 +834,7 @@ xfs_dir2_leaf_addname(
880 return error; 834 return error;
881 } 835 }
882 hdr = dbp->b_addr; 836 hdr = dbp->b_addr;
883 bf = xfs_dir3_data_bestfree_p(hdr); 837 bf = dp->d_ops->data_bestfree_p(hdr);
884 grown = 0; 838 grown = 0;
885 } 839 }
886 /* 840 /*
@@ -893,7 +847,7 @@ xfs_dir2_leaf_addname(
893 /* 847 /*
894 * Mark the initial part of our freespace in use for the new entry. 848 * Mark the initial part of our freespace in use for the new entry.
895 */ 849 */
896 xfs_dir2_data_use_free(tp, dbp, dup, 850 xfs_dir2_data_use_free(tp, dp, dbp, dup,
897 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, 851 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length,
898 &needlog, &needscan); 852 &needlog, &needscan);
899 /* 853 /*
@@ -903,20 +857,20 @@ xfs_dir2_leaf_addname(
903 dep->inumber = cpu_to_be64(args->inumber); 857 dep->inumber = cpu_to_be64(args->inumber);
904 dep->namelen = args->namelen; 858 dep->namelen = args->namelen;
905 memcpy(dep->name, args->name, dep->namelen); 859 memcpy(dep->name, args->name, dep->namelen);
906 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); 860 dp->d_ops->data_put_ftype(dep, args->filetype);
907 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 861 tagp = dp->d_ops->data_entry_tag_p(dep);
908 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 862 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
909 /* 863 /*
910 * Need to scan fix up the bestfree table. 864 * Need to scan fix up the bestfree table.
911 */ 865 */
912 if (needscan) 866 if (needscan)
913 xfs_dir2_data_freescan(mp, hdr, &needlog); 867 xfs_dir2_data_freescan(dp, hdr, &needlog);
914 /* 868 /*
915 * Need to log the data block's header. 869 * Need to log the data block's header.
916 */ 870 */
917 if (needlog) 871 if (needlog)
918 xfs_dir2_data_log_header(tp, dbp); 872 xfs_dir2_data_log_header(tp, dp, dbp);
919 xfs_dir2_data_log_entry(tp, dbp, dep); 873 xfs_dir2_data_log_entry(tp, dp, dbp, dep);
920 /* 874 /*
921 * If the bests table needs to be changed, do it. 875 * If the bests table needs to be changed, do it.
922 * Log the change unless we've already done that. 876 * Log the change unless we've already done that.
@@ -939,10 +893,10 @@ xfs_dir2_leaf_addname(
939 /* 893 /*
940 * Log the leaf fields and give up the buffers. 894 * Log the leaf fields and give up the buffers.
941 */ 895 */
942 xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); 896 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
943 xfs_dir3_leaf_log_header(tp, lbp); 897 xfs_dir3_leaf_log_header(tp, dp, lbp);
944 xfs_dir3_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); 898 xfs_dir3_leaf_log_ents(tp, dp, lbp, lfloglow, lfloghigh);
945 xfs_dir3_leaf_check(mp, lbp); 899 xfs_dir3_leaf_check(dp, lbp);
946 xfs_dir3_data_check(dp, dbp); 900 xfs_dir3_data_check(dp, dbp);
947 return 0; 901 return 0;
948} 902}
@@ -962,6 +916,7 @@ xfs_dir3_leaf_compact(
962 int loglow; /* first leaf entry to log */ 916 int loglow; /* first leaf entry to log */
963 int to; /* target leaf index */ 917 int to; /* target leaf index */
964 struct xfs_dir2_leaf_entry *ents; 918 struct xfs_dir2_leaf_entry *ents;
919 struct xfs_inode *dp = args->dp;
965 920
966 leaf = bp->b_addr; 921 leaf = bp->b_addr;
967 if (!leafhdr->stale) 922 if (!leafhdr->stale)
@@ -970,7 +925,7 @@ xfs_dir3_leaf_compact(
970 /* 925 /*
971 * Compress out the stale entries in place. 926 * Compress out the stale entries in place.
972 */ 927 */
973 ents = xfs_dir3_leaf_ents_p(leaf); 928 ents = dp->d_ops->leaf_ents_p(leaf);
974 for (from = to = 0, loglow = -1; from < leafhdr->count; from++) { 929 for (from = to = 0, loglow = -1; from < leafhdr->count; from++) {
975 if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) 930 if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
976 continue; 931 continue;
@@ -991,10 +946,10 @@ xfs_dir3_leaf_compact(
991 leafhdr->count -= leafhdr->stale; 946 leafhdr->count -= leafhdr->stale;
992 leafhdr->stale = 0; 947 leafhdr->stale = 0;
993 948
994 xfs_dir3_leaf_hdr_to_disk(leaf, leafhdr); 949 dp->d_ops->leaf_hdr_to_disk(leaf, leafhdr);
995 xfs_dir3_leaf_log_header(args->trans, bp); 950 xfs_dir3_leaf_log_header(args->trans, dp, bp);
996 if (loglow != -1) 951 if (loglow != -1)
997 xfs_dir3_leaf_log_ents(args->trans, bp, loglow, to - 1); 952 xfs_dir3_leaf_log_ents(args->trans, dp, bp, loglow, to - 1);
998} 953}
999 954
1000/* 955/*
@@ -1121,10 +1076,11 @@ xfs_dir3_leaf_log_bests(
1121 */ 1076 */
1122void 1077void
1123xfs_dir3_leaf_log_ents( 1078xfs_dir3_leaf_log_ents(
1124 xfs_trans_t *tp, /* transaction pointer */ 1079 struct xfs_trans *tp,
1125 struct xfs_buf *bp, /* leaf buffer */ 1080 struct xfs_inode *dp,
1126 int first, /* first entry to log */ 1081 struct xfs_buf *bp,
1127 int last) /* last entry to log */ 1082 int first,
1083 int last)
1128{ 1084{
1129 xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */ 1085 xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */
1130 xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ 1086 xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */
@@ -1136,7 +1092,7 @@ xfs_dir3_leaf_log_ents(
1136 leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || 1092 leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
1137 leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); 1093 leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC));
1138 1094
1139 ents = xfs_dir3_leaf_ents_p(leaf); 1095 ents = dp->d_ops->leaf_ents_p(leaf);
1140 firstlep = &ents[first]; 1096 firstlep = &ents[first];
1141 lastlep = &ents[last]; 1097 lastlep = &ents[last];
1142 xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), 1098 xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf),
@@ -1149,6 +1105,7 @@ xfs_dir3_leaf_log_ents(
1149void 1105void
1150xfs_dir3_leaf_log_header( 1106xfs_dir3_leaf_log_header(
1151 struct xfs_trans *tp, 1107 struct xfs_trans *tp,
1108 struct xfs_inode *dp,
1152 struct xfs_buf *bp) 1109 struct xfs_buf *bp)
1153{ 1110{
1154 struct xfs_dir2_leaf *leaf = bp->b_addr; 1111 struct xfs_dir2_leaf *leaf = bp->b_addr;
@@ -1159,7 +1116,7 @@ xfs_dir3_leaf_log_header(
1159 leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); 1116 leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC));
1160 1117
1161 xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), 1118 xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf),
1162 xfs_dir3_leaf_hdr_size(leaf) - 1); 1119 dp->d_ops->leaf_hdr_size - 1);
1163} 1120}
1164 1121
1165/* 1122/*
@@ -1214,9 +1171,9 @@ xfs_dir2_leaf_lookup(
1214 } 1171 }
1215 tp = args->trans; 1172 tp = args->trans;
1216 dp = args->dp; 1173 dp = args->dp;
1217 xfs_dir3_leaf_check(dp->i_mount, lbp); 1174 xfs_dir3_leaf_check(dp, lbp);
1218 leaf = lbp->b_addr; 1175 leaf = lbp->b_addr;
1219 ents = xfs_dir3_leaf_ents_p(leaf); 1176 ents = dp->d_ops->leaf_ents_p(leaf);
1220 /* 1177 /*
1221 * Get to the leaf entry and contained data entry address. 1178 * Get to the leaf entry and contained data entry address.
1222 */ 1179 */
@@ -1232,7 +1189,7 @@ xfs_dir2_leaf_lookup(
1232 * Return the found inode number & CI name if appropriate 1189 * Return the found inode number & CI name if appropriate
1233 */ 1190 */
1234 args->inumber = be64_to_cpu(dep->inumber); 1191 args->inumber = be64_to_cpu(dep->inumber);
1235 args->filetype = xfs_dir3_dirent_get_ftype(dp->i_mount, dep); 1192 args->filetype = dp->d_ops->data_get_ftype(dep);
1236 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); 1193 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
1237 xfs_trans_brelse(tp, dbp); 1194 xfs_trans_brelse(tp, dbp);
1238 xfs_trans_brelse(tp, lbp); 1195 xfs_trans_brelse(tp, lbp);
@@ -1279,9 +1236,9 @@ xfs_dir2_leaf_lookup_int(
1279 1236
1280 *lbpp = lbp; 1237 *lbpp = lbp;
1281 leaf = lbp->b_addr; 1238 leaf = lbp->b_addr;
1282 xfs_dir3_leaf_check(mp, lbp); 1239 xfs_dir3_leaf_check(dp, lbp);
1283 ents = xfs_dir3_leaf_ents_p(leaf); 1240 ents = dp->d_ops->leaf_ents_p(leaf);
1284 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 1241 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1285 1242
1286 /* 1243 /*
1287 * Look for the first leaf entry with our hash value. 1244 * Look for the first leaf entry with our hash value.
@@ -1415,9 +1372,9 @@ xfs_dir2_leaf_removename(
1415 leaf = lbp->b_addr; 1372 leaf = lbp->b_addr;
1416 hdr = dbp->b_addr; 1373 hdr = dbp->b_addr;
1417 xfs_dir3_data_check(dp, dbp); 1374 xfs_dir3_data_check(dp, dbp);
1418 bf = xfs_dir3_data_bestfree_p(hdr); 1375 bf = dp->d_ops->data_bestfree_p(hdr);
1419 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 1376 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1420 ents = xfs_dir3_leaf_ents_p(leaf); 1377 ents = dp->d_ops->leaf_ents_p(leaf);
1421 /* 1378 /*
1422 * Point to the leaf entry, use that to point to the data entry. 1379 * Point to the leaf entry, use that to point to the data entry.
1423 */ 1380 */
@@ -1433,27 +1390,27 @@ xfs_dir2_leaf_removename(
1433 /* 1390 /*
1434 * Mark the former data entry unused. 1391 * Mark the former data entry unused.
1435 */ 1392 */
1436 xfs_dir2_data_make_free(tp, dbp, 1393 xfs_dir2_data_make_free(tp, dp, dbp,
1437 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), 1394 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
1438 xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan); 1395 dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
1439 /* 1396 /*
1440 * We just mark the leaf entry stale by putting a null in it. 1397 * We just mark the leaf entry stale by putting a null in it.
1441 */ 1398 */
1442 leafhdr.stale++; 1399 leafhdr.stale++;
1443 xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); 1400 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
1444 xfs_dir3_leaf_log_header(tp, lbp); 1401 xfs_dir3_leaf_log_header(tp, dp, lbp);
1445 1402
1446 lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); 1403 lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
1447 xfs_dir3_leaf_log_ents(tp, lbp, index, index); 1404 xfs_dir3_leaf_log_ents(tp, dp, lbp, index, index);
1448 1405
1449 /* 1406 /*
1450 * Scan the freespace in the data block again if necessary, 1407 * Scan the freespace in the data block again if necessary,
1451 * log the data block header if necessary. 1408 * log the data block header if necessary.
1452 */ 1409 */
1453 if (needscan) 1410 if (needscan)
1454 xfs_dir2_data_freescan(mp, hdr, &needlog); 1411 xfs_dir2_data_freescan(dp, hdr, &needlog);
1455 if (needlog) 1412 if (needlog)
1456 xfs_dir2_data_log_header(tp, dbp); 1413 xfs_dir2_data_log_header(tp, dp, dbp);
1457 /* 1414 /*
1458 * If the longest freespace in the data block has changed, 1415 * If the longest freespace in the data block has changed,
1459 * put the new value in the bests table and log that. 1416 * put the new value in the bests table and log that.
@@ -1467,7 +1424,7 @@ xfs_dir2_leaf_removename(
1467 * If the data block is now empty then get rid of the data block. 1424 * If the data block is now empty then get rid of the data block.
1468 */ 1425 */
1469 if (be16_to_cpu(bf[0].length) == 1426 if (be16_to_cpu(bf[0].length) ==
1470 mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)) { 1427 mp->m_dirblksize - dp->d_ops->data_entry_offset) {
1471 ASSERT(db != mp->m_dirdatablk); 1428 ASSERT(db != mp->m_dirdatablk);
1472 if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { 1429 if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {
1473 /* 1430 /*
@@ -1478,7 +1435,7 @@ xfs_dir2_leaf_removename(
1478 */ 1435 */
1479 if (error == ENOSPC && args->total == 0) 1436 if (error == ENOSPC && args->total == 0)
1480 error = 0; 1437 error = 0;
1481 xfs_dir3_leaf_check(mp, lbp); 1438 xfs_dir3_leaf_check(dp, lbp);
1482 return error; 1439 return error;
1483 } 1440 }
1484 dbp = NULL; 1441 dbp = NULL;
@@ -1512,7 +1469,7 @@ xfs_dir2_leaf_removename(
1512 else if (db != mp->m_dirdatablk) 1469 else if (db != mp->m_dirdatablk)
1513 dbp = NULL; 1470 dbp = NULL;
1514 1471
1515 xfs_dir3_leaf_check(mp, lbp); 1472 xfs_dir3_leaf_check(dp, lbp);
1516 /* 1473 /*
1517 * See if we can convert to block form. 1474 * See if we can convert to block form.
1518 */ 1475 */
@@ -1547,7 +1504,7 @@ xfs_dir2_leaf_replace(
1547 } 1504 }
1548 dp = args->dp; 1505 dp = args->dp;
1549 leaf = lbp->b_addr; 1506 leaf = lbp->b_addr;
1550 ents = xfs_dir3_leaf_ents_p(leaf); 1507 ents = dp->d_ops->leaf_ents_p(leaf);
1551 /* 1508 /*
1552 * Point to the leaf entry, get data address from it. 1509 * Point to the leaf entry, get data address from it.
1553 */ 1510 */
@@ -1563,10 +1520,10 @@ xfs_dir2_leaf_replace(
1563 * Put the new inode number in, log it. 1520 * Put the new inode number in, log it.
1564 */ 1521 */
1565 dep->inumber = cpu_to_be64(args->inumber); 1522 dep->inumber = cpu_to_be64(args->inumber);
1566 xfs_dir3_dirent_put_ftype(dp->i_mount, dep, args->filetype); 1523 dp->d_ops->data_put_ftype(dep, args->filetype);
1567 tp = args->trans; 1524 tp = args->trans;
1568 xfs_dir2_data_log_entry(tp, dbp, dep); 1525 xfs_dir2_data_log_entry(tp, dp, dbp, dep);
1569 xfs_dir3_leaf_check(dp->i_mount, lbp); 1526 xfs_dir3_leaf_check(dp, lbp);
1570 xfs_trans_brelse(tp, lbp); 1527 xfs_trans_brelse(tp, lbp);
1571 return 0; 1528 return 0;
1572} 1529}
@@ -1592,8 +1549,8 @@ xfs_dir2_leaf_search_hash(
1592 struct xfs_dir3_icleaf_hdr leafhdr; 1549 struct xfs_dir3_icleaf_hdr leafhdr;
1593 1550
1594 leaf = lbp->b_addr; 1551 leaf = lbp->b_addr;
1595 ents = xfs_dir3_leaf_ents_p(leaf); 1552 ents = args->dp->d_ops->leaf_ents_p(leaf);
1596 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 1553 args->dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1597 1554
1598 /* 1555 /*
1599 * Note, the table cannot be empty, so we have to go through the loop. 1556 * Note, the table cannot be empty, so we have to go through the loop.
@@ -1661,12 +1618,12 @@ xfs_dir2_leaf_trim_data(
1661#ifdef DEBUG 1618#ifdef DEBUG
1662{ 1619{
1663 struct xfs_dir2_data_hdr *hdr = dbp->b_addr; 1620 struct xfs_dir2_data_hdr *hdr = dbp->b_addr;
1664 struct xfs_dir2_data_free *bf = xfs_dir3_data_bestfree_p(hdr); 1621 struct xfs_dir2_data_free *bf = dp->d_ops->data_bestfree_p(hdr);
1665 1622
1666 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 1623 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
1667 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); 1624 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
1668 ASSERT(be16_to_cpu(bf[0].length) == 1625 ASSERT(be16_to_cpu(bf[0].length) ==
1669 mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)); 1626 mp->m_dirblksize - dp->d_ops->data_entry_offset);
1670 ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); 1627 ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
1671} 1628}
1672#endif 1629#endif
@@ -1782,7 +1739,7 @@ xfs_dir2_node_to_leaf(
1782 return 0; 1739 return 0;
1783 lbp = state->path.blk[0].bp; 1740 lbp = state->path.blk[0].bp;
1784 leaf = lbp->b_addr; 1741 leaf = lbp->b_addr;
1785 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 1742 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1786 1743
1787 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || 1744 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
1788 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); 1745 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
@@ -1794,7 +1751,7 @@ xfs_dir2_node_to_leaf(
1794 if (error) 1751 if (error)
1795 return error; 1752 return error;
1796 free = fbp->b_addr; 1753 free = fbp->b_addr;
1797 xfs_dir3_free_hdr_from_disk(&freehdr, free); 1754 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1798 1755
1799 ASSERT(!freehdr.firstdb); 1756 ASSERT(!freehdr.firstdb);
1800 1757
@@ -1828,14 +1785,14 @@ xfs_dir2_node_to_leaf(
1828 /* 1785 /*
1829 * Set up the leaf bests table. 1786 * Set up the leaf bests table.
1830 */ 1787 */
1831 memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free), 1788 memcpy(xfs_dir2_leaf_bests_p(ltp), dp->d_ops->free_bests_p(free),
1832 freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); 1789 freehdr.nvalid * sizeof(xfs_dir2_data_off_t));
1833 1790
1834 xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); 1791 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
1835 xfs_dir3_leaf_log_header(tp, lbp); 1792 xfs_dir3_leaf_log_header(tp, dp, lbp);
1836 xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); 1793 xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
1837 xfs_dir3_leaf_log_tail(tp, lbp); 1794 xfs_dir3_leaf_log_tail(tp, lbp);
1838 xfs_dir3_leaf_check(mp, lbp); 1795 xfs_dir3_leaf_check(dp, lbp);
1839 1796
1840 /* 1797 /*
1841 * Get rid of the freespace block. 1798 * Get rid of the freespace block.
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 4c3dba7ffb74..56369d4509d5 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -18,22 +18,21 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_format.h"
22#include "xfs_log.h" 22#include "xfs_log_format.h"
23#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_mount.h" 26#include "xfs_mount.h"
27#include "xfs_da_format.h"
27#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h" 29#include "xfs_inode.h"
31#include "xfs_bmap.h" 30#include "xfs_bmap.h"
32#include "xfs_dir2_format.h"
33#include "xfs_dir2.h" 31#include "xfs_dir2.h"
34#include "xfs_dir2_priv.h" 32#include "xfs_dir2_priv.h"
35#include "xfs_error.h" 33#include "xfs_error.h"
36#include "xfs_trace.h" 34#include "xfs_trace.h"
35#include "xfs_trans.h"
37#include "xfs_buf_item.h" 36#include "xfs_buf_item.h"
38#include "xfs_cksum.h" 37#include "xfs_cksum.h"
39 38
@@ -55,21 +54,21 @@ static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
55 * Check internal consistency of a leafn block. 54 * Check internal consistency of a leafn block.
56 */ 55 */
57#ifdef DEBUG 56#ifdef DEBUG
58#define xfs_dir3_leaf_check(mp, bp) \ 57#define xfs_dir3_leaf_check(dp, bp) \
59do { \ 58do { \
60 if (!xfs_dir3_leafn_check((mp), (bp))) \ 59 if (!xfs_dir3_leafn_check((dp), (bp))) \
61 ASSERT(0); \ 60 ASSERT(0); \
62} while (0); 61} while (0);
63 62
64static bool 63static bool
65xfs_dir3_leafn_check( 64xfs_dir3_leafn_check(
66 struct xfs_mount *mp, 65 struct xfs_inode *dp,
67 struct xfs_buf *bp) 66 struct xfs_buf *bp)
68{ 67{
69 struct xfs_dir2_leaf *leaf = bp->b_addr; 68 struct xfs_dir2_leaf *leaf = bp->b_addr;
70 struct xfs_dir3_icleaf_hdr leafhdr; 69 struct xfs_dir3_icleaf_hdr leafhdr;
71 70
72 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 71 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
73 72
74 if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) { 73 if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) {
75 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; 74 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
@@ -78,10 +77,10 @@ xfs_dir3_leafn_check(
78 } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC) 77 } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC)
79 return false; 78 return false;
80 79
81 return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); 80 return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf);
82} 81}
83#else 82#else
84#define xfs_dir3_leaf_check(mp, bp) 83#define xfs_dir3_leaf_check(dp, bp)
85#endif 84#endif
86 85
87static bool 86static bool
@@ -193,53 +192,6 @@ xfs_dir2_free_try_read(
193 return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp); 192 return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp);
194} 193}
195 194
196
197void
198xfs_dir3_free_hdr_from_disk(
199 struct xfs_dir3_icfree_hdr *to,
200 struct xfs_dir2_free *from)
201{
202 if (from->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)) {
203 to->magic = be32_to_cpu(from->hdr.magic);
204 to->firstdb = be32_to_cpu(from->hdr.firstdb);
205 to->nvalid = be32_to_cpu(from->hdr.nvalid);
206 to->nused = be32_to_cpu(from->hdr.nused);
207 } else {
208 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from;
209
210 to->magic = be32_to_cpu(hdr3->hdr.magic);
211 to->firstdb = be32_to_cpu(hdr3->firstdb);
212 to->nvalid = be32_to_cpu(hdr3->nvalid);
213 to->nused = be32_to_cpu(hdr3->nused);
214 }
215
216 ASSERT(to->magic == XFS_DIR2_FREE_MAGIC ||
217 to->magic == XFS_DIR3_FREE_MAGIC);
218}
219
220static void
221xfs_dir3_free_hdr_to_disk(
222 struct xfs_dir2_free *to,
223 struct xfs_dir3_icfree_hdr *from)
224{
225 ASSERT(from->magic == XFS_DIR2_FREE_MAGIC ||
226 from->magic == XFS_DIR3_FREE_MAGIC);
227
228 if (from->magic == XFS_DIR2_FREE_MAGIC) {
229 to->hdr.magic = cpu_to_be32(from->magic);
230 to->hdr.firstdb = cpu_to_be32(from->firstdb);
231 to->hdr.nvalid = cpu_to_be32(from->nvalid);
232 to->hdr.nused = cpu_to_be32(from->nused);
233 } else {
234 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to;
235
236 hdr3->hdr.magic = cpu_to_be32(from->magic);
237 hdr3->firstdb = cpu_to_be32(from->firstdb);
238 hdr3->nvalid = cpu_to_be32(from->nvalid);
239 hdr3->nused = cpu_to_be32(from->nused);
240 }
241}
242
243static int 195static int
244xfs_dir3_free_get_buf( 196xfs_dir3_free_get_buf(
245 struct xfs_trans *tp, 197 struct xfs_trans *tp,
@@ -277,7 +229,7 @@ xfs_dir3_free_get_buf(
277 uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); 229 uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid);
278 } else 230 } else
279 hdr.magic = XFS_DIR2_FREE_MAGIC; 231 hdr.magic = XFS_DIR2_FREE_MAGIC;
280 xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); 232 dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr);
281 *bpp = bp; 233 *bpp = bp;
282 return 0; 234 return 0;
283} 235}
@@ -288,6 +240,7 @@ xfs_dir3_free_get_buf(
288STATIC void 240STATIC void
289xfs_dir2_free_log_bests( 241xfs_dir2_free_log_bests(
290 struct xfs_trans *tp, 242 struct xfs_trans *tp,
243 struct xfs_inode *dp,
291 struct xfs_buf *bp, 244 struct xfs_buf *bp,
292 int first, /* first entry to log */ 245 int first, /* first entry to log */
293 int last) /* last entry to log */ 246 int last) /* last entry to log */
@@ -296,7 +249,7 @@ xfs_dir2_free_log_bests(
296 __be16 *bests; 249 __be16 *bests;
297 250
298 free = bp->b_addr; 251 free = bp->b_addr;
299 bests = xfs_dir3_free_bests_p(tp->t_mountp, free); 252 bests = dp->d_ops->free_bests_p(free);
300 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || 253 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
301 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); 254 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
302 xfs_trans_log_buf(tp, bp, 255 xfs_trans_log_buf(tp, bp,
@@ -311,6 +264,7 @@ xfs_dir2_free_log_bests(
311static void 264static void
312xfs_dir2_free_log_header( 265xfs_dir2_free_log_header(
313 struct xfs_trans *tp, 266 struct xfs_trans *tp,
267 struct xfs_inode *dp,
314 struct xfs_buf *bp) 268 struct xfs_buf *bp)
315{ 269{
316#ifdef DEBUG 270#ifdef DEBUG
@@ -320,7 +274,7 @@ xfs_dir2_free_log_header(
320 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || 274 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
321 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); 275 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
322#endif 276#endif
323 xfs_trans_log_buf(tp, bp, 0, xfs_dir3_free_hdr_size(tp->t_mountp) - 1); 277 xfs_trans_log_buf(tp, bp, 0, dp->d_ops->free_hdr_size - 1);
324} 278}
325 279
326/* 280/*
@@ -369,7 +323,7 @@ xfs_dir2_leaf_to_node(
369 return error; 323 return error;
370 324
371 free = fbp->b_addr; 325 free = fbp->b_addr;
372 xfs_dir3_free_hdr_from_disk(&freehdr, free); 326 dp->d_ops->free_hdr_from_disk(&freehdr, free);
373 leaf = lbp->b_addr; 327 leaf = lbp->b_addr;
374 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 328 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
375 ASSERT(be32_to_cpu(ltp->bestcount) <= 329 ASSERT(be32_to_cpu(ltp->bestcount) <=
@@ -380,7 +334,7 @@ xfs_dir2_leaf_to_node(
380 * Count active entries. 334 * Count active entries.
381 */ 335 */
382 from = xfs_dir2_leaf_bests_p(ltp); 336 from = xfs_dir2_leaf_bests_p(ltp);
383 to = xfs_dir3_free_bests_p(mp, free); 337 to = dp->d_ops->free_bests_p(free);
384 for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { 338 for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
385 if ((off = be16_to_cpu(*from)) != NULLDATAOFF) 339 if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
386 n++; 340 n++;
@@ -393,9 +347,9 @@ xfs_dir2_leaf_to_node(
393 freehdr.nused = n; 347 freehdr.nused = n;
394 freehdr.nvalid = be32_to_cpu(ltp->bestcount); 348 freehdr.nvalid = be32_to_cpu(ltp->bestcount);
395 349
396 xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr); 350 dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
397 xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); 351 xfs_dir2_free_log_bests(tp, dp, fbp, 0, freehdr.nvalid - 1);
398 xfs_dir2_free_log_header(tp, fbp); 352 xfs_dir2_free_log_header(tp, dp, fbp);
399 353
400 /* 354 /*
401 * Converting the leaf to a leafnode is just a matter of changing the 355 * Converting the leaf to a leafnode is just a matter of changing the
@@ -409,8 +363,8 @@ xfs_dir2_leaf_to_node(
409 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); 363 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
410 lbp->b_ops = &xfs_dir3_leafn_buf_ops; 364 lbp->b_ops = &xfs_dir3_leafn_buf_ops;
411 xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF); 365 xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF);
412 xfs_dir3_leaf_log_header(tp, lbp); 366 xfs_dir3_leaf_log_header(tp, dp, lbp);
413 xfs_dir3_leaf_check(mp, lbp); 367 xfs_dir3_leaf_check(dp, lbp);
414 return 0; 368 return 0;
415} 369}
416 370
@@ -443,8 +397,8 @@ xfs_dir2_leafn_add(
443 mp = dp->i_mount; 397 mp = dp->i_mount;
444 tp = args->trans; 398 tp = args->trans;
445 leaf = bp->b_addr; 399 leaf = bp->b_addr;
446 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 400 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
447 ents = xfs_dir3_leaf_ents_p(leaf); 401 ents = dp->d_ops->leaf_ents_p(leaf);
448 402
449 /* 403 /*
450 * Quick check just to make sure we are not going to index 404 * Quick check just to make sure we are not going to index
@@ -460,7 +414,7 @@ xfs_dir2_leafn_add(
460 * a compact. 414 * a compact.
461 */ 415 */
462 416
463 if (leafhdr.count == xfs_dir3_max_leaf_ents(mp, leaf)) { 417 if (leafhdr.count == dp->d_ops->leaf_max_ents(mp)) {
464 if (!leafhdr.stale) 418 if (!leafhdr.stale)
465 return XFS_ERROR(ENOSPC); 419 return XFS_ERROR(ENOSPC);
466 compact = leafhdr.stale > 1; 420 compact = leafhdr.stale > 1;
@@ -498,30 +452,30 @@ xfs_dir2_leafn_add(
498 lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, 452 lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp,
499 args->blkno, args->index)); 453 args->blkno, args->index));
500 454
501 xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); 455 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
502 xfs_dir3_leaf_log_header(tp, bp); 456 xfs_dir3_leaf_log_header(tp, dp, bp);
503 xfs_dir3_leaf_log_ents(tp, bp, lfloglow, lfloghigh); 457 xfs_dir3_leaf_log_ents(tp, dp, bp, lfloglow, lfloghigh);
504 xfs_dir3_leaf_check(mp, bp); 458 xfs_dir3_leaf_check(dp, bp);
505 return 0; 459 return 0;
506} 460}
507 461
508#ifdef DEBUG 462#ifdef DEBUG
509static void 463static void
510xfs_dir2_free_hdr_check( 464xfs_dir2_free_hdr_check(
511 struct xfs_mount *mp, 465 struct xfs_inode *dp,
512 struct xfs_buf *bp, 466 struct xfs_buf *bp,
513 xfs_dir2_db_t db) 467 xfs_dir2_db_t db)
514{ 468{
515 struct xfs_dir3_icfree_hdr hdr; 469 struct xfs_dir3_icfree_hdr hdr;
516 470
517 xfs_dir3_free_hdr_from_disk(&hdr, bp->b_addr); 471 dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr);
518 472
519 ASSERT((hdr.firstdb % xfs_dir3_free_max_bests(mp)) == 0); 473 ASSERT((hdr.firstdb % dp->d_ops->free_max_bests(dp->i_mount)) == 0);
520 ASSERT(hdr.firstdb <= db); 474 ASSERT(hdr.firstdb <= db);
521 ASSERT(db < hdr.firstdb + hdr.nvalid); 475 ASSERT(db < hdr.firstdb + hdr.nvalid);
522} 476}
523#else 477#else
524#define xfs_dir2_free_hdr_check(mp, dp, db) 478#define xfs_dir2_free_hdr_check(dp, bp, db)
525#endif /* DEBUG */ 479#endif /* DEBUG */
526 480
527/* 481/*
@@ -530,6 +484,7 @@ xfs_dir2_free_hdr_check(
530 */ 484 */
531xfs_dahash_t /* hash value */ 485xfs_dahash_t /* hash value */
532xfs_dir2_leafn_lasthash( 486xfs_dir2_leafn_lasthash(
487 struct xfs_inode *dp,
533 struct xfs_buf *bp, /* leaf buffer */ 488 struct xfs_buf *bp, /* leaf buffer */
534 int *count) /* count of entries in leaf */ 489 int *count) /* count of entries in leaf */
535{ 490{
@@ -537,7 +492,7 @@ xfs_dir2_leafn_lasthash(
537 struct xfs_dir2_leaf_entry *ents; 492 struct xfs_dir2_leaf_entry *ents;
538 struct xfs_dir3_icleaf_hdr leafhdr; 493 struct xfs_dir3_icleaf_hdr leafhdr;
539 494
540 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 495 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
541 496
542 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || 497 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
543 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); 498 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
@@ -547,7 +502,7 @@ xfs_dir2_leafn_lasthash(
547 if (!leafhdr.count) 502 if (!leafhdr.count)
548 return 0; 503 return 0;
549 504
550 ents = xfs_dir3_leaf_ents_p(leaf); 505 ents = dp->d_ops->leaf_ents_p(leaf);
551 return be32_to_cpu(ents[leafhdr.count - 1].hashval); 506 return be32_to_cpu(ents[leafhdr.count - 1].hashval);
552} 507}
553 508
@@ -584,10 +539,10 @@ xfs_dir2_leafn_lookup_for_addname(
584 tp = args->trans; 539 tp = args->trans;
585 mp = dp->i_mount; 540 mp = dp->i_mount;
586 leaf = bp->b_addr; 541 leaf = bp->b_addr;
587 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 542 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
588 ents = xfs_dir3_leaf_ents_p(leaf); 543 ents = dp->d_ops->leaf_ents_p(leaf);
589 544
590 xfs_dir3_leaf_check(mp, bp); 545 xfs_dir3_leaf_check(dp, bp);
591 ASSERT(leafhdr.count > 0); 546 ASSERT(leafhdr.count > 0);
592 547
593 /* 548 /*
@@ -605,7 +560,7 @@ xfs_dir2_leafn_lookup_for_addname(
605 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || 560 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
606 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); 561 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
607 } 562 }
608 length = xfs_dir3_data_entsize(mp, args->namelen); 563 length = dp->d_ops->data_entsize(args->namelen);
609 /* 564 /*
610 * Loop over leaf entries with the right hash value. 565 * Loop over leaf entries with the right hash value.
611 */ 566 */
@@ -637,7 +592,7 @@ xfs_dir2_leafn_lookup_for_addname(
637 * Convert the data block to the free block 592 * Convert the data block to the free block
638 * holding its freespace information. 593 * holding its freespace information.
639 */ 594 */
640 newfdb = xfs_dir2_db_to_fdb(mp, newdb); 595 newfdb = dp->d_ops->db_to_fdb(mp, newdb);
641 /* 596 /*
642 * If it's not the one we have in hand, read it in. 597 * If it's not the one we have in hand, read it in.
643 */ 598 */
@@ -655,16 +610,16 @@ xfs_dir2_leafn_lookup_for_addname(
655 return error; 610 return error;
656 free = curbp->b_addr; 611 free = curbp->b_addr;
657 612
658 xfs_dir2_free_hdr_check(mp, curbp, curdb); 613 xfs_dir2_free_hdr_check(dp, curbp, curdb);
659 } 614 }
660 /* 615 /*
661 * Get the index for our entry. 616 * Get the index for our entry.
662 */ 617 */
663 fi = xfs_dir2_db_to_fdindex(mp, curdb); 618 fi = dp->d_ops->db_to_fdindex(mp, curdb);
664 /* 619 /*
665 * If it has room, return it. 620 * If it has room, return it.
666 */ 621 */
667 bests = xfs_dir3_free_bests_p(mp, free); 622 bests = dp->d_ops->free_bests_p(free);
668 if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) { 623 if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) {
669 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", 624 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
670 XFS_ERRLEVEL_LOW, mp); 625 XFS_ERRLEVEL_LOW, mp);
@@ -734,10 +689,10 @@ xfs_dir2_leafn_lookup_for_entry(
734 tp = args->trans; 689 tp = args->trans;
735 mp = dp->i_mount; 690 mp = dp->i_mount;
736 leaf = bp->b_addr; 691 leaf = bp->b_addr;
737 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 692 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
738 ents = xfs_dir3_leaf_ents_p(leaf); 693 ents = dp->d_ops->leaf_ents_p(leaf);
739 694
740 xfs_dir3_leaf_check(mp, bp); 695 xfs_dir3_leaf_check(dp, bp);
741 ASSERT(leafhdr.count > 0); 696 ASSERT(leafhdr.count > 0);
742 697
743 /* 698 /*
@@ -816,7 +771,7 @@ xfs_dir2_leafn_lookup_for_entry(
816 xfs_trans_brelse(tp, state->extrablk.bp); 771 xfs_trans_brelse(tp, state->extrablk.bp);
817 args->cmpresult = cmp; 772 args->cmpresult = cmp;
818 args->inumber = be64_to_cpu(dep->inumber); 773 args->inumber = be64_to_cpu(dep->inumber);
819 args->filetype = xfs_dir3_dirent_get_ftype(mp, dep); 774 args->filetype = dp->d_ops->data_get_ftype(dep);
820 *indexp = index; 775 *indexp = index;
821 state->extravalid = 1; 776 state->extravalid = 1;
822 state->extrablk.bp = curbp; 777 state->extrablk.bp = curbp;
@@ -907,7 +862,7 @@ xfs_dir3_leafn_moveents(
907 if (start_d < dhdr->count) { 862 if (start_d < dhdr->count) {
908 memmove(&dents[start_d + count], &dents[start_d], 863 memmove(&dents[start_d + count], &dents[start_d],
909 (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); 864 (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t));
910 xfs_dir3_leaf_log_ents(tp, bp_d, start_d + count, 865 xfs_dir3_leaf_log_ents(tp, args->dp, bp_d, start_d + count,
911 count + dhdr->count - 1); 866 count + dhdr->count - 1);
912 } 867 }
913 /* 868 /*
@@ -929,7 +884,8 @@ xfs_dir3_leafn_moveents(
929 */ 884 */
930 memcpy(&dents[start_d], &sents[start_s], 885 memcpy(&dents[start_d], &sents[start_s],
931 count * sizeof(xfs_dir2_leaf_entry_t)); 886 count * sizeof(xfs_dir2_leaf_entry_t));
932 xfs_dir3_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1); 887 xfs_dir3_leaf_log_ents(tp, args->dp, bp_d,
888 start_d, start_d + count - 1);
933 889
934 /* 890 /*
935 * If there are source entries after the ones we copied, 891 * If there are source entries after the ones we copied,
@@ -938,7 +894,8 @@ xfs_dir3_leafn_moveents(
938 if (start_s + count < shdr->count) { 894 if (start_s + count < shdr->count) {
939 memmove(&sents[start_s], &sents[start_s + count], 895 memmove(&sents[start_s], &sents[start_s + count],
940 count * sizeof(xfs_dir2_leaf_entry_t)); 896 count * sizeof(xfs_dir2_leaf_entry_t));
941 xfs_dir3_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1); 897 xfs_dir3_leaf_log_ents(tp, args->dp, bp_s,
898 start_s, start_s + count - 1);
942 } 899 }
943 900
944 /* 901 /*
@@ -956,6 +913,7 @@ xfs_dir3_leafn_moveents(
956 */ 913 */
957int /* sort order */ 914int /* sort order */
958xfs_dir2_leafn_order( 915xfs_dir2_leafn_order(
916 struct xfs_inode *dp,
959 struct xfs_buf *leaf1_bp, /* leaf1 buffer */ 917 struct xfs_buf *leaf1_bp, /* leaf1 buffer */
960 struct xfs_buf *leaf2_bp) /* leaf2 buffer */ 918 struct xfs_buf *leaf2_bp) /* leaf2 buffer */
961{ 919{
@@ -966,10 +924,10 @@ xfs_dir2_leafn_order(
966 struct xfs_dir3_icleaf_hdr hdr1; 924 struct xfs_dir3_icleaf_hdr hdr1;
967 struct xfs_dir3_icleaf_hdr hdr2; 925 struct xfs_dir3_icleaf_hdr hdr2;
968 926
969 xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); 927 dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1);
970 xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); 928 dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2);
971 ents1 = xfs_dir3_leaf_ents_p(leaf1); 929 ents1 = dp->d_ops->leaf_ents_p(leaf1);
972 ents2 = xfs_dir3_leaf_ents_p(leaf2); 930 ents2 = dp->d_ops->leaf_ents_p(leaf2);
973 931
974 if (hdr1.count > 0 && hdr2.count > 0 && 932 if (hdr1.count > 0 && hdr2.count > 0 &&
975 (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) || 933 (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) ||
@@ -1007,12 +965,13 @@ xfs_dir2_leafn_rebalance(
1007 struct xfs_dir2_leaf_entry *ents2; 965 struct xfs_dir2_leaf_entry *ents2;
1008 struct xfs_dir3_icleaf_hdr hdr1; 966 struct xfs_dir3_icleaf_hdr hdr1;
1009 struct xfs_dir3_icleaf_hdr hdr2; 967 struct xfs_dir3_icleaf_hdr hdr2;
968 struct xfs_inode *dp = state->args->dp;
1010 969
1011 args = state->args; 970 args = state->args;
1012 /* 971 /*
1013 * If the block order is wrong, swap the arguments. 972 * If the block order is wrong, swap the arguments.
1014 */ 973 */
1015 if ((swap = xfs_dir2_leafn_order(blk1->bp, blk2->bp))) { 974 if ((swap = xfs_dir2_leafn_order(dp, blk1->bp, blk2->bp))) {
1016 xfs_da_state_blk_t *tmp; /* temp for block swap */ 975 xfs_da_state_blk_t *tmp; /* temp for block swap */
1017 976
1018 tmp = blk1; 977 tmp = blk1;
@@ -1021,10 +980,10 @@ xfs_dir2_leafn_rebalance(
1021 } 980 }
1022 leaf1 = blk1->bp->b_addr; 981 leaf1 = blk1->bp->b_addr;
1023 leaf2 = blk2->bp->b_addr; 982 leaf2 = blk2->bp->b_addr;
1024 xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); 983 dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1);
1025 xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); 984 dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2);
1026 ents1 = xfs_dir3_leaf_ents_p(leaf1); 985 ents1 = dp->d_ops->leaf_ents_p(leaf1);
1027 ents2 = xfs_dir3_leaf_ents_p(leaf2); 986 ents2 = dp->d_ops->leaf_ents_p(leaf2);
1028 987
1029 oldsum = hdr1.count + hdr2.count; 988 oldsum = hdr1.count + hdr2.count;
1030#if defined(DEBUG) || defined(XFS_WARN) 989#if defined(DEBUG) || defined(XFS_WARN)
@@ -1070,13 +1029,13 @@ xfs_dir2_leafn_rebalance(
1070 ASSERT(hdr1.stale + hdr2.stale == oldstale); 1029 ASSERT(hdr1.stale + hdr2.stale == oldstale);
1071 1030
1072 /* log the changes made when moving the entries */ 1031 /* log the changes made when moving the entries */
1073 xfs_dir3_leaf_hdr_to_disk(leaf1, &hdr1); 1032 dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1);
1074 xfs_dir3_leaf_hdr_to_disk(leaf2, &hdr2); 1033 dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2);
1075 xfs_dir3_leaf_log_header(args->trans, blk1->bp); 1034 xfs_dir3_leaf_log_header(args->trans, dp, blk1->bp);
1076 xfs_dir3_leaf_log_header(args->trans, blk2->bp); 1035 xfs_dir3_leaf_log_header(args->trans, dp, blk2->bp);
1077 1036
1078 xfs_dir3_leaf_check(args->dp->i_mount, blk1->bp); 1037 xfs_dir3_leaf_check(dp, blk1->bp);
1079 xfs_dir3_leaf_check(args->dp->i_mount, blk2->bp); 1038 xfs_dir3_leaf_check(dp, blk2->bp);
1080 1039
1081 /* 1040 /*
1082 * Mark whether we're inserting into the old or new leaf. 1041 * Mark whether we're inserting into the old or new leaf.
@@ -1097,11 +1056,11 @@ xfs_dir2_leafn_rebalance(
1097 * Finally sanity check just to make sure we are not returning a 1056 * Finally sanity check just to make sure we are not returning a
1098 * negative index 1057 * negative index
1099 */ 1058 */
1100 if(blk2->index < 0) { 1059 if (blk2->index < 0) {
1101 state->inleaf = 1; 1060 state->inleaf = 1;
1102 blk2->index = 0; 1061 blk2->index = 0;
1103 xfs_alert(args->dp->i_mount, 1062 xfs_alert(dp->i_mount,
1104 "%s: picked the wrong leaf? reverting original leaf: blk1->index %d\n", 1063 "%s: picked the wrong leaf? reverting original leaf: blk1->index %d",
1105 __func__, blk1->index); 1064 __func__, blk1->index);
1106 } 1065 }
1107} 1066}
@@ -1120,17 +1079,17 @@ xfs_dir3_data_block_free(
1120 int logfree = 0; 1079 int logfree = 0;
1121 __be16 *bests; 1080 __be16 *bests;
1122 struct xfs_dir3_icfree_hdr freehdr; 1081 struct xfs_dir3_icfree_hdr freehdr;
1082 struct xfs_inode *dp = args->dp;
1123 1083
1124 xfs_dir3_free_hdr_from_disk(&freehdr, free); 1084 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1125 1085 bests = dp->d_ops->free_bests_p(free);
1126 bests = xfs_dir3_free_bests_p(tp->t_mountp, free);
1127 if (hdr) { 1086 if (hdr) {
1128 /* 1087 /*
1129 * Data block is not empty, just set the free entry to the new 1088 * Data block is not empty, just set the free entry to the new
1130 * value. 1089 * value.
1131 */ 1090 */
1132 bests[findex] = cpu_to_be16(longest); 1091 bests[findex] = cpu_to_be16(longest);
1133 xfs_dir2_free_log_bests(tp, fbp, findex, findex); 1092 xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex);
1134 return 0; 1093 return 0;
1135 } 1094 }
1136 1095
@@ -1157,8 +1116,8 @@ xfs_dir3_data_block_free(
1157 logfree = 1; 1116 logfree = 1;
1158 } 1117 }
1159 1118
1160 xfs_dir3_free_hdr_to_disk(free, &freehdr); 1119 dp->d_ops->free_hdr_to_disk(free, &freehdr);
1161 xfs_dir2_free_log_header(tp, fbp); 1120 xfs_dir2_free_log_header(tp, dp, fbp);
1162 1121
1163 /* 1122 /*
1164 * If there are no useful entries left in the block, get rid of the 1123 * If there are no useful entries left in the block, get rid of the
@@ -1182,7 +1141,7 @@ xfs_dir3_data_block_free(
1182 1141
1183 /* Log the free entry that changed, unless we got rid of it. */ 1142 /* Log the free entry that changed, unless we got rid of it. */
1184 if (logfree) 1143 if (logfree)
1185 xfs_dir2_free_log_bests(tp, fbp, findex, findex); 1144 xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex);
1186 return 0; 1145 return 0;
1187} 1146}
1188 1147
@@ -1222,8 +1181,8 @@ xfs_dir2_leafn_remove(
1222 tp = args->trans; 1181 tp = args->trans;
1223 mp = dp->i_mount; 1182 mp = dp->i_mount;
1224 leaf = bp->b_addr; 1183 leaf = bp->b_addr;
1225 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 1184 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1226 ents = xfs_dir3_leaf_ents_p(leaf); 1185 ents = dp->d_ops->leaf_ents_p(leaf);
1227 1186
1228 /* 1187 /*
1229 * Point to the entry we're removing. 1188 * Point to the entry we're removing.
@@ -1243,11 +1202,11 @@ xfs_dir2_leafn_remove(
1243 * Log the leaf block changes. 1202 * Log the leaf block changes.
1244 */ 1203 */
1245 leafhdr.stale++; 1204 leafhdr.stale++;
1246 xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); 1205 dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr);
1247 xfs_dir3_leaf_log_header(tp, bp); 1206 xfs_dir3_leaf_log_header(tp, dp, bp);
1248 1207
1249 lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); 1208 lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
1250 xfs_dir3_leaf_log_ents(tp, bp, index, index); 1209 xfs_dir3_leaf_log_ents(tp, dp, bp, index, index);
1251 1210
1252 /* 1211 /*
1253 * Make the data entry free. Keep track of the longest freespace 1212 * Make the data entry free. Keep track of the longest freespace
@@ -1256,19 +1215,19 @@ xfs_dir2_leafn_remove(
1256 dbp = dblk->bp; 1215 dbp = dblk->bp;
1257 hdr = dbp->b_addr; 1216 hdr = dbp->b_addr;
1258 dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); 1217 dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
1259 bf = xfs_dir3_data_bestfree_p(hdr); 1218 bf = dp->d_ops->data_bestfree_p(hdr);
1260 longest = be16_to_cpu(bf[0].length); 1219 longest = be16_to_cpu(bf[0].length);
1261 needlog = needscan = 0; 1220 needlog = needscan = 0;
1262 xfs_dir2_data_make_free(tp, dbp, off, 1221 xfs_dir2_data_make_free(tp, dp, dbp, off,
1263 xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan); 1222 dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
1264 /* 1223 /*
1265 * Rescan the data block freespaces for bestfree. 1224 * Rescan the data block freespaces for bestfree.
1266 * Log the data block header if needed. 1225 * Log the data block header if needed.
1267 */ 1226 */
1268 if (needscan) 1227 if (needscan)
1269 xfs_dir2_data_freescan(mp, hdr, &needlog); 1228 xfs_dir2_data_freescan(dp, hdr, &needlog);
1270 if (needlog) 1229 if (needlog)
1271 xfs_dir2_data_log_header(tp, dbp); 1230 xfs_dir2_data_log_header(tp, dp, dbp);
1272 xfs_dir3_data_check(dp, dbp); 1231 xfs_dir3_data_check(dp, dbp);
1273 /* 1232 /*
1274 * If the longest data block freespace changes, need to update 1233 * If the longest data block freespace changes, need to update
@@ -1285,7 +1244,7 @@ xfs_dir2_leafn_remove(
1285 * Convert the data block number to a free block, 1244 * Convert the data block number to a free block,
1286 * read in the free block. 1245 * read in the free block.
1287 */ 1246 */
1288 fdb = xfs_dir2_db_to_fdb(mp, db); 1247 fdb = dp->d_ops->db_to_fdb(mp, db);
1289 error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb), 1248 error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb),
1290 &fbp); 1249 &fbp);
1291 if (error) 1250 if (error)
@@ -1294,22 +1253,22 @@ xfs_dir2_leafn_remove(
1294#ifdef DEBUG 1253#ifdef DEBUG
1295 { 1254 {
1296 struct xfs_dir3_icfree_hdr freehdr; 1255 struct xfs_dir3_icfree_hdr freehdr;
1297 xfs_dir3_free_hdr_from_disk(&freehdr, free); 1256 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1298 ASSERT(freehdr.firstdb == xfs_dir3_free_max_bests(mp) * 1257 ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(mp) *
1299 (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); 1258 (fdb - XFS_DIR2_FREE_FIRSTDB(mp)));
1300 } 1259 }
1301#endif 1260#endif
1302 /* 1261 /*
1303 * Calculate which entry we need to fix. 1262 * Calculate which entry we need to fix.
1304 */ 1263 */
1305 findex = xfs_dir2_db_to_fdindex(mp, db); 1264 findex = dp->d_ops->db_to_fdindex(mp, db);
1306 longest = be16_to_cpu(bf[0].length); 1265 longest = be16_to_cpu(bf[0].length);
1307 /* 1266 /*
1308 * If the data block is now empty we can get rid of it 1267 * If the data block is now empty we can get rid of it
1309 * (usually). 1268 * (usually).
1310 */ 1269 */
1311 if (longest == mp->m_dirblksize - 1270 if (longest == mp->m_dirblksize -
1312 xfs_dir3_data_entry_offset(hdr)) { 1271 dp->d_ops->data_entry_offset) {
1313 /* 1272 /*
1314 * Try to punch out the data block. 1273 * Try to punch out the data block.
1315 */ 1274 */
@@ -1336,12 +1295,12 @@ xfs_dir2_leafn_remove(
1336 return error; 1295 return error;
1337 } 1296 }
1338 1297
1339 xfs_dir3_leaf_check(mp, bp); 1298 xfs_dir3_leaf_check(dp, bp);
1340 /* 1299 /*
1341 * Return indication of whether this leaf block is empty enough 1300 * Return indication of whether this leaf block is empty enough
1342 * to justify trying to join it with a neighbor. 1301 * to justify trying to join it with a neighbor.
1343 */ 1302 */
1344 *rval = (xfs_dir3_leaf_hdr_size(leaf) + 1303 *rval = (dp->d_ops->leaf_hdr_size +
1345 (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < 1304 (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) <
1346 mp->m_dir_magicpct; 1305 mp->m_dir_magicpct;
1347 return 0; 1306 return 0;
@@ -1360,13 +1319,14 @@ xfs_dir2_leafn_split(
1360 xfs_dablk_t blkno; /* new leaf block number */ 1319 xfs_dablk_t blkno; /* new leaf block number */
1361 int error; /* error return value */ 1320 int error; /* error return value */
1362 xfs_mount_t *mp; /* filesystem mount point */ 1321 xfs_mount_t *mp; /* filesystem mount point */
1322 struct xfs_inode *dp;
1363 1323
1364 /* 1324 /*
1365 * Allocate space for a new leaf node. 1325 * Allocate space for a new leaf node.
1366 */ 1326 */
1367 args = state->args; 1327 args = state->args;
1368 mp = args->dp->i_mount; 1328 dp = args->dp;
1369 ASSERT(args != NULL); 1329 mp = dp->i_mount;
1370 ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC); 1330 ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC);
1371 error = xfs_da_grow_inode(args, &blkno); 1331 error = xfs_da_grow_inode(args, &blkno);
1372 if (error) { 1332 if (error) {
@@ -1401,10 +1361,10 @@ xfs_dir2_leafn_split(
1401 /* 1361 /*
1402 * Update last hashval in each block since we added the name. 1362 * Update last hashval in each block since we added the name.
1403 */ 1363 */
1404 oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL); 1364 oldblk->hashval = xfs_dir2_leafn_lasthash(dp, oldblk->bp, NULL);
1405 newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL); 1365 newblk->hashval = xfs_dir2_leafn_lasthash(dp, newblk->bp, NULL);
1406 xfs_dir3_leaf_check(mp, oldblk->bp); 1366 xfs_dir3_leaf_check(dp, oldblk->bp);
1407 xfs_dir3_leaf_check(mp, newblk->bp); 1367 xfs_dir3_leaf_check(dp, newblk->bp);
1408 return error; 1368 return error;
1409} 1369}
1410 1370
@@ -1434,6 +1394,7 @@ xfs_dir2_leafn_toosmall(
1434 int rval; /* result from path_shift */ 1394 int rval; /* result from path_shift */
1435 struct xfs_dir3_icleaf_hdr leafhdr; 1395 struct xfs_dir3_icleaf_hdr leafhdr;
1436 struct xfs_dir2_leaf_entry *ents; 1396 struct xfs_dir2_leaf_entry *ents;
1397 struct xfs_inode *dp = state->args->dp;
1437 1398
1438 /* 1399 /*
1439 * Check for the degenerate case of the block being over 50% full. 1400 * Check for the degenerate case of the block being over 50% full.
@@ -1442,12 +1403,12 @@ xfs_dir2_leafn_toosmall(
1442 */ 1403 */
1443 blk = &state->path.blk[state->path.active - 1]; 1404 blk = &state->path.blk[state->path.active - 1];
1444 leaf = blk->bp->b_addr; 1405 leaf = blk->bp->b_addr;
1445 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 1406 dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
1446 ents = xfs_dir3_leaf_ents_p(leaf); 1407 ents = dp->d_ops->leaf_ents_p(leaf);
1447 xfs_dir3_leaf_check(state->args->dp->i_mount, blk->bp); 1408 xfs_dir3_leaf_check(dp, blk->bp);
1448 1409
1449 count = leafhdr.count - leafhdr.stale; 1410 count = leafhdr.count - leafhdr.stale;
1450 bytes = xfs_dir3_leaf_hdr_size(leaf) + count * sizeof(ents[0]); 1411 bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]);
1451 if (bytes > (state->blocksize >> 1)) { 1412 if (bytes > (state->blocksize >> 1)) {
1452 /* 1413 /*
1453 * Blk over 50%, don't try to join. 1414 * Blk over 50%, don't try to join.
@@ -1492,7 +1453,7 @@ xfs_dir2_leafn_toosmall(
1492 /* 1453 /*
1493 * Read the sibling leaf block. 1454 * Read the sibling leaf block.
1494 */ 1455 */
1495 error = xfs_dir3_leafn_read(state->args->trans, state->args->dp, 1456 error = xfs_dir3_leafn_read(state->args->trans, dp,
1496 blkno, -1, &bp); 1457 blkno, -1, &bp);
1497 if (error) 1458 if (error)
1498 return error; 1459 return error;
@@ -1504,8 +1465,8 @@ xfs_dir2_leafn_toosmall(
1504 bytes = state->blocksize - (state->blocksize >> 2); 1465 bytes = state->blocksize - (state->blocksize >> 2);
1505 1466
1506 leaf = bp->b_addr; 1467 leaf = bp->b_addr;
1507 xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf); 1468 dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf);
1508 ents = xfs_dir3_leaf_ents_p(leaf); 1469 ents = dp->d_ops->leaf_ents_p(leaf);
1509 count += hdr2.count - hdr2.stale; 1470 count += hdr2.count - hdr2.stale;
1510 bytes -= count * sizeof(ents[0]); 1471 bytes -= count * sizeof(ents[0]);
1511 1472
@@ -1559,6 +1520,7 @@ xfs_dir2_leafn_unbalance(
1559 struct xfs_dir3_icleaf_hdr drophdr; 1520 struct xfs_dir3_icleaf_hdr drophdr;
1560 struct xfs_dir2_leaf_entry *sents; 1521 struct xfs_dir2_leaf_entry *sents;
1561 struct xfs_dir2_leaf_entry *dents; 1522 struct xfs_dir2_leaf_entry *dents;
1523 struct xfs_inode *dp = state->args->dp;
1562 1524
1563 args = state->args; 1525 args = state->args;
1564 ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); 1526 ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
@@ -1566,10 +1528,10 @@ xfs_dir2_leafn_unbalance(
1566 drop_leaf = drop_blk->bp->b_addr; 1528 drop_leaf = drop_blk->bp->b_addr;
1567 save_leaf = save_blk->bp->b_addr; 1529 save_leaf = save_blk->bp->b_addr;
1568 1530
1569 xfs_dir3_leaf_hdr_from_disk(&savehdr, save_leaf); 1531 dp->d_ops->leaf_hdr_from_disk(&savehdr, save_leaf);
1570 xfs_dir3_leaf_hdr_from_disk(&drophdr, drop_leaf); 1532 dp->d_ops->leaf_hdr_from_disk(&drophdr, drop_leaf);
1571 sents = xfs_dir3_leaf_ents_p(save_leaf); 1533 sents = dp->d_ops->leaf_ents_p(save_leaf);
1572 dents = xfs_dir3_leaf_ents_p(drop_leaf); 1534 dents = dp->d_ops->leaf_ents_p(drop_leaf);
1573 1535
1574 /* 1536 /*
1575 * If there are any stale leaf entries, take this opportunity 1537 * If there are any stale leaf entries, take this opportunity
@@ -1584,7 +1546,7 @@ xfs_dir2_leafn_unbalance(
1584 * Move the entries from drop to the appropriate end of save. 1546 * Move the entries from drop to the appropriate end of save.
1585 */ 1547 */
1586 drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval); 1548 drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval);
1587 if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp)) 1549 if (xfs_dir2_leafn_order(dp, save_blk->bp, drop_blk->bp))
1588 xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, 1550 xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0,
1589 save_blk->bp, &savehdr, sents, 0, 1551 save_blk->bp, &savehdr, sents, 0,
1590 drophdr.count); 1552 drophdr.count);
@@ -1595,13 +1557,13 @@ xfs_dir2_leafn_unbalance(
1595 save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval); 1557 save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval);
1596 1558
1597 /* log the changes made when moving the entries */ 1559 /* log the changes made when moving the entries */
1598 xfs_dir3_leaf_hdr_to_disk(save_leaf, &savehdr); 1560 dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr);
1599 xfs_dir3_leaf_hdr_to_disk(drop_leaf, &drophdr); 1561 dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr);
1600 xfs_dir3_leaf_log_header(args->trans, save_blk->bp); 1562 xfs_dir3_leaf_log_header(args->trans, dp, save_blk->bp);
1601 xfs_dir3_leaf_log_header(args->trans, drop_blk->bp); 1563 xfs_dir3_leaf_log_header(args->trans, dp, drop_blk->bp);
1602 1564
1603 xfs_dir3_leaf_check(args->dp->i_mount, save_blk->bp); 1565 xfs_dir3_leaf_check(dp, save_blk->bp);
1604 xfs_dir3_leaf_check(args->dp->i_mount, drop_blk->bp); 1566 xfs_dir3_leaf_check(dp, drop_blk->bp);
1605} 1567}
1606 1568
1607/* 1569/*
@@ -1712,7 +1674,7 @@ xfs_dir2_node_addname_int(
1712 dp = args->dp; 1674 dp = args->dp;
1713 mp = dp->i_mount; 1675 mp = dp->i_mount;
1714 tp = args->trans; 1676 tp = args->trans;
1715 length = xfs_dir3_data_entsize(mp, args->namelen); 1677 length = dp->d_ops->data_entsize(args->namelen);
1716 /* 1678 /*
1717 * If we came in with a freespace block that means that lookup 1679 * If we came in with a freespace block that means that lookup
1718 * found an entry with our hash value. This is the freespace 1680 * found an entry with our hash value. This is the freespace
@@ -1726,8 +1688,8 @@ xfs_dir2_node_addname_int(
1726 ifbno = fblk->blkno; 1688 ifbno = fblk->blkno;
1727 free = fbp->b_addr; 1689 free = fbp->b_addr;
1728 findex = fblk->index; 1690 findex = fblk->index;
1729 bests = xfs_dir3_free_bests_p(mp, free); 1691 bests = dp->d_ops->free_bests_p(free);
1730 xfs_dir3_free_hdr_from_disk(&freehdr, free); 1692 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1731 1693
1732 /* 1694 /*
1733 * This means the free entry showed that the data block had 1695 * This means the free entry showed that the data block had
@@ -1819,8 +1781,8 @@ xfs_dir2_node_addname_int(
1819 * and the freehdr are actually initialised if they are placed 1781 * and the freehdr are actually initialised if they are placed
1820 * there, so we have to do it here to avoid warnings. Blech. 1782 * there, so we have to do it here to avoid warnings. Blech.
1821 */ 1783 */
1822 bests = xfs_dir3_free_bests_p(mp, free); 1784 bests = dp->d_ops->free_bests_p(free);
1823 xfs_dir3_free_hdr_from_disk(&freehdr, free); 1785 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1824 if (be16_to_cpu(bests[findex]) != NULLDATAOFF && 1786 if (be16_to_cpu(bests[findex]) != NULLDATAOFF &&
1825 be16_to_cpu(bests[findex]) >= length) 1787 be16_to_cpu(bests[findex]) >= length)
1826 dbno = freehdr.firstdb + findex; 1788 dbno = freehdr.firstdb + findex;
@@ -1871,7 +1833,7 @@ xfs_dir2_node_addname_int(
1871 * Get the freespace block corresponding to the data block 1833 * Get the freespace block corresponding to the data block
1872 * that was just allocated. 1834 * that was just allocated.
1873 */ 1835 */
1874 fbno = xfs_dir2_db_to_fdb(mp, dbno); 1836 fbno = dp->d_ops->db_to_fdb(mp, dbno);
1875 error = xfs_dir2_free_try_read(tp, dp, 1837 error = xfs_dir2_free_try_read(tp, dp,
1876 xfs_dir2_db_to_da(mp, fbno), 1838 xfs_dir2_db_to_da(mp, fbno),
1877 &fbp); 1839 &fbp);
@@ -1888,12 +1850,12 @@ xfs_dir2_node_addname_int(
1888 if (error) 1850 if (error)
1889 return error; 1851 return error;
1890 1852
1891 if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { 1853 if (unlikely(dp->d_ops->db_to_fdb(mp, dbno) != fbno)) {
1892 xfs_alert(mp, 1854 xfs_alert(mp,
1893 "%s: dir ino %llu needed freesp block %lld for\n" 1855 "%s: dir ino %llu needed freesp block %lld for\n"
1894 " data block %lld, got %lld ifbno %llu lastfbno %d", 1856 " data block %lld, got %lld ifbno %llu lastfbno %d",
1895 __func__, (unsigned long long)dp->i_ino, 1857 __func__, (unsigned long long)dp->i_ino,
1896 (long long)xfs_dir2_db_to_fdb(mp, dbno), 1858 (long long)dp->d_ops->db_to_fdb(mp, dbno),
1897 (long long)dbno, (long long)fbno, 1859 (long long)dbno, (long long)fbno,
1898 (unsigned long long)ifbno, lastfbno); 1860 (unsigned long long)ifbno, lastfbno);
1899 if (fblk) { 1861 if (fblk) {
@@ -1918,30 +1880,30 @@ xfs_dir2_node_addname_int(
1918 if (error) 1880 if (error)
1919 return error; 1881 return error;
1920 free = fbp->b_addr; 1882 free = fbp->b_addr;
1921 bests = xfs_dir3_free_bests_p(mp, free); 1883 bests = dp->d_ops->free_bests_p(free);
1922 xfs_dir3_free_hdr_from_disk(&freehdr, free); 1884 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1923 1885
1924 /* 1886 /*
1925 * Remember the first slot as our empty slot. 1887 * Remember the first slot as our empty slot.
1926 */ 1888 */
1927 freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * 1889 freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
1928 xfs_dir3_free_max_bests(mp); 1890 dp->d_ops->free_max_bests(mp);
1929 } else { 1891 } else {
1930 free = fbp->b_addr; 1892 free = fbp->b_addr;
1931 bests = xfs_dir3_free_bests_p(mp, free); 1893 bests = dp->d_ops->free_bests_p(free);
1932 xfs_dir3_free_hdr_from_disk(&freehdr, free); 1894 dp->d_ops->free_hdr_from_disk(&freehdr, free);
1933 } 1895 }
1934 1896
1935 /* 1897 /*
1936 * Set the freespace block index from the data block number. 1898 * Set the freespace block index from the data block number.
1937 */ 1899 */
1938 findex = xfs_dir2_db_to_fdindex(mp, dbno); 1900 findex = dp->d_ops->db_to_fdindex(mp, dbno);
1939 /* 1901 /*
1940 * If it's after the end of the current entries in the 1902 * If it's after the end of the current entries in the
1941 * freespace block, extend that table. 1903 * freespace block, extend that table.
1942 */ 1904 */
1943 if (findex >= freehdr.nvalid) { 1905 if (findex >= freehdr.nvalid) {
1944 ASSERT(findex < xfs_dir3_free_max_bests(mp)); 1906 ASSERT(findex < dp->d_ops->free_max_bests(mp));
1945 freehdr.nvalid = findex + 1; 1907 freehdr.nvalid = findex + 1;
1946 /* 1908 /*
1947 * Tag new entry so nused will go up. 1909 * Tag new entry so nused will go up.
@@ -1954,8 +1916,8 @@ xfs_dir2_node_addname_int(
1954 */ 1916 */
1955 if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { 1917 if (bests[findex] == cpu_to_be16(NULLDATAOFF)) {
1956 freehdr.nused++; 1918 freehdr.nused++;
1957 xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr); 1919 dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
1958 xfs_dir2_free_log_header(tp, fbp); 1920 xfs_dir2_free_log_header(tp, dp, fbp);
1959 } 1921 }
1960 /* 1922 /*
1961 * Update the real value in the table. 1923 * Update the real value in the table.
@@ -1963,7 +1925,7 @@ xfs_dir2_node_addname_int(
1963 * change again. 1925 * change again.
1964 */ 1926 */
1965 hdr = dbp->b_addr; 1927 hdr = dbp->b_addr;
1966 bf = xfs_dir3_data_bestfree_p(hdr); 1928 bf = dp->d_ops->data_bestfree_p(hdr);
1967 bests[findex] = bf[0].length; 1929 bests[findex] = bf[0].length;
1968 logfree = 1; 1930 logfree = 1;
1969 } 1931 }
@@ -1985,7 +1947,7 @@ xfs_dir2_node_addname_int(
1985 if (error) 1947 if (error)
1986 return error; 1948 return error;
1987 hdr = dbp->b_addr; 1949 hdr = dbp->b_addr;
1988 bf = xfs_dir3_data_bestfree_p(hdr); 1950 bf = dp->d_ops->data_bestfree_p(hdr);
1989 logfree = 0; 1951 logfree = 0;
1990 } 1952 }
1991 ASSERT(be16_to_cpu(bf[0].length) >= length); 1953 ASSERT(be16_to_cpu(bf[0].length) >= length);
@@ -1998,7 +1960,7 @@ xfs_dir2_node_addname_int(
1998 /* 1960 /*
1999 * Mark the first part of the unused space, inuse for us. 1961 * Mark the first part of the unused space, inuse for us.
2000 */ 1962 */
2001 xfs_dir2_data_use_free(tp, dbp, dup, 1963 xfs_dir2_data_use_free(tp, dp, dbp, dup,
2002 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, 1964 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length,
2003 &needlog, &needscan); 1965 &needlog, &needscan);
2004 /* 1966 /*
@@ -2008,24 +1970,24 @@ xfs_dir2_node_addname_int(
2008 dep->inumber = cpu_to_be64(args->inumber); 1970 dep->inumber = cpu_to_be64(args->inumber);
2009 dep->namelen = args->namelen; 1971 dep->namelen = args->namelen;
2010 memcpy(dep->name, args->name, dep->namelen); 1972 memcpy(dep->name, args->name, dep->namelen);
2011 xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); 1973 dp->d_ops->data_put_ftype(dep, args->filetype);
2012 tagp = xfs_dir3_data_entry_tag_p(mp, dep); 1974 tagp = dp->d_ops->data_entry_tag_p(dep);
2013 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1975 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
2014 xfs_dir2_data_log_entry(tp, dbp, dep); 1976 xfs_dir2_data_log_entry(tp, dp, dbp, dep);
2015 /* 1977 /*
2016 * Rescan the block for bestfree if needed. 1978 * Rescan the block for bestfree if needed.
2017 */ 1979 */
2018 if (needscan) 1980 if (needscan)
2019 xfs_dir2_data_freescan(mp, hdr, &needlog); 1981 xfs_dir2_data_freescan(dp, hdr, &needlog);
2020 /* 1982 /*
2021 * Log the data block header if needed. 1983 * Log the data block header if needed.
2022 */ 1984 */
2023 if (needlog) 1985 if (needlog)
2024 xfs_dir2_data_log_header(tp, dbp); 1986 xfs_dir2_data_log_header(tp, dp, dbp);
2025 /* 1987 /*
2026 * If the freespace entry is now wrong, update it. 1988 * If the freespace entry is now wrong, update it.
2027 */ 1989 */
2028 bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */ 1990 bests = dp->d_ops->free_bests_p(free); /* gcc is so stupid */
2029 if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) { 1991 if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) {
2030 bests[findex] = bf[0].length; 1992 bests[findex] = bf[0].length;
2031 logfree = 1; 1993 logfree = 1;
@@ -2034,7 +1996,7 @@ xfs_dir2_node_addname_int(
2034 * Log the freespace entry if needed. 1996 * Log the freespace entry if needed.
2035 */ 1997 */
2036 if (logfree) 1998 if (logfree)
2037 xfs_dir2_free_log_bests(tp, fbp, findex, findex); 1999 xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex);
2038 /* 2000 /*
2039 * Return the data block and offset in args, then drop the data block. 2001 * Return the data block and offset in args, then drop the data block.
2040 */ 2002 */
@@ -2212,7 +2174,7 @@ xfs_dir2_node_replace(
2212 blk = &state->path.blk[state->path.active - 1]; 2174 blk = &state->path.blk[state->path.active - 1];
2213 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); 2175 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
2214 leaf = blk->bp->b_addr; 2176 leaf = blk->bp->b_addr;
2215 ents = xfs_dir3_leaf_ents_p(leaf); 2177 ents = args->dp->d_ops->leaf_ents_p(leaf);
2216 lep = &ents[blk->index]; 2178 lep = &ents[blk->index];
2217 ASSERT(state->extravalid); 2179 ASSERT(state->extravalid);
2218 /* 2180 /*
@@ -2229,8 +2191,9 @@ xfs_dir2_node_replace(
2229 * Fill in the new inode number and log the entry. 2191 * Fill in the new inode number and log the entry.
2230 */ 2192 */
2231 dep->inumber = cpu_to_be64(inum); 2193 dep->inumber = cpu_to_be64(inum);
2232 xfs_dir3_dirent_put_ftype(state->mp, dep, args->filetype); 2194 args->dp->d_ops->data_put_ftype(dep, args->filetype);
2233 xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep); 2195 xfs_dir2_data_log_entry(args->trans, args->dp,
2196 state->extrablk.bp, dep);
2234 rval = 0; 2197 rval = 0;
2235 } 2198 }
2236 /* 2199 /*
@@ -2285,7 +2248,7 @@ xfs_dir2_node_trim_free(
2285 if (!bp) 2248 if (!bp)
2286 return 0; 2249 return 0;
2287 free = bp->b_addr; 2250 free = bp->b_addr;
2288 xfs_dir3_free_hdr_from_disk(&freehdr, free); 2251 dp->d_ops->free_hdr_from_disk(&freehdr, free);
2289 2252
2290 /* 2253 /*
2291 * If there are used entries, there's nothing to do. 2254 * If there are used entries, there's nothing to do.
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h
index 1bad84c40829..8b9d2281f85b 100644
--- a/fs/xfs/xfs_dir2_priv.h
+++ b/fs/xfs/xfs_dir2_priv.h
@@ -59,7 +59,8 @@ extern int xfs_dir3_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp,
59 59
60extern struct xfs_dir2_data_free * 60extern struct xfs_dir2_data_free *
61xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, 61xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr,
62 struct xfs_dir2_data_unused *dup, int *loghead); 62 struct xfs_dir2_data_free *bf, struct xfs_dir2_data_unused *dup,
63 int *loghead);
63extern int xfs_dir3_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno, 64extern int xfs_dir3_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
64 struct xfs_buf **bpp); 65 struct xfs_buf **bpp);
65 66
@@ -76,9 +77,9 @@ extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr,
76 int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); 77 int *lowstalep, int *highstalep, int *lowlogp, int *highlogp);
77extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, 78extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno,
78 struct xfs_buf **bpp, __uint16_t magic); 79 struct xfs_buf **bpp, __uint16_t magic);
79extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, 80extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_inode *dp,
80 int first, int last); 81 struct xfs_buf *bp, int first, int last);
81extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, 82extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, struct xfs_inode *dp,
82 struct xfs_buf *bp); 83 struct xfs_buf *bp);
83extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); 84extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args);
84extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); 85extern int xfs_dir2_leaf_removename(struct xfs_da_args *args);
@@ -93,21 +94,18 @@ xfs_dir3_leaf_find_entry(struct xfs_dir3_icleaf_hdr *leafhdr,
93 int lowstale, int highstale, int *lfloglow, int *lfloghigh); 94 int lowstale, int highstale, int *lfloglow, int *lfloghigh);
94extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); 95extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state);
95 96
96extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, 97extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, struct xfs_inode *dp,
97 struct xfs_dir2_leaf *from);
98extern void xfs_dir3_leaf_hdr_to_disk(struct xfs_dir2_leaf *to,
99 struct xfs_dir3_icleaf_hdr *from);
100extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp,
101 struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf); 98 struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf);
102 99
103/* xfs_dir2_node.c */ 100/* xfs_dir2_node.c */
104extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, 101extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args,
105 struct xfs_buf *lbp); 102 struct xfs_buf *lbp);
106extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_buf *bp, int *count); 103extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_inode *dp,
104 struct xfs_buf *bp, int *count);
107extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp, 105extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp,
108 struct xfs_da_args *args, int *indexp, 106 struct xfs_da_args *args, int *indexp,
109 struct xfs_da_state *state); 107 struct xfs_da_state *state);
110extern int xfs_dir2_leafn_order(struct xfs_buf *leaf1_bp, 108extern int xfs_dir2_leafn_order(struct xfs_inode *dp, struct xfs_buf *leaf1_bp,
111 struct xfs_buf *leaf2_bp); 109 struct xfs_buf *leaf2_bp);
112extern int xfs_dir2_leafn_split(struct xfs_da_state *state, 110extern int xfs_dir2_leafn_split(struct xfs_da_state *state,
113 struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk); 111 struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk);
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index 8f84153e98a8..c4e50c6ed584 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -18,23 +18,23 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 24#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_mount.h" 27#include "xfs_mount.h"
28#include "xfs_da_format.h"
28#include "xfs_da_btree.h" 29#include "xfs_da_btree.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 30#include "xfs_inode.h"
32#include "xfs_dir2_format.h"
33#include "xfs_dir2.h" 31#include "xfs_dir2.h"
34#include "xfs_dir2_priv.h" 32#include "xfs_dir2_priv.h"
35#include "xfs_error.h" 33#include "xfs_error.h"
36#include "xfs_trace.h" 34#include "xfs_trace.h"
37#include "xfs_bmap.h" 35#include "xfs_bmap.h"
36#include "xfs_trans.h"
37#include "xfs_dinode.h"
38 38
39/* 39/*
40 * Directory file type support functions 40 * Directory file type support functions
@@ -119,9 +119,9 @@ xfs_dir2_sf_getdents(
119 * mp->m_dirdatablk. 119 * mp->m_dirdatablk.
120 */ 120 */
121 dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 121 dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
122 xfs_dir3_data_dot_offset(mp)); 122 dp->d_ops->data_dot_offset);
123 dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 123 dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
124 xfs_dir3_data_dotdot_offset(mp)); 124 dp->d_ops->data_dotdot_offset);
125 125
126 /* 126 /*
127 * Put . entry unless we're starting past it. 127 * Put . entry unless we're starting past it.
@@ -136,7 +136,7 @@ xfs_dir2_sf_getdents(
136 * Put .. entry unless we're starting past it. 136 * Put .. entry unless we're starting past it.
137 */ 137 */
138 if (ctx->pos <= dotdot_offset) { 138 if (ctx->pos <= dotdot_offset) {
139 ino = xfs_dir2_sf_get_parent_ino(sfp); 139 ino = dp->d_ops->sf_get_parent_ino(sfp);
140 ctx->pos = dotdot_offset & 0x7fffffff; 140 ctx->pos = dotdot_offset & 0x7fffffff;
141 if (!dir_emit(ctx, "..", 2, ino, DT_DIR)) 141 if (!dir_emit(ctx, "..", 2, ino, DT_DIR))
142 return 0; 142 return 0;
@@ -153,17 +153,17 @@ xfs_dir2_sf_getdents(
153 xfs_dir2_sf_get_offset(sfep)); 153 xfs_dir2_sf_get_offset(sfep));
154 154
155 if (ctx->pos > off) { 155 if (ctx->pos > off) {
156 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 156 sfep = dp->d_ops->sf_nextentry(sfp, sfep);
157 continue; 157 continue;
158 } 158 }
159 159
160 ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep); 160 ino = dp->d_ops->sf_get_ino(sfp, sfep);
161 filetype = xfs_dir3_sfe_get_ftype(mp, sfp, sfep); 161 filetype = dp->d_ops->sf_get_ftype(sfep);
162 ctx->pos = off & 0x7fffffff; 162 ctx->pos = off & 0x7fffffff;
163 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, 163 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino,
164 xfs_dir3_get_dtype(mp, filetype))) 164 xfs_dir3_get_dtype(mp, filetype)))
165 return 0; 165 return 0;
166 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 166 sfep = dp->d_ops->sf_nextentry(sfp, sfep);
167 } 167 }
168 168
169 ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & 169 ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
@@ -213,7 +213,7 @@ xfs_dir2_block_getdents(
213 * Set up values for the loop. 213 * Set up values for the loop.
214 */ 214 */
215 btp = xfs_dir2_block_tail_p(mp, hdr); 215 btp = xfs_dir2_block_tail_p(mp, hdr);
216 ptr = (char *)xfs_dir3_data_entry_p(hdr); 216 ptr = (char *)dp->d_ops->data_entry_p(hdr);
217 endptr = (char *)xfs_dir2_block_leaf_p(btp); 217 endptr = (char *)xfs_dir2_block_leaf_p(btp);
218 218
219 /* 219 /*
@@ -237,7 +237,7 @@ xfs_dir2_block_getdents(
237 /* 237 /*
238 * Bump pointer for the next iteration. 238 * Bump pointer for the next iteration.
239 */ 239 */
240 ptr += xfs_dir3_data_entsize(mp, dep->namelen); 240 ptr += dp->d_ops->data_entsize(dep->namelen);
241 /* 241 /*
242 * The entry is before the desired starting point, skip it. 242 * The entry is before the desired starting point, skip it.
243 */ 243 */
@@ -248,7 +248,7 @@ xfs_dir2_block_getdents(
248 (char *)dep - (char *)hdr); 248 (char *)dep - (char *)hdr);
249 249
250 ctx->pos = cook & 0x7fffffff; 250 ctx->pos = cook & 0x7fffffff;
251 filetype = xfs_dir3_dirent_get_ftype(mp, dep); 251 filetype = dp->d_ops->data_get_ftype(dep);
252 /* 252 /*
253 * If it didn't fit, set the final offset to here & return. 253 * If it didn't fit, set the final offset to here & return.
254 */ 254 */
@@ -578,13 +578,13 @@ xfs_dir2_leaf_getdents(
578 /* 578 /*
579 * Find our position in the block. 579 * Find our position in the block.
580 */ 580 */
581 ptr = (char *)xfs_dir3_data_entry_p(hdr); 581 ptr = (char *)dp->d_ops->data_entry_p(hdr);
582 byteoff = xfs_dir2_byte_to_off(mp, curoff); 582 byteoff = xfs_dir2_byte_to_off(mp, curoff);
583 /* 583 /*
584 * Skip past the header. 584 * Skip past the header.
585 */ 585 */
586 if (byteoff == 0) 586 if (byteoff == 0)
587 curoff += xfs_dir3_data_entry_offset(hdr); 587 curoff += dp->d_ops->data_entry_offset;
588 /* 588 /*
589 * Skip past entries until we reach our offset. 589 * Skip past entries until we reach our offset.
590 */ 590 */
@@ -601,7 +601,7 @@ xfs_dir2_leaf_getdents(
601 } 601 }
602 dep = (xfs_dir2_data_entry_t *)ptr; 602 dep = (xfs_dir2_data_entry_t *)ptr;
603 length = 603 length =
604 xfs_dir3_data_entsize(mp, dep->namelen); 604 dp->d_ops->data_entsize(dep->namelen);
605 ptr += length; 605 ptr += length;
606 } 606 }
607 /* 607 /*
@@ -632,8 +632,8 @@ xfs_dir2_leaf_getdents(
632 } 632 }
633 633
634 dep = (xfs_dir2_data_entry_t *)ptr; 634 dep = (xfs_dir2_data_entry_t *)ptr;
635 length = xfs_dir3_data_entsize(mp, dep->namelen); 635 length = dp->d_ops->data_entsize(dep->namelen);
636 filetype = xfs_dir3_dirent_get_ftype(mp, dep); 636 filetype = dp->d_ops->data_get_ftype(dep);
637 637
638 ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; 638 ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff;
639 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 639 if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 3ef6d402084c..aafc6e46cb58 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -17,22 +17,22 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_format.h"
21#include "xfs_log.h" 21#include "xfs_log_format.h"
22#include "xfs_trans.h" 22#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_ag.h" 24#include "xfs_ag.h"
25#include "xfs_mount.h" 25#include "xfs_mount.h"
26#include "xfs_da_format.h"
26#include "xfs_da_btree.h" 27#include "xfs_da_btree.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_dinode.h"
29#include "xfs_inode.h" 28#include "xfs_inode.h"
29#include "xfs_trans.h"
30#include "xfs_inode_item.h" 30#include "xfs_inode_item.h"
31#include "xfs_error.h" 31#include "xfs_error.h"
32#include "xfs_dir2_format.h"
33#include "xfs_dir2.h" 32#include "xfs_dir2.h"
34#include "xfs_dir2_priv.h" 33#include "xfs_dir2_priv.h"
35#include "xfs_trace.h" 34#include "xfs_trace.h"
35#include "xfs_dinode.h"
36 36
37/* 37/*
38 * Prototypes for internal functions. 38 * Prototypes for internal functions.
@@ -57,89 +57,6 @@ static void xfs_dir2_sf_toino8(xfs_da_args_t *args);
57#endif /* XFS_BIG_INUMS */ 57#endif /* XFS_BIG_INUMS */
58 58
59/* 59/*
60 * Inode numbers in short-form directories can come in two versions,
61 * either 4 bytes or 8 bytes wide. These helpers deal with the
62 * two forms transparently by looking at the headers i8count field.
63 *
64 * For 64-bit inode number the most significant byte must be zero.
65 */
66static xfs_ino_t
67xfs_dir2_sf_get_ino(
68 struct xfs_dir2_sf_hdr *hdr,
69 xfs_dir2_inou_t *from)
70{
71 if (hdr->i8count)
72 return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
73 else
74 return get_unaligned_be32(&from->i4.i);
75}
76
77static void
78xfs_dir2_sf_put_ino(
79 struct xfs_dir2_sf_hdr *hdr,
80 xfs_dir2_inou_t *to,
81 xfs_ino_t ino)
82{
83 ASSERT((ino & 0xff00000000000000ULL) == 0);
84
85 if (hdr->i8count)
86 put_unaligned_be64(ino, &to->i8.i);
87 else
88 put_unaligned_be32(ino, &to->i4.i);
89}
90
91xfs_ino_t
92xfs_dir2_sf_get_parent_ino(
93 struct xfs_dir2_sf_hdr *hdr)
94{
95 return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
96}
97
98void
99xfs_dir2_sf_put_parent_ino(
100 struct xfs_dir2_sf_hdr *hdr,
101 xfs_ino_t ino)
102{
103 xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
104}
105
106/*
107 * In short-form directory entries the inode numbers are stored at variable
108 * offset behind the entry name. If the entry stores a filetype value, then it
109 * sits between the name and the inode number. Hence the inode numbers may only
110 * be accessed through the helpers below.
111 */
112static xfs_dir2_inou_t *
113xfs_dir3_sfe_inop(
114 struct xfs_mount *mp,
115 struct xfs_dir2_sf_entry *sfep)
116{
117 __uint8_t *ptr = &sfep->name[sfep->namelen];
118 if (xfs_sb_version_hasftype(&mp->m_sb))
119 ptr++;
120 return (xfs_dir2_inou_t *)ptr;
121}
122
123xfs_ino_t
124xfs_dir3_sfe_get_ino(
125 struct xfs_mount *mp,
126 struct xfs_dir2_sf_hdr *hdr,
127 struct xfs_dir2_sf_entry *sfep)
128{
129 return xfs_dir2_sf_get_ino(hdr, xfs_dir3_sfe_inop(mp, sfep));
130}
131
132void
133xfs_dir3_sfe_put_ino(
134 struct xfs_mount *mp,
135 struct xfs_dir2_sf_hdr *hdr,
136 struct xfs_dir2_sf_entry *sfep,
137 xfs_ino_t ino)
138{
139 xfs_dir2_sf_put_ino(hdr, xfs_dir3_sfe_inop(mp, sfep), ino);
140}
141
142/*
143 * Given a block directory (dp/block), calculate its size as a shortform (sf) 60 * Given a block directory (dp/block), calculate its size as a shortform (sf)
144 * directory and a header for the sf directory, if it will fit it the 61 * directory and a header for the sf directory, if it will fit it the
145 * space currently present in the inode. If it won't fit, the output 62 * space currently present in the inode. If it won't fit, the output
@@ -226,7 +143,7 @@ xfs_dir2_block_sfsize(
226 */ 143 */
227 sfhp->count = count; 144 sfhp->count = count;
228 sfhp->i8count = i8count; 145 sfhp->i8count = i8count;
229 xfs_dir2_sf_put_parent_ino(sfhp, parent); 146 dp->d_ops->sf_put_parent_ino(sfhp, parent);
230 return size; 147 return size;
231} 148}
232 149
@@ -293,7 +210,7 @@ xfs_dir2_block_to_sf(
293 * Set up to loop over the block's entries. 210 * Set up to loop over the block's entries.
294 */ 211 */
295 btp = xfs_dir2_block_tail_p(mp, hdr); 212 btp = xfs_dir2_block_tail_p(mp, hdr);
296 ptr = (char *)xfs_dir3_data_entry_p(hdr); 213 ptr = (char *)dp->d_ops->data_entry_p(hdr);
297 endptr = (char *)xfs_dir2_block_leaf_p(btp); 214 endptr = (char *)xfs_dir2_block_leaf_p(btp);
298 sfep = xfs_dir2_sf_firstentry(sfp); 215 sfep = xfs_dir2_sf_firstentry(sfp);
299 /* 216 /*
@@ -321,7 +238,7 @@ xfs_dir2_block_to_sf(
321 else if (dep->namelen == 2 && 238 else if (dep->namelen == 2 &&
322 dep->name[0] == '.' && dep->name[1] == '.') 239 dep->name[0] == '.' && dep->name[1] == '.')
323 ASSERT(be64_to_cpu(dep->inumber) == 240 ASSERT(be64_to_cpu(dep->inumber) ==
324 xfs_dir2_sf_get_parent_ino(sfp)); 241 dp->d_ops->sf_get_parent_ino(sfp));
325 /* 242 /*
326 * Normal entry, copy it into shortform. 243 * Normal entry, copy it into shortform.
327 */ 244 */
@@ -331,14 +248,14 @@ xfs_dir2_block_to_sf(
331 (xfs_dir2_data_aoff_t) 248 (xfs_dir2_data_aoff_t)
332 ((char *)dep - (char *)hdr)); 249 ((char *)dep - (char *)hdr));
333 memcpy(sfep->name, dep->name, dep->namelen); 250 memcpy(sfep->name, dep->name, dep->namelen);
334 xfs_dir3_sfe_put_ino(mp, sfp, sfep, 251 dp->d_ops->sf_put_ino(sfp, sfep,
335 be64_to_cpu(dep->inumber)); 252 be64_to_cpu(dep->inumber));
336 xfs_dir3_sfe_put_ftype(mp, sfp, sfep, 253 dp->d_ops->sf_put_ftype(sfep,
337 xfs_dir3_dirent_get_ftype(mp, dep)); 254 dp->d_ops->data_get_ftype(dep));
338 255
339 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 256 sfep = dp->d_ops->sf_nextentry(sfp, sfep);
340 } 257 }
341 ptr += xfs_dir3_data_entsize(mp, dep->namelen); 258 ptr += dp->d_ops->data_entsize(dep->namelen);
342 } 259 }
343 ASSERT((char *)sfep - (char *)sfp == size); 260 ASSERT((char *)sfep - (char *)sfp == size);
344 xfs_dir2_sf_check(args); 261 xfs_dir2_sf_check(args);
@@ -389,7 +306,7 @@ xfs_dir2_sf_addname(
389 /* 306 /*
390 * Compute entry (and change in) size. 307 * Compute entry (and change in) size.
391 */ 308 */
392 add_entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen); 309 add_entsize = dp->d_ops->sf_entsize(sfp, args->namelen);
393 incr_isize = add_entsize; 310 incr_isize = add_entsize;
394 objchange = 0; 311 objchange = 0;
395#if XFS_BIG_INUMS 312#if XFS_BIG_INUMS
@@ -483,8 +400,7 @@ xfs_dir2_sf_addname_easy(
483 /* 400 /*
484 * Grow the in-inode space. 401 * Grow the in-inode space.
485 */ 402 */
486 xfs_idata_realloc(dp, 403 xfs_idata_realloc(dp, dp->d_ops->sf_entsize(sfp, args->namelen),
487 xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen),
488 XFS_DATA_FORK); 404 XFS_DATA_FORK);
489 /* 405 /*
490 * Need to set up again due to realloc of the inode data. 406 * Need to set up again due to realloc of the inode data.
@@ -497,8 +413,8 @@ xfs_dir2_sf_addname_easy(
497 sfep->namelen = args->namelen; 413 sfep->namelen = args->namelen;
498 xfs_dir2_sf_put_offset(sfep, offset); 414 xfs_dir2_sf_put_offset(sfep, offset);
499 memcpy(sfep->name, args->name, sfep->namelen); 415 memcpy(sfep->name, args->name, sfep->namelen);
500 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, args->inumber); 416 dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
501 xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep, args->filetype); 417 dp->d_ops->sf_put_ftype(sfep, args->filetype);
502 418
503 /* 419 /*
504 * Update the header and inode. 420 * Update the header and inode.
@@ -557,13 +473,13 @@ xfs_dir2_sf_addname_hard(
557 * to insert the new entry. 473 * to insert the new entry.
558 * If it's going to end up at the end then oldsfep will point there. 474 * If it's going to end up at the end then oldsfep will point there.
559 */ 475 */
560 for (offset = xfs_dir3_data_first_offset(mp), 476 for (offset = dp->d_ops->data_first_offset,
561 oldsfep = xfs_dir2_sf_firstentry(oldsfp), 477 oldsfep = xfs_dir2_sf_firstentry(oldsfp),
562 add_datasize = xfs_dir3_data_entsize(mp, args->namelen), 478 add_datasize = dp->d_ops->data_entsize(args->namelen),
563 eof = (char *)oldsfep == &buf[old_isize]; 479 eof = (char *)oldsfep == &buf[old_isize];
564 !eof; 480 !eof;
565 offset = new_offset + xfs_dir3_data_entsize(mp, oldsfep->namelen), 481 offset = new_offset + dp->d_ops->data_entsize(oldsfep->namelen),
566 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep), 482 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep),
567 eof = (char *)oldsfep == &buf[old_isize]) { 483 eof = (char *)oldsfep == &buf[old_isize]) {
568 new_offset = xfs_dir2_sf_get_offset(oldsfep); 484 new_offset = xfs_dir2_sf_get_offset(oldsfep);
569 if (offset + add_datasize <= new_offset) 485 if (offset + add_datasize <= new_offset)
@@ -592,8 +508,8 @@ xfs_dir2_sf_addname_hard(
592 sfep->namelen = args->namelen; 508 sfep->namelen = args->namelen;
593 xfs_dir2_sf_put_offset(sfep, offset); 509 xfs_dir2_sf_put_offset(sfep, offset);
594 memcpy(sfep->name, args->name, sfep->namelen); 510 memcpy(sfep->name, args->name, sfep->namelen);
595 xfs_dir3_sfe_put_ino(mp, sfp, sfep, args->inumber); 511 dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
596 xfs_dir3_sfe_put_ftype(mp, sfp, sfep, args->filetype); 512 dp->d_ops->sf_put_ftype(sfep, args->filetype);
597 sfp->count++; 513 sfp->count++;
598#if XFS_BIG_INUMS 514#if XFS_BIG_INUMS
599 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange) 515 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -603,7 +519,7 @@ xfs_dir2_sf_addname_hard(
603 * If there's more left to copy, do that. 519 * If there's more left to copy, do that.
604 */ 520 */
605 if (!eof) { 521 if (!eof) {
606 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 522 sfep = dp->d_ops->sf_nextentry(sfp, sfep);
607 memcpy(sfep, oldsfep, old_isize - nbytes); 523 memcpy(sfep, oldsfep, old_isize - nbytes);
608 } 524 }
609 kmem_free(buf); 525 kmem_free(buf);
@@ -639,8 +555,8 @@ xfs_dir2_sf_addname_pick(
639 mp = dp->i_mount; 555 mp = dp->i_mount;
640 556
641 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 557 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
642 size = xfs_dir3_data_entsize(mp, args->namelen); 558 size = dp->d_ops->data_entsize(args->namelen);
643 offset = xfs_dir3_data_first_offset(mp); 559 offset = dp->d_ops->data_first_offset;
644 sfep = xfs_dir2_sf_firstentry(sfp); 560 sfep = xfs_dir2_sf_firstentry(sfp);
645 holefit = 0; 561 holefit = 0;
646 /* 562 /*
@@ -652,8 +568,8 @@ xfs_dir2_sf_addname_pick(
652 if (!holefit) 568 if (!holefit)
653 holefit = offset + size <= xfs_dir2_sf_get_offset(sfep); 569 holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
654 offset = xfs_dir2_sf_get_offset(sfep) + 570 offset = xfs_dir2_sf_get_offset(sfep) +
655 xfs_dir3_data_entsize(mp, sfep->namelen); 571 dp->d_ops->data_entsize(sfep->namelen);
656 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); 572 sfep = dp->d_ops->sf_nextentry(sfp, sfep);
657 } 573 }
658 /* 574 /*
659 * Calculate data bytes used excluding the new entry, if this 575 * Calculate data bytes used excluding the new entry, if this
@@ -713,21 +629,20 @@ xfs_dir2_sf_check(
713 mp = dp->i_mount; 629 mp = dp->i_mount;
714 630
715 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 631 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
716 offset = xfs_dir3_data_first_offset(mp); 632 offset = dp->d_ops->data_first_offset;
717 ino = xfs_dir2_sf_get_parent_ino(sfp); 633 ino = dp->d_ops->sf_get_parent_ino(sfp);
718 i8count = ino > XFS_DIR2_MAX_SHORT_INUM; 634 i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
719 635
720 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); 636 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
721 i < sfp->count; 637 i < sfp->count;
722 i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep)) { 638 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
723 ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset); 639 ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
724 ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep); 640 ino = dp->d_ops->sf_get_ino(sfp, sfep);
725 i8count += ino > XFS_DIR2_MAX_SHORT_INUM; 641 i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
726 offset = 642 offset =
727 xfs_dir2_sf_get_offset(sfep) + 643 xfs_dir2_sf_get_offset(sfep) +
728 xfs_dir3_data_entsize(mp, sfep->namelen); 644 dp->d_ops->data_entsize(sfep->namelen);
729 ASSERT(xfs_dir3_sfe_get_ftype(mp, sfp, sfep) < 645 ASSERT(dp->d_ops->sf_get_ftype(sfep) < XFS_DIR3_FT_MAX);
730 XFS_DIR3_FT_MAX);
731 } 646 }
732 ASSERT(i8count == sfp->i8count); 647 ASSERT(i8count == sfp->i8count);
733 ASSERT(XFS_BIG_INUMS || i8count == 0); 648 ASSERT(XFS_BIG_INUMS || i8count == 0);
@@ -783,7 +698,7 @@ xfs_dir2_sf_create(
783 /* 698 /*
784 * Now can put in the inode number, since i8count is set. 699 * Now can put in the inode number, since i8count is set.
785 */ 700 */
786 xfs_dir2_sf_put_parent_ino(sfp, pino); 701 dp->d_ops->sf_put_parent_ino(sfp, pino);
787 sfp->count = 0; 702 sfp->count = 0;
788 dp->i_d.di_size = size; 703 dp->i_d.di_size = size;
789 xfs_dir2_sf_check(args); 704 xfs_dir2_sf_check(args);
@@ -838,7 +753,7 @@ xfs_dir2_sf_lookup(
838 */ 753 */
839 if (args->namelen == 2 && 754 if (args->namelen == 2 &&
840 args->name[0] == '.' && args->name[1] == '.') { 755 args->name[0] == '.' && args->name[1] == '.') {
841 args->inumber = xfs_dir2_sf_get_parent_ino(sfp); 756 args->inumber = dp->d_ops->sf_get_parent_ino(sfp);
842 args->cmpresult = XFS_CMP_EXACT; 757 args->cmpresult = XFS_CMP_EXACT;
843 args->filetype = XFS_DIR3_FT_DIR; 758 args->filetype = XFS_DIR3_FT_DIR;
844 return XFS_ERROR(EEXIST); 759 return XFS_ERROR(EEXIST);
@@ -848,7 +763,7 @@ xfs_dir2_sf_lookup(
848 */ 763 */
849 ci_sfep = NULL; 764 ci_sfep = NULL;
850 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 765 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
851 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) { 766 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
852 /* 767 /*
853 * Compare name and if it's an exact match, return the inode 768 * Compare name and if it's an exact match, return the inode
854 * number. If it's the first case-insensitive match, store the 769 * number. If it's the first case-insensitive match, store the
@@ -858,10 +773,8 @@ xfs_dir2_sf_lookup(
858 sfep->namelen); 773 sfep->namelen);
859 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { 774 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
860 args->cmpresult = cmp; 775 args->cmpresult = cmp;
861 args->inumber = xfs_dir3_sfe_get_ino(dp->i_mount, 776 args->inumber = dp->d_ops->sf_get_ino(sfp, sfep);
862 sfp, sfep); 777 args->filetype = dp->d_ops->sf_get_ftype(sfep);
863 args->filetype = xfs_dir3_sfe_get_ftype(dp->i_mount,
864 sfp, sfep);
865 if (cmp == XFS_CMP_EXACT) 778 if (cmp == XFS_CMP_EXACT)
866 return XFS_ERROR(EEXIST); 779 return XFS_ERROR(EEXIST);
867 ci_sfep = sfep; 780 ci_sfep = sfep;
@@ -917,10 +830,10 @@ xfs_dir2_sf_removename(
917 * Find the one we're deleting. 830 * Find the one we're deleting.
918 */ 831 */
919 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 832 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
920 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) { 833 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
921 if (xfs_da_compname(args, sfep->name, sfep->namelen) == 834 if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
922 XFS_CMP_EXACT) { 835 XFS_CMP_EXACT) {
923 ASSERT(xfs_dir3_sfe_get_ino(dp->i_mount, sfp, sfep) == 836 ASSERT(dp->d_ops->sf_get_ino(sfp, sfep) ==
924 args->inumber); 837 args->inumber);
925 break; 838 break;
926 } 839 }
@@ -934,7 +847,7 @@ xfs_dir2_sf_removename(
934 * Calculate sizes. 847 * Calculate sizes.
935 */ 848 */
936 byteoff = (int)((char *)sfep - (char *)sfp); 849 byteoff = (int)((char *)sfep - (char *)sfp);
937 entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen); 850 entsize = dp->d_ops->sf_entsize(sfp, args->namelen);
938 newsize = oldsize - entsize; 851 newsize = oldsize - entsize;
939 /* 852 /*
940 * Copy the part if any after the removed entry, sliding it down. 853 * Copy the part if any after the removed entry, sliding it down.
@@ -1041,28 +954,25 @@ xfs_dir2_sf_replace(
1041 if (args->namelen == 2 && 954 if (args->namelen == 2 &&
1042 args->name[0] == '.' && args->name[1] == '.') { 955 args->name[0] == '.' && args->name[1] == '.') {
1043#if XFS_BIG_INUMS || defined(DEBUG) 956#if XFS_BIG_INUMS || defined(DEBUG)
1044 ino = xfs_dir2_sf_get_parent_ino(sfp); 957 ino = dp->d_ops->sf_get_parent_ino(sfp);
1045 ASSERT(args->inumber != ino); 958 ASSERT(args->inumber != ino);
1046#endif 959#endif
1047 xfs_dir2_sf_put_parent_ino(sfp, args->inumber); 960 dp->d_ops->sf_put_parent_ino(sfp, args->inumber);
1048 } 961 }
1049 /* 962 /*
1050 * Normal entry, look for the name. 963 * Normal entry, look for the name.
1051 */ 964 */
1052 else { 965 else {
1053 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 966 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
1054 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) { 967 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
1055 if (xfs_da_compname(args, sfep->name, sfep->namelen) == 968 if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
1056 XFS_CMP_EXACT) { 969 XFS_CMP_EXACT) {
1057#if XFS_BIG_INUMS || defined(DEBUG) 970#if XFS_BIG_INUMS || defined(DEBUG)
1058 ino = xfs_dir3_sfe_get_ino(dp->i_mount, 971 ino = dp->d_ops->sf_get_ino(sfp, sfep);
1059 sfp, sfep);
1060 ASSERT(args->inumber != ino); 972 ASSERT(args->inumber != ino);
1061#endif 973#endif
1062 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, 974 dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
1063 args->inumber); 975 dp->d_ops->sf_put_ftype(sfep, args->filetype);
1064 xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep,
1065 args->filetype);
1066 break; 976 break;
1067 } 977 }
1068 } 978 }
@@ -1165,22 +1075,21 @@ xfs_dir2_sf_toino4(
1165 */ 1075 */
1166 sfp->count = oldsfp->count; 1076 sfp->count = oldsfp->count;
1167 sfp->i8count = 0; 1077 sfp->i8count = 0;
1168 xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp)); 1078 dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp));
1169 /* 1079 /*
1170 * Copy the entries field by field. 1080 * Copy the entries field by field.
1171 */ 1081 */
1172 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1082 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1173 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1083 oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1174 i < sfp->count; 1084 i < sfp->count;
1175 i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep), 1085 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep),
1176 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) { 1086 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) {
1177 sfep->namelen = oldsfep->namelen; 1087 sfep->namelen = oldsfep->namelen;
1178 sfep->offset = oldsfep->offset; 1088 sfep->offset = oldsfep->offset;
1179 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1089 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1180 xfs_dir3_sfe_put_ino(mp, sfp, sfep, 1090 dp->d_ops->sf_put_ino(sfp, sfep,
1181 xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep)); 1091 dp->d_ops->sf_get_ino(oldsfp, oldsfep));
1182 xfs_dir3_sfe_put_ftype(mp, sfp, sfep, 1092 dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep));
1183 xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep));
1184 } 1093 }
1185 /* 1094 /*
1186 * Clean up the inode. 1095 * Clean up the inode.
@@ -1244,22 +1153,21 @@ xfs_dir2_sf_toino8(
1244 */ 1153 */
1245 sfp->count = oldsfp->count; 1154 sfp->count = oldsfp->count;
1246 sfp->i8count = 1; 1155 sfp->i8count = 1;
1247 xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp)); 1156 dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp));
1248 /* 1157 /*
1249 * Copy the entries field by field. 1158 * Copy the entries field by field.
1250 */ 1159 */
1251 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1160 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1252 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1161 oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1253 i < sfp->count; 1162 i < sfp->count;
1254 i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep), 1163 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep),
1255 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) { 1164 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) {
1256 sfep->namelen = oldsfep->namelen; 1165 sfep->namelen = oldsfep->namelen;
1257 sfep->offset = oldsfep->offset; 1166 sfep->offset = oldsfep->offset;
1258 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1167 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1259 xfs_dir3_sfe_put_ino(mp, sfp, sfep, 1168 dp->d_ops->sf_put_ino(sfp, sfep,
1260 xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep)); 1169 dp->d_ops->sf_get_ino(oldsfp, oldsfep));
1261 xfs_dir3_sfe_put_ftype(mp, sfp, sfep, 1170 dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep));
1262 xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep));
1263 } 1171 }
1264 /* 1172 /*
1265 * Clean up the inode. 1173 * Clean up the inode.
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index 45560ee1a4ba..8367d6dc18c9 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -17,22 +17,21 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_format.h" 19#include "xfs_format.h"
20#include "xfs_log.h" 20#include "xfs_log_format.h"
21#include "xfs_trans.h" 21#include "xfs_trans_resv.h"
22#include "xfs_sb.h" 22#include "xfs_sb.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_mount.h" 24#include "xfs_mount.h"
25#include "xfs_quota.h" 25#include "xfs_quota.h"
26#include "xfs_alloc_btree.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_ialloc_btree.h"
29#include "xfs_btree.h"
30#include "xfs_inode.h" 26#include "xfs_inode.h"
27#include "xfs_btree.h"
28#include "xfs_alloc_btree.h"
31#include "xfs_alloc.h" 29#include "xfs_alloc.h"
32#include "xfs_error.h" 30#include "xfs_error.h"
33#include "xfs_extent_busy.h" 31#include "xfs_extent_busy.h"
34#include "xfs_discard.h" 32#include "xfs_discard.h"
35#include "xfs_trace.h" 33#include "xfs_trace.h"
34#include "xfs_log.h"
36 35
37STATIC int 36STATIC int
38xfs_trim_extents( 37xfs_trim_extents(
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 1ee776d477c3..6b1e695caf0e 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -18,28 +18,28 @@
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_format.h" 20#include "xfs_format.h"
21#include "xfs_log_format.h"
22#include "xfs_shared.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_alloc.h"
27#include "xfs_quota.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_inode.h" 28#include "xfs_inode.h"
31#include "xfs_bmap.h" 29#include "xfs_bmap.h"
32#include "xfs_bmap_util.h" 30#include "xfs_bmap_util.h"
33#include "xfs_rtalloc.h" 31#include "xfs_alloc.h"
32#include "xfs_quota.h"
34#include "xfs_error.h" 33#include "xfs_error.h"
35#include "xfs_itable.h" 34#include "xfs_trans.h"
36#include "xfs_attr.h"
37#include "xfs_buf_item.h" 35#include "xfs_buf_item.h"
38#include "xfs_trans_space.h" 36#include "xfs_trans_space.h"
39#include "xfs_trans_priv.h" 37#include "xfs_trans_priv.h"
40#include "xfs_qm.h" 38#include "xfs_qm.h"
41#include "xfs_cksum.h" 39#include "xfs_cksum.h"
42#include "xfs_trace.h" 40#include "xfs_trace.h"
41#include "xfs_log.h"
42#include "xfs_bmap_btree.h"
43 43
44/* 44/*
45 * Lock order: 45 * Lock order:
@@ -292,118 +292,6 @@ xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
292 dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5; 292 dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
293} 293}
294 294
295STATIC bool
296xfs_dquot_buf_verify_crc(
297 struct xfs_mount *mp,
298 struct xfs_buf *bp)
299{
300 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
301 int ndquots;
302 int i;
303
304 if (!xfs_sb_version_hascrc(&mp->m_sb))
305 return true;
306
307 /*
308 * if we are in log recovery, the quota subsystem has not been
309 * initialised so we have no quotainfo structure. In that case, we need
310 * to manually calculate the number of dquots in the buffer.
311 */
312 if (mp->m_quotainfo)
313 ndquots = mp->m_quotainfo->qi_dqperchunk;
314 else
315 ndquots = xfs_qm_calc_dquots_per_chunk(mp,
316 XFS_BB_TO_FSB(mp, bp->b_length));
317
318 for (i = 0; i < ndquots; i++, d++) {
319 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
320 XFS_DQUOT_CRC_OFF))
321 return false;
322 if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
323 return false;
324 }
325 return true;
326}
327
328STATIC bool
329xfs_dquot_buf_verify(
330 struct xfs_mount *mp,
331 struct xfs_buf *bp)
332{
333 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
334 xfs_dqid_t id = 0;
335 int ndquots;
336 int i;
337
338 /*
339 * if we are in log recovery, the quota subsystem has not been
340 * initialised so we have no quotainfo structure. In that case, we need
341 * to manually calculate the number of dquots in the buffer.
342 */
343 if (mp->m_quotainfo)
344 ndquots = mp->m_quotainfo->qi_dqperchunk;
345 else
346 ndquots = xfs_qm_calc_dquots_per_chunk(mp, bp->b_length);
347
348 /*
349 * On the first read of the buffer, verify that each dquot is valid.
350 * We don't know what the id of the dquot is supposed to be, just that
351 * they should be increasing monotonically within the buffer. If the
352 * first id is corrupt, then it will fail on the second dquot in the
353 * buffer so corruptions could point to the wrong dquot in this case.
354 */
355 for (i = 0; i < ndquots; i++) {
356 struct xfs_disk_dquot *ddq;
357 int error;
358
359 ddq = &d[i].dd_diskdq;
360
361 if (i == 0)
362 id = be32_to_cpu(ddq->d_id);
363
364 error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
365 "xfs_dquot_buf_verify");
366 if (error)
367 return false;
368 }
369 return true;
370}
371
372static void
373xfs_dquot_buf_read_verify(
374 struct xfs_buf *bp)
375{
376 struct xfs_mount *mp = bp->b_target->bt_mount;
377
378 if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) {
379 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
380 xfs_buf_ioerror(bp, EFSCORRUPTED);
381 }
382}
383
384/*
385 * we don't calculate the CRC here as that is done when the dquot is flushed to
386 * the buffer after the update is done. This ensures that the dquot in the
387 * buffer always has an up-to-date CRC value.
388 */
389void
390xfs_dquot_buf_write_verify(
391 struct xfs_buf *bp)
392{
393 struct xfs_mount *mp = bp->b_target->bt_mount;
394
395 if (!xfs_dquot_buf_verify(mp, bp)) {
396 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
397 xfs_buf_ioerror(bp, EFSCORRUPTED);
398 return;
399 }
400}
401
402const struct xfs_buf_ops xfs_dquot_buf_ops = {
403 .verify_read = xfs_dquot_buf_read_verify,
404 .verify_write = xfs_dquot_buf_write_verify,
405};
406
407/* 295/*
408 * Allocate a block and fill it with dquots. 296 * Allocate a block and fill it with dquots.
409 * This is called when the bmapi finds a hole. 297 * This is called when the bmapi finds a hole.
@@ -514,6 +402,7 @@ xfs_qm_dqalloc(
514 402
515 return (error); 403 return (error);
516} 404}
405
517STATIC int 406STATIC int
518xfs_qm_dqrepair( 407xfs_qm_dqrepair(
519 struct xfs_mount *mp, 408 struct xfs_mount *mp,
@@ -547,7 +436,7 @@ xfs_qm_dqrepair(
547 /* Do the actual repair of dquots in this buffer */ 436 /* Do the actual repair of dquots in this buffer */
548 for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) { 437 for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) {
549 ddq = &d[i].dd_diskdq; 438 ddq = &d[i].dd_diskdq;
550 error = xfs_qm_dqcheck(mp, ddq, firstid + i, 439 error = xfs_dqcheck(mp, ddq, firstid + i,
551 dqp->dq_flags & XFS_DQ_ALLTYPES, 440 dqp->dq_flags & XFS_DQ_ALLTYPES,
552 XFS_QMOPT_DQREPAIR, "xfs_qm_dqrepair"); 441 XFS_QMOPT_DQREPAIR, "xfs_qm_dqrepair");
553 if (error) { 442 if (error) {
@@ -1133,7 +1022,7 @@ xfs_qm_dqflush(
1133 /* 1022 /*
1134 * A simple sanity check in case we got a corrupted dquot.. 1023 * A simple sanity check in case we got a corrupted dquot..
1135 */ 1024 */
1136 error = xfs_qm_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0, 1025 error = xfs_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0,
1137 XFS_QMOPT_DOWARN, "dqflush (incore copy)"); 1026 XFS_QMOPT_DOWARN, "dqflush (incore copy)");
1138 if (error) { 1027 if (error) {
1139 xfs_buf_relse(bp); 1028 xfs_buf_relse(bp);
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index 55abbca2883d..d22ed0053c32 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -172,6 +172,4 @@ static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
172 return dqp; 172 return dqp;
173} 173}
174 174
175extern const struct xfs_buf_ops xfs_dquot_buf_ops;
176
177#endif /* __XFS_DQUOT_H__ */ 175#endif /* __XFS_DQUOT_H__ */
diff --git a/fs/xfs/xfs_dquot_buf.c b/fs/xfs/xfs_dquot_buf.c
new file mode 100644
index 000000000000..d401457d2f25
--- /dev/null
+++ b/fs/xfs/xfs_dquot_buf.c
@@ -0,0 +1,288 @@
1/*
2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * Copyright (c) 2013 Red Hat, Inc.
4 * All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#include "xfs.h"
20#include "xfs_fs.h"
21#include "xfs_shared.h"
22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_mount.h"
28#include "xfs_inode.h"
29#include "xfs_quota.h"
30#include "xfs_trans.h"
31#include "xfs_qm.h"
32#include "xfs_error.h"
33#include "xfs_cksum.h"
34#include "xfs_trace.h"
35
36int
37xfs_calc_dquots_per_chunk(
38 struct xfs_mount *mp,
39 unsigned int nbblks) /* basic block units */
40{
41 unsigned int ndquots;
42
43 ASSERT(nbblks > 0);
44 ndquots = BBTOB(nbblks);
45 do_div(ndquots, sizeof(xfs_dqblk_t));
46
47 return ndquots;
48}
49
50/*
51 * Do some primitive error checking on ondisk dquot data structures.
52 */
53int
54xfs_dqcheck(
55 struct xfs_mount *mp,
56 xfs_disk_dquot_t *ddq,
57 xfs_dqid_t id,
58 uint type, /* used only when IO_dorepair is true */
59 uint flags,
60 char *str)
61{
62 xfs_dqblk_t *d = (xfs_dqblk_t *)ddq;
63 int errs = 0;
64
65 /*
66 * We can encounter an uninitialized dquot buffer for 2 reasons:
67 * 1. If we crash while deleting the quotainode(s), and those blks got
68 * used for user data. This is because we take the path of regular
69 * file deletion; however, the size field of quotainodes is never
70 * updated, so all the tricks that we play in itruncate_finish
71 * don't quite matter.
72 *
73 * 2. We don't play the quota buffers when there's a quotaoff logitem.
74 * But the allocation will be replayed so we'll end up with an
75 * uninitialized quota block.
76 *
77 * This is all fine; things are still consistent, and we haven't lost
78 * any quota information. Just don't complain about bad dquot blks.
79 */
80 if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) {
81 if (flags & XFS_QMOPT_DOWARN)
82 xfs_alert(mp,
83 "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
84 str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
85 errs++;
86 }
87 if (ddq->d_version != XFS_DQUOT_VERSION) {
88 if (flags & XFS_QMOPT_DOWARN)
89 xfs_alert(mp,
90 "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
91 str, id, ddq->d_version, XFS_DQUOT_VERSION);
92 errs++;
93 }
94
95 if (ddq->d_flags != XFS_DQ_USER &&
96 ddq->d_flags != XFS_DQ_PROJ &&
97 ddq->d_flags != XFS_DQ_GROUP) {
98 if (flags & XFS_QMOPT_DOWARN)
99 xfs_alert(mp,
100 "%s : XFS dquot ID 0x%x, unknown flags 0x%x",
101 str, id, ddq->d_flags);
102 errs++;
103 }
104
105 if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
106 if (flags & XFS_QMOPT_DOWARN)
107 xfs_alert(mp,
108 "%s : ondisk-dquot 0x%p, ID mismatch: "
109 "0x%x expected, found id 0x%x",
110 str, ddq, id, be32_to_cpu(ddq->d_id));
111 errs++;
112 }
113
114 if (!errs && ddq->d_id) {
115 if (ddq->d_blk_softlimit &&
116 be64_to_cpu(ddq->d_bcount) >
117 be64_to_cpu(ddq->d_blk_softlimit)) {
118 if (!ddq->d_btimer) {
119 if (flags & XFS_QMOPT_DOWARN)
120 xfs_alert(mp,
121 "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",
122 str, (int)be32_to_cpu(ddq->d_id), ddq);
123 errs++;
124 }
125 }
126 if (ddq->d_ino_softlimit &&
127 be64_to_cpu(ddq->d_icount) >
128 be64_to_cpu(ddq->d_ino_softlimit)) {
129 if (!ddq->d_itimer) {
130 if (flags & XFS_QMOPT_DOWARN)
131 xfs_alert(mp,
132 "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",
133 str, (int)be32_to_cpu(ddq->d_id), ddq);
134 errs++;
135 }
136 }
137 if (ddq->d_rtb_softlimit &&
138 be64_to_cpu(ddq->d_rtbcount) >
139 be64_to_cpu(ddq->d_rtb_softlimit)) {
140 if (!ddq->d_rtbtimer) {
141 if (flags & XFS_QMOPT_DOWARN)
142 xfs_alert(mp,
143 "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",
144 str, (int)be32_to_cpu(ddq->d_id), ddq);
145 errs++;
146 }
147 }
148 }
149
150 if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
151 return errs;
152
153 if (flags & XFS_QMOPT_DOWARN)
154 xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);
155
156 /*
157 * Typically, a repair is only requested by quotacheck.
158 */
159 ASSERT(id != -1);
160 ASSERT(flags & XFS_QMOPT_DQREPAIR);
161 memset(d, 0, sizeof(xfs_dqblk_t));
162
163 d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
164 d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
165 d->dd_diskdq.d_flags = type;
166 d->dd_diskdq.d_id = cpu_to_be32(id);
167
168 if (xfs_sb_version_hascrc(&mp->m_sb)) {
169 uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
170 xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
171 XFS_DQUOT_CRC_OFF);
172 }
173
174 return errs;
175}
176
177STATIC bool
178xfs_dquot_buf_verify_crc(
179 struct xfs_mount *mp,
180 struct xfs_buf *bp)
181{
182 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
183 int ndquots;
184 int i;
185
186 if (!xfs_sb_version_hascrc(&mp->m_sb))
187 return true;
188
189 /*
190 * if we are in log recovery, the quota subsystem has not been
191 * initialised so we have no quotainfo structure. In that case, we need
192 * to manually calculate the number of dquots in the buffer.
193 */
194 if (mp->m_quotainfo)
195 ndquots = mp->m_quotainfo->qi_dqperchunk;
196 else
197 ndquots = xfs_calc_dquots_per_chunk(mp,
198 XFS_BB_TO_FSB(mp, bp->b_length));
199
200 for (i = 0; i < ndquots; i++, d++) {
201 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
202 XFS_DQUOT_CRC_OFF))
203 return false;
204 if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
205 return false;
206 }
207 return true;
208}
209
210STATIC bool
211xfs_dquot_buf_verify(
212 struct xfs_mount *mp,
213 struct xfs_buf *bp)
214{
215 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
216 xfs_dqid_t id = 0;
217 int ndquots;
218 int i;
219
220 /*
221 * if we are in log recovery, the quota subsystem has not been
222 * initialised so we have no quotainfo structure. In that case, we need
223 * to manually calculate the number of dquots in the buffer.
224 */
225 if (mp->m_quotainfo)
226 ndquots = mp->m_quotainfo->qi_dqperchunk;
227 else
228 ndquots = xfs_calc_dquots_per_chunk(mp, bp->b_length);
229
230 /*
231 * On the first read of the buffer, verify that each dquot is valid.
232 * We don't know what the id of the dquot is supposed to be, just that
233 * they should be increasing monotonically within the buffer. If the
234 * first id is corrupt, then it will fail on the second dquot in the
235 * buffer so corruptions could point to the wrong dquot in this case.
236 */
237 for (i = 0; i < ndquots; i++) {
238 struct xfs_disk_dquot *ddq;
239 int error;
240
241 ddq = &d[i].dd_diskdq;
242
243 if (i == 0)
244 id = be32_to_cpu(ddq->d_id);
245
246 error = xfs_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
247 "xfs_dquot_buf_verify");
248 if (error)
249 return false;
250 }
251 return true;
252}
253
254static void
255xfs_dquot_buf_read_verify(
256 struct xfs_buf *bp)
257{
258 struct xfs_mount *mp = bp->b_target->bt_mount;
259
260 if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) {
261 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
262 xfs_buf_ioerror(bp, EFSCORRUPTED);
263 }
264}
265
266/*
267 * we don't calculate the CRC here as that is done when the dquot is flushed to
268 * the buffer after the update is done. This ensures that the dquot in the
269 * buffer always has an up-to-date CRC value.
270 */
271static void
272xfs_dquot_buf_write_verify(
273 struct xfs_buf *bp)
274{
275 struct xfs_mount *mp = bp->b_target->bt_mount;
276
277 if (!xfs_dquot_buf_verify(mp, bp)) {
278 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
279 xfs_buf_ioerror(bp, EFSCORRUPTED);
280 return;
281 }
282}
283
284const struct xfs_buf_ops xfs_dquot_buf_ops = {
285 .verify_read = xfs_dquot_buf_read_verify,
286 .verify_write = xfs_dquot_buf_write_verify,
287};
288
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index e838d84b4e85..92e5f62eefc6 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -18,23 +18,19 @@
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_format.h" 20#include "xfs_format.h"
21#include "xfs_log.h" 21#include "xfs_log_format.h"
22#include "xfs_trans.h" 22#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_ag.h" 24#include "xfs_ag.h"
25#include "xfs_alloc.h"
26#include "xfs_quota.h"
27#include "xfs_mount.h" 25#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_inode.h" 26#include "xfs_inode.h"
30#include "xfs_bmap.h" 27#include "xfs_quota.h"
31#include "xfs_rtalloc.h"
32#include "xfs_error.h" 28#include "xfs_error.h"
33#include "xfs_itable.h" 29#include "xfs_trans.h"
34#include "xfs_attr.h"
35#include "xfs_buf_item.h" 30#include "xfs_buf_item.h"
36#include "xfs_trans_priv.h" 31#include "xfs_trans_priv.h"
37#include "xfs_qm.h" 32#include "xfs_qm.h"
33#include "xfs_log.h"
38 34
39static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip) 35static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip)
40{ 36{
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 1123d93ff795..9995b807d627 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -16,16 +16,13 @@
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_format.h"
19#include "xfs_fs.h" 20#include "xfs_fs.h"
20#include "xfs_types.h" 21#include "xfs_log_format.h"
21#include "xfs_log.h" 22#include "xfs_trans_resv.h"
22#include "xfs_trans.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_ag.h" 24#include "xfs_ag.h"
25#include "xfs_mount.h" 25#include "xfs_mount.h"
26#include "xfs_bmap_btree.h"
27#include "xfs_dinode.h"
28#include "xfs_inode.h"
29#include "xfs_error.h" 26#include "xfs_error.h"
30 27
31#ifdef DEBUG 28#ifdef DEBUG
@@ -159,7 +156,7 @@ xfs_error_report(
159{ 156{
160 if (level <= xfs_error_level) { 157 if (level <= xfs_error_level) {
161 xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, 158 xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
162 "Internal error %s at line %d of file %s. Caller 0x%p\n", 159 "Internal error %s at line %d of file %s. Caller 0x%p",
163 tag, linenum, filename, ra); 160 tag, linenum, filename, ra);
164 161
165 xfs_stack_trace(); 162 xfs_stack_trace();
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index 066df425c14f..1399e187d425 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -16,21 +16,21 @@
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_types.h" 19#include "xfs_format.h"
20#include "xfs_log.h" 20#include "xfs_log_format.h"
21#include "xfs_trans.h" 21#include "xfs_trans_resv.h"
22#include "xfs_sb.h" 22#include "xfs_sb.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_mount.h" 24#include "xfs_mount.h"
25#include "xfs_da_btree.h" 25#include "xfs_da_format.h"
26#include "xfs_dir2_format.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_export.h" 27#include "xfs_export.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_inode.h" 28#include "xfs_inode.h"
29#include "xfs_trans.h"
31#include "xfs_inode_item.h" 30#include "xfs_inode_item.h"
32#include "xfs_trace.h" 31#include "xfs_trace.h"
33#include "xfs_icache.h" 32#include "xfs_icache.h"
33#include "xfs_log.h"
34 34
35/* 35/*
36 * Note that we only accept fileids which are long enough rather than allow 36 * Note that we only accept fileids which are long enough rather than allow
diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c
index e43708e2f080..fd22f69049d4 100644
--- a/fs/xfs/xfs_extent_busy.c
+++ b/fs/xfs/xfs_extent_busy.c
@@ -19,17 +19,18 @@
19 */ 19 */
20#include "xfs.h" 20#include "xfs.h"
21#include "xfs_fs.h" 21#include "xfs_fs.h"
22#include "xfs_types.h" 22#include "xfs_format.h"
23#include "xfs_log.h" 23#include "xfs_log_format.h"
24#include "xfs_trans.h" 24#include "xfs_shared.h"
25#include "xfs_trans_resv.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_alloc.h" 29#include "xfs_alloc.h"
30#include "xfs_inode.h"
31#include "xfs_extent_busy.h" 30#include "xfs_extent_busy.h"
32#include "xfs_trace.h" 31#include "xfs_trace.h"
32#include "xfs_trans.h"
33#include "xfs_log.h"
33 34
34void 35void
35xfs_extent_busy_insert( 36xfs_extent_busy_insert(
diff --git a/fs/xfs/xfs_extent_busy.h b/fs/xfs/xfs_extent_busy.h
index 985412d65ba5..bfff284d2dcc 100644
--- a/fs/xfs/xfs_extent_busy.h
+++ b/fs/xfs/xfs_extent_busy.h
@@ -20,6 +20,10 @@
20#ifndef __XFS_EXTENT_BUSY_H__ 20#ifndef __XFS_EXTENT_BUSY_H__
21#define __XFS_EXTENT_BUSY_H__ 21#define __XFS_EXTENT_BUSY_H__
22 22
23struct xfs_mount;
24struct xfs_trans;
25struct xfs_alloc_arg;
26
23/* 27/*
24 * Busy block/extent entry. Indexed by a rbtree in perag to mark blocks that 28 * Busy block/extent entry. Indexed by a rbtree in perag to mark blocks that
25 * have been freed but whose transactions aren't committed to disk yet. 29 * have been freed but whose transactions aren't committed to disk yet.
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index dc53e8febbbe..3680d04f973f 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -17,14 +17,14 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_log_format.h"
21#include "xfs_log.h" 21#include "xfs_trans_resv.h"
22#include "xfs_trans.h"
23#include "xfs_buf_item.h"
24#include "xfs_sb.h" 22#include "xfs_sb.h"
25#include "xfs_ag.h" 23#include "xfs_ag.h"
26#include "xfs_mount.h" 24#include "xfs_mount.h"
25#include "xfs_trans.h"
27#include "xfs_trans_priv.h" 26#include "xfs_trans_priv.h"
27#include "xfs_buf_item.h"
28#include "xfs_extfree_item.h" 28#include "xfs_extfree_item.h"
29 29
30 30
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 4c749ab543d0..52c91e143725 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -17,25 +17,27 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_log.h" 20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_sb.h" 24#include "xfs_sb.h"
22#include "xfs_ag.h" 25#include "xfs_ag.h"
23#include "xfs_trans.h"
24#include "xfs_mount.h" 26#include "xfs_mount.h"
25#include "xfs_bmap_btree.h" 27#include "xfs_da_format.h"
26#include "xfs_alloc.h" 28#include "xfs_da_btree.h"
27#include "xfs_dinode.h"
28#include "xfs_inode.h" 29#include "xfs_inode.h"
30#include "xfs_trans.h"
29#include "xfs_inode_item.h" 31#include "xfs_inode_item.h"
30#include "xfs_bmap.h" 32#include "xfs_bmap.h"
31#include "xfs_bmap_util.h" 33#include "xfs_bmap_util.h"
32#include "xfs_error.h" 34#include "xfs_error.h"
33#include "xfs_da_btree.h"
34#include "xfs_dir2_format.h"
35#include "xfs_dir2.h" 35#include "xfs_dir2.h"
36#include "xfs_dir2_priv.h" 36#include "xfs_dir2_priv.h"
37#include "xfs_ioctl.h" 37#include "xfs_ioctl.h"
38#include "xfs_trace.h" 38#include "xfs_trace.h"
39#include "xfs_log.h"
40#include "xfs_dinode.h"
39 41
40#include <linux/aio.h> 42#include <linux/aio.h>
41#include <linux/dcache.h> 43#include <linux/dcache.h>
@@ -805,44 +807,64 @@ out:
805 807
806STATIC long 808STATIC long
807xfs_file_fallocate( 809xfs_file_fallocate(
808 struct file *file, 810 struct file *file,
809 int mode, 811 int mode,
810 loff_t offset, 812 loff_t offset,
811 loff_t len) 813 loff_t len)
812{ 814{
813 struct inode *inode = file_inode(file); 815 struct inode *inode = file_inode(file);
814 long error; 816 struct xfs_inode *ip = XFS_I(inode);
815 loff_t new_size = 0; 817 struct xfs_trans *tp;
816 xfs_flock64_t bf; 818 long error;
817 xfs_inode_t *ip = XFS_I(inode); 819 loff_t new_size = 0;
818 int cmd = XFS_IOC_RESVSP;
819 int attr_flags = XFS_ATTR_NOLOCK;
820 820
821 if (!S_ISREG(inode->i_mode))
822 return -EINVAL;
821 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) 823 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
822 return -EOPNOTSUPP; 824 return -EOPNOTSUPP;
823 825
824 bf.l_whence = 0;
825 bf.l_start = offset;
826 bf.l_len = len;
827
828 xfs_ilock(ip, XFS_IOLOCK_EXCL); 826 xfs_ilock(ip, XFS_IOLOCK_EXCL);
827 if (mode & FALLOC_FL_PUNCH_HOLE) {
828 error = xfs_free_file_space(ip, offset, len);
829 if (error)
830 goto out_unlock;
831 } else {
832 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
833 offset + len > i_size_read(inode)) {
834 new_size = offset + len;
835 error = -inode_newsize_ok(inode, new_size);
836 if (error)
837 goto out_unlock;
838 }
829 839
830 if (mode & FALLOC_FL_PUNCH_HOLE) 840 error = xfs_alloc_file_space(ip, offset, len,
831 cmd = XFS_IOC_UNRESVSP; 841 XFS_BMAPI_PREALLOC);
832
833 /* check the new inode size is valid before allocating */
834 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
835 offset + len > i_size_read(inode)) {
836 new_size = offset + len;
837 error = inode_newsize_ok(inode, new_size);
838 if (error) 842 if (error)
839 goto out_unlock; 843 goto out_unlock;
840 } 844 }
841 845
842 if (file->f_flags & O_DSYNC) 846 tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID);
843 attr_flags |= XFS_ATTR_SYNC; 847 error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0);
848 if (error) {
849 xfs_trans_cancel(tp, 0);
850 goto out_unlock;
851 }
852
853 xfs_ilock(ip, XFS_ILOCK_EXCL);
854 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
855 ip->i_d.di_mode &= ~S_ISUID;
856 if (ip->i_d.di_mode & S_IXGRP)
857 ip->i_d.di_mode &= ~S_ISGID;
858
859 if (!(mode & FALLOC_FL_PUNCH_HOLE))
860 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
844 861
845 error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags); 862 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
863 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
864
865 if (file->f_flags & O_DSYNC)
866 xfs_trans_set_sync(tp);
867 error = xfs_trans_commit(tp, 0);
846 if (error) 868 if (error)
847 goto out_unlock; 869 goto out_unlock;
848 870
@@ -852,12 +874,12 @@ xfs_file_fallocate(
852 874
853 iattr.ia_valid = ATTR_SIZE; 875 iattr.ia_valid = ATTR_SIZE;
854 iattr.ia_size = new_size; 876 iattr.ia_size = new_size;
855 error = -xfs_setattr_size(ip, &iattr, XFS_ATTR_NOLOCK); 877 error = xfs_setattr_size(ip, &iattr);
856 } 878 }
857 879
858out_unlock: 880out_unlock:
859 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 881 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
860 return error; 882 return -error;
861} 883}
862 884
863 885
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index ce78e654d37b..12b6e7701985 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -16,19 +16,19 @@
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_log.h" 19#include "xfs_format.h"
20#include "xfs_bmap_btree.h" 20#include "xfs_log_format.h"
21#include "xfs_inum.h" 21#include "xfs_trans_resv.h"
22#include "xfs_dinode.h"
23#include "xfs_inode.h"
24#include "xfs_ag.h" 22#include "xfs_ag.h"
25#include "xfs_trans.h"
26#include "xfs_sb.h" 23#include "xfs_sb.h"
27#include "xfs_mount.h" 24#include "xfs_mount.h"
25#include "xfs_inum.h"
26#include "xfs_inode.h"
28#include "xfs_bmap.h" 27#include "xfs_bmap.h"
29#include "xfs_bmap_util.h" 28#include "xfs_bmap_util.h"
30#include "xfs_alloc.h" 29#include "xfs_alloc.h"
31#include "xfs_mru_cache.h" 30#include "xfs_mru_cache.h"
31#include "xfs_dinode.h"
32#include "xfs_filestream.h" 32#include "xfs_filestream.h"
33#include "xfs_trace.h" 33#include "xfs_trace.h"
34 34
diff --git a/fs/xfs/xfs_format.h b/fs/xfs/xfs_format.h
index 35c08ff54ca0..b6ab5a3cfa12 100644
--- a/fs/xfs/xfs_format.h
+++ b/fs/xfs/xfs_format.h
@@ -156,14 +156,259 @@ struct xfs_dsymlink_hdr {
156 ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ 156 ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
157 sizeof(struct xfs_dsymlink_hdr) : 0)) 157 sizeof(struct xfs_dsymlink_hdr) : 0))
158 158
159int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); 159
160int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, 160/*
161 uint32_t size, struct xfs_buf *bp); 161 * Allocation Btree format definitions
162bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, 162 *
163 uint32_t size, struct xfs_buf *bp); 163 * There are two on-disk btrees, one sorted by blockno and one sorted
164void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp, 164 * by blockcount and blockno. All blocks look the same to make the code
165 struct xfs_inode *ip, struct xfs_ifork *ifp); 165 * simpler; if we have time later, we'll make the optimizations.
166 166 */
167extern const struct xfs_buf_ops xfs_symlink_buf_ops; 167#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */
168#define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */
169#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */
170#define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */
171
172/*
173 * Data record/key structure
174 */
175typedef struct xfs_alloc_rec {
176 __be32 ar_startblock; /* starting block number */
177 __be32 ar_blockcount; /* count of free blocks */
178} xfs_alloc_rec_t, xfs_alloc_key_t;
179
180typedef struct xfs_alloc_rec_incore {
181 xfs_agblock_t ar_startblock; /* starting block number */
182 xfs_extlen_t ar_blockcount; /* count of free blocks */
183} xfs_alloc_rec_incore_t;
184
185/* btree pointer type */
186typedef __be32 xfs_alloc_ptr_t;
187
188/*
189 * Block numbers in the AG:
190 * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
191 */
192#define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1))
193#define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1))
194
195
196/*
197 * Inode Allocation Btree format definitions
198 *
199 * There is a btree for the inode map per allocation group.
200 */
201#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */
202#define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */
203
204typedef __uint64_t xfs_inofree_t;
205#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t))
206#define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3)
207#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1)
208#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i))
209
210static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
211{
212 return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i;
213}
214
215/*
216 * Data record structure
217 */
218typedef struct xfs_inobt_rec {
219 __be32 ir_startino; /* starting inode number */
220 __be32 ir_freecount; /* count of free inodes (set bits) */
221 __be64 ir_free; /* free inode mask */
222} xfs_inobt_rec_t;
223
224typedef struct xfs_inobt_rec_incore {
225 xfs_agino_t ir_startino; /* starting inode number */
226 __int32_t ir_freecount; /* count of free inodes (set bits) */
227 xfs_inofree_t ir_free; /* free inode mask */
228} xfs_inobt_rec_incore_t;
229
230
231/*
232 * Key structure
233 */
234typedef struct xfs_inobt_key {
235 __be32 ir_startino; /* starting inode number */
236} xfs_inobt_key_t;
237
238/* btree pointer type */
239typedef __be32 xfs_inobt_ptr_t;
240
241/*
242 * block numbers in the AG.
243 */
244#define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1))
245#define XFS_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
246
247
248
249/*
250 * BMAP Btree format definitions
251 *
252 * This includes both the root block definition that sits inside an inode fork
253 * and the record/pointer formats for the leaf/node in the blocks.
254 */
255#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */
256#define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */
257
258/*
259 * Bmap root header, on-disk form only.
260 */
261typedef struct xfs_bmdr_block {
262 __be16 bb_level; /* 0 is a leaf */
263 __be16 bb_numrecs; /* current # of data records */
264} xfs_bmdr_block_t;
265
266/*
267 * Bmap btree record and extent descriptor.
268 * l0:63 is an extent flag (value 1 indicates non-normal).
269 * l0:9-62 are startoff.
270 * l0:0-8 and l1:21-63 are startblock.
271 * l1:0-20 are blockcount.
272 */
273#define BMBT_EXNTFLAG_BITLEN 1
274#define BMBT_STARTOFF_BITLEN 54
275#define BMBT_STARTBLOCK_BITLEN 52
276#define BMBT_BLOCKCOUNT_BITLEN 21
277
278typedef struct xfs_bmbt_rec {
279 __be64 l0, l1;
280} xfs_bmbt_rec_t;
281
282typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
283typedef xfs_bmbt_rec_t xfs_bmdr_rec_t;
284
285typedef struct xfs_bmbt_rec_host {
286 __uint64_t l0, l1;
287} xfs_bmbt_rec_host_t;
288
289/*
290 * Values and macros for delayed-allocation startblock fields.
291 */
292#define STARTBLOCKVALBITS 17
293#define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20)
294#define DSTARTBLOCKMASKBITS (15 + 20)
295#define STARTBLOCKMASK \
296 (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
297#define DSTARTBLOCKMASK \
298 (((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
299
300static inline int isnullstartblock(xfs_fsblock_t x)
301{
302 return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK;
303}
304
305static inline int isnulldstartblock(xfs_dfsbno_t x)
306{
307 return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK;
308}
309
310static inline xfs_fsblock_t nullstartblock(int k)
311{
312 ASSERT(k < (1 << STARTBLOCKVALBITS));
313 return STARTBLOCKMASK | (k);
314}
315
316static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
317{
318 return (xfs_filblks_t)((x) & ~STARTBLOCKMASK);
319}
320
321/*
322 * Possible extent formats.
323 */
324typedef enum {
325 XFS_EXTFMT_NOSTATE = 0,
326 XFS_EXTFMT_HASSTATE
327} xfs_exntfmt_t;
328
329/*
330 * Possible extent states.
331 */
332typedef enum {
333 XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
334 XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
335} xfs_exntst_t;
336
337/*
338 * Incore version of above.
339 */
340typedef struct xfs_bmbt_irec
341{
342 xfs_fileoff_t br_startoff; /* starting file offset */
343 xfs_fsblock_t br_startblock; /* starting block number */
344 xfs_filblks_t br_blockcount; /* number of blocks */
345 xfs_exntst_t br_state; /* extent state */
346} xfs_bmbt_irec_t;
347
348/*
349 * Key structure for non-leaf levels of the tree.
350 */
351typedef struct xfs_bmbt_key {
352 __be64 br_startoff; /* starting file offset */
353} xfs_bmbt_key_t, xfs_bmdr_key_t;
354
355/* btree pointer type */
356typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
357
358
359/*
360 * Generic Btree block format definitions
361 *
362 * This is a combination of the actual format used on disk for short and long
363 * format btrees. The first three fields are shared by both format, but the
364 * pointers are different and should be used with care.
365 *
366 * To get the size of the actual short or long form headers please use the size
367 * macros below. Never use sizeof(xfs_btree_block).
368 *
369 * The blkno, crc, lsn, owner and uuid fields are only available in filesystems
370 * with the crc feature bit, and all accesses to them must be conditional on
371 * that flag.
372 */
373struct xfs_btree_block {
374 __be32 bb_magic; /* magic number for block type */
375 __be16 bb_level; /* 0 is a leaf */
376 __be16 bb_numrecs; /* current # of data records */
377 union {
378 struct {
379 __be32 bb_leftsib;
380 __be32 bb_rightsib;
381
382 __be64 bb_blkno;
383 __be64 bb_lsn;
384 uuid_t bb_uuid;
385 __be32 bb_owner;
386 __le32 bb_crc;
387 } s; /* short form pointers */
388 struct {
389 __be64 bb_leftsib;
390 __be64 bb_rightsib;
391
392 __be64 bb_blkno;
393 __be64 bb_lsn;
394 uuid_t bb_uuid;
395 __be64 bb_owner;
396 __le32 bb_crc;
397 __be32 bb_pad; /* padding for alignment */
398 } l; /* long form pointers */
399 } bb_u; /* rest */
400};
401
402#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */
403#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */
404
405/* sizes of CRC enabled btree blocks */
406#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40)
407#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48)
408
409#define XFS_BTREE_SBLOCK_CRC_OFF \
410 offsetof(struct xfs_btree_block, bb_u.s.bb_crc)
411#define XFS_BTREE_LBLOCK_CRC_OFF \
412 offsetof(struct xfs_btree_block, bb_u.l.bb_crc)
168 413
169#endif /* __XFS_FORMAT_H__ */ 414#endif /* __XFS_FORMAT_H__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 18272c766a50..c5fc116dfaa3 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -233,11 +233,11 @@ typedef struct xfs_fsop_resblks {
233#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ 233#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */
234#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ 234#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */
235#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ 235#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */
236#define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */ 236#define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */
237#define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ 237#define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */
238#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ 238#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */
239#define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ 239#define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */
240 240#define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */
241 241
242/* 242/*
243 * Minimum and maximum sizes need for growth checks. 243 * Minimum and maximum sizes need for growth checks.
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index e64ee5288b86..a6e54b3319bd 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -17,28 +17,29 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log.h" 21#include "xfs_format.h"
22#include "xfs_trans.h" 22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_mount.h" 26#include "xfs_mount.h"
26#include "xfs_bmap_btree.h"
27#include "xfs_alloc_btree.h"
28#include "xfs_ialloc_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h" 27#include "xfs_inode.h"
28#include "xfs_trans.h"
31#include "xfs_inode_item.h" 29#include "xfs_inode_item.h"
32#include "xfs_btree.h"
33#include "xfs_error.h" 30#include "xfs_error.h"
31#include "xfs_btree.h"
32#include "xfs_alloc_btree.h"
34#include "xfs_alloc.h" 33#include "xfs_alloc.h"
35#include "xfs_ialloc.h" 34#include "xfs_ialloc.h"
36#include "xfs_fsops.h" 35#include "xfs_fsops.h"
37#include "xfs_itable.h" 36#include "xfs_itable.h"
38#include "xfs_trans_space.h" 37#include "xfs_trans_space.h"
39#include "xfs_rtalloc.h" 38#include "xfs_rtalloc.h"
40#include "xfs_filestream.h"
41#include "xfs_trace.h" 39#include "xfs_trace.h"
40#include "xfs_log.h"
41#include "xfs_dinode.h"
42#include "xfs_filestream.h"
42 43
43/* 44/*
44 * File system operations 45 * File system operations
@@ -101,7 +102,9 @@ xfs_fs_geometry(
101 (xfs_sb_version_hasprojid32bit(&mp->m_sb) ? 102 (xfs_sb_version_hasprojid32bit(&mp->m_sb) ?
102 XFS_FSOP_GEOM_FLAGS_PROJID32 : 0) | 103 XFS_FSOP_GEOM_FLAGS_PROJID32 : 0) |
103 (xfs_sb_version_hascrc(&mp->m_sb) ? 104 (xfs_sb_version_hascrc(&mp->m_sb) ?
104 XFS_FSOP_GEOM_FLAGS_V5SB : 0); 105 XFS_FSOP_GEOM_FLAGS_V5SB : 0) |
106 (xfs_sb_version_hasftype(&mp->m_sb) ?
107 XFS_FSOP_GEOM_FLAGS_FTYPE : 0);
105 geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? 108 geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ?
106 mp->m_sb.sb_logsectsize : BBSIZE; 109 mp->m_sb.sb_logsectsize : BBSIZE;
107 geo->rtsectsize = mp->m_sb.sb_blocksize; 110 geo->rtsectsize = mp->m_sb.sb_blocksize;
@@ -153,7 +156,7 @@ xfs_growfs_data_private(
153 xfs_buf_t *bp; 156 xfs_buf_t *bp;
154 int bucket; 157 int bucket;
155 int dpct; 158 int dpct;
156 int error; 159 int error, saved_error = 0;
157 xfs_agnumber_t nagcount; 160 xfs_agnumber_t nagcount;
158 xfs_agnumber_t nagimax = 0; 161 xfs_agnumber_t nagimax = 0;
159 xfs_rfsblock_t nb, nb_mod; 162 xfs_rfsblock_t nb, nb_mod;
@@ -496,29 +499,33 @@ xfs_growfs_data_private(
496 error = ENOMEM; 499 error = ENOMEM;
497 } 500 }
498 501
502 /*
503 * If we get an error reading or writing alternate superblocks,
504 * continue. xfs_repair chooses the "best" superblock based
505 * on most matches; if we break early, we'll leave more
506 * superblocks un-updated than updated, and xfs_repair may
507 * pick them over the properly-updated primary.
508 */
499 if (error) { 509 if (error) {
500 xfs_warn(mp, 510 xfs_warn(mp,
501 "error %d reading secondary superblock for ag %d", 511 "error %d reading secondary superblock for ag %d",
502 error, agno); 512 error, agno);
503 break; 513 saved_error = error;
514 continue;
504 } 515 }
505 xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS); 516 xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
506 517
507 /*
508 * If we get an error writing out the alternate superblocks,
509 * just issue a warning and continue. The real work is
510 * already done and committed.
511 */
512 error = xfs_bwrite(bp); 518 error = xfs_bwrite(bp);
513 xfs_buf_relse(bp); 519 xfs_buf_relse(bp);
514 if (error) { 520 if (error) {
515 xfs_warn(mp, 521 xfs_warn(mp,
516 "write error %d updating secondary superblock for ag %d", 522 "write error %d updating secondary superblock for ag %d",
517 error, agno); 523 error, agno);
518 break; /* no point in continuing */ 524 saved_error = error;
525 continue;
519 } 526 }
520 } 527 }
521 return error; 528 return saved_error ? saved_error : error;
522 529
523 error0: 530 error0:
524 xfs_trans_cancel(tp, XFS_TRANS_ABORT); 531 xfs_trans_cancel(tp, XFS_TRANS_ABORT);
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index ccf2fb143962..e87719c5bebe 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -17,29 +17,30 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h" 25#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_alloc_btree.h"
30#include "xfs_ialloc_btree.h"
31#include "xfs_dinode.h"
32#include "xfs_inode.h" 29#include "xfs_inode.h"
33#include "xfs_btree.h" 30#include "xfs_btree.h"
34#include "xfs_ialloc.h" 31#include "xfs_ialloc.h"
32#include "xfs_ialloc_btree.h"
35#include "xfs_alloc.h" 33#include "xfs_alloc.h"
36#include "xfs_rtalloc.h" 34#include "xfs_rtalloc.h"
37#include "xfs_error.h" 35#include "xfs_error.h"
38#include "xfs_bmap.h" 36#include "xfs_bmap.h"
39#include "xfs_cksum.h" 37#include "xfs_cksum.h"
38#include "xfs_trans.h"
40#include "xfs_buf_item.h" 39#include "xfs_buf_item.h"
41#include "xfs_icreate_item.h" 40#include "xfs_icreate_item.h"
42#include "xfs_icache.h" 41#include "xfs_icache.h"
42#include "xfs_dinode.h"
43#include "xfs_trace.h"
43 44
44 45
45/* 46/*
@@ -1627,8 +1628,9 @@ xfs_read_agi(
1627{ 1628{
1628 int error; 1629 int error;
1629 1630
1630 ASSERT(agno != NULLAGNUMBER); 1631 trace_xfs_read_agi(mp, agno);
1631 1632
1633 ASSERT(agno != NULLAGNUMBER);
1632 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, 1634 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
1633 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), 1635 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
1634 XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops); 1636 XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops);
@@ -1651,6 +1653,8 @@ xfs_ialloc_read_agi(
1651 struct xfs_perag *pag; /* per allocation group data */ 1653 struct xfs_perag *pag; /* per allocation group data */
1652 int error; 1654 int error;
1653 1655
1656 trace_xfs_ialloc_read_agi(mp, agno);
1657
1654 error = xfs_read_agi(mp, tp, agno, bpp); 1658 error = xfs_read_agi(mp, tp, agno, bpp);
1655 if (error) 1659 if (error)
1656 return error; 1660 return error;
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h
index 68c07320f096..a8f76a5ff418 100644
--- a/fs/xfs/xfs_ialloc.h
+++ b/fs/xfs/xfs_ialloc.h
@@ -23,6 +23,7 @@ struct xfs_dinode;
23struct xfs_imap; 23struct xfs_imap;
24struct xfs_mount; 24struct xfs_mount;
25struct xfs_trans; 25struct xfs_trans;
26struct xfs_btree_cur;
26 27
27/* 28/*
28 * Allocation parameters for inode allocation. 29 * Allocation parameters for inode allocation.
@@ -42,7 +43,7 @@ struct xfs_trans;
42static inline struct xfs_dinode * 43static inline struct xfs_dinode *
43xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) 44xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o)
44{ 45{
45 return (xfs_dinode_t *) 46 return (struct xfs_dinode *)
46 (xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog)); 47 (xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog));
47} 48}
48 49
@@ -158,6 +159,4 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp,
158 xfs_agnumber_t agno, xfs_agblock_t agbno, 159 xfs_agnumber_t agno, xfs_agblock_t agbno,
159 xfs_agblock_t length, unsigned int gen); 160 xfs_agblock_t length, unsigned int gen);
160 161
161extern const struct xfs_buf_ops xfs_agi_buf_ops;
162
163#endif /* __XFS_IALLOC_H__ */ 162#endif /* __XFS_IALLOC_H__ */
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 5448eb6b8c12..c8fa5bbb36de 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -17,24 +17,23 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_alloc_btree.h"
29#include "xfs_ialloc_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 28#include "xfs_inode.h"
32#include "xfs_btree.h" 29#include "xfs_btree.h"
33#include "xfs_ialloc.h" 30#include "xfs_ialloc.h"
31#include "xfs_ialloc_btree.h"
34#include "xfs_alloc.h" 32#include "xfs_alloc.h"
35#include "xfs_error.h" 33#include "xfs_error.h"
36#include "xfs_trace.h" 34#include "xfs_trace.h"
37#include "xfs_cksum.h" 35#include "xfs_cksum.h"
36#include "xfs_trans.h"
38 37
39 38
40STATIC int 39STATIC int
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 3ac36b7642e9..f38b22011c4e 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -27,55 +27,6 @@ struct xfs_btree_cur;
27struct xfs_mount; 27struct xfs_mount;
28 28
29/* 29/*
30 * There is a btree for the inode map per allocation group.
31 */
32#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */
33#define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */
34
35typedef __uint64_t xfs_inofree_t;
36#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t))
37#define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3)
38#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1)
39#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i))
40
41static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
42{
43 return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i;
44}
45
46/*
47 * Data record structure
48 */
49typedef struct xfs_inobt_rec {
50 __be32 ir_startino; /* starting inode number */
51 __be32 ir_freecount; /* count of free inodes (set bits) */
52 __be64 ir_free; /* free inode mask */
53} xfs_inobt_rec_t;
54
55typedef struct xfs_inobt_rec_incore {
56 xfs_agino_t ir_startino; /* starting inode number */
57 __int32_t ir_freecount; /* count of free inodes (set bits) */
58 xfs_inofree_t ir_free; /* free inode mask */
59} xfs_inobt_rec_incore_t;
60
61
62/*
63 * Key structure
64 */
65typedef struct xfs_inobt_key {
66 __be32 ir_startino; /* starting inode number */
67} xfs_inobt_key_t;
68
69/* btree pointer type */
70typedef __be32 xfs_inobt_ptr_t;
71
72/*
73 * block numbers in the AG.
74 */
75#define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1))
76#define XFS_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
77
78/*
79 * Btree block header size depends on a superblock flag. 30 * Btree block header size depends on a superblock flag.
80 */ 31 */
81#define XFS_INOBT_BLOCK_LEN(mp) \ 32#define XFS_INOBT_BLOCK_LEN(mp) \
@@ -110,6 +61,4 @@ extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
110 struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t); 61 struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t);
111extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); 62extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);
112 63
113extern const struct xfs_buf_ops xfs_inobt_buf_ops;
114
115#endif /* __XFS_IALLOC_BTREE_H__ */ 64#endif /* __XFS_IALLOC_BTREE_H__ */
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 474807a401c8..98d35244eecc 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -18,24 +18,19 @@
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_format.h" 20#include "xfs_format.h"
21#include "xfs_types.h" 21#include "xfs_log_format.h"
22#include "xfs_log.h" 22#include "xfs_trans_resv.h"
23#include "xfs_log_priv.h"
24#include "xfs_inum.h" 23#include "xfs_inum.h"
25#include "xfs_trans.h"
26#include "xfs_trans_priv.h"
27#include "xfs_sb.h" 24#include "xfs_sb.h"
28#include "xfs_ag.h" 25#include "xfs_ag.h"
29#include "xfs_mount.h" 26#include "xfs_mount.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_inode.h" 27#include "xfs_inode.h"
32#include "xfs_dinode.h"
33#include "xfs_error.h" 28#include "xfs_error.h"
34#include "xfs_filestream.h" 29#include "xfs_trans.h"
30#include "xfs_trans_priv.h"
35#include "xfs_inode_item.h" 31#include "xfs_inode_item.h"
36#include "xfs_quota.h" 32#include "xfs_quota.h"
37#include "xfs_trace.h" 33#include "xfs_trace.h"
38#include "xfs_fsops.h"
39#include "xfs_icache.h" 34#include "xfs_icache.h"
40#include "xfs_bmap_util.h" 35#include "xfs_bmap_util.h"
41 36
@@ -500,11 +495,6 @@ xfs_inode_ag_walk_grab(
500 if (!igrab(inode)) 495 if (!igrab(inode))
501 return ENOENT; 496 return ENOENT;
502 497
503 if (is_bad_inode(inode)) {
504 IRELE(ip);
505 return ENOENT;
506 }
507
508 /* inode is valid */ 498 /* inode is valid */
509 return 0; 499 return 0;
510 500
@@ -918,8 +908,6 @@ restart:
918 xfs_iflock(ip); 908 xfs_iflock(ip);
919 } 909 }
920 910
921 if (is_bad_inode(VFS_I(ip)))
922 goto reclaim;
923 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { 911 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
924 xfs_iunpin_wait(ip); 912 xfs_iunpin_wait(ip);
925 xfs_iflush_abort(ip, false); 913 xfs_iflush_abort(ip, false);
diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
index 5a5a593994d4..d2eaccfa73f4 100644
--- a/fs/xfs/xfs_icreate_item.c
+++ b/fs/xfs/xfs_icreate_item.c
@@ -17,13 +17,14 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log_format.h"
22#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 23#include "xfs_bit.h"
22#include "xfs_log.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_mount.h" 26#include "xfs_mount.h"
27#include "xfs_trans.h"
27#include "xfs_trans_priv.h" 28#include "xfs_trans_priv.h"
28#include "xfs_error.h" 29#include "xfs_error.h"
29#include "xfs_icreate_item.h" 30#include "xfs_icreate_item.h"
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e3d75385aa76..001aa893ed59 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -19,39 +19,38 @@
19 19
20#include "xfs.h" 20#include "xfs.h"
21#include "xfs_fs.h" 21#include "xfs_fs.h"
22#include "xfs_shared.h"
22#include "xfs_format.h" 23#include "xfs_format.h"
23#include "xfs_log.h" 24#include "xfs_log_format.h"
25#include "xfs_trans_resv.h"
24#include "xfs_inum.h" 26#include "xfs_inum.h"
25#include "xfs_trans.h"
26#include "xfs_trans_space.h"
27#include "xfs_trans_priv.h"
28#include "xfs_sb.h" 27#include "xfs_sb.h"
29#include "xfs_ag.h" 28#include "xfs_ag.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
30#include "xfs_inode.h"
31#include "xfs_da_format.h"
31#include "xfs_da_btree.h" 32#include "xfs_da_btree.h"
32#include "xfs_dir2_format.h"
33#include "xfs_dir2.h" 33#include "xfs_dir2.h"
34#include "xfs_bmap_btree.h"
35#include "xfs_alloc_btree.h"
36#include "xfs_ialloc_btree.h"
37#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
38#include "xfs_attr.h" 35#include "xfs_attr.h"
39#include "xfs_dinode.h" 36#include "xfs_trans_space.h"
40#include "xfs_inode.h" 37#include "xfs_trans.h"
41#include "xfs_buf_item.h" 38#include "xfs_buf_item.h"
42#include "xfs_inode_item.h" 39#include "xfs_inode_item.h"
43#include "xfs_btree.h"
44#include "xfs_alloc.h"
45#include "xfs_ialloc.h" 40#include "xfs_ialloc.h"
46#include "xfs_bmap.h" 41#include "xfs_bmap.h"
47#include "xfs_bmap_util.h" 42#include "xfs_bmap_util.h"
48#include "xfs_error.h" 43#include "xfs_error.h"
49#include "xfs_quota.h" 44#include "xfs_quota.h"
45#include "xfs_dinode.h"
50#include "xfs_filestream.h" 46#include "xfs_filestream.h"
51#include "xfs_cksum.h" 47#include "xfs_cksum.h"
52#include "xfs_trace.h" 48#include "xfs_trace.h"
53#include "xfs_icache.h" 49#include "xfs_icache.h"
54#include "xfs_symlink.h" 50#include "xfs_symlink.h"
51#include "xfs_trans_priv.h"
52#include "xfs_log.h"
53#include "xfs_bmap_btree.h"
55 54
56kmem_zone_t *xfs_inode_zone; 55kmem_zone_t *xfs_inode_zone;
57 56
@@ -1663,6 +1662,126 @@ xfs_release(
1663} 1662}
1664 1663
1665/* 1664/*
1665 * xfs_inactive_truncate
1666 *
1667 * Called to perform a truncate when an inode becomes unlinked.
1668 */
1669STATIC int
1670xfs_inactive_truncate(
1671 struct xfs_inode *ip)
1672{
1673 struct xfs_mount *mp = ip->i_mount;
1674 struct xfs_trans *tp;
1675 int error;
1676
1677 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
1678 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
1679 if (error) {
1680 ASSERT(XFS_FORCED_SHUTDOWN(mp));
1681 xfs_trans_cancel(tp, 0);
1682 return error;
1683 }
1684
1685 xfs_ilock(ip, XFS_ILOCK_EXCL);
1686 xfs_trans_ijoin(tp, ip, 0);
1687
1688 /*
1689 * Log the inode size first to prevent stale data exposure in the event
1690 * of a system crash before the truncate completes. See the related
1691 * comment in xfs_setattr_size() for details.
1692 */
1693 ip->i_d.di_size = 0;
1694 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1695
1696 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
1697 if (error)
1698 goto error_trans_cancel;
1699
1700 ASSERT(ip->i_d.di_nextents == 0);
1701
1702 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
1703 if (error)
1704 goto error_unlock;
1705
1706 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1707 return 0;
1708
1709error_trans_cancel:
1710 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
1711error_unlock:
1712 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1713 return error;
1714}
1715
1716/*
1717 * xfs_inactive_ifree()
1718 *
1719 * Perform the inode free when an inode is unlinked.
1720 */
1721STATIC int
1722xfs_inactive_ifree(
1723 struct xfs_inode *ip)
1724{
1725 xfs_bmap_free_t free_list;
1726 xfs_fsblock_t first_block;
1727 int committed;
1728 struct xfs_mount *mp = ip->i_mount;
1729 struct xfs_trans *tp;
1730 int error;
1731
1732 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
1733 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0);
1734 if (error) {
1735 ASSERT(XFS_FORCED_SHUTDOWN(mp));
1736 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
1737 return error;
1738 }
1739
1740 xfs_ilock(ip, XFS_ILOCK_EXCL);
1741 xfs_trans_ijoin(tp, ip, 0);
1742
1743 xfs_bmap_init(&free_list, &first_block);
1744 error = xfs_ifree(tp, ip, &free_list);
1745 if (error) {
1746 /*
1747 * If we fail to free the inode, shut down. The cancel
1748 * might do that, we need to make sure. Otherwise the
1749 * inode might be lost for a long time or forever.
1750 */
1751 if (!XFS_FORCED_SHUTDOWN(mp)) {
1752 xfs_notice(mp, "%s: xfs_ifree returned error %d",
1753 __func__, error);
1754 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
1755 }
1756 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
1757 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1758 return error;
1759 }
1760
1761 /*
1762 * Credit the quota account(s). The inode is gone.
1763 */
1764 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
1765
1766 /*
1767 * Just ignore errors at this point. There is nothing we can
1768 * do except to try to keep going. Make sure it's not a silent
1769 * error.
1770 */
1771 error = xfs_bmap_finish(&tp, &free_list, &committed);
1772 if (error)
1773 xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
1774 __func__, error);
1775 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
1776 if (error)
1777 xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
1778 __func__, error);
1779
1780 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1781 return 0;
1782}
1783
1784/*
1666 * xfs_inactive 1785 * xfs_inactive
1667 * 1786 *
1668 * This is called when the vnode reference count for the vnode 1787 * This is called when the vnode reference count for the vnode
@@ -1670,16 +1789,11 @@ xfs_release(
1670 * now be truncated. Also, we clear all of the read-ahead state 1789 * now be truncated. Also, we clear all of the read-ahead state
1671 * kept for the inode here since the file is now closed. 1790 * kept for the inode here since the file is now closed.
1672 */ 1791 */
1673int 1792void
1674xfs_inactive( 1793xfs_inactive(
1675 xfs_inode_t *ip) 1794 xfs_inode_t *ip)
1676{ 1795{
1677 xfs_bmap_free_t free_list;
1678 xfs_fsblock_t first_block;
1679 int committed;
1680 struct xfs_trans *tp;
1681 struct xfs_mount *mp; 1796 struct xfs_mount *mp;
1682 struct xfs_trans_res *resp;
1683 int error; 1797 int error;
1684 int truncate = 0; 1798 int truncate = 0;
1685 1799
@@ -1687,19 +1801,17 @@ xfs_inactive(
1687 * If the inode is already free, then there can be nothing 1801 * If the inode is already free, then there can be nothing
1688 * to clean up here. 1802 * to clean up here.
1689 */ 1803 */
1690 if (ip->i_d.di_mode == 0 || is_bad_inode(VFS_I(ip))) { 1804 if (ip->i_d.di_mode == 0) {
1691 ASSERT(ip->i_df.if_real_bytes == 0); 1805 ASSERT(ip->i_df.if_real_bytes == 0);
1692 ASSERT(ip->i_df.if_broot_bytes == 0); 1806 ASSERT(ip->i_df.if_broot_bytes == 0);
1693 return VN_INACTIVE_CACHE; 1807 return;
1694 } 1808 }
1695 1809
1696 mp = ip->i_mount; 1810 mp = ip->i_mount;
1697 1811
1698 error = 0;
1699
1700 /* If this is a read-only mount, don't do this (would generate I/O) */ 1812 /* If this is a read-only mount, don't do this (would generate I/O) */
1701 if (mp->m_flags & XFS_MOUNT_RDONLY) 1813 if (mp->m_flags & XFS_MOUNT_RDONLY)
1702 goto out; 1814 return;
1703 1815
1704 if (ip->i_d.di_nlink != 0) { 1816 if (ip->i_d.di_nlink != 0) {
1705 /* 1817 /*
@@ -1707,12 +1819,10 @@ xfs_inactive(
1707 * cache. Post-eof blocks must be freed, lest we end up with 1819 * cache. Post-eof blocks must be freed, lest we end up with
1708 * broken free space accounting. 1820 * broken free space accounting.
1709 */ 1821 */
1710 if (xfs_can_free_eofblocks(ip, true)) { 1822 if (xfs_can_free_eofblocks(ip, true))
1711 error = xfs_free_eofblocks(mp, ip, false); 1823 xfs_free_eofblocks(mp, ip, false);
1712 if (error) 1824
1713 return VN_INACTIVE_CACHE; 1825 return;
1714 }
1715 goto out;
1716 } 1826 }
1717 1827
1718 if (S_ISREG(ip->i_d.di_mode) && 1828 if (S_ISREG(ip->i_d.di_mode) &&
@@ -1722,36 +1832,14 @@ xfs_inactive(
1722 1832
1723 error = xfs_qm_dqattach(ip, 0); 1833 error = xfs_qm_dqattach(ip, 0);
1724 if (error) 1834 if (error)
1725 return VN_INACTIVE_CACHE; 1835 return;
1726 1836
1727 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 1837 if (S_ISLNK(ip->i_d.di_mode))
1728 resp = (truncate || S_ISLNK(ip->i_d.di_mode)) ? 1838 error = xfs_inactive_symlink(ip);
1729 &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree; 1839 else if (truncate)
1730 1840 error = xfs_inactive_truncate(ip);
1731 error = xfs_trans_reserve(tp, resp, 0, 0); 1841 if (error)
1732 if (error) { 1842 return;
1733 ASSERT(XFS_FORCED_SHUTDOWN(mp));
1734 xfs_trans_cancel(tp, 0);
1735 return VN_INACTIVE_CACHE;
1736 }
1737
1738 xfs_ilock(ip, XFS_ILOCK_EXCL);
1739 xfs_trans_ijoin(tp, ip, 0);
1740
1741 if (S_ISLNK(ip->i_d.di_mode)) {
1742 error = xfs_inactive_symlink(ip, &tp);
1743 if (error)
1744 goto out_cancel;
1745 } else if (truncate) {
1746 ip->i_d.di_size = 0;
1747 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1748
1749 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
1750 if (error)
1751 goto out_cancel;
1752
1753 ASSERT(ip->i_d.di_nextents == 0);
1754 }
1755 1843
1756 /* 1844 /*
1757 * If there are attributes associated with the file then blow them away 1845 * If there are attributes associated with the file then blow them away
@@ -1762,25 +1850,9 @@ xfs_inactive(
1762 if (ip->i_d.di_anextents > 0) { 1850 if (ip->i_d.di_anextents > 0) {
1763 ASSERT(ip->i_d.di_forkoff != 0); 1851 ASSERT(ip->i_d.di_forkoff != 0);
1764 1852
1765 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
1766 if (error)
1767 goto out_unlock;
1768
1769 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1770
1771 error = xfs_attr_inactive(ip); 1853 error = xfs_attr_inactive(ip);
1772 if (error) 1854 if (error)
1773 goto out; 1855 return;
1774
1775 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
1776 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0);
1777 if (error) {
1778 xfs_trans_cancel(tp, 0);
1779 goto out;
1780 }
1781
1782 xfs_ilock(ip, XFS_ILOCK_EXCL);
1783 xfs_trans_ijoin(tp, ip, 0);
1784 } 1856 }
1785 1857
1786 if (ip->i_afp) 1858 if (ip->i_afp)
@@ -1791,52 +1863,14 @@ xfs_inactive(
1791 /* 1863 /*
1792 * Free the inode. 1864 * Free the inode.
1793 */ 1865 */
1794 xfs_bmap_init(&free_list, &first_block); 1866 error = xfs_inactive_ifree(ip);
1795 error = xfs_ifree(tp, ip, &free_list); 1867 if (error)
1796 if (error) { 1868 return;
1797 /*
1798 * If we fail to free the inode, shut down. The cancel
1799 * might do that, we need to make sure. Otherwise the
1800 * inode might be lost for a long time or forever.
1801 */
1802 if (!XFS_FORCED_SHUTDOWN(mp)) {
1803 xfs_notice(mp, "%s: xfs_ifree returned error %d",
1804 __func__, error);
1805 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
1806 }
1807 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
1808 } else {
1809 /*
1810 * Credit the quota account(s). The inode is gone.
1811 */
1812 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
1813
1814 /*
1815 * Just ignore errors at this point. There is nothing we can
1816 * do except to try to keep going. Make sure it's not a silent
1817 * error.
1818 */
1819 error = xfs_bmap_finish(&tp, &free_list, &committed);
1820 if (error)
1821 xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
1822 __func__, error);
1823 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
1824 if (error)
1825 xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
1826 __func__, error);
1827 }
1828 1869
1829 /* 1870 /*
1830 * Release the dquots held by inode, if any. 1871 * Release the dquots held by inode, if any.
1831 */ 1872 */
1832 xfs_qm_dqdetach(ip); 1873 xfs_qm_dqdetach(ip);
1833out_unlock:
1834 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1835out:
1836 return VN_INACTIVE_CACHE;
1837out_cancel:
1838 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
1839 goto out_unlock;
1840} 1874}
1841 1875
1842/* 1876/*
@@ -2370,6 +2404,33 @@ xfs_iunpin_wait(
2370 __xfs_iunpin_wait(ip); 2404 __xfs_iunpin_wait(ip);
2371} 2405}
2372 2406
2407/*
2408 * Removing an inode from the namespace involves removing the directory entry
2409 * and dropping the link count on the inode. Removing the directory entry can
2410 * result in locking an AGF (directory blocks were freed) and removing a link
2411 * count can result in placing the inode on an unlinked list which results in
2412 * locking an AGI.
2413 *
2414 * The big problem here is that we have an ordering constraint on AGF and AGI
2415 * locking - inode allocation locks the AGI, then can allocate a new extent for
2416 * new inodes, locking the AGF after the AGI. Similarly, freeing the inode
2417 * removes the inode from the unlinked list, requiring that we lock the AGI
2418 * first, and then freeing the inode can result in an inode chunk being freed
2419 * and hence freeing disk space requiring that we lock an AGF.
2420 *
2421 * Hence the ordering that is imposed by other parts of the code is AGI before
2422 * AGF. This means we cannot remove the directory entry before we drop the inode
2423 * reference count and put it on the unlinked list as this results in a lock
2424 * order of AGF then AGI, and this can deadlock against inode allocation and
2425 * freeing. Therefore we must drop the link counts before we remove the
2426 * directory entry.
2427 *
2428 * This is still safe from a transactional point of view - it is not until we
2429 * get to xfs_bmap_finish() that we have the possibility of multiple
2430 * transactions in this operation. Hence as long as we remove the directory
2431 * entry and drop the link count in the first transaction of the remove
2432 * operation, there are no transactional constraints on the ordering here.
2433 */
2373int 2434int
2374xfs_remove( 2435xfs_remove(
2375 xfs_inode_t *dp, 2436 xfs_inode_t *dp,
@@ -2439,6 +2500,7 @@ xfs_remove(
2439 /* 2500 /*
2440 * If we're removing a directory perform some additional validation. 2501 * If we're removing a directory perform some additional validation.
2441 */ 2502 */
2503 cancel_flags |= XFS_TRANS_ABORT;
2442 if (is_dir) { 2504 if (is_dir) {
2443 ASSERT(ip->i_d.di_nlink >= 2); 2505 ASSERT(ip->i_d.di_nlink >= 2);
2444 if (ip->i_d.di_nlink != 2) { 2506 if (ip->i_d.di_nlink != 2) {
@@ -2449,31 +2511,16 @@ xfs_remove(
2449 error = XFS_ERROR(ENOTEMPTY); 2511 error = XFS_ERROR(ENOTEMPTY);
2450 goto out_trans_cancel; 2512 goto out_trans_cancel;
2451 } 2513 }
2452 }
2453 2514
2454 xfs_bmap_init(&free_list, &first_block); 2515 /* Drop the link from ip's "..". */
2455 error = xfs_dir_removename(tp, dp, name, ip->i_ino,
2456 &first_block, &free_list, resblks);
2457 if (error) {
2458 ASSERT(error != ENOENT);
2459 goto out_bmap_cancel;
2460 }
2461 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
2462
2463 if (is_dir) {
2464 /*
2465 * Drop the link from ip's "..".
2466 */
2467 error = xfs_droplink(tp, dp); 2516 error = xfs_droplink(tp, dp);
2468 if (error) 2517 if (error)
2469 goto out_bmap_cancel; 2518 goto out_trans_cancel;
2470 2519
2471 /* 2520 /* Drop the "." link from ip to self. */
2472 * Drop the "." link from ip to self.
2473 */
2474 error = xfs_droplink(tp, ip); 2521 error = xfs_droplink(tp, ip);
2475 if (error) 2522 if (error)
2476 goto out_bmap_cancel; 2523 goto out_trans_cancel;
2477 } else { 2524 } else {
2478 /* 2525 /*
2479 * When removing a non-directory we need to log the parent 2526 * When removing a non-directory we need to log the parent
@@ -2482,20 +2529,24 @@ xfs_remove(
2482 */ 2529 */
2483 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 2530 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
2484 } 2531 }
2532 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
2485 2533
2486 /* 2534 /* Drop the link from dp to ip. */
2487 * Drop the link from dp to ip.
2488 */
2489 error = xfs_droplink(tp, ip); 2535 error = xfs_droplink(tp, ip);
2490 if (error) 2536 if (error)
2491 goto out_bmap_cancel; 2537 goto out_trans_cancel;
2492 2538
2493 /* 2539 /* Determine if this is the last link while the inode is locked */
2494 * Determine if this is the last link while
2495 * we are in the transaction.
2496 */
2497 link_zero = (ip->i_d.di_nlink == 0); 2540 link_zero = (ip->i_d.di_nlink == 0);
2498 2541
2542 xfs_bmap_init(&free_list, &first_block);
2543 error = xfs_dir_removename(tp, dp, name, ip->i_ino,
2544 &first_block, &free_list, resblks);
2545 if (error) {
2546 ASSERT(error != ENOENT);
2547 goto out_bmap_cancel;
2548 }
2549
2499 /* 2550 /*
2500 * If this is a synchronous mount, make sure that the 2551 * If this is a synchronous mount, make sure that the
2501 * remove transaction goes to disk before returning to 2552 * remove transaction goes to disk before returning to
@@ -2525,7 +2576,6 @@ xfs_remove(
2525 2576
2526 out_bmap_cancel: 2577 out_bmap_cancel:
2527 xfs_bmap_cancel(&free_list); 2578 xfs_bmap_cancel(&free_list);
2528 cancel_flags |= XFS_TRANS_ABORT;
2529 out_trans_cancel: 2579 out_trans_cancel:
2530 xfs_trans_cancel(tp, cancel_flags); 2580 xfs_trans_cancel(tp, cancel_flags);
2531 std_return: 2581 std_return:
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 4a91358c1470..9e6efccbae04 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -24,7 +24,6 @@
24/* 24/*
25 * Kernel only inode definitions 25 * Kernel only inode definitions
26 */ 26 */
27
28struct xfs_dinode; 27struct xfs_dinode;
29struct xfs_inode; 28struct xfs_inode;
30struct xfs_buf; 29struct xfs_buf;
@@ -50,6 +49,9 @@ typedef struct xfs_inode {
50 xfs_ifork_t *i_afp; /* attribute fork pointer */ 49 xfs_ifork_t *i_afp; /* attribute fork pointer */
51 xfs_ifork_t i_df; /* data fork */ 50 xfs_ifork_t i_df; /* data fork */
52 51
52 /* operations vectors */
53 const struct xfs_dir_ops *d_ops; /* directory ops vector */
54
53 /* Transaction and locking information. */ 55 /* Transaction and locking information. */
54 struct xfs_inode_log_item *i_itemp; /* logging information */ 56 struct xfs_inode_log_item *i_itemp; /* logging information */
55 mrlock_t i_lock; /* inode lock */ 57 mrlock_t i_lock; /* inode lock */
@@ -316,7 +318,7 @@ static inline int xfs_isiflocked(struct xfs_inode *ip)
316 318
317 319
318int xfs_release(struct xfs_inode *ip); 320int xfs_release(struct xfs_inode *ip);
319int xfs_inactive(struct xfs_inode *ip); 321void xfs_inactive(struct xfs_inode *ip);
320int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, 322int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
321 struct xfs_inode **ipp, struct xfs_name *ci_name); 323 struct xfs_inode **ipp, struct xfs_name *ci_name);
322int xfs_create(struct xfs_inode *dp, struct xfs_name *name, 324int xfs_create(struct xfs_inode *dp, struct xfs_name *name,
diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c
index 63382d37f565..4fc9f39dd89e 100644
--- a/fs/xfs/xfs_inode_buf.c
+++ b/fs/xfs/xfs_inode_buf.c
@@ -17,20 +17,20 @@
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_log.h" 22#include "xfs_log_format.h"
22#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_mount.h" 26#include "xfs_mount.h"
26#include "xfs_bmap_btree.h"
27#include "xfs_ialloc_btree.h"
28#include "xfs_dinode.h"
29#include "xfs_inode.h" 27#include "xfs_inode.h"
30#include "xfs_error.h" 28#include "xfs_error.h"
31#include "xfs_cksum.h" 29#include "xfs_cksum.h"
32#include "xfs_icache.h" 30#include "xfs_icache.h"
31#include "xfs_trans.h"
33#include "xfs_ialloc.h" 32#include "xfs_ialloc.h"
33#include "xfs_dinode.h"
34 34
35/* 35/*
36 * Check that none of the inode's in the buffer have a next 36 * Check that none of the inode's in the buffer have a next
diff --git a/fs/xfs/xfs_inode_buf.h b/fs/xfs/xfs_inode_buf.h
index abba0ae8cf2d..9308c47f2a52 100644
--- a/fs/xfs/xfs_inode_buf.h
+++ b/fs/xfs/xfs_inode_buf.h
@@ -47,7 +47,4 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
47#define xfs_inobp_check(mp, bp) 47#define xfs_inobp_check(mp, bp)
48#endif /* DEBUG */ 48#endif /* DEBUG */
49 49
50extern const struct xfs_buf_ops xfs_inode_buf_ops;
51extern const struct xfs_buf_ops xfs_inode_buf_ra_ops;
52
53#endif /* __XFS_INODE_BUF_H__ */ 50#endif /* __XFS_INODE_BUF_H__ */
diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c
index 02f1083955bb..cfee14a83cfe 100644
--- a/fs/xfs/xfs_inode_fork.c
+++ b/fs/xfs/xfs_inode_fork.c
@@ -20,31 +20,21 @@
20#include "xfs.h" 20#include "xfs.h"
21#include "xfs_fs.h" 21#include "xfs_fs.h"
22#include "xfs_format.h" 22#include "xfs_format.h"
23#include "xfs_log.h" 23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
24#include "xfs_inum.h" 25#include "xfs_inum.h"
25#include "xfs_trans.h"
26#include "xfs_trans_priv.h"
27#include "xfs_sb.h" 26#include "xfs_sb.h"
28#include "xfs_ag.h" 27#include "xfs_ag.h"
29#include "xfs_mount.h" 28#include "xfs_mount.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_attr_sf.h"
34#include "xfs_dinode.h"
35#include "xfs_inode.h" 29#include "xfs_inode.h"
36#include "xfs_buf_item.h" 30#include "xfs_trans.h"
37#include "xfs_inode_item.h" 31#include "xfs_inode_item.h"
38#include "xfs_btree.h" 32#include "xfs_bmap_btree.h"
39#include "xfs_alloc.h"
40#include "xfs_ialloc.h"
41#include "xfs_bmap.h" 33#include "xfs_bmap.h"
42#include "xfs_error.h" 34#include "xfs_error.h"
43#include "xfs_quota.h"
44#include "xfs_filestream.h"
45#include "xfs_cksum.h"
46#include "xfs_trace.h" 35#include "xfs_trace.h"
47#include "xfs_icache.h" 36#include "xfs_attr_sf.h"
37#include "xfs_dinode.h"
48 38
49kmem_zone_t *xfs_ifork_zone; 39kmem_zone_t *xfs_ifork_zone;
50 40
@@ -1031,15 +1021,14 @@ xfs_iext_add(
1031 * the next index needed in the indirection array. 1021 * the next index needed in the indirection array.
1032 */ 1022 */
1033 else { 1023 else {
1034 int count = ext_diff; 1024 uint count = ext_diff;
1035 1025
1036 while (count) { 1026 while (count) {
1037 erp = xfs_iext_irec_new(ifp, erp_idx); 1027 erp = xfs_iext_irec_new(ifp, erp_idx);
1038 erp->er_extcount = count; 1028 erp->er_extcount = min(count, XFS_LINEAR_EXTS);
1039 count -= MIN(count, (int)XFS_LINEAR_EXTS); 1029 count -= erp->er_extcount;
1040 if (count) { 1030 if (count)
1041 erp_idx++; 1031 erp_idx++;
1042 }
1043 } 1032 }
1044 } 1033 }
1045 } 1034 }
@@ -1359,7 +1348,7 @@ xfs_iext_remove_indirect(
1359void 1348void
1360xfs_iext_realloc_direct( 1349xfs_iext_realloc_direct(
1361 xfs_ifork_t *ifp, /* inode fork pointer */ 1350 xfs_ifork_t *ifp, /* inode fork pointer */
1362 int new_size) /* new size of extents */ 1351 int new_size) /* new size of extents after adding */
1363{ 1352{
1364 int rnew_size; /* real new size of extents */ 1353 int rnew_size; /* real new size of extents */
1365 1354
@@ -1397,13 +1386,8 @@ xfs_iext_realloc_direct(
1397 rnew_size - ifp->if_real_bytes); 1386 rnew_size - ifp->if_real_bytes);
1398 } 1387 }
1399 } 1388 }
1400 /* 1389 /* Switch from the inline extent buffer to a direct extent list */
1401 * Switch from the inline extent buffer to a direct
1402 * extent list. Be sure to include the inline extent
1403 * bytes in new_size.
1404 */
1405 else { 1390 else {
1406 new_size += ifp->if_bytes;
1407 if (!is_power_of_2(new_size)) { 1391 if (!is_power_of_2(new_size)) {
1408 rnew_size = roundup_pow_of_two(new_size); 1392 rnew_size = roundup_pow_of_two(new_size);
1409 } 1393 }
diff --git a/fs/xfs/xfs_inode_fork.h b/fs/xfs/xfs_inode_fork.h
index 28661a0d9058..eb329a1ea888 100644
--- a/fs/xfs/xfs_inode_fork.h
+++ b/fs/xfs/xfs_inode_fork.h
@@ -19,6 +19,7 @@
19#define __XFS_INODE_FORK_H__ 19#define __XFS_INODE_FORK_H__
20 20
21struct xfs_inode_log_item; 21struct xfs_inode_log_item;
22struct xfs_dinode;
22 23
23/* 24/*
24 * The following xfs_ext_irec_t struct introduces a second (top) level 25 * The following xfs_ext_irec_t struct introduces a second (top) level
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 378081109844..7c0d391f9a6e 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -17,19 +17,19 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_format.h"
21#include "xfs_log.h" 21#include "xfs_log_format.h"
22#include "xfs_trans.h" 22#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_ag.h" 24#include "xfs_ag.h"
25#include "xfs_mount.h" 25#include "xfs_mount.h"
26#include "xfs_trans_priv.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_dinode.h"
29#include "xfs_inode.h" 26#include "xfs_inode.h"
27#include "xfs_trans.h"
30#include "xfs_inode_item.h" 28#include "xfs_inode_item.h"
31#include "xfs_error.h" 29#include "xfs_error.h"
32#include "xfs_trace.h" 30#include "xfs_trace.h"
31#include "xfs_trans_priv.h"
32#include "xfs_dinode.h"
33 33
34 34
35kmem_zone_t *xfs_ili_zone; /* inode log item zone */ 35kmem_zone_t *xfs_ili_zone; /* inode log item zone */
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 668e8f4ccf5e..4d613401a5e0 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -17,32 +17,31 @@
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_log.h" 22#include "xfs_log_format.h"
22#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_alloc.h"
26#include "xfs_mount.h" 26#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_dinode.h"
29#include "xfs_inode.h" 27#include "xfs_inode.h"
30#include "xfs_ioctl.h" 28#include "xfs_ioctl.h"
29#include "xfs_alloc.h"
31#include "xfs_rtalloc.h" 30#include "xfs_rtalloc.h"
32#include "xfs_itable.h" 31#include "xfs_itable.h"
33#include "xfs_error.h" 32#include "xfs_error.h"
34#include "xfs_attr.h" 33#include "xfs_attr.h"
35#include "xfs_bmap.h" 34#include "xfs_bmap.h"
36#include "xfs_bmap_util.h" 35#include "xfs_bmap_util.h"
37#include "xfs_buf_item.h"
38#include "xfs_fsops.h" 36#include "xfs_fsops.h"
39#include "xfs_discard.h" 37#include "xfs_discard.h"
40#include "xfs_quota.h" 38#include "xfs_quota.h"
41#include "xfs_inode_item.h"
42#include "xfs_export.h" 39#include "xfs_export.h"
43#include "xfs_trace.h" 40#include "xfs_trace.h"
44#include "xfs_icache.h" 41#include "xfs_icache.h"
45#include "xfs_symlink.h" 42#include "xfs_symlink.h"
43#include "xfs_dinode.h"
44#include "xfs_trans.h"
46 45
47#include <linux/capability.h> 46#include <linux/capability.h>
48#include <linux/dcache.h> 47#include <linux/dcache.h>
@@ -641,7 +640,11 @@ xfs_ioc_space(
641 unsigned int cmd, 640 unsigned int cmd,
642 xfs_flock64_t *bf) 641 xfs_flock64_t *bf)
643{ 642{
644 int attr_flags = 0; 643 struct xfs_mount *mp = ip->i_mount;
644 struct xfs_trans *tp;
645 struct iattr iattr;
646 bool setprealloc = false;
647 bool clrprealloc = false;
645 int error; 648 int error;
646 649
647 /* 650 /*
@@ -661,19 +664,128 @@ xfs_ioc_space(
661 if (!S_ISREG(inode->i_mode)) 664 if (!S_ISREG(inode->i_mode))
662 return -XFS_ERROR(EINVAL); 665 return -XFS_ERROR(EINVAL);
663 666
664 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 667 error = mnt_want_write_file(filp);
665 attr_flags |= XFS_ATTR_NONBLOCK; 668 if (error)
669 return error;
666 670
667 if (filp->f_flags & O_DSYNC) 671 xfs_ilock(ip, XFS_IOLOCK_EXCL);
668 attr_flags |= XFS_ATTR_SYNC; 672
673 switch (bf->l_whence) {
674 case 0: /*SEEK_SET*/
675 break;
676 case 1: /*SEEK_CUR*/
677 bf->l_start += filp->f_pos;
678 break;
679 case 2: /*SEEK_END*/
680 bf->l_start += XFS_ISIZE(ip);
681 break;
682 default:
683 error = XFS_ERROR(EINVAL);
684 goto out_unlock;
685 }
669 686
670 if (ioflags & IO_INVIS) 687 /*
671 attr_flags |= XFS_ATTR_DMI; 688 * length of <= 0 for resv/unresv/zero is invalid. length for
689 * alloc/free is ignored completely and we have no idea what userspace
690 * might have set it to, so set it to zero to allow range
691 * checks to pass.
692 */
693 switch (cmd) {
694 case XFS_IOC_ZERO_RANGE:
695 case XFS_IOC_RESVSP:
696 case XFS_IOC_RESVSP64:
697 case XFS_IOC_UNRESVSP:
698 case XFS_IOC_UNRESVSP64:
699 if (bf->l_len <= 0) {
700 error = XFS_ERROR(EINVAL);
701 goto out_unlock;
702 }
703 break;
704 default:
705 bf->l_len = 0;
706 break;
707 }
708
709 if (bf->l_start < 0 ||
710 bf->l_start > mp->m_super->s_maxbytes ||
711 bf->l_start + bf->l_len < 0 ||
712 bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) {
713 error = XFS_ERROR(EINVAL);
714 goto out_unlock;
715 }
716
717 switch (cmd) {
718 case XFS_IOC_ZERO_RANGE:
719 error = xfs_zero_file_space(ip, bf->l_start, bf->l_len);
720 if (!error)
721 setprealloc = true;
722 break;
723 case XFS_IOC_RESVSP:
724 case XFS_IOC_RESVSP64:
725 error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len,
726 XFS_BMAPI_PREALLOC);
727 if (!error)
728 setprealloc = true;
729 break;
730 case XFS_IOC_UNRESVSP:
731 case XFS_IOC_UNRESVSP64:
732 error = xfs_free_file_space(ip, bf->l_start, bf->l_len);
733 break;
734 case XFS_IOC_ALLOCSP:
735 case XFS_IOC_ALLOCSP64:
736 case XFS_IOC_FREESP:
737 case XFS_IOC_FREESP64:
738 if (bf->l_start > XFS_ISIZE(ip)) {
739 error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
740 bf->l_start - XFS_ISIZE(ip), 0);
741 if (error)
742 goto out_unlock;
743 }
744
745 iattr.ia_valid = ATTR_SIZE;
746 iattr.ia_size = bf->l_start;
747
748 error = xfs_setattr_size(ip, &iattr);
749 if (!error)
750 clrprealloc = true;
751 break;
752 default:
753 ASSERT(0);
754 error = XFS_ERROR(EINVAL);
755 }
672 756
673 error = mnt_want_write_file(filp);
674 if (error) 757 if (error)
675 return error; 758 goto out_unlock;
676 error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); 759
760 tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
761 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0);
762 if (error) {
763 xfs_trans_cancel(tp, 0);
764 goto out_unlock;
765 }
766
767 xfs_ilock(ip, XFS_ILOCK_EXCL);
768 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
769
770 if (!(ioflags & IO_INVIS)) {
771 ip->i_d.di_mode &= ~S_ISUID;
772 if (ip->i_d.di_mode & S_IXGRP)
773 ip->i_d.di_mode &= ~S_ISGID;
774 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
775 }
776
777 if (setprealloc)
778 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
779 else if (clrprealloc)
780 ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
781
782 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
783 if (filp->f_flags & O_DSYNC)
784 xfs_trans_set_sync(tp);
785 error = xfs_trans_commit(tp, 0);
786
787out_unlock:
788 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
677 mnt_drop_write_file(filp); 789 mnt_drop_write_file(filp);
678 return -error; 790 return -error;
679} 791}
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index f671f7e472ac..e8fb1231db81 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -22,14 +22,13 @@
22#include <asm/uaccess.h> 22#include <asm/uaccess.h>
23#include "xfs.h" 23#include "xfs.h"
24#include "xfs_fs.h" 24#include "xfs_fs.h"
25#include "xfs_log.h" 25#include "xfs_format.h"
26#include "xfs_trans.h" 26#include "xfs_log_format.h"
27#include "xfs_trans_resv.h"
27#include "xfs_sb.h" 28#include "xfs_sb.h"
28#include "xfs_ag.h" 29#include "xfs_ag.h"
29#include "xfs_mount.h" 30#include "xfs_mount.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_vnode.h" 31#include "xfs_vnode.h"
32#include "xfs_dinode.h"
33#include "xfs_inode.h" 32#include "xfs_inode.h"
34#include "xfs_itable.h" 33#include "xfs_itable.h"
35#include "xfs_error.h" 34#include "xfs_error.h"
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 8d4d49b6fbf3..22d1cbea283d 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -17,34 +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_log.h" 22#include "xfs_log_format.h"
22#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_alloc.h"
26#include "xfs_quota.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_alloc_btree.h"
30#include "xfs_ialloc_btree.h"
31#include "xfs_dinode.h"
32#include "xfs_inode.h" 27#include "xfs_inode.h"
33#include "xfs_inode_item.h"
34#include "xfs_btree.h" 28#include "xfs_btree.h"
29#include "xfs_bmap_btree.h"
35#include "xfs_bmap.h" 30#include "xfs_bmap.h"
36#include "xfs_bmap_util.h" 31#include "xfs_bmap_util.h"
37#include "xfs_rtalloc.h"
38#include "xfs_error.h" 32#include "xfs_error.h"
39#include "xfs_itable.h" 33#include "xfs_trans.h"
40#include "xfs_attr.h"
41#include "xfs_buf_item.h"
42#include "xfs_trans_space.h" 34#include "xfs_trans_space.h"
43#include "xfs_iomap.h" 35#include "xfs_iomap.h"
44#include "xfs_trace.h" 36#include "xfs_trace.h"
45#include "xfs_icache.h" 37#include "xfs_icache.h"
38#include "xfs_quota.h"
46#include "xfs_dquot_item.h" 39#include "xfs_dquot_item.h"
47#include "xfs_dquot.h" 40#include "xfs_dquot.h"
41#include "xfs_dinode.h"
48 42
49 43
50#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ 44#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \
@@ -110,7 +104,7 @@ xfs_alert_fsblock_zero(
110 xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, 104 xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
111 "Access to block zero in inode %llu " 105 "Access to block zero in inode %llu "
112 "start_block: %llx start_off: %llx " 106 "start_block: %llx start_off: %llx "
113 "blkcnt: %llx extent-state: %x\n", 107 "blkcnt: %llx extent-state: %x",
114 (unsigned long long)ip->i_ino, 108 (unsigned long long)ip->i_ino,
115 (unsigned long long)imap->br_startblock, 109 (unsigned long long)imap->br_startblock,
116 (unsigned long long)imap->br_startoff, 110 (unsigned long long)imap->br_startoff,
@@ -655,7 +649,6 @@ int
655xfs_iomap_write_allocate( 649xfs_iomap_write_allocate(
656 xfs_inode_t *ip, 650 xfs_inode_t *ip,
657 xfs_off_t offset, 651 xfs_off_t offset,
658 size_t count,
659 xfs_bmbt_irec_t *imap) 652 xfs_bmbt_irec_t *imap)
660{ 653{
661 xfs_mount_t *mp = ip->i_mount; 654 xfs_mount_t *mp = ip->i_mount;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index 80615760959a..411fbb8919ef 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -21,12 +21,12 @@
21struct xfs_inode; 21struct xfs_inode;
22struct xfs_bmbt_irec; 22struct xfs_bmbt_irec;
23 23
24extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, 24int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
25 struct xfs_bmbt_irec *, int); 25 struct xfs_bmbt_irec *, int);
26extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, 26int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t,
27 struct xfs_bmbt_irec *); 27 struct xfs_bmbt_irec *);
28extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t, 28int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t,
29 struct xfs_bmbt_irec *); 29 struct xfs_bmbt_irec *);
30extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t); 30int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t);
31 31
32#endif /* __XFS_IOMAP_H__*/ 32#endif /* __XFS_IOMAP_H__*/
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 */
diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h
index d81fb41205ec..d2c5057b5cc4 100644
--- a/fs/xfs/xfs_iops.h
+++ b/fs/xfs/xfs_iops.h
@@ -30,14 +30,10 @@ extern void xfs_setup_inode(struct xfs_inode *);
30/* 30/*
31 * Internal setattr interfaces. 31 * Internal setattr interfaces.
32 */ 32 */
33#define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */ 33#define XFS_ATTR_NOACL 0x01 /* Don't call xfs_acl_chmod */
34#define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if op would block */
35#define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */
36#define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */
37#define XFS_ATTR_SYNC 0x10 /* synchronous operation required */
38 34
39extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, 35extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap,
40 int flags); 36 int flags);
41extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap, int flags); 37extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap);
42 38
43#endif /* __XFS_IOPS_H__ */ 39#endif /* __XFS_IOPS_H__ */
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 084b3e1741fd..c237ad15d500 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -17,24 +17,23 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log.h" 21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
22#include "xfs_inum.h" 24#include "xfs_inum.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_alloc_btree.h"
29#include "xfs_ialloc_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h" 28#include "xfs_inode.h"
29#include "xfs_btree.h"
32#include "xfs_ialloc.h" 30#include "xfs_ialloc.h"
31#include "xfs_ialloc_btree.h"
33#include "xfs_itable.h" 32#include "xfs_itable.h"
34#include "xfs_error.h" 33#include "xfs_error.h"
35#include "xfs_btree.h"
36#include "xfs_trace.h" 34#include "xfs_trace.h"
37#include "xfs_icache.h" 35#include "xfs_icache.h"
36#include "xfs_dinode.h"
38 37
39STATIC int 38STATIC int
40xfs_internal_inum( 39xfs_internal_inum(
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index a2dea108071a..8497a00e399d 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -17,21 +17,19 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log.h" 21#include "xfs_format.h"
22#include "xfs_trans.h" 22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_mount.h" 26#include "xfs_mount.h"
26#include "xfs_error.h" 27#include "xfs_error.h"
28#include "xfs_trans.h"
29#include "xfs_trans_priv.h"
30#include "xfs_log.h"
27#include "xfs_log_priv.h" 31#include "xfs_log_priv.h"
28#include "xfs_buf_item.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_log_recover.h" 32#include "xfs_log_recover.h"
33#include "xfs_trans_priv.h"
34#include "xfs_dinode.h"
35#include "xfs_inode.h" 33#include "xfs_inode.h"
36#include "xfs_trace.h" 34#include "xfs_trace.h"
37#include "xfs_fsops.h" 35#include "xfs_fsops.h"
@@ -1000,27 +998,34 @@ xfs_log_space_wake(
1000} 998}
1001 999
1002/* 1000/*
1003 * Determine if we have a transaction that has gone to disk 1001 * Determine if we have a transaction that has gone to disk that needs to be
1004 * that needs to be covered. To begin the transition to the idle state 1002 * covered. To begin the transition to the idle state firstly the log needs to
1005 * firstly the log needs to be idle (no AIL and nothing in the iclogs). 1003 * be idle. That means the CIL, the AIL and the iclogs needs to be empty before
1006 * If we are then in a state where covering is needed, the caller is informed 1004 * we start attempting to cover the log.
1007 * that dummy transactions are required to move the log into the idle state.
1008 * 1005 *
1009 * Because this is called as part of the sync process, we should also indicate 1006 * Only if we are then in a state where covering is needed, the caller is
1010 * that dummy transactions should be issued in anything but the covered or 1007 * informed that dummy transactions are required to move the log into the idle
1011 * idle states. This ensures that the log tail is accurately reflected in 1008 * state.
1012 * the log at the end of the sync, hence if a crash occurrs avoids replay 1009 *
1013 * of transactions where the metadata is already on disk. 1010 * If there are any items in the AIl or CIL, then we do not want to attempt to
1011 * cover the log as we may be in a situation where there isn't log space
1012 * available to run a dummy transaction and this can lead to deadlocks when the
1013 * tail of the log is pinned by an item that is modified in the CIL. Hence
1014 * there's no point in running a dummy transaction at this point because we
1015 * can't start trying to idle the log until both the CIL and AIL are empty.
1014 */ 1016 */
1015int 1017int
1016xfs_log_need_covered(xfs_mount_t *mp) 1018xfs_log_need_covered(xfs_mount_t *mp)
1017{ 1019{
1018 int needed = 0;
1019 struct xlog *log = mp->m_log; 1020 struct xlog *log = mp->m_log;
1021 int needed = 0;
1020 1022
1021 if (!xfs_fs_writable(mp)) 1023 if (!xfs_fs_writable(mp))
1022 return 0; 1024 return 0;
1023 1025
1026 if (!xlog_cil_empty(log))
1027 return 0;
1028
1024 spin_lock(&log->l_icloglock); 1029 spin_lock(&log->l_icloglock);
1025 switch (log->l_covered_state) { 1030 switch (log->l_covered_state) {
1026 case XLOG_STATE_COVER_DONE: 1031 case XLOG_STATE_COVER_DONE:
@@ -1029,14 +1034,17 @@ xfs_log_need_covered(xfs_mount_t *mp)
1029 break; 1034 break;
1030 case XLOG_STATE_COVER_NEED: 1035 case XLOG_STATE_COVER_NEED:
1031 case XLOG_STATE_COVER_NEED2: 1036 case XLOG_STATE_COVER_NEED2:
1032 if (!xfs_ail_min_lsn(log->l_ailp) && 1037 if (xfs_ail_min_lsn(log->l_ailp))
1033 xlog_iclogs_empty(log)) { 1038 break;
1034 if (log->l_covered_state == XLOG_STATE_COVER_NEED) 1039 if (!xlog_iclogs_empty(log))
1035 log->l_covered_state = XLOG_STATE_COVER_DONE; 1040 break;
1036 else 1041
1037 log->l_covered_state = XLOG_STATE_COVER_DONE2; 1042 needed = 1;
1038 } 1043 if (log->l_covered_state == XLOG_STATE_COVER_NEED)
1039 /* FALLTHRU */ 1044 log->l_covered_state = XLOG_STATE_COVER_DONE;
1045 else
1046 log->l_covered_state = XLOG_STATE_COVER_DONE2;
1047 break;
1040 default: 1048 default:
1041 needed = 1; 1049 needed = 1;
1042 break; 1050 break;
@@ -1068,6 +1076,7 @@ xlog_assign_tail_lsn_locked(
1068 tail_lsn = lip->li_lsn; 1076 tail_lsn = lip->li_lsn;
1069 else 1077 else
1070 tail_lsn = atomic64_read(&log->l_last_sync_lsn); 1078 tail_lsn = atomic64_read(&log->l_last_sync_lsn);
1079 trace_xfs_log_assign_tail_lsn(log, tail_lsn);
1071 atomic64_set(&log->l_tail_lsn, tail_lsn); 1080 atomic64_set(&log->l_tail_lsn, tail_lsn);
1072 return tail_lsn; 1081 return tail_lsn;
1073} 1082}
@@ -1979,7 +1988,7 @@ xlog_print_tic_res(
1979 1988
1980 for (i = 0; i < ticket->t_res_num; i++) { 1989 for (i = 0; i < ticket->t_res_num; i++) {
1981 uint r_type = ticket->t_res_arr[i].r_type; 1990 uint r_type = ticket->t_res_arr[i].r_type;
1982 xfs_warn(mp, "region[%u]: %s - %u bytes\n", i, 1991 xfs_warn(mp, "region[%u]: %s - %u bytes", i,
1983 ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ? 1992 ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ?
1984 "bad-rtype" : res_type_str[r_type-1]), 1993 "bad-rtype" : res_type_str[r_type-1]),
1985 ticket->t_res_arr[i].r_len); 1994 ticket->t_res_arr[i].r_len);
@@ -3702,11 +3711,9 @@ xlog_verify_iclog(
3702 /* check validity of iclog pointers */ 3711 /* check validity of iclog pointers */
3703 spin_lock(&log->l_icloglock); 3712 spin_lock(&log->l_icloglock);
3704 icptr = log->l_iclog; 3713 icptr = log->l_iclog;
3705 for (i=0; i < log->l_iclog_bufs; i++) { 3714 for (i = 0; i < log->l_iclog_bufs; i++, icptr = icptr->ic_next)
3706 if (icptr == NULL) 3715 ASSERT(icptr);
3707 xfs_emerg(log->l_mp, "%s: invalid ptr", __func__); 3716
3708 icptr = icptr->ic_next;
3709 }
3710 if (icptr != log->l_iclog) 3717 if (icptr != log->l_iclog)
3711 xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__); 3718 xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__);
3712 spin_unlock(&log->l_icloglock); 3719 spin_unlock(&log->l_icloglock);
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 1c458487f000..e148719e0a5d 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -18,8 +18,6 @@
18#ifndef __XFS_LOG_H__ 18#ifndef __XFS_LOG_H__
19#define __XFS_LOG_H__ 19#define __XFS_LOG_H__
20 20
21#include "xfs_log_format.h"
22
23struct xfs_log_vec { 21struct xfs_log_vec {
24 struct xfs_log_vec *lv_next; /* next lv in build list */ 22 struct xfs_log_vec *lv_next; /* next lv in build list */
25 int lv_niovecs; /* number of iovecs in lv */ 23 int lv_niovecs; /* number of iovecs in lv */
@@ -82,11 +80,7 @@ struct xlog_ticket;
82struct xfs_log_item; 80struct xfs_log_item;
83struct xfs_item_ops; 81struct xfs_item_ops;
84struct xfs_trans; 82struct xfs_trans;
85 83struct xfs_log_callback;
86void xfs_log_item_init(struct xfs_mount *mp,
87 struct xfs_log_item *item,
88 int type,
89 const struct xfs_item_ops *ops);
90 84
91xfs_lsn_t xfs_log_done(struct xfs_mount *mp, 85xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
92 struct xlog_ticket *ticket, 86 struct xlog_ticket *ticket,
@@ -114,7 +108,7 @@ xfs_lsn_t xlog_assign_tail_lsn_locked(struct xfs_mount *mp);
114void xfs_log_space_wake(struct xfs_mount *mp); 108void xfs_log_space_wake(struct xfs_mount *mp);
115int xfs_log_notify(struct xfs_mount *mp, 109int xfs_log_notify(struct xfs_mount *mp,
116 struct xlog_in_core *iclog, 110 struct xlog_in_core *iclog,
117 xfs_log_callback_t *callback_entry); 111 struct xfs_log_callback *callback_entry);
118int xfs_log_release_iclog(struct xfs_mount *mp, 112int xfs_log_release_iclog(struct xfs_mount *mp,
119 struct xlog_in_core *iclog); 113 struct xlog_in_core *iclog);
120int xfs_log_reserve(struct xfs_mount *mp, 114int xfs_log_reserve(struct xfs_mount *mp,
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index cfe97973ba36..5eb51fc5eb84 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -17,11 +17,9 @@
17 17
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_log_format.h"
21#include "xfs_log.h" 21#include "xfs_shared.h"
22#include "xfs_trans.h" 22#include "xfs_trans_resv.h"
23#include "xfs_trans_priv.h"
24#include "xfs_log_priv.h"
25#include "xfs_sb.h" 23#include "xfs_sb.h"
26#include "xfs_ag.h" 24#include "xfs_ag.h"
27#include "xfs_mount.h" 25#include "xfs_mount.h"
@@ -29,6 +27,10 @@
29#include "xfs_alloc.h" 27#include "xfs_alloc.h"
30#include "xfs_extent_busy.h" 28#include "xfs_extent_busy.h"
31#include "xfs_discard.h" 29#include "xfs_discard.h"
30#include "xfs_trans.h"
31#include "xfs_trans_priv.h"
32#include "xfs_log.h"
33#include "xfs_log_priv.h"
32 34
33/* 35/*
34 * Allocate a new ticket. Failing to get a new ticket makes it really hard to 36 * Allocate a new ticket. Failing to get a new ticket makes it really hard to
@@ -711,6 +713,20 @@ xlog_cil_push_foreground(
711 xlog_cil_push(log); 713 xlog_cil_push(log);
712} 714}
713 715
716bool
717xlog_cil_empty(
718 struct xlog *log)
719{
720 struct xfs_cil *cil = log->l_cilp;
721 bool empty = false;
722
723 spin_lock(&cil->xc_push_lock);
724 if (list_empty(&cil->xc_cil))
725 empty = true;
726 spin_unlock(&cil->xc_push_lock);
727 return empty;
728}
729
714/* 730/*
715 * Commit a transaction with the given vector to the Committed Item List. 731 * Commit a transaction with the given vector to the Committed Item List.
716 * 732 *
diff --git a/fs/xfs/xfs_log_format.h b/fs/xfs/xfs_log_format.h
index ca7e28a8ed31..f0969c77bdbe 100644
--- a/fs/xfs/xfs_log_format.h
+++ b/fs/xfs/xfs_log_format.h
@@ -234,178 +234,6 @@ typedef struct xfs_trans_header {
234 { XFS_LI_ICREATE, "XFS_LI_ICREATE" } 234 { XFS_LI_ICREATE, "XFS_LI_ICREATE" }
235 235
236/* 236/*
237 * Transaction types. Used to distinguish types of buffers.
238 */
239#define XFS_TRANS_SETATTR_NOT_SIZE 1
240#define XFS_TRANS_SETATTR_SIZE 2
241#define XFS_TRANS_INACTIVE 3
242#define XFS_TRANS_CREATE 4
243#define XFS_TRANS_CREATE_TRUNC 5
244#define XFS_TRANS_TRUNCATE_FILE 6
245#define XFS_TRANS_REMOVE 7
246#define XFS_TRANS_LINK 8
247#define XFS_TRANS_RENAME 9
248#define XFS_TRANS_MKDIR 10
249#define XFS_TRANS_RMDIR 11
250#define XFS_TRANS_SYMLINK 12
251#define XFS_TRANS_SET_DMATTRS 13
252#define XFS_TRANS_GROWFS 14
253#define XFS_TRANS_STRAT_WRITE 15
254#define XFS_TRANS_DIOSTRAT 16
255/* 17 was XFS_TRANS_WRITE_SYNC */
256#define XFS_TRANS_WRITEID 18
257#define XFS_TRANS_ADDAFORK 19
258#define XFS_TRANS_ATTRINVAL 20
259#define XFS_TRANS_ATRUNCATE 21
260#define XFS_TRANS_ATTR_SET 22
261#define XFS_TRANS_ATTR_RM 23
262#define XFS_TRANS_ATTR_FLAG 24
263#define XFS_TRANS_CLEAR_AGI_BUCKET 25
264#define XFS_TRANS_QM_SBCHANGE 26
265/*
266 * Dummy entries since we use the transaction type to index into the
267 * trans_type[] in xlog_recover_print_trans_head()
268 */
269#define XFS_TRANS_DUMMY1 27
270#define XFS_TRANS_DUMMY2 28
271#define XFS_TRANS_QM_QUOTAOFF 29
272#define XFS_TRANS_QM_DQALLOC 30
273#define XFS_TRANS_QM_SETQLIM 31
274#define XFS_TRANS_QM_DQCLUSTER 32
275#define XFS_TRANS_QM_QINOCREATE 33
276#define XFS_TRANS_QM_QUOTAOFF_END 34
277#define XFS_TRANS_SB_UNIT 35
278#define XFS_TRANS_FSYNC_TS 36
279#define XFS_TRANS_GROWFSRT_ALLOC 37
280#define XFS_TRANS_GROWFSRT_ZERO 38
281#define XFS_TRANS_GROWFSRT_FREE 39
282#define XFS_TRANS_SWAPEXT 40
283#define XFS_TRANS_SB_COUNT 41
284#define XFS_TRANS_CHECKPOINT 42
285#define XFS_TRANS_ICREATE 43
286#define XFS_TRANS_TYPE_MAX 43
287/* new transaction types need to be reflected in xfs_logprint(8) */
288
289#define XFS_TRANS_TYPES \
290 { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \
291 { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \
292 { XFS_TRANS_INACTIVE, "INACTIVE" }, \
293 { XFS_TRANS_CREATE, "CREATE" }, \
294 { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \
295 { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \
296 { XFS_TRANS_REMOVE, "REMOVE" }, \
297 { XFS_TRANS_LINK, "LINK" }, \
298 { XFS_TRANS_RENAME, "RENAME" }, \
299 { XFS_TRANS_MKDIR, "MKDIR" }, \
300 { XFS_TRANS_RMDIR, "RMDIR" }, \
301 { XFS_TRANS_SYMLINK, "SYMLINK" }, \
302 { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \
303 { XFS_TRANS_GROWFS, "GROWFS" }, \
304 { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \
305 { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \
306 { XFS_TRANS_WRITEID, "WRITEID" }, \
307 { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \
308 { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \
309 { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \
310 { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \
311 { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \
312 { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \
313 { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \
314 { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \
315 { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \
316 { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \
317 { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \
318 { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \
319 { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \
320 { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \
321 { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \
322 { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \
323 { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \
324 { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \
325 { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \
326 { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \
327 { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \
328 { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \
329 { XFS_TRANS_DUMMY1, "DUMMY1" }, \
330 { XFS_TRANS_DUMMY2, "DUMMY2" }, \
331 { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" }
332
333/*
334 * This structure is used to track log items associated with
335 * a transaction. It points to the log item and keeps some
336 * flags to track the state of the log item. It also tracks
337 * the amount of space needed to log the item it describes
338 * once we get to commit processing (see xfs_trans_commit()).
339 */
340struct xfs_log_item_desc {
341 struct xfs_log_item *lid_item;
342 struct list_head lid_trans;
343 unsigned char lid_flags;
344};
345
346#define XFS_LID_DIRTY 0x1
347
348/*
349 * Values for t_flags.
350 */
351#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */
352#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */
353#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */
354#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */
355#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */
356#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */
357#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer
358 count in superblock */
359
360/*
361 * Values for call flags parameter.
362 */
363#define XFS_TRANS_RELEASE_LOG_RES 0x4
364#define XFS_TRANS_ABORT 0x8
365
366/*
367 * Field values for xfs_trans_mod_sb.
368 */
369#define XFS_TRANS_SB_ICOUNT 0x00000001
370#define XFS_TRANS_SB_IFREE 0x00000002
371#define XFS_TRANS_SB_FDBLOCKS 0x00000004
372#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008
373#define XFS_TRANS_SB_FREXTENTS 0x00000010
374#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020
375#define XFS_TRANS_SB_DBLOCKS 0x00000040
376#define XFS_TRANS_SB_AGCOUNT 0x00000080
377#define XFS_TRANS_SB_IMAXPCT 0x00000100
378#define XFS_TRANS_SB_REXTSIZE 0x00000200
379#define XFS_TRANS_SB_RBMBLOCKS 0x00000400
380#define XFS_TRANS_SB_RBLOCKS 0x00000800
381#define XFS_TRANS_SB_REXTENTS 0x00001000
382#define XFS_TRANS_SB_REXTSLOG 0x00002000
383
384/*
385 * Here we centralize the specification of XFS meta-data buffer
386 * reference count values. This determine how hard the buffer
387 * cache tries to hold onto the buffer.
388 */
389#define XFS_AGF_REF 4
390#define XFS_AGI_REF 4
391#define XFS_AGFL_REF 3
392#define XFS_INO_BTREE_REF 3
393#define XFS_ALLOC_BTREE_REF 2
394#define XFS_BMAP_BTREE_REF 2
395#define XFS_DIR_BTREE_REF 2
396#define XFS_INO_REF 2
397#define XFS_ATTR_BTREE_REF 1
398#define XFS_DQUOT_REF 1
399
400/*
401 * Flags for xfs_trans_ichgtime().
402 */
403#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */
404#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */
405#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */
406
407
408/*
409 * Inode Log Item Format definitions. 237 * Inode Log Item Format definitions.
410 * 238 *
411 * This is the structure used to lay out an inode log item in the 239 * This is the structure used to lay out an inode log item in the
@@ -797,7 +625,6 @@ typedef struct xfs_qoff_logformat {
797 char qf_pad[12]; /* padding for future */ 625 char qf_pad[12]; /* padding for future */
798} xfs_qoff_logformat_t; 626} xfs_qoff_logformat_t;
799 627
800
801/* 628/*
802 * Disk quotas status in m_qflags, and also sb_qflags. 16 bits. 629 * Disk quotas status in m_qflags, and also sb_qflags. 16 bits.
803 */ 630 */
@@ -849,8 +676,4 @@ struct xfs_icreate_log {
849 __be32 icl_gen; /* inode generation number to use */ 676 __be32 icl_gen; /* inode generation number to use */
850}; 677};
851 678
852int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes);
853int xfs_log_calc_minimum_size(struct xfs_mount *);
854
855
856#endif /* __XFS_LOG_FORMAT_H__ */ 679#endif /* __XFS_LOG_FORMAT_H__ */
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 136654b9400d..9bc403a9e54f 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -22,6 +22,7 @@ struct xfs_buf;
22struct xlog; 22struct xlog;
23struct xlog_ticket; 23struct xlog_ticket;
24struct xfs_mount; 24struct xfs_mount;
25struct xfs_log_callback;
25 26
26/* 27/*
27 * Flags for log structure 28 * Flags for log structure
@@ -227,8 +228,8 @@ typedef struct xlog_in_core {
227 228
228 /* Callback structures need their own cacheline */ 229 /* Callback structures need their own cacheline */
229 spinlock_t ic_callback_lock ____cacheline_aligned_in_smp; 230 spinlock_t ic_callback_lock ____cacheline_aligned_in_smp;
230 xfs_log_callback_t *ic_callback; 231 struct xfs_log_callback *ic_callback;
231 xfs_log_callback_t **ic_callback_tail; 232 struct xfs_log_callback **ic_callback_tail;
232 233
233 /* reference counts need their own cacheline */ 234 /* reference counts need their own cacheline */
234 atomic_t ic_refcnt ____cacheline_aligned_in_smp; 235 atomic_t ic_refcnt ____cacheline_aligned_in_smp;
@@ -254,7 +255,7 @@ struct xfs_cil_ctx {
254 int space_used; /* aggregate size of regions */ 255 int space_used; /* aggregate size of regions */
255 struct list_head busy_extents; /* busy extents in chkpt */ 256 struct list_head busy_extents; /* busy extents in chkpt */
256 struct xfs_log_vec *lv_chain; /* logvecs being pushed */ 257 struct xfs_log_vec *lv_chain; /* logvecs being pushed */
257 xfs_log_callback_t log_cb; /* completion callback hook. */ 258 struct xfs_log_callback log_cb; /* completion callback hook. */
258 struct list_head committing; /* ctx committing list */ 259 struct list_head committing; /* ctx committing list */
259}; 260};
260 261
@@ -514,12 +515,10 @@ xlog_assign_grant_head(atomic64_t *head, int cycle, int space)
514/* 515/*
515 * Committed Item List interfaces 516 * Committed Item List interfaces
516 */ 517 */
517int 518int xlog_cil_init(struct xlog *log);
518xlog_cil_init(struct xlog *log); 519void xlog_cil_init_post_recovery(struct xlog *log);
519void 520void xlog_cil_destroy(struct xlog *log);
520xlog_cil_init_post_recovery(struct xlog *log); 521bool xlog_cil_empty(struct xlog *log);
521void
522xlog_cil_destroy(struct xlog *log);
523 522
524/* 523/*
525 * CIL force routines 524 * CIL force routines
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 39797490a1f1..b6b669df40f3 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -17,42 +17,34 @@
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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h" 25#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
28#include "xfs_error.h" 29#include "xfs_da_format.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_btree.h"
33#include "xfs_dinode.h"
34#include "xfs_inode.h" 30#include "xfs_inode.h"
35#include "xfs_inode_item.h" 31#include "xfs_trans.h"
36#include "xfs_alloc.h" 32#include "xfs_log.h"
37#include "xfs_ialloc.h"
38#include "xfs_log_priv.h" 33#include "xfs_log_priv.h"
39#include "xfs_buf_item.h"
40#include "xfs_log_recover.h" 34#include "xfs_log_recover.h"
35#include "xfs_inode_item.h"
41#include "xfs_extfree_item.h" 36#include "xfs_extfree_item.h"
42#include "xfs_trans_priv.h" 37#include "xfs_trans_priv.h"
38#include "xfs_alloc.h"
39#include "xfs_ialloc.h"
43#include "xfs_quota.h" 40#include "xfs_quota.h"
44#include "xfs_cksum.h" 41#include "xfs_cksum.h"
45#include "xfs_trace.h" 42#include "xfs_trace.h"
46#include "xfs_icache.h" 43#include "xfs_icache.h"
47#include "xfs_icreate_item.h" 44#include "xfs_bmap_btree.h"
48 45#include "xfs_dinode.h"
49/* Need all the magic numbers and buffer ops structures from these headers */ 46#include "xfs_error.h"
50#include "xfs_symlink.h"
51#include "xfs_da_btree.h"
52#include "xfs_dir2_format.h"
53#include "xfs_dir2.h" 47#include "xfs_dir2.h"
54#include "xfs_attr_leaf.h"
55#include "xfs_attr_remote.h"
56 48
57#define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) 49#define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1)
58 50
@@ -305,9 +297,9 @@ xlog_header_check_dump(
305 xfs_mount_t *mp, 297 xfs_mount_t *mp,
306 xlog_rec_header_t *head) 298 xlog_rec_header_t *head)
307{ 299{
308 xfs_debug(mp, "%s: SB : uuid = %pU, fmt = %d\n", 300 xfs_debug(mp, "%s: SB : uuid = %pU, fmt = %d",
309 __func__, &mp->m_sb.sb_uuid, XLOG_FMT); 301 __func__, &mp->m_sb.sb_uuid, XLOG_FMT);
310 xfs_debug(mp, " log : uuid = %pU, fmt = %d\n", 302 xfs_debug(mp, " log : uuid = %pU, fmt = %d",
311 &head->h_fs_uuid, be32_to_cpu(head->h_fmt)); 303 &head->h_fs_uuid, be32_to_cpu(head->h_fmt));
312} 304}
313#else 305#else
@@ -2362,7 +2354,7 @@ xlog_recover_do_reg_buffer(
2362 item->ri_buf[i].i_len, __func__); 2354 item->ri_buf[i].i_len, __func__);
2363 goto next; 2355 goto next;
2364 } 2356 }
2365 error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr, 2357 error = xfs_dqcheck(mp, item->ri_buf[i].i_addr,
2366 -1, 0, XFS_QMOPT_DOWARN, 2358 -1, 0, XFS_QMOPT_DOWARN,
2367 "dquot_buf_recover"); 2359 "dquot_buf_recover");
2368 if (error) 2360 if (error)
@@ -2394,133 +2386,6 @@ xlog_recover_do_reg_buffer(
2394} 2386}
2395 2387
2396/* 2388/*
2397 * Do some primitive error checking on ondisk dquot data structures.
2398 */
2399int
2400xfs_qm_dqcheck(
2401 struct xfs_mount *mp,
2402 xfs_disk_dquot_t *ddq,
2403 xfs_dqid_t id,
2404 uint type, /* used only when IO_dorepair is true */
2405 uint flags,
2406 char *str)
2407{
2408 xfs_dqblk_t *d = (xfs_dqblk_t *)ddq;
2409 int errs = 0;
2410
2411 /*
2412 * We can encounter an uninitialized dquot buffer for 2 reasons:
2413 * 1. If we crash while deleting the quotainode(s), and those blks got
2414 * used for user data. This is because we take the path of regular
2415 * file deletion; however, the size field of quotainodes is never
2416 * updated, so all the tricks that we play in itruncate_finish
2417 * don't quite matter.
2418 *
2419 * 2. We don't play the quota buffers when there's a quotaoff logitem.
2420 * But the allocation will be replayed so we'll end up with an
2421 * uninitialized quota block.
2422 *
2423 * This is all fine; things are still consistent, and we haven't lost
2424 * any quota information. Just don't complain about bad dquot blks.
2425 */
2426 if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) {
2427 if (flags & XFS_QMOPT_DOWARN)
2428 xfs_alert(mp,
2429 "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
2430 str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
2431 errs++;
2432 }
2433 if (ddq->d_version != XFS_DQUOT_VERSION) {
2434 if (flags & XFS_QMOPT_DOWARN)
2435 xfs_alert(mp,
2436 "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
2437 str, id, ddq->d_version, XFS_DQUOT_VERSION);
2438 errs++;
2439 }
2440
2441 if (ddq->d_flags != XFS_DQ_USER &&
2442 ddq->d_flags != XFS_DQ_PROJ &&
2443 ddq->d_flags != XFS_DQ_GROUP) {
2444 if (flags & XFS_QMOPT_DOWARN)
2445 xfs_alert(mp,
2446 "%s : XFS dquot ID 0x%x, unknown flags 0x%x",
2447 str, id, ddq->d_flags);
2448 errs++;
2449 }
2450
2451 if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
2452 if (flags & XFS_QMOPT_DOWARN)
2453 xfs_alert(mp,
2454 "%s : ondisk-dquot 0x%p, ID mismatch: "
2455 "0x%x expected, found id 0x%x",
2456 str, ddq, id, be32_to_cpu(ddq->d_id));
2457 errs++;
2458 }
2459
2460 if (!errs && ddq->d_id) {
2461 if (ddq->d_blk_softlimit &&
2462 be64_to_cpu(ddq->d_bcount) >
2463 be64_to_cpu(ddq->d_blk_softlimit)) {
2464 if (!ddq->d_btimer) {
2465 if (flags & XFS_QMOPT_DOWARN)
2466 xfs_alert(mp,
2467 "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",
2468 str, (int)be32_to_cpu(ddq->d_id), ddq);
2469 errs++;
2470 }
2471 }
2472 if (ddq->d_ino_softlimit &&
2473 be64_to_cpu(ddq->d_icount) >
2474 be64_to_cpu(ddq->d_ino_softlimit)) {
2475 if (!ddq->d_itimer) {
2476 if (flags & XFS_QMOPT_DOWARN)
2477 xfs_alert(mp,
2478 "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",
2479 str, (int)be32_to_cpu(ddq->d_id), ddq);
2480 errs++;
2481 }
2482 }
2483 if (ddq->d_rtb_softlimit &&
2484 be64_to_cpu(ddq->d_rtbcount) >
2485 be64_to_cpu(ddq->d_rtb_softlimit)) {
2486 if (!ddq->d_rtbtimer) {
2487 if (flags & XFS_QMOPT_DOWARN)
2488 xfs_alert(mp,
2489 "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",
2490 str, (int)be32_to_cpu(ddq->d_id), ddq);
2491 errs++;
2492 }
2493 }
2494 }
2495
2496 if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
2497 return errs;
2498
2499 if (flags & XFS_QMOPT_DOWARN)
2500 xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);
2501
2502 /*
2503 * Typically, a repair is only requested by quotacheck.
2504 */
2505 ASSERT(id != -1);
2506 ASSERT(flags & XFS_QMOPT_DQREPAIR);
2507 memset(d, 0, sizeof(xfs_dqblk_t));
2508
2509 d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
2510 d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
2511 d->dd_diskdq.d_flags = type;
2512 d->dd_diskdq.d_id = cpu_to_be32(id);
2513
2514 if (xfs_sb_version_hascrc(&mp->m_sb)) {
2515 uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
2516 xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
2517 XFS_DQUOT_CRC_OFF);
2518 }
2519
2520 return errs;
2521}
2522
2523/*
2524 * Perform a dquot buffer recovery. 2389 * Perform a dquot buffer recovery.
2525 * Simple algorithm: if we have found a QUOTAOFF log item of the same type 2390 * Simple algorithm: if we have found a QUOTAOFF log item of the same type
2526 * (ie. USR or GRP), then just toss this buffer away; don't recover it. 2391 * (ie. USR or GRP), then just toss this buffer away; don't recover it.
@@ -3125,7 +2990,7 @@ xlog_recover_dquot_pass2(
3125 */ 2990 */
3126 dq_f = item->ri_buf[0].i_addr; 2991 dq_f = item->ri_buf[0].i_addr;
3127 ASSERT(dq_f); 2992 ASSERT(dq_f);
3128 error = xfs_qm_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, 2993 error = xfs_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
3129 "xlog_recover_dquot_pass2 (log copy)"); 2994 "xlog_recover_dquot_pass2 (log copy)");
3130 if (error) 2995 if (error)
3131 return XFS_ERROR(EIO); 2996 return XFS_ERROR(EIO);
@@ -3145,7 +3010,7 @@ xlog_recover_dquot_pass2(
3145 * was among a chunk of dquots created earlier, and we did some 3010 * was among a chunk of dquots created earlier, and we did some
3146 * minimal initialization then. 3011 * minimal initialization then.
3147 */ 3012 */
3148 error = xfs_qm_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, 3013 error = xfs_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
3149 "xlog_recover_dquot_pass2"); 3014 "xlog_recover_dquot_pass2");
3150 if (error) { 3015 if (error) {
3151 xfs_buf_relse(bp); 3016 xfs_buf_relse(bp);
@@ -4077,7 +3942,7 @@ xlog_unpack_data_crc(
4077 if (crc != rhead->h_crc) { 3942 if (crc != rhead->h_crc) {
4078 if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) { 3943 if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
4079 xfs_alert(log->l_mp, 3944 xfs_alert(log->l_mp,
4080 "log record CRC mismatch: found 0x%x, expected 0x%x.\n", 3945 "log record CRC mismatch: found 0x%x, expected 0x%x.",
4081 le32_to_cpu(rhead->h_crc), 3946 le32_to_cpu(rhead->h_crc),
4082 le32_to_cpu(crc)); 3947 le32_to_cpu(crc));
4083 xfs_hex_dump(dp, 32); 3948 xfs_hex_dump(dp, 32);
diff --git a/fs/xfs/xfs_log_rlimit.c b/fs/xfs/xfs_log_rlimit.c
index bbcec0bbc12d..2af1a0a4d0f1 100644
--- a/fs/xfs/xfs_log_rlimit.c
+++ b/fs/xfs/xfs_log_rlimit.c
@@ -17,16 +17,19 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_log.h" 20#include "xfs_shared.h"
21#include "xfs_trans.h" 21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
22#include "xfs_ag.h" 24#include "xfs_ag.h"
23#include "xfs_sb.h" 25#include "xfs_sb.h"
24#include "xfs_mount.h" 26#include "xfs_mount.h"
27#include "xfs_da_format.h"
25#include "xfs_trans_space.h" 28#include "xfs_trans_space.h"
26#include "xfs_bmap_btree.h"
27#include "xfs_inode.h" 29#include "xfs_inode.h"
28#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
29#include "xfs_attr_leaf.h" 31#include "xfs_attr_leaf.h"
32#include "xfs_bmap_btree.h"
30 33
31/* 34/*
32 * Calculate the maximum length in bytes that would be required for a local 35 * Calculate the maximum length in bytes that would be required for a local
diff --git a/fs/xfs/xfs_message.c b/fs/xfs/xfs_message.c
index 9163dc140532..63ca2f0420b1 100644
--- a/fs/xfs/xfs_message.c
+++ b/fs/xfs/xfs_message.c
@@ -17,9 +17,8 @@
17 17
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_log_format.h"
21#include "xfs_log.h" 21#include "xfs_trans_resv.h"
22#include "xfs_trans.h"
23#include "xfs_sb.h" 22#include "xfs_sb.h"
24#include "xfs_ag.h" 23#include "xfs_ag.h"
25#include "xfs_mount.h" 24#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 5dcc68019d1b..da88f167af78 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -17,35 +17,30 @@
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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h" 25#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_trans_priv.h"
26#include "xfs_sb.h" 26#include "xfs_sb.h"
27#include "xfs_ag.h" 27#include "xfs_ag.h"
28#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_da_btree.h" 29#include "xfs_da_format.h"
30#include "xfs_dir2_format.h"
31#include "xfs_dir2.h"
32#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h"
35#include "xfs_dinode.h"
36#include "xfs_inode.h" 30#include "xfs_inode.h"
37#include "xfs_btree.h" 31#include "xfs_dir2.h"
38#include "xfs_ialloc.h" 32#include "xfs_ialloc.h"
39#include "xfs_alloc.h" 33#include "xfs_alloc.h"
40#include "xfs_rtalloc.h" 34#include "xfs_rtalloc.h"
41#include "xfs_bmap.h" 35#include "xfs_bmap.h"
36#include "xfs_trans.h"
37#include "xfs_trans_priv.h"
38#include "xfs_log.h"
42#include "xfs_error.h" 39#include "xfs_error.h"
43#include "xfs_quota.h" 40#include "xfs_quota.h"
44#include "xfs_fsops.h" 41#include "xfs_fsops.h"
45#include "xfs_trace.h" 42#include "xfs_trace.h"
46#include "xfs_icache.h" 43#include "xfs_icache.h"
47#include "xfs_cksum.h"
48#include "xfs_buf_item.h"
49 44
50 45
51#ifdef HAVE_PERCPU_SB 46#ifdef HAVE_PERCPU_SB
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 1fa0584b5627..1d8101a10d8e 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -26,6 +26,7 @@ struct xfs_mru_cache;
26struct xfs_nameops; 26struct xfs_nameops;
27struct xfs_ail; 27struct xfs_ail;
28struct xfs_quotainfo; 28struct xfs_quotainfo;
29struct xfs_dir_ops;
29 30
30#ifdef HAVE_PERCPU_SB 31#ifdef HAVE_PERCPU_SB
31 32
@@ -148,6 +149,8 @@ typedef struct xfs_mount {
148 int m_dir_magicpct; /* 37% of the dir blocksize */ 149 int m_dir_magicpct; /* 37% of the dir blocksize */
149 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ 150 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
150 const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */ 151 const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */
152 const struct xfs_dir_ops *m_dir_inode_ops; /* vector of dir inode ops */
153 const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */
151 int m_dirblksize; /* directory block sz--bytes */ 154 int m_dirblksize; /* directory block sz--bytes */
152 int m_dirblkfsbs; /* directory block sz--fsbs */ 155 int m_dirblkfsbs; /* directory block sz--fsbs */
153 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ 156 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 3e6c2e6c9cd2..14a4996cfec6 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -17,31 +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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_alloc.h"
27#include "xfs_quota.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_ialloc_btree.h"
31#include "xfs_dinode.h"
32#include "xfs_inode.h" 28#include "xfs_inode.h"
33#include "xfs_ialloc.h" 29#include "xfs_ialloc.h"
34#include "xfs_itable.h" 30#include "xfs_itable.h"
35#include "xfs_rtalloc.h" 31#include "xfs_quota.h"
36#include "xfs_error.h" 32#include "xfs_error.h"
37#include "xfs_bmap.h" 33#include "xfs_bmap.h"
38#include "xfs_attr.h" 34#include "xfs_bmap_btree.h"
39#include "xfs_buf_item.h" 35#include "xfs_trans.h"
40#include "xfs_trans_space.h" 36#include "xfs_trans_space.h"
41#include "xfs_qm.h" 37#include "xfs_qm.h"
42#include "xfs_trace.h" 38#include "xfs_trace.h"
43#include "xfs_icache.h" 39#include "xfs_icache.h"
44#include "xfs_cksum.h" 40#include "xfs_cksum.h"
41#include "xfs_dinode.h"
45 42
46/* 43/*
47 * The global quota manager. There is only one of these for the entire 44 * The global quota manager. There is only one of these for the entire
@@ -664,20 +661,6 @@ xfs_qm_dqdetach(
664 } 661 }
665} 662}
666 663
667int
668xfs_qm_calc_dquots_per_chunk(
669 struct xfs_mount *mp,
670 unsigned int nbblks) /* basic block units */
671{
672 unsigned int ndquots;
673
674 ASSERT(nbblks > 0);
675 ndquots = BBTOB(nbblks);
676 do_div(ndquots, sizeof(xfs_dqblk_t));
677
678 return ndquots;
679}
680
681struct xfs_qm_isolate { 664struct xfs_qm_isolate {
682 struct list_head buffers; 665 struct list_head buffers;
683 struct list_head dispose; 666 struct list_head dispose;
@@ -858,7 +841,7 @@ xfs_qm_init_quotainfo(
858 841
859 /* Precalc some constants */ 842 /* Precalc some constants */
860 qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); 843 qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB);
861 qinf->qi_dqperchunk = xfs_qm_calc_dquots_per_chunk(mp, 844 qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(mp,
862 qinf->qi_dqchunklen); 845 qinf->qi_dqchunklen);
863 846
864 mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD); 847 mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD);
@@ -1092,10 +1075,10 @@ xfs_qm_reset_dqcounts(
1092 /* 1075 /*
1093 * Do a sanity check, and if needed, repair the dqblk. Don't 1076 * Do a sanity check, and if needed, repair the dqblk. Don't
1094 * output any warnings because it's perfectly possible to 1077 * output any warnings because it's perfectly possible to
1095 * find uninitialised dquot blks. See comment in xfs_qm_dqcheck. 1078 * find uninitialised dquot blks. See comment in xfs_dqcheck.
1096 */ 1079 */
1097 (void) xfs_qm_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, 1080 xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR,
1098 "xfs_quotacheck"); 1081 "xfs_quotacheck");
1099 ddq->d_bcount = 0; 1082 ddq->d_bcount = 0;
1100 ddq->d_icount = 0; 1083 ddq->d_icount = 0;
1101 ddq->d_rtbcount = 0; 1084 ddq->d_rtbcount = 0;
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 2b602df9c242..a788b66a5cb1 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -103,8 +103,6 @@ xfs_dq_to_quota_inode(struct xfs_dquot *dqp)
103 return NULL; 103 return NULL;
104} 104}
105 105
106extern int xfs_qm_calc_dquots_per_chunk(struct xfs_mount *mp,
107 unsigned int nbblks);
108extern void xfs_trans_mod_dquot(struct xfs_trans *, 106extern void xfs_trans_mod_dquot(struct xfs_trans *,
109 struct xfs_dquot *, uint, long); 107 struct xfs_dquot *, uint, long);
110extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, 108extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index 3af50ccdfac1..e9be63abd8d2 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -18,21 +18,15 @@
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_format.h" 20#include "xfs_format.h"
21#include "xfs_log.h" 21#include "xfs_log_format.h"
22#include "xfs_trans.h" 22#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_ag.h" 24#include "xfs_ag.h"
25#include "xfs_alloc.h"
26#include "xfs_quota.h" 25#include "xfs_quota.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_inode.h" 27#include "xfs_inode.h"
30#include "xfs_itable.h"
31#include "xfs_bmap.h"
32#include "xfs_rtalloc.h"
33#include "xfs_error.h" 28#include "xfs_error.h"
34#include "xfs_attr.h" 29#include "xfs_trans.h"
35#include "xfs_buf_item.h"
36#include "xfs_qm.h" 30#include "xfs_qm.h"
37 31
38 32
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 8174aad0b388..437c9198031a 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -20,24 +20,18 @@
20 20
21#include "xfs.h" 21#include "xfs.h"
22#include "xfs_fs.h" 22#include "xfs_fs.h"
23#include "xfs_shared.h"
23#include "xfs_format.h" 24#include "xfs_format.h"
25#include "xfs_log_format.h"
26#include "xfs_trans_resv.h"
24#include "xfs_bit.h" 27#include "xfs_bit.h"
25#include "xfs_log.h"
26#include "xfs_trans.h"
27#include "xfs_sb.h" 28#include "xfs_sb.h"
28#include "xfs_ag.h" 29#include "xfs_ag.h"
29#include "xfs_alloc.h"
30#include "xfs_quota.h"
31#include "xfs_mount.h" 30#include "xfs_mount.h"
32#include "xfs_bmap_btree.h"
33#include "xfs_inode.h" 31#include "xfs_inode.h"
34#include "xfs_inode_item.h" 32#include "xfs_trans.h"
35#include "xfs_itable.h"
36#include "xfs_bmap.h"
37#include "xfs_rtalloc.h"
38#include "xfs_error.h" 33#include "xfs_error.h"
39#include "xfs_attr.h" 34#include "xfs_quota.h"
40#include "xfs_buf_item.h"
41#include "xfs_qm.h" 35#include "xfs_qm.h"
42#include "xfs_trace.h" 36#include "xfs_trace.h"
43#include "xfs_icache.h" 37#include "xfs_icache.h"
@@ -287,7 +281,7 @@ xfs_qm_scall_trunc_qfiles(
287 int error = 0, error2 = 0; 281 int error = 0, error2 = 0;
288 282
289 if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { 283 if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
290 xfs_debug(mp, "%s: flags=%x m_qflags=%x\n", 284 xfs_debug(mp, "%s: flags=%x m_qflags=%x",
291 __func__, flags, mp->m_qflags); 285 __func__, flags, mp->m_qflags);
292 return XFS_ERROR(EINVAL); 286 return XFS_ERROR(EINVAL);
293 } 287 }
@@ -325,7 +319,7 @@ xfs_qm_scall_quotaon(
325 sbflags = 0; 319 sbflags = 0;
326 320
327 if (flags == 0) { 321 if (flags == 0) {
328 xfs_debug(mp, "%s: zero flags, m_qflags=%x\n", 322 xfs_debug(mp, "%s: zero flags, m_qflags=%x",
329 __func__, mp->m_qflags); 323 __func__, mp->m_qflags);
330 return XFS_ERROR(EINVAL); 324 return XFS_ERROR(EINVAL);
331 } 325 }
@@ -348,7 +342,7 @@ xfs_qm_scall_quotaon(
348 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 && 342 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
349 (flags & XFS_PQUOTA_ENFD))) { 343 (flags & XFS_PQUOTA_ENFD))) {
350 xfs_debug(mp, 344 xfs_debug(mp,
351 "%s: Can't enforce without acct, flags=%x sbflags=%x\n", 345 "%s: Can't enforce without acct, flags=%x sbflags=%x",
352 __func__, flags, mp->m_sb.sb_qflags); 346 __func__, flags, mp->m_sb.sb_qflags);
353 return XFS_ERROR(EINVAL); 347 return XFS_ERROR(EINVAL);
354 } 348 }
@@ -648,7 +642,7 @@ xfs_qm_scall_setqlim(
648 q->qi_bsoftlimit = soft; 642 q->qi_bsoftlimit = soft;
649 } 643 }
650 } else { 644 } else {
651 xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft); 645 xfs_debug(mp, "blkhard %Ld < blksoft %Ld", hard, soft);
652 } 646 }
653 hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ? 647 hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
654 (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) : 648 (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
@@ -664,7 +658,7 @@ xfs_qm_scall_setqlim(
664 q->qi_rtbsoftlimit = soft; 658 q->qi_rtbsoftlimit = soft;
665 } 659 }
666 } else { 660 } else {
667 xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft); 661 xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld", hard, soft);
668 } 662 }
669 663
670 hard = (newlim->d_fieldmask & FS_DQ_IHARD) ? 664 hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
@@ -681,7 +675,7 @@ xfs_qm_scall_setqlim(
681 q->qi_isoftlimit = soft; 675 q->qi_isoftlimit = soft;
682 } 676 }
683 } else { 677 } else {
684 xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft); 678 xfs_debug(mp, "ihard %Ld < isoft %Ld", hard, soft);
685 } 679 }
686 680
687 /* 681 /*
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index e7d84d2d8683..5376dd406ba2 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -150,10 +150,6 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
150 xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \ 150 xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
151 f | XFS_QMOPT_RES_REGBLKS) 151 f | XFS_QMOPT_RES_REGBLKS)
152 152
153extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *,
154 xfs_dqid_t, uint, uint, char *);
155extern int xfs_mount_reset_sbqflags(struct xfs_mount *); 153extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
156 154
157extern const struct xfs_buf_ops xfs_dquot_buf_ops;
158
159#endif /* __XFS_QUOTA_H__ */ 155#endif /* __XFS_QUOTA_H__ */
diff --git a/fs/xfs/xfs_quota_defs.h b/fs/xfs/xfs_quota_defs.h
index e6b0d6e1f4f2..b3b2b1065c0f 100644
--- a/fs/xfs/xfs_quota_defs.h
+++ b/fs/xfs/xfs_quota_defs.h
@@ -154,4 +154,8 @@ typedef __uint16_t xfs_qwarncnt_t;
154 (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA) 154 (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
155#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) 155#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
156 156
157extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq,
158 xfs_dqid_t id, uint type, uint flags, char *str);
159extern int xfs_calc_dquots_per_chunk(struct xfs_mount *mp, unsigned int nbblks);
160
157#endif /* __XFS_QUOTA_H__ */ 161#endif /* __XFS_QUOTA_H__ */
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index 1326d81596c2..af33cafe69b6 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -17,15 +17,14 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_format.h" 19#include "xfs_format.h"
20#include "xfs_log_format.h"
20#include "xfs_trans_resv.h" 21#include "xfs_trans_resv.h"
21#include "xfs_log.h"
22#include "xfs_sb.h" 22#include "xfs_sb.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_mount.h" 24#include "xfs_mount.h"
25#include "xfs_inode.h"
25#include "xfs_quota.h" 26#include "xfs_quota.h"
26#include "xfs_trans.h" 27#include "xfs_trans.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_inode.h"
29#include "xfs_qm.h" 28#include "xfs_qm.h"
30#include <linux/quota.h> 29#include <linux/quota.h>
31 30
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 6f9e63c9fc26..a6a76b2b6a85 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -17,172 +17,260 @@
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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_bmap_btree.h"
28#include "xfs_dinode.h"
29#include "xfs_inode.h" 28#include "xfs_inode.h"
30#include "xfs_alloc.h"
31#include "xfs_bmap.h" 29#include "xfs_bmap.h"
32#include "xfs_bmap_util.h" 30#include "xfs_bmap_util.h"
33#include "xfs_rtalloc.h" 31#include "xfs_bmap_btree.h"
34#include "xfs_fsops.h" 32#include "xfs_alloc.h"
35#include "xfs_error.h" 33#include "xfs_error.h"
36#include "xfs_inode_item.h" 34#include "xfs_trans.h"
37#include "xfs_trans_space.h" 35#include "xfs_trans_space.h"
38#include "xfs_trace.h" 36#include "xfs_trace.h"
39#include "xfs_buf.h" 37#include "xfs_buf.h"
40#include "xfs_icache.h" 38#include "xfs_icache.h"
39#include "xfs_dinode.h"
40#include "xfs_rtalloc.h"
41 41
42 42
43/* 43/*
44 * Prototypes for internal functions. 44 * Read and return the summary information for a given extent size,
45 * bitmap block combination.
46 * Keeps track of a current summary block, so we don't keep reading
47 * it from the buffer cache.
45 */ 48 */
49STATIC int /* error */
50xfs_rtget_summary(
51 xfs_mount_t *mp, /* file system mount structure */
52 xfs_trans_t *tp, /* transaction pointer */
53 int log, /* log2 of extent size */
54 xfs_rtblock_t bbno, /* bitmap block number */
55 xfs_buf_t **rbpp, /* in/out: summary block buffer */
56 xfs_fsblock_t *rsb, /* in/out: summary block number */
57 xfs_suminfo_t *sum) /* out: summary info for this block */
58{
59 xfs_buf_t *bp; /* buffer for summary block */
60 int error; /* error value */
61 xfs_fsblock_t sb; /* summary fsblock */
62 int so; /* index into the summary file */
63 xfs_suminfo_t *sp; /* pointer to returned data */
46 64
65 /*
66 * Compute entry number in the summary file.
67 */
68 so = XFS_SUMOFFS(mp, log, bbno);
69 /*
70 * Compute the block number in the summary file.
71 */
72 sb = XFS_SUMOFFSTOBLOCK(mp, so);
73 /*
74 * If we have an old buffer, and the block number matches, use that.
75 */
76 if (rbpp && *rbpp && *rsb == sb)
77 bp = *rbpp;
78 /*
79 * Otherwise we have to get the buffer.
80 */
81 else {
82 /*
83 * If there was an old one, get rid of it first.
84 */
85 if (rbpp && *rbpp)
86 xfs_trans_brelse(tp, *rbpp);
87 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
88 if (error) {
89 return error;
90 }
91 /*
92 * Remember this buffer and block for the next call.
93 */
94 if (rbpp) {
95 *rbpp = bp;
96 *rsb = sb;
97 }
98 }
99 /*
100 * Point to the summary information & copy it out.
101 */
102 sp = XFS_SUMPTR(mp, bp, so);
103 *sum = *sp;
104 /*
105 * Drop the buffer if we're not asked to remember it.
106 */
107 if (!rbpp)
108 xfs_trans_brelse(tp, bp);
109 return 0;
110}
47 111
48STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
49 xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *);
50STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int,
51 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *);
52STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
53 xfs_extlen_t, int, xfs_rtblock_t *, int *);
54STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
55 xfs_rtblock_t, xfs_rtblock_t *);
56STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
57 xfs_rtblock_t, xfs_rtblock_t *);
58STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int,
59 xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *);
60STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
61 xfs_extlen_t, int);
62STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
63 xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);
64
65/*
66 * Internal functions.
67 */
68 112
69/* 113/*
70 * Allocate space to the bitmap or summary file, and zero it, for growfs. 114 * Return whether there are any free extents in the size range given
115 * by low and high, for the bitmap block bbno.
71 */ 116 */
72STATIC int /* error */ 117STATIC int /* error */
73xfs_growfs_rt_alloc( 118xfs_rtany_summary(
74 xfs_mount_t *mp, /* file system mount point */ 119 xfs_mount_t *mp, /* file system mount structure */
75 xfs_extlen_t oblocks, /* old count of blocks */ 120 xfs_trans_t *tp, /* transaction pointer */
76 xfs_extlen_t nblocks, /* new count of blocks */ 121 int low, /* low log2 extent size */
77 xfs_inode_t *ip) /* inode (bitmap/summary) */ 122 int high, /* high log2 extent size */
123 xfs_rtblock_t bbno, /* bitmap block number */
124 xfs_buf_t **rbpp, /* in/out: summary block buffer */
125 xfs_fsblock_t *rsb, /* in/out: summary block number */
126 int *stat) /* out: any good extents here? */
78{ 127{
79 xfs_fileoff_t bno; /* block number in file */ 128 int error; /* error value */
80 xfs_buf_t *bp; /* temporary buffer for zeroing */ 129 int log; /* loop counter, log2 of ext. size */
81 int committed; /* transaction committed flag */ 130 xfs_suminfo_t sum; /* summary data */
82 xfs_daddr_t d; /* disk block address */
83 int error; /* error return value */
84 xfs_fsblock_t firstblock; /* first block allocated in xaction */
85 xfs_bmap_free_t flist; /* list of freed blocks */
86 xfs_fsblock_t fsbno; /* filesystem block for bno */
87 xfs_bmbt_irec_t map; /* block map output */
88 int nmap; /* number of block maps */
89 int resblks; /* space reservation */
90 131
91 /* 132 /*
92 * Allocate space to the file, as necessary. 133 * Loop over logs of extent sizes. Order is irrelevant.
93 */ 134 */
94 while (oblocks < nblocks) { 135 for (log = low; log <= high; log++) {
95 int cancelflags = 0;
96 xfs_trans_t *tp;
97
98 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
99 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
100 /* 136 /*
101 * Reserve space & log for one extent added to the file. 137 * Get one summary datum.
102 */ 138 */
103 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata, 139 error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
104 resblks, 0); 140 if (error) {
105 if (error) 141 return error;
106 goto error_cancel; 142 }
107 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
108 /* 143 /*
109 * Lock the inode. 144 * If there are any, return success.
110 */ 145 */
111 xfs_ilock(ip, XFS_ILOCK_EXCL); 146 if (sum) {
112 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 147 *stat = 1;
148 return 0;
149 }
150 }
151 /*
152 * Found nothing, return failure.
153 */
154 *stat = 0;
155 return 0;
156}
113 157
114 xfs_bmap_init(&flist, &firstblock); 158
115 /* 159/*
116 * Allocate blocks to the bitmap file. 160 * Copy and transform the summary file, given the old and new
117 */ 161 * parameters in the mount structures.
118 nmap = 1; 162 */
119 cancelflags |= XFS_TRANS_ABORT; 163STATIC int /* error */
120 error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, 164xfs_rtcopy_summary(
121 XFS_BMAPI_METADATA, &firstblock, 165 xfs_mount_t *omp, /* old file system mount point */
122 resblks, &map, &nmap, &flist); 166 xfs_mount_t *nmp, /* new file system mount point */
123 if (!error && nmap < 1) 167 xfs_trans_t *tp) /* transaction pointer */
124 error = XFS_ERROR(ENOSPC); 168{
125 if (error) 169 xfs_rtblock_t bbno; /* bitmap block number */
126 goto error_cancel; 170 xfs_buf_t *bp; /* summary buffer */
127 /* 171 int error; /* error return value */
128 * Free any blocks freed up in the transaction, then commit. 172 int log; /* summary level number (log length) */
129 */ 173 xfs_suminfo_t sum; /* summary data */
130 error = xfs_bmap_finish(&tp, &flist, &committed); 174 xfs_fsblock_t sumbno; /* summary block number */
131 if (error) 175
132 goto error_cancel; 176 bp = NULL;
133 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 177 for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
134 if (error) 178 for (bbno = omp->m_sb.sb_rbmblocks - 1;
135 goto error; 179 (xfs_srtblock_t)bbno >= 0;
136 /* 180 bbno--) {
137 * Now we need to clear the allocated blocks. 181 error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
138 * Do this one block per transaction, to keep it simple. 182 &sumbno, &sum);
139 */
140 cancelflags = 0;
141 for (bno = map.br_startoff, fsbno = map.br_startblock;
142 bno < map.br_startoff + map.br_blockcount;
143 bno++, fsbno++) {
144 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
145 /*
146 * Reserve log for one block zeroing.
147 */
148 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero,
149 0, 0);
150 if (error) 183 if (error)
151 goto error_cancel; 184 return error;
152 /* 185 if (sum == 0)
153 * Lock the bitmap inode. 186 continue;
154 */ 187 error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
155 xfs_ilock(ip, XFS_ILOCK_EXCL); 188 &bp, &sumbno);
156 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
157 /*
158 * Get a buffer for the block.
159 */
160 d = XFS_FSB_TO_DADDR(mp, fsbno);
161 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
162 mp->m_bsize, 0);
163 if (bp == NULL) {
164 error = XFS_ERROR(EIO);
165error_cancel:
166 xfs_trans_cancel(tp, cancelflags);
167 goto error;
168 }
169 memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
170 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
171 /*
172 * Commit the transaction.
173 */
174 error = xfs_trans_commit(tp, 0);
175 if (error) 189 if (error)
176 goto error; 190 return error;
191 error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
192 &bp, &sumbno);
193 if (error)
194 return error;
195 ASSERT(sum > 0);
177 } 196 }
178 /*
179 * Go on to the next extent, if any.
180 */
181 oblocks = map.br_startoff + map.br_blockcount;
182 } 197 }
183 return 0; 198 return 0;
199}
200/*
201 * Mark an extent specified by start and len allocated.
202 * Updates all the summary information as well as the bitmap.
203 */
204STATIC int /* error */
205xfs_rtallocate_range(
206 xfs_mount_t *mp, /* file system mount point */
207 xfs_trans_t *tp, /* transaction pointer */
208 xfs_rtblock_t start, /* start block to allocate */
209 xfs_extlen_t len, /* length to allocate */
210 xfs_buf_t **rbpp, /* in/out: summary block buffer */
211 xfs_fsblock_t *rsb) /* in/out: summary block number */
212{
213 xfs_rtblock_t end; /* end of the allocated extent */
214 int error; /* error value */
215 xfs_rtblock_t postblock = 0; /* first block allocated > end */
216 xfs_rtblock_t preblock = 0; /* first block allocated < start */
184 217
185error: 218 end = start + len - 1;
219 /*
220 * Assume we're allocating out of the middle of a free extent.
221 * We need to find the beginning and end of the extent so we can
222 * properly update the summary.
223 */
224 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
225 if (error) {
226 return error;
227 }
228 /*
229 * Find the next allocated block (end of free extent).
230 */
231 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
232 &postblock);
233 if (error) {
234 return error;
235 }
236 /*
237 * Decrement the summary information corresponding to the entire
238 * (old) free extent.
239 */
240 error = xfs_rtmodify_summary(mp, tp,
241 XFS_RTBLOCKLOG(postblock + 1 - preblock),
242 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
243 if (error) {
244 return error;
245 }
246 /*
247 * If there are blocks not being allocated at the front of the
248 * old extent, add summary data for them to be free.
249 */
250 if (preblock < start) {
251 error = xfs_rtmodify_summary(mp, tp,
252 XFS_RTBLOCKLOG(start - preblock),
253 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
254 if (error) {
255 return error;
256 }
257 }
258 /*
259 * If there are blocks not being allocated at the end of the
260 * old extent, add summary data for them to be free.
261 */
262 if (postblock > end) {
263 error = xfs_rtmodify_summary(mp, tp,
264 XFS_RTBLOCKLOG(postblock - end),
265 XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
266 if (error) {
267 return error;
268 }
269 }
270 /*
271 * Modify the bitmap to mark this extent allocated.
272 */
273 error = xfs_rtmodify_range(mp, tp, start, len, 0);
186 return error; 274 return error;
187} 275}
188 276
@@ -721,1112 +809,126 @@ xfs_rtallocate_extent_size(
721} 809}
722 810
723/* 811/*
724 * Mark an extent specified by start and len allocated. 812 * Allocate space to the bitmap or summary file, and zero it, for growfs.
725 * Updates all the summary information as well as the bitmap.
726 */ 813 */
727STATIC int /* error */ 814STATIC int /* error */
728xfs_rtallocate_range( 815xfs_growfs_rt_alloc(
729 xfs_mount_t *mp, /* file system mount point */ 816 xfs_mount_t *mp, /* file system mount point */
730 xfs_trans_t *tp, /* transaction pointer */ 817 xfs_extlen_t oblocks, /* old count of blocks */
731 xfs_rtblock_t start, /* start block to allocate */ 818 xfs_extlen_t nblocks, /* new count of blocks */
732 xfs_extlen_t len, /* length to allocate */ 819 xfs_inode_t *ip) /* inode (bitmap/summary) */
733 xfs_buf_t **rbpp, /* in/out: summary block buffer */
734 xfs_fsblock_t *rsb) /* in/out: summary block number */
735{ 820{
736 xfs_rtblock_t end; /* end of the allocated extent */ 821 xfs_fileoff_t bno; /* block number in file */
737 int error; /* error value */ 822 xfs_buf_t *bp; /* temporary buffer for zeroing */
738 xfs_rtblock_t postblock = 0; /* first block allocated > end */ 823 int committed; /* transaction committed flag */
739 xfs_rtblock_t preblock = 0; /* first block allocated < start */ 824 xfs_daddr_t d; /* disk block address */
825 int error; /* error return value */
826 xfs_fsblock_t firstblock; /* first block allocated in xaction */
827 xfs_bmap_free_t flist; /* list of freed blocks */
828 xfs_fsblock_t fsbno; /* filesystem block for bno */
829 xfs_bmbt_irec_t map; /* block map output */
830 int nmap; /* number of block maps */
831 int resblks; /* space reservation */
740 832
741 end = start + len - 1;
742 /*
743 * Assume we're allocating out of the middle of a free extent.
744 * We need to find the beginning and end of the extent so we can
745 * properly update the summary.
746 */
747 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
748 if (error) {
749 return error;
750 }
751 /*
752 * Find the next allocated block (end of free extent).
753 */
754 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
755 &postblock);
756 if (error) {
757 return error;
758 }
759 /*
760 * Decrement the summary information corresponding to the entire
761 * (old) free extent.
762 */
763 error = xfs_rtmodify_summary(mp, tp,
764 XFS_RTBLOCKLOG(postblock + 1 - preblock),
765 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
766 if (error) {
767 return error;
768 }
769 /*
770 * If there are blocks not being allocated at the front of the
771 * old extent, add summary data for them to be free.
772 */
773 if (preblock < start) {
774 error = xfs_rtmodify_summary(mp, tp,
775 XFS_RTBLOCKLOG(start - preblock),
776 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
777 if (error) {
778 return error;
779 }
780 }
781 /*
782 * If there are blocks not being allocated at the end of the
783 * old extent, add summary data for them to be free.
784 */
785 if (postblock > end) {
786 error = xfs_rtmodify_summary(mp, tp,
787 XFS_RTBLOCKLOG(postblock - end),
788 XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
789 if (error) {
790 return error;
791 }
792 }
793 /* 833 /*
794 * Modify the bitmap to mark this extent allocated. 834 * Allocate space to the file, as necessary.
795 */ 835 */
796 error = xfs_rtmodify_range(mp, tp, start, len, 0); 836 while (oblocks < nblocks) {
797 return error; 837 int cancelflags = 0;
798} 838 xfs_trans_t *tp;
799
800/*
801 * Return whether there are any free extents in the size range given
802 * by low and high, for the bitmap block bbno.
803 */
804STATIC int /* error */
805xfs_rtany_summary(
806 xfs_mount_t *mp, /* file system mount structure */
807 xfs_trans_t *tp, /* transaction pointer */
808 int low, /* low log2 extent size */
809 int high, /* high log2 extent size */
810 xfs_rtblock_t bbno, /* bitmap block number */
811 xfs_buf_t **rbpp, /* in/out: summary block buffer */
812 xfs_fsblock_t *rsb, /* in/out: summary block number */
813 int *stat) /* out: any good extents here? */
814{
815 int error; /* error value */
816 int log; /* loop counter, log2 of ext. size */
817 xfs_suminfo_t sum; /* summary data */
818 839
819 /* 840 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
820 * Loop over logs of extent sizes. Order is irrelevant. 841 resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
821 */
822 for (log = low; log <= high; log++) {
823 /* 842 /*
824 * Get one summary datum. 843 * Reserve space & log for one extent added to the file.
825 */ 844 */
826 error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); 845 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata,
827 if (error) { 846 resblks, 0);
828 return error; 847 if (error)
829 } 848 goto error_cancel;
849 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
830 /* 850 /*
831 * If there are any, return success. 851 * Lock the inode.
832 */ 852 */
833 if (sum) { 853 xfs_ilock(ip, XFS_ILOCK_EXCL);
834 *stat = 1; 854 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
835 return 0;
836 }
837 }
838 /*
839 * Found nothing, return failure.
840 */
841 *stat = 0;
842 return 0;
843}
844
845/*
846 * Get a buffer for the bitmap or summary file block specified.
847 * The buffer is returned read and locked.
848 */
849STATIC int /* error */
850xfs_rtbuf_get(
851 xfs_mount_t *mp, /* file system mount structure */
852 xfs_trans_t *tp, /* transaction pointer */
853 xfs_rtblock_t block, /* block number in bitmap or summary */
854 int issum, /* is summary not bitmap */
855 xfs_buf_t **bpp) /* output: buffer for the block */
856{
857 xfs_buf_t *bp; /* block buffer, result */
858 xfs_inode_t *ip; /* bitmap or summary inode */
859 xfs_bmbt_irec_t map;
860 int nmap = 1;
861 int error; /* error value */
862
863 ip = issum ? mp->m_rsumip : mp->m_rbmip;
864
865 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
866 if (error)
867 return error;
868
869 ASSERT(map.br_startblock != NULLFSBLOCK);
870 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
871 XFS_FSB_TO_DADDR(mp, map.br_startblock),
872 mp->m_bsize, 0, &bp, NULL);
873 if (error)
874 return error;
875 ASSERT(!xfs_buf_geterror(bp));
876 *bpp = bp;
877 return 0;
878}
879
880#ifdef DEBUG
881/*
882 * Check that the given extent (block range) is allocated already.
883 */
884STATIC int /* error */
885xfs_rtcheck_alloc_range(
886 xfs_mount_t *mp, /* file system mount point */
887 xfs_trans_t *tp, /* transaction pointer */
888 xfs_rtblock_t bno, /* starting block number of extent */
889 xfs_extlen_t len, /* length of extent */
890 int *stat) /* out: 1 for allocated, 0 for not */
891{
892 xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
893
894 return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat);
895}
896#endif
897
898/*
899 * Check that the given range is either all allocated (val = 0) or
900 * all free (val = 1).
901 */
902STATIC int /* error */
903xfs_rtcheck_range(
904 xfs_mount_t *mp, /* file system mount point */
905 xfs_trans_t *tp, /* transaction pointer */
906 xfs_rtblock_t start, /* starting block number of extent */
907 xfs_extlen_t len, /* length of extent */
908 int val, /* 1 for free, 0 for allocated */
909 xfs_rtblock_t *new, /* out: first block not matching */
910 int *stat) /* out: 1 for matches, 0 for not */
911{
912 xfs_rtword_t *b; /* current word in buffer */
913 int bit; /* bit number in the word */
914 xfs_rtblock_t block; /* bitmap block number */
915 xfs_buf_t *bp; /* buf for the block */
916 xfs_rtword_t *bufp; /* starting word in buffer */
917 int error; /* error value */
918 xfs_rtblock_t i; /* current bit number rel. to start */
919 xfs_rtblock_t lastbit; /* last useful bit in word */
920 xfs_rtword_t mask; /* mask of relevant bits for value */
921 xfs_rtword_t wdiff; /* difference from wanted value */
922 int word; /* word number in the buffer */
923 855
924 /* 856 xfs_bmap_init(&flist, &firstblock);
925 * Compute starting bitmap block number
926 */
927 block = XFS_BITTOBLOCK(mp, start);
928 /*
929 * Read the bitmap block.
930 */
931 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
932 if (error) {
933 return error;
934 }
935 bufp = bp->b_addr;
936 /*
937 * Compute the starting word's address, and starting bit.
938 */
939 word = XFS_BITTOWORD(mp, start);
940 b = &bufp[word];
941 bit = (int)(start & (XFS_NBWORD - 1));
942 /*
943 * 0 (allocated) => all zero's; 1 (free) => all one's.
944 */
945 val = -val;
946 /*
947 * If not starting on a word boundary, deal with the first
948 * (partial) word.
949 */
950 if (bit) {
951 /*
952 * Compute first bit not examined.
953 */
954 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
955 /*
956 * Mask of relevant bits.
957 */
958 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
959 /*
960 * Compute difference between actual and desired value.
961 */
962 if ((wdiff = (*b ^ val) & mask)) {
963 /*
964 * Different, compute first wrong bit and return.
965 */
966 xfs_trans_brelse(tp, bp);
967 i = XFS_RTLOBIT(wdiff) - bit;
968 *new = start + i;
969 *stat = 0;
970 return 0;
971 }
972 i = lastbit - bit;
973 /*
974 * Go on to next block if that's where the next word is
975 * and we need the next word.
976 */
977 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
978 /*
979 * If done with this block, get the next one.
980 */
981 xfs_trans_brelse(tp, bp);
982 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
983 if (error) {
984 return error;
985 }
986 b = bufp = bp->b_addr;
987 word = 0;
988 } else {
989 /*
990 * Go on to the next word in the buffer.
991 */
992 b++;
993 }
994 } else {
995 /*
996 * Starting on a word boundary, no partial word.
997 */
998 i = 0;
999 }
1000 /*
1001 * Loop over whole words in buffers. When we use up one buffer
1002 * we move on to the next one.
1003 */
1004 while (len - i >= XFS_NBWORD) {
1005 /*
1006 * Compute difference between actual and desired value.
1007 */
1008 if ((wdiff = *b ^ val)) {
1009 /*
1010 * Different, compute first wrong bit and return.
1011 */
1012 xfs_trans_brelse(tp, bp);
1013 i += XFS_RTLOBIT(wdiff);
1014 *new = start + i;
1015 *stat = 0;
1016 return 0;
1017 }
1018 i += XFS_NBWORD;
1019 /* 857 /*
1020 * Go on to next block if that's where the next word is 858 * Allocate blocks to the bitmap file.
1021 * and we need the next word.
1022 */ 859 */
1023 if (++word == XFS_BLOCKWSIZE(mp) && i < len) { 860 nmap = 1;
1024 /* 861 cancelflags |= XFS_TRANS_ABORT;
1025 * If done with this block, get the next one. 862 error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
1026 */ 863 XFS_BMAPI_METADATA, &firstblock,
1027 xfs_trans_brelse(tp, bp); 864 resblks, &map, &nmap, &flist);
1028 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 865 if (!error && nmap < 1)
1029 if (error) { 866 error = XFS_ERROR(ENOSPC);
1030 return error; 867 if (error)
1031 } 868 goto error_cancel;
1032 b = bufp = bp->b_addr;
1033 word = 0;
1034 } else {
1035 /*
1036 * Go on to the next word in the buffer.
1037 */
1038 b++;
1039 }
1040 }
1041 /*
1042 * If not ending on a word boundary, deal with the last
1043 * (partial) word.
1044 */
1045 if ((lastbit = len - i)) {
1046 /* 869 /*
1047 * Mask of relevant bits. 870 * Free any blocks freed up in the transaction, then commit.
1048 */ 871 */
1049 mask = ((xfs_rtword_t)1 << lastbit) - 1; 872 error = xfs_bmap_finish(&tp, &flist, &committed);
873 if (error)
874 goto error_cancel;
875 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
876 if (error)
877 goto error;
1050 /* 878 /*
1051 * Compute difference between actual and desired value. 879 * Now we need to clear the allocated blocks.
880 * Do this one block per transaction, to keep it simple.
1052 */ 881 */
1053 if ((wdiff = (*b ^ val) & mask)) { 882 cancelflags = 0;
883 for (bno = map.br_startoff, fsbno = map.br_startblock;
884 bno < map.br_startoff + map.br_blockcount;
885 bno++, fsbno++) {
886 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
1054 /* 887 /*
1055 * Different, compute first wrong bit and return. 888 * Reserve log for one block zeroing.
1056 */ 889 */
1057 xfs_trans_brelse(tp, bp); 890 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero,
1058 i += XFS_RTLOBIT(wdiff); 891 0, 0);
1059 *new = start + i;
1060 *stat = 0;
1061 return 0;
1062 } else
1063 i = len;
1064 }
1065 /*
1066 * Successful, return.
1067 */
1068 xfs_trans_brelse(tp, bp);
1069 *new = start + i;
1070 *stat = 1;
1071 return 0;
1072}
1073
1074/*
1075 * Copy and transform the summary file, given the old and new
1076 * parameters in the mount structures.
1077 */
1078STATIC int /* error */
1079xfs_rtcopy_summary(
1080 xfs_mount_t *omp, /* old file system mount point */
1081 xfs_mount_t *nmp, /* new file system mount point */
1082 xfs_trans_t *tp) /* transaction pointer */
1083{
1084 xfs_rtblock_t bbno; /* bitmap block number */
1085 xfs_buf_t *bp; /* summary buffer */
1086 int error; /* error return value */
1087 int log; /* summary level number (log length) */
1088 xfs_suminfo_t sum; /* summary data */
1089 xfs_fsblock_t sumbno; /* summary block number */
1090
1091 bp = NULL;
1092 for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
1093 for (bbno = omp->m_sb.sb_rbmblocks - 1;
1094 (xfs_srtblock_t)bbno >= 0;
1095 bbno--) {
1096 error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
1097 &sumbno, &sum);
1098 if (error)
1099 return error;
1100 if (sum == 0)
1101 continue;
1102 error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
1103 &bp, &sumbno);
1104 if (error)
1105 return error;
1106 error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
1107 &bp, &sumbno);
1108 if (error) 892 if (error)
1109 return error; 893 goto error_cancel;
1110 ASSERT(sum > 0);
1111 }
1112 }
1113 return 0;
1114}
1115
1116/*
1117 * Searching backward from start to limit, find the first block whose
1118 * allocated/free state is different from start's.
1119 */
1120STATIC int /* error */
1121xfs_rtfind_back(
1122 xfs_mount_t *mp, /* file system mount point */
1123 xfs_trans_t *tp, /* transaction pointer */
1124 xfs_rtblock_t start, /* starting block to look at */
1125 xfs_rtblock_t limit, /* last block to look at */
1126 xfs_rtblock_t *rtblock) /* out: start block found */
1127{
1128 xfs_rtword_t *b; /* current word in buffer */
1129 int bit; /* bit number in the word */
1130 xfs_rtblock_t block; /* bitmap block number */
1131 xfs_buf_t *bp; /* buf for the block */
1132 xfs_rtword_t *bufp; /* starting word in buffer */
1133 int error; /* error value */
1134 xfs_rtblock_t firstbit; /* first useful bit in the word */
1135 xfs_rtblock_t i; /* current bit number rel. to start */
1136 xfs_rtblock_t len; /* length of inspected area */
1137 xfs_rtword_t mask; /* mask of relevant bits for value */
1138 xfs_rtword_t want; /* mask for "good" values */
1139 xfs_rtword_t wdiff; /* difference from wanted value */
1140 int word; /* word number in the buffer */
1141
1142 /*
1143 * Compute and read in starting bitmap block for starting block.
1144 */
1145 block = XFS_BITTOBLOCK(mp, start);
1146 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1147 if (error) {
1148 return error;
1149 }
1150 bufp = bp->b_addr;
1151 /*
1152 * Get the first word's index & point to it.
1153 */
1154 word = XFS_BITTOWORD(mp, start);
1155 b = &bufp[word];
1156 bit = (int)(start & (XFS_NBWORD - 1));
1157 len = start - limit + 1;
1158 /*
1159 * Compute match value, based on the bit at start: if 1 (free)
1160 * then all-ones, else all-zeroes.
1161 */
1162 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1163 /*
1164 * If the starting position is not word-aligned, deal with the
1165 * partial word.
1166 */
1167 if (bit < XFS_NBWORD - 1) {
1168 /*
1169 * Calculate first (leftmost) bit number to look at,
1170 * and mask for all the relevant bits in this word.
1171 */
1172 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
1173 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
1174 firstbit;
1175 /*
1176 * Calculate the difference between the value there
1177 * and what we're looking for.
1178 */
1179 if ((wdiff = (*b ^ want) & mask)) {
1180 /*
1181 * Different. Mark where we are and return.
1182 */
1183 xfs_trans_brelse(tp, bp);
1184 i = bit - XFS_RTHIBIT(wdiff);
1185 *rtblock = start - i + 1;
1186 return 0;
1187 }
1188 i = bit - firstbit + 1;
1189 /*
1190 * Go on to previous block if that's where the previous word is
1191 * and we need the previous word.
1192 */
1193 if (--word == -1 && i < len) {
1194 /*
1195 * If done with this block, get the previous one.
1196 */
1197 xfs_trans_brelse(tp, bp);
1198 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1199 if (error) {
1200 return error;
1201 }
1202 bufp = bp->b_addr;
1203 word = XFS_BLOCKWMASK(mp);
1204 b = &bufp[word];
1205 } else {
1206 /*
1207 * Go on to the previous word in the buffer.
1208 */
1209 b--;
1210 }
1211 } else {
1212 /*
1213 * Starting on a word boundary, no partial word.
1214 */
1215 i = 0;
1216 }
1217 /*
1218 * Loop over whole words in buffers. When we use up one buffer
1219 * we move on to the previous one.
1220 */
1221 while (len - i >= XFS_NBWORD) {
1222 /*
1223 * Compute difference between actual and desired value.
1224 */
1225 if ((wdiff = *b ^ want)) {
1226 /*
1227 * Different, mark where we are and return.
1228 */
1229 xfs_trans_brelse(tp, bp);
1230 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1231 *rtblock = start - i + 1;
1232 return 0;
1233 }
1234 i += XFS_NBWORD;
1235 /*
1236 * Go on to previous block if that's where the previous word is
1237 * and we need the previous word.
1238 */
1239 if (--word == -1 && i < len) {
1240 /*
1241 * If done with this block, get the previous one.
1242 */
1243 xfs_trans_brelse(tp, bp);
1244 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
1245 if (error) {
1246 return error;
1247 }
1248 bufp = bp->b_addr;
1249 word = XFS_BLOCKWMASK(mp);
1250 b = &bufp[word];
1251 } else {
1252 /*
1253 * Go on to the previous word in the buffer.
1254 */
1255 b--;
1256 }
1257 }
1258 /*
1259 * If not ending on a word boundary, deal with the last
1260 * (partial) word.
1261 */
1262 if (len - i) {
1263 /*
1264 * Calculate first (leftmost) bit number to look at,
1265 * and mask for all the relevant bits in this word.
1266 */
1267 firstbit = XFS_NBWORD - (len - i);
1268 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
1269 /*
1270 * Compute difference between actual and desired value.
1271 */
1272 if ((wdiff = (*b ^ want) & mask)) {
1273 /*
1274 * Different, mark where we are and return.
1275 */
1276 xfs_trans_brelse(tp, bp);
1277 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
1278 *rtblock = start - i + 1;
1279 return 0;
1280 } else
1281 i = len;
1282 }
1283 /*
1284 * No match, return that we scanned the whole area.
1285 */
1286 xfs_trans_brelse(tp, bp);
1287 *rtblock = start - i + 1;
1288 return 0;
1289}
1290
1291/*
1292 * Searching forward from start to limit, find the first block whose
1293 * allocated/free state is different from start's.
1294 */
1295STATIC int /* error */
1296xfs_rtfind_forw(
1297 xfs_mount_t *mp, /* file system mount point */
1298 xfs_trans_t *tp, /* transaction pointer */
1299 xfs_rtblock_t start, /* starting block to look at */
1300 xfs_rtblock_t limit, /* last block to look at */
1301 xfs_rtblock_t *rtblock) /* out: start block found */
1302{
1303 xfs_rtword_t *b; /* current word in buffer */
1304 int bit; /* bit number in the word */
1305 xfs_rtblock_t block; /* bitmap block number */
1306 xfs_buf_t *bp; /* buf for the block */
1307 xfs_rtword_t *bufp; /* starting word in buffer */
1308 int error; /* error value */
1309 xfs_rtblock_t i; /* current bit number rel. to start */
1310 xfs_rtblock_t lastbit; /* last useful bit in the word */
1311 xfs_rtblock_t len; /* length of inspected area */
1312 xfs_rtword_t mask; /* mask of relevant bits for value */
1313 xfs_rtword_t want; /* mask for "good" values */
1314 xfs_rtword_t wdiff; /* difference from wanted value */
1315 int word; /* word number in the buffer */
1316
1317 /*
1318 * Compute and read in starting bitmap block for starting block.
1319 */
1320 block = XFS_BITTOBLOCK(mp, start);
1321 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1322 if (error) {
1323 return error;
1324 }
1325 bufp = bp->b_addr;
1326 /*
1327 * Get the first word's index & point to it.
1328 */
1329 word = XFS_BITTOWORD(mp, start);
1330 b = &bufp[word];
1331 bit = (int)(start & (XFS_NBWORD - 1));
1332 len = limit - start + 1;
1333 /*
1334 * Compute match value, based on the bit at start: if 1 (free)
1335 * then all-ones, else all-zeroes.
1336 */
1337 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
1338 /*
1339 * If the starting position is not word-aligned, deal with the
1340 * partial word.
1341 */
1342 if (bit) {
1343 /*
1344 * Calculate last (rightmost) bit number to look at,
1345 * and mask for all the relevant bits in this word.
1346 */
1347 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1348 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1349 /*
1350 * Calculate the difference between the value there
1351 * and what we're looking for.
1352 */
1353 if ((wdiff = (*b ^ want) & mask)) {
1354 /*
1355 * Different. Mark where we are and return.
1356 */
1357 xfs_trans_brelse(tp, bp);
1358 i = XFS_RTLOBIT(wdiff) - bit;
1359 *rtblock = start + i - 1;
1360 return 0;
1361 }
1362 i = lastbit - bit;
1363 /*
1364 * Go on to next block if that's where the next word is
1365 * and we need the next word.
1366 */
1367 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1368 /*
1369 * If done with this block, get the previous one.
1370 */
1371 xfs_trans_brelse(tp, bp);
1372 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1373 if (error) {
1374 return error;
1375 }
1376 b = bufp = bp->b_addr;
1377 word = 0;
1378 } else {
1379 /*
1380 * Go on to the previous word in the buffer.
1381 */
1382 b++;
1383 }
1384 } else {
1385 /*
1386 * Starting on a word boundary, no partial word.
1387 */
1388 i = 0;
1389 }
1390 /*
1391 * Loop over whole words in buffers. When we use up one buffer
1392 * we move on to the next one.
1393 */
1394 while (len - i >= XFS_NBWORD) {
1395 /*
1396 * Compute difference between actual and desired value.
1397 */
1398 if ((wdiff = *b ^ want)) {
1399 /* 894 /*
1400 * Different, mark where we are and return. 895 * Lock the bitmap inode.
1401 */ 896 */
1402 xfs_trans_brelse(tp, bp); 897 xfs_ilock(ip, XFS_ILOCK_EXCL);
1403 i += XFS_RTLOBIT(wdiff); 898 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1404 *rtblock = start + i - 1;
1405 return 0;
1406 }
1407 i += XFS_NBWORD;
1408 /*
1409 * Go on to next block if that's where the next word is
1410 * and we need the next word.
1411 */
1412 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1413 /* 899 /*
1414 * If done with this block, get the next one. 900 * Get a buffer for the block.
1415 */ 901 */
1416 xfs_trans_brelse(tp, bp); 902 d = XFS_FSB_TO_DADDR(mp, fsbno);
1417 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 903 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
1418 if (error) { 904 mp->m_bsize, 0);
1419 return error; 905 if (bp == NULL) {
906 error = XFS_ERROR(EIO);
907error_cancel:
908 xfs_trans_cancel(tp, cancelflags);
909 goto error;
1420 } 910 }
1421 b = bufp = bp->b_addr; 911 memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
1422 word = 0; 912 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
1423 } else {
1424 /* 913 /*
1425 * Go on to the next word in the buffer. 914 * Commit the transaction.
1426 */ 915 */
1427 b++; 916 error = xfs_trans_commit(tp, 0);
917 if (error)
918 goto error;
1428 } 919 }
1429 }
1430 /*
1431 * If not ending on a word boundary, deal with the last
1432 * (partial) word.
1433 */
1434 if ((lastbit = len - i)) {
1435 /*
1436 * Calculate mask for all the relevant bits in this word.
1437 */
1438 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1439 /* 920 /*
1440 * Compute difference between actual and desired value. 921 * Go on to the next extent, if any.
1441 */ 922 */
1442 if ((wdiff = (*b ^ want) & mask)) { 923 oblocks = map.br_startoff + map.br_blockcount;
1443 /*
1444 * Different, mark where we are and return.
1445 */
1446 xfs_trans_brelse(tp, bp);
1447 i += XFS_RTLOBIT(wdiff);
1448 *rtblock = start + i - 1;
1449 return 0;
1450 } else
1451 i = len;
1452 } 924 }
1453 /*
1454 * No match, return that we scanned the whole area.
1455 */
1456 xfs_trans_brelse(tp, bp);
1457 *rtblock = start + i - 1;
1458 return 0; 925 return 0;
1459}
1460 926
1461/* 927error:
1462 * Mark an extent specified by start and len freed.
1463 * Updates all the summary information as well as the bitmap.
1464 */
1465STATIC int /* error */
1466xfs_rtfree_range(
1467 xfs_mount_t *mp, /* file system mount point */
1468 xfs_trans_t *tp, /* transaction pointer */
1469 xfs_rtblock_t start, /* starting block to free */
1470 xfs_extlen_t len, /* length to free */
1471 xfs_buf_t **rbpp, /* in/out: summary block buffer */
1472 xfs_fsblock_t *rsb) /* in/out: summary block number */
1473{
1474 xfs_rtblock_t end; /* end of the freed extent */
1475 int error; /* error value */
1476 xfs_rtblock_t postblock; /* first block freed > end */
1477 xfs_rtblock_t preblock; /* first block freed < start */
1478
1479 end = start + len - 1;
1480 /*
1481 * Modify the bitmap to mark this extent freed.
1482 */
1483 error = xfs_rtmodify_range(mp, tp, start, len, 1);
1484 if (error) {
1485 return error;
1486 }
1487 /*
1488 * Assume we're freeing out of the middle of an allocated extent.
1489 * We need to find the beginning and end of the extent so we can
1490 * properly update the summary.
1491 */
1492 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
1493 if (error) {
1494 return error;
1495 }
1496 /*
1497 * Find the next allocated block (end of allocated extent).
1498 */
1499 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
1500 &postblock);
1501 if (error)
1502 return error;
1503 /*
1504 * If there are blocks not being freed at the front of the
1505 * old extent, add summary data for them to be allocated.
1506 */
1507 if (preblock < start) {
1508 error = xfs_rtmodify_summary(mp, tp,
1509 XFS_RTBLOCKLOG(start - preblock),
1510 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
1511 if (error) {
1512 return error;
1513 }
1514 }
1515 /*
1516 * If there are blocks not being freed at the end of the
1517 * old extent, add summary data for them to be allocated.
1518 */
1519 if (postblock > end) {
1520 error = xfs_rtmodify_summary(mp, tp,
1521 XFS_RTBLOCKLOG(postblock - end),
1522 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
1523 if (error) {
1524 return error;
1525 }
1526 }
1527 /*
1528 * Increment the summary information corresponding to the entire
1529 * (new) free extent.
1530 */
1531 error = xfs_rtmodify_summary(mp, tp,
1532 XFS_RTBLOCKLOG(postblock + 1 - preblock),
1533 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
1534 return error; 928 return error;
1535} 929}
1536 930
1537/* 931/*
1538 * Read and return the summary information for a given extent size,
1539 * bitmap block combination.
1540 * Keeps track of a current summary block, so we don't keep reading
1541 * it from the buffer cache.
1542 */
1543STATIC int /* error */
1544xfs_rtget_summary(
1545 xfs_mount_t *mp, /* file system mount structure */
1546 xfs_trans_t *tp, /* transaction pointer */
1547 int log, /* log2 of extent size */
1548 xfs_rtblock_t bbno, /* bitmap block number */
1549 xfs_buf_t **rbpp, /* in/out: summary block buffer */
1550 xfs_fsblock_t *rsb, /* in/out: summary block number */
1551 xfs_suminfo_t *sum) /* out: summary info for this block */
1552{
1553 xfs_buf_t *bp; /* buffer for summary block */
1554 int error; /* error value */
1555 xfs_fsblock_t sb; /* summary fsblock */
1556 int so; /* index into the summary file */
1557 xfs_suminfo_t *sp; /* pointer to returned data */
1558
1559 /*
1560 * Compute entry number in the summary file.
1561 */
1562 so = XFS_SUMOFFS(mp, log, bbno);
1563 /*
1564 * Compute the block number in the summary file.
1565 */
1566 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1567 /*
1568 * If we have an old buffer, and the block number matches, use that.
1569 */
1570 if (rbpp && *rbpp && *rsb == sb)
1571 bp = *rbpp;
1572 /*
1573 * Otherwise we have to get the buffer.
1574 */
1575 else {
1576 /*
1577 * If there was an old one, get rid of it first.
1578 */
1579 if (rbpp && *rbpp)
1580 xfs_trans_brelse(tp, *rbpp);
1581 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1582 if (error) {
1583 return error;
1584 }
1585 /*
1586 * Remember this buffer and block for the next call.
1587 */
1588 if (rbpp) {
1589 *rbpp = bp;
1590 *rsb = sb;
1591 }
1592 }
1593 /*
1594 * Point to the summary information & copy it out.
1595 */
1596 sp = XFS_SUMPTR(mp, bp, so);
1597 *sum = *sp;
1598 /*
1599 * Drop the buffer if we're not asked to remember it.
1600 */
1601 if (!rbpp)
1602 xfs_trans_brelse(tp, bp);
1603 return 0;
1604}
1605
1606/*
1607 * Set the given range of bitmap bits to the given value.
1608 * Do whatever I/O and logging is required.
1609 */
1610STATIC int /* error */
1611xfs_rtmodify_range(
1612 xfs_mount_t *mp, /* file system mount point */
1613 xfs_trans_t *tp, /* transaction pointer */
1614 xfs_rtblock_t start, /* starting block to modify */
1615 xfs_extlen_t len, /* length of extent to modify */
1616 int val) /* 1 for free, 0 for allocated */
1617{
1618 xfs_rtword_t *b; /* current word in buffer */
1619 int bit; /* bit number in the word */
1620 xfs_rtblock_t block; /* bitmap block number */
1621 xfs_buf_t *bp; /* buf for the block */
1622 xfs_rtword_t *bufp; /* starting word in buffer */
1623 int error; /* error value */
1624 xfs_rtword_t *first; /* first used word in the buffer */
1625 int i; /* current bit number rel. to start */
1626 int lastbit; /* last useful bit in word */
1627 xfs_rtword_t mask; /* mask o frelevant bits for value */
1628 int word; /* word number in the buffer */
1629
1630 /*
1631 * Compute starting bitmap block number.
1632 */
1633 block = XFS_BITTOBLOCK(mp, start);
1634 /*
1635 * Read the bitmap block, and point to its data.
1636 */
1637 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
1638 if (error) {
1639 return error;
1640 }
1641 bufp = bp->b_addr;
1642 /*
1643 * Compute the starting word's address, and starting bit.
1644 */
1645 word = XFS_BITTOWORD(mp, start);
1646 first = b = &bufp[word];
1647 bit = (int)(start & (XFS_NBWORD - 1));
1648 /*
1649 * 0 (allocated) => all zeroes; 1 (free) => all ones.
1650 */
1651 val = -val;
1652 /*
1653 * If not starting on a word boundary, deal with the first
1654 * (partial) word.
1655 */
1656 if (bit) {
1657 /*
1658 * Compute first bit not changed and mask of relevant bits.
1659 */
1660 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
1661 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
1662 /*
1663 * Set/clear the active bits.
1664 */
1665 if (val)
1666 *b |= mask;
1667 else
1668 *b &= ~mask;
1669 i = lastbit - bit;
1670 /*
1671 * Go on to the next block if that's where the next word is
1672 * and we need the next word.
1673 */
1674 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1675 /*
1676 * Log the changed part of this block.
1677 * Get the next one.
1678 */
1679 xfs_trans_log_buf(tp, bp,
1680 (uint)((char *)first - (char *)bufp),
1681 (uint)((char *)b - (char *)bufp));
1682 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1683 if (error) {
1684 return error;
1685 }
1686 first = b = bufp = bp->b_addr;
1687 word = 0;
1688 } else {
1689 /*
1690 * Go on to the next word in the buffer
1691 */
1692 b++;
1693 }
1694 } else {
1695 /*
1696 * Starting on a word boundary, no partial word.
1697 */
1698 i = 0;
1699 }
1700 /*
1701 * Loop over whole words in buffers. When we use up one buffer
1702 * we move on to the next one.
1703 */
1704 while (len - i >= XFS_NBWORD) {
1705 /*
1706 * Set the word value correctly.
1707 */
1708 *b = val;
1709 i += XFS_NBWORD;
1710 /*
1711 * Go on to the next block if that's where the next word is
1712 * and we need the next word.
1713 */
1714 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
1715 /*
1716 * Log the changed part of this block.
1717 * Get the next one.
1718 */
1719 xfs_trans_log_buf(tp, bp,
1720 (uint)((char *)first - (char *)bufp),
1721 (uint)((char *)b - (char *)bufp));
1722 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
1723 if (error) {
1724 return error;
1725 }
1726 first = b = bufp = bp->b_addr;
1727 word = 0;
1728 } else {
1729 /*
1730 * Go on to the next word in the buffer
1731 */
1732 b++;
1733 }
1734 }
1735 /*
1736 * If not ending on a word boundary, deal with the last
1737 * (partial) word.
1738 */
1739 if ((lastbit = len - i)) {
1740 /*
1741 * Compute a mask of relevant bits.
1742 */
1743 bit = 0;
1744 mask = ((xfs_rtword_t)1 << lastbit) - 1;
1745 /*
1746 * Set/clear the active bits.
1747 */
1748 if (val)
1749 *b |= mask;
1750 else
1751 *b &= ~mask;
1752 b++;
1753 }
1754 /*
1755 * Log any remaining changed bytes.
1756 */
1757 if (b > first)
1758 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
1759 (uint)((char *)b - (char *)bufp - 1));
1760 return 0;
1761}
1762
1763/*
1764 * Read and modify the summary information for a given extent size,
1765 * bitmap block combination.
1766 * Keeps track of a current summary block, so we don't keep reading
1767 * it from the buffer cache.
1768 */
1769STATIC int /* error */
1770xfs_rtmodify_summary(
1771 xfs_mount_t *mp, /* file system mount point */
1772 xfs_trans_t *tp, /* transaction pointer */
1773 int log, /* log2 of extent size */
1774 xfs_rtblock_t bbno, /* bitmap block number */
1775 int delta, /* change to make to summary info */
1776 xfs_buf_t **rbpp, /* in/out: summary block buffer */
1777 xfs_fsblock_t *rsb) /* in/out: summary block number */
1778{
1779 xfs_buf_t *bp; /* buffer for the summary block */
1780 int error; /* error value */
1781 xfs_fsblock_t sb; /* summary fsblock */
1782 int so; /* index into the summary file */
1783 xfs_suminfo_t *sp; /* pointer to returned data */
1784
1785 /*
1786 * Compute entry number in the summary file.
1787 */
1788 so = XFS_SUMOFFS(mp, log, bbno);
1789 /*
1790 * Compute the block number in the summary file.
1791 */
1792 sb = XFS_SUMOFFSTOBLOCK(mp, so);
1793 /*
1794 * If we have an old buffer, and the block number matches, use that.
1795 */
1796 if (rbpp && *rbpp && *rsb == sb)
1797 bp = *rbpp;
1798 /*
1799 * Otherwise we have to get the buffer.
1800 */
1801 else {
1802 /*
1803 * If there was an old one, get rid of it first.
1804 */
1805 if (rbpp && *rbpp)
1806 xfs_trans_brelse(tp, *rbpp);
1807 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
1808 if (error) {
1809 return error;
1810 }
1811 /*
1812 * Remember this buffer and block for the next call.
1813 */
1814 if (rbpp) {
1815 *rbpp = bp;
1816 *rsb = sb;
1817 }
1818 }
1819 /*
1820 * Point to the summary information, modify and log it.
1821 */
1822 sp = XFS_SUMPTR(mp, bp, so);
1823 *sp += delta;
1824 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
1825 (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
1826 return 0;
1827}
1828
1829/*
1830 * Visible (exported) functions. 932 * Visible (exported) functions.
1831 */ 933 */
1832 934
@@ -2129,66 +1231,6 @@ xfs_rtallocate_extent(
2129} 1231}
2130 1232
2131/* 1233/*
2132 * Free an extent in the realtime subvolume. Length is expressed in
2133 * realtime extents, as is the block number.
2134 */
2135int /* error */
2136xfs_rtfree_extent(
2137 xfs_trans_t *tp, /* transaction pointer */
2138 xfs_rtblock_t bno, /* starting block number to free */
2139 xfs_extlen_t len) /* length of extent freed */
2140{
2141 int error; /* error value */
2142 xfs_mount_t *mp; /* file system mount structure */
2143 xfs_fsblock_t sb; /* summary file block number */
2144 xfs_buf_t *sumbp; /* summary file block buffer */
2145
2146 mp = tp->t_mountp;
2147
2148 ASSERT(mp->m_rbmip->i_itemp != NULL);
2149 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
2150
2151#ifdef DEBUG
2152 /*
2153 * Check to see that this whole range is currently allocated.
2154 */
2155 {
2156 int stat; /* result from checking range */
2157
2158 error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
2159 if (error) {
2160 return error;
2161 }
2162 ASSERT(stat);
2163 }
2164#endif
2165 sumbp = NULL;
2166 /*
2167 * Free the range of realtime blocks.
2168 */
2169 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
2170 if (error) {
2171 return error;
2172 }
2173 /*
2174 * Mark more blocks free in the superblock.
2175 */
2176 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
2177 /*
2178 * If we've now freed all the blocks, reset the file sequence
2179 * number to 0.
2180 */
2181 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
2182 mp->m_sb.sb_rextents) {
2183 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
2184 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
2185 *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
2186 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
2187 }
2188 return 0;
2189}
2190
2191/*
2192 * Initialize realtime fields in the mount structure. 1234 * Initialize realtime fields in the mount structure.
2193 */ 1235 */
2194int /* error */ 1236int /* error */
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index b2a1a24c0e2f..752b63d10300 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -95,6 +95,30 @@ xfs_growfs_rt(
95 struct xfs_mount *mp, /* file system mount structure */ 95 struct xfs_mount *mp, /* file system mount structure */
96 xfs_growfs_rt_t *in); /* user supplied growfs struct */ 96 xfs_growfs_rt_t *in); /* user supplied growfs struct */
97 97
98/*
99 * From xfs_rtbitmap.c
100 */
101int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp,
102 xfs_rtblock_t block, int issum, struct xfs_buf **bpp);
103int xfs_rtcheck_range(struct xfs_mount *mp, struct xfs_trans *tp,
104 xfs_rtblock_t start, xfs_extlen_t len, int val,
105 xfs_rtblock_t *new, int *stat);
106int xfs_rtfind_back(struct xfs_mount *mp, struct xfs_trans *tp,
107 xfs_rtblock_t start, xfs_rtblock_t limit,
108 xfs_rtblock_t *rtblock);
109int xfs_rtfind_forw(struct xfs_mount *mp, struct xfs_trans *tp,
110 xfs_rtblock_t start, xfs_rtblock_t limit,
111 xfs_rtblock_t *rtblock);
112int xfs_rtmodify_range(struct xfs_mount *mp, struct xfs_trans *tp,
113 xfs_rtblock_t start, xfs_extlen_t len, int val);
114int xfs_rtmodify_summary(struct xfs_mount *mp, struct xfs_trans *tp, int log,
115 xfs_rtblock_t bbno, int delta, xfs_buf_t **rbpp,
116 xfs_fsblock_t *rsb);
117int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp,
118 xfs_rtblock_t start, xfs_extlen_t len,
119 struct xfs_buf **rbpp, xfs_fsblock_t *rsb);
120
121
98#else 122#else
99# define xfs_rtallocate_extent(t,b,min,max,l,a,f,p,rb) (ENOSYS) 123# define xfs_rtallocate_extent(t,b,min,max,l,a,f,p,rb) (ENOSYS)
100# define xfs_rtfree_extent(t,b,l) (ENOSYS) 124# define xfs_rtfree_extent(t,b,l) (ENOSYS)
diff --git a/fs/xfs/xfs_rtbitmap.c b/fs/xfs/xfs_rtbitmap.c
new file mode 100644
index 000000000000..b1f2fe8af4a8
--- /dev/null
+++ b/fs/xfs/xfs_rtbitmap.c
@@ -0,0 +1,974 @@
1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
24#include "xfs_bit.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_mount.h"
28#include "xfs_inode.h"
29#include "xfs_bmap.h"
30#include "xfs_bmap_util.h"
31#include "xfs_bmap_btree.h"
32#include "xfs_alloc.h"
33#include "xfs_error.h"
34#include "xfs_trans.h"
35#include "xfs_trans_space.h"
36#include "xfs_trace.h"
37#include "xfs_buf.h"
38#include "xfs_icache.h"
39#include "xfs_dinode.h"
40#include "xfs_rtalloc.h"
41
42
43/*
44 * Realtime allocator bitmap functions shared with userspace.
45 */
46
47/*
48 * Get a buffer for the bitmap or summary file block specified.
49 * The buffer is returned read and locked.
50 */
51int
52xfs_rtbuf_get(
53 xfs_mount_t *mp, /* file system mount structure */
54 xfs_trans_t *tp, /* transaction pointer */
55 xfs_rtblock_t block, /* block number in bitmap or summary */
56 int issum, /* is summary not bitmap */
57 xfs_buf_t **bpp) /* output: buffer for the block */
58{
59 xfs_buf_t *bp; /* block buffer, result */
60 xfs_inode_t *ip; /* bitmap or summary inode */
61 xfs_bmbt_irec_t map;
62 int nmap = 1;
63 int error; /* error value */
64
65 ip = issum ? mp->m_rsumip : mp->m_rbmip;
66
67 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
68 if (error)
69 return error;
70
71 ASSERT(map.br_startblock != NULLFSBLOCK);
72 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
73 XFS_FSB_TO_DADDR(mp, map.br_startblock),
74 mp->m_bsize, 0, &bp, NULL);
75 if (error)
76 return error;
77 ASSERT(!xfs_buf_geterror(bp));
78 *bpp = bp;
79 return 0;
80}
81
82/*
83 * Searching backward from start to limit, find the first block whose
84 * allocated/free state is different from start's.
85 */
86int
87xfs_rtfind_back(
88 xfs_mount_t *mp, /* file system mount point */
89 xfs_trans_t *tp, /* transaction pointer */
90 xfs_rtblock_t start, /* starting block to look at */
91 xfs_rtblock_t limit, /* last block to look at */
92 xfs_rtblock_t *rtblock) /* out: start block found */
93{
94 xfs_rtword_t *b; /* current word in buffer */
95 int bit; /* bit number in the word */
96 xfs_rtblock_t block; /* bitmap block number */
97 xfs_buf_t *bp; /* buf for the block */
98 xfs_rtword_t *bufp; /* starting word in buffer */
99 int error; /* error value */
100 xfs_rtblock_t firstbit; /* first useful bit in the word */
101 xfs_rtblock_t i; /* current bit number rel. to start */
102 xfs_rtblock_t len; /* length of inspected area */
103 xfs_rtword_t mask; /* mask of relevant bits for value */
104 xfs_rtword_t want; /* mask for "good" values */
105 xfs_rtword_t wdiff; /* difference from wanted value */
106 int word; /* word number in the buffer */
107
108 /*
109 * Compute and read in starting bitmap block for starting block.
110 */
111 block = XFS_BITTOBLOCK(mp, start);
112 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
113 if (error) {
114 return error;
115 }
116 bufp = bp->b_addr;
117 /*
118 * Get the first word's index & point to it.
119 */
120 word = XFS_BITTOWORD(mp, start);
121 b = &bufp[word];
122 bit = (int)(start & (XFS_NBWORD - 1));
123 len = start - limit + 1;
124 /*
125 * Compute match value, based on the bit at start: if 1 (free)
126 * then all-ones, else all-zeroes.
127 */
128 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
129 /*
130 * If the starting position is not word-aligned, deal with the
131 * partial word.
132 */
133 if (bit < XFS_NBWORD - 1) {
134 /*
135 * Calculate first (leftmost) bit number to look at,
136 * and mask for all the relevant bits in this word.
137 */
138 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
139 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
140 firstbit;
141 /*
142 * Calculate the difference between the value there
143 * and what we're looking for.
144 */
145 if ((wdiff = (*b ^ want) & mask)) {
146 /*
147 * Different. Mark where we are and return.
148 */
149 xfs_trans_brelse(tp, bp);
150 i = bit - XFS_RTHIBIT(wdiff);
151 *rtblock = start - i + 1;
152 return 0;
153 }
154 i = bit - firstbit + 1;
155 /*
156 * Go on to previous block if that's where the previous word is
157 * and we need the previous word.
158 */
159 if (--word == -1 && i < len) {
160 /*
161 * If done with this block, get the previous one.
162 */
163 xfs_trans_brelse(tp, bp);
164 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
165 if (error) {
166 return error;
167 }
168 bufp = bp->b_addr;
169 word = XFS_BLOCKWMASK(mp);
170 b = &bufp[word];
171 } else {
172 /*
173 * Go on to the previous word in the buffer.
174 */
175 b--;
176 }
177 } else {
178 /*
179 * Starting on a word boundary, no partial word.
180 */
181 i = 0;
182 }
183 /*
184 * Loop over whole words in buffers. When we use up one buffer
185 * we move on to the previous one.
186 */
187 while (len - i >= XFS_NBWORD) {
188 /*
189 * Compute difference between actual and desired value.
190 */
191 if ((wdiff = *b ^ want)) {
192 /*
193 * Different, mark where we are and return.
194 */
195 xfs_trans_brelse(tp, bp);
196 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
197 *rtblock = start - i + 1;
198 return 0;
199 }
200 i += XFS_NBWORD;
201 /*
202 * Go on to previous block if that's where the previous word is
203 * and we need the previous word.
204 */
205 if (--word == -1 && i < len) {
206 /*
207 * If done with this block, get the previous one.
208 */
209 xfs_trans_brelse(tp, bp);
210 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
211 if (error) {
212 return error;
213 }
214 bufp = bp->b_addr;
215 word = XFS_BLOCKWMASK(mp);
216 b = &bufp[word];
217 } else {
218 /*
219 * Go on to the previous word in the buffer.
220 */
221 b--;
222 }
223 }
224 /*
225 * If not ending on a word boundary, deal with the last
226 * (partial) word.
227 */
228 if (len - i) {
229 /*
230 * Calculate first (leftmost) bit number to look at,
231 * and mask for all the relevant bits in this word.
232 */
233 firstbit = XFS_NBWORD - (len - i);
234 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
235 /*
236 * Compute difference between actual and desired value.
237 */
238 if ((wdiff = (*b ^ want) & mask)) {
239 /*
240 * Different, mark where we are and return.
241 */
242 xfs_trans_brelse(tp, bp);
243 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
244 *rtblock = start - i + 1;
245 return 0;
246 } else
247 i = len;
248 }
249 /*
250 * No match, return that we scanned the whole area.
251 */
252 xfs_trans_brelse(tp, bp);
253 *rtblock = start - i + 1;
254 return 0;
255}
256
257/*
258 * Searching forward from start to limit, find the first block whose
259 * allocated/free state is different from start's.
260 */
261int
262xfs_rtfind_forw(
263 xfs_mount_t *mp, /* file system mount point */
264 xfs_trans_t *tp, /* transaction pointer */
265 xfs_rtblock_t start, /* starting block to look at */
266 xfs_rtblock_t limit, /* last block to look at */
267 xfs_rtblock_t *rtblock) /* out: start block found */
268{
269 xfs_rtword_t *b; /* current word in buffer */
270 int bit; /* bit number in the word */
271 xfs_rtblock_t block; /* bitmap block number */
272 xfs_buf_t *bp; /* buf for the block */
273 xfs_rtword_t *bufp; /* starting word in buffer */
274 int error; /* error value */
275 xfs_rtblock_t i; /* current bit number rel. to start */
276 xfs_rtblock_t lastbit; /* last useful bit in the word */
277 xfs_rtblock_t len; /* length of inspected area */
278 xfs_rtword_t mask; /* mask of relevant bits for value */
279 xfs_rtword_t want; /* mask for "good" values */
280 xfs_rtword_t wdiff; /* difference from wanted value */
281 int word; /* word number in the buffer */
282
283 /*
284 * Compute and read in starting bitmap block for starting block.
285 */
286 block = XFS_BITTOBLOCK(mp, start);
287 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
288 if (error) {
289 return error;
290 }
291 bufp = bp->b_addr;
292 /*
293 * Get the first word's index & point to it.
294 */
295 word = XFS_BITTOWORD(mp, start);
296 b = &bufp[word];
297 bit = (int)(start & (XFS_NBWORD - 1));
298 len = limit - start + 1;
299 /*
300 * Compute match value, based on the bit at start: if 1 (free)
301 * then all-ones, else all-zeroes.
302 */
303 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
304 /*
305 * If the starting position is not word-aligned, deal with the
306 * partial word.
307 */
308 if (bit) {
309 /*
310 * Calculate last (rightmost) bit number to look at,
311 * and mask for all the relevant bits in this word.
312 */
313 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
314 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
315 /*
316 * Calculate the difference between the value there
317 * and what we're looking for.
318 */
319 if ((wdiff = (*b ^ want) & mask)) {
320 /*
321 * Different. Mark where we are and return.
322 */
323 xfs_trans_brelse(tp, bp);
324 i = XFS_RTLOBIT(wdiff) - bit;
325 *rtblock = start + i - 1;
326 return 0;
327 }
328 i = lastbit - bit;
329 /*
330 * Go on to next block if that's where the next word is
331 * and we need the next word.
332 */
333 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
334 /*
335 * If done with this block, get the previous one.
336 */
337 xfs_trans_brelse(tp, bp);
338 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
339 if (error) {
340 return error;
341 }
342 b = bufp = bp->b_addr;
343 word = 0;
344 } else {
345 /*
346 * Go on to the previous word in the buffer.
347 */
348 b++;
349 }
350 } else {
351 /*
352 * Starting on a word boundary, no partial word.
353 */
354 i = 0;
355 }
356 /*
357 * Loop over whole words in buffers. When we use up one buffer
358 * we move on to the next one.
359 */
360 while (len - i >= XFS_NBWORD) {
361 /*
362 * Compute difference between actual and desired value.
363 */
364 if ((wdiff = *b ^ want)) {
365 /*
366 * Different, mark where we are and return.
367 */
368 xfs_trans_brelse(tp, bp);
369 i += XFS_RTLOBIT(wdiff);
370 *rtblock = start + i - 1;
371 return 0;
372 }
373 i += XFS_NBWORD;
374 /*
375 * Go on to next block if that's where the next word is
376 * and we need the next word.
377 */
378 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
379 /*
380 * If done with this block, get the next one.
381 */
382 xfs_trans_brelse(tp, bp);
383 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
384 if (error) {
385 return error;
386 }
387 b = bufp = bp->b_addr;
388 word = 0;
389 } else {
390 /*
391 * Go on to the next word in the buffer.
392 */
393 b++;
394 }
395 }
396 /*
397 * If not ending on a word boundary, deal with the last
398 * (partial) word.
399 */
400 if ((lastbit = len - i)) {
401 /*
402 * Calculate mask for all the relevant bits in this word.
403 */
404 mask = ((xfs_rtword_t)1 << lastbit) - 1;
405 /*
406 * Compute difference between actual and desired value.
407 */
408 if ((wdiff = (*b ^ want) & mask)) {
409 /*
410 * Different, mark where we are and return.
411 */
412 xfs_trans_brelse(tp, bp);
413 i += XFS_RTLOBIT(wdiff);
414 *rtblock = start + i - 1;
415 return 0;
416 } else
417 i = len;
418 }
419 /*
420 * No match, return that we scanned the whole area.
421 */
422 xfs_trans_brelse(tp, bp);
423 *rtblock = start + i - 1;
424 return 0;
425}
426
427/*
428 * Read and modify the summary information for a given extent size,
429 * bitmap block combination.
430 * Keeps track of a current summary block, so we don't keep reading
431 * it from the buffer cache.
432 */
433int
434xfs_rtmodify_summary(
435 xfs_mount_t *mp, /* file system mount point */
436 xfs_trans_t *tp, /* transaction pointer */
437 int log, /* log2 of extent size */
438 xfs_rtblock_t bbno, /* bitmap block number */
439 int delta, /* change to make to summary info */
440 xfs_buf_t **rbpp, /* in/out: summary block buffer */
441 xfs_fsblock_t *rsb) /* in/out: summary block number */
442{
443 xfs_buf_t *bp; /* buffer for the summary block */
444 int error; /* error value */
445 xfs_fsblock_t sb; /* summary fsblock */
446 int so; /* index into the summary file */
447 xfs_suminfo_t *sp; /* pointer to returned data */
448
449 /*
450 * Compute entry number in the summary file.
451 */
452 so = XFS_SUMOFFS(mp, log, bbno);
453 /*
454 * Compute the block number in the summary file.
455 */
456 sb = XFS_SUMOFFSTOBLOCK(mp, so);
457 /*
458 * If we have an old buffer, and the block number matches, use that.
459 */
460 if (rbpp && *rbpp && *rsb == sb)
461 bp = *rbpp;
462 /*
463 * Otherwise we have to get the buffer.
464 */
465 else {
466 /*
467 * If there was an old one, get rid of it first.
468 */
469 if (rbpp && *rbpp)
470 xfs_trans_brelse(tp, *rbpp);
471 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
472 if (error) {
473 return error;
474 }
475 /*
476 * Remember this buffer and block for the next call.
477 */
478 if (rbpp) {
479 *rbpp = bp;
480 *rsb = sb;
481 }
482 }
483 /*
484 * Point to the summary information, modify and log it.
485 */
486 sp = XFS_SUMPTR(mp, bp, so);
487 *sp += delta;
488 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
489 (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
490 return 0;
491}
492
493/*
494 * Set the given range of bitmap bits to the given value.
495 * Do whatever I/O and logging is required.
496 */
497int
498xfs_rtmodify_range(
499 xfs_mount_t *mp, /* file system mount point */
500 xfs_trans_t *tp, /* transaction pointer */
501 xfs_rtblock_t start, /* starting block to modify */
502 xfs_extlen_t len, /* length of extent to modify */
503 int val) /* 1 for free, 0 for allocated */
504{
505 xfs_rtword_t *b; /* current word in buffer */
506 int bit; /* bit number in the word */
507 xfs_rtblock_t block; /* bitmap block number */
508 xfs_buf_t *bp; /* buf for the block */
509 xfs_rtword_t *bufp; /* starting word in buffer */
510 int error; /* error value */
511 xfs_rtword_t *first; /* first used word in the buffer */
512 int i; /* current bit number rel. to start */
513 int lastbit; /* last useful bit in word */
514 xfs_rtword_t mask; /* mask o frelevant bits for value */
515 int word; /* word number in the buffer */
516
517 /*
518 * Compute starting bitmap block number.
519 */
520 block = XFS_BITTOBLOCK(mp, start);
521 /*
522 * Read the bitmap block, and point to its data.
523 */
524 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
525 if (error) {
526 return error;
527 }
528 bufp = bp->b_addr;
529 /*
530 * Compute the starting word's address, and starting bit.
531 */
532 word = XFS_BITTOWORD(mp, start);
533 first = b = &bufp[word];
534 bit = (int)(start & (XFS_NBWORD - 1));
535 /*
536 * 0 (allocated) => all zeroes; 1 (free) => all ones.
537 */
538 val = -val;
539 /*
540 * If not starting on a word boundary, deal with the first
541 * (partial) word.
542 */
543 if (bit) {
544 /*
545 * Compute first bit not changed and mask of relevant bits.
546 */
547 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
548 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
549 /*
550 * Set/clear the active bits.
551 */
552 if (val)
553 *b |= mask;
554 else
555 *b &= ~mask;
556 i = lastbit - bit;
557 /*
558 * Go on to the next block if that's where the next word is
559 * and we need the next word.
560 */
561 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
562 /*
563 * Log the changed part of this block.
564 * Get the next one.
565 */
566 xfs_trans_log_buf(tp, bp,
567 (uint)((char *)first - (char *)bufp),
568 (uint)((char *)b - (char *)bufp));
569 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
570 if (error) {
571 return error;
572 }
573 first = b = bufp = bp->b_addr;
574 word = 0;
575 } else {
576 /*
577 * Go on to the next word in the buffer
578 */
579 b++;
580 }
581 } else {
582 /*
583 * Starting on a word boundary, no partial word.
584 */
585 i = 0;
586 }
587 /*
588 * Loop over whole words in buffers. When we use up one buffer
589 * we move on to the next one.
590 */
591 while (len - i >= XFS_NBWORD) {
592 /*
593 * Set the word value correctly.
594 */
595 *b = val;
596 i += XFS_NBWORD;
597 /*
598 * Go on to the next block if that's where the next word is
599 * and we need the next word.
600 */
601 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
602 /*
603 * Log the changed part of this block.
604 * Get the next one.
605 */
606 xfs_trans_log_buf(tp, bp,
607 (uint)((char *)first - (char *)bufp),
608 (uint)((char *)b - (char *)bufp));
609 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
610 if (error) {
611 return error;
612 }
613 first = b = bufp = bp->b_addr;
614 word = 0;
615 } else {
616 /*
617 * Go on to the next word in the buffer
618 */
619 b++;
620 }
621 }
622 /*
623 * If not ending on a word boundary, deal with the last
624 * (partial) word.
625 */
626 if ((lastbit = len - i)) {
627 /*
628 * Compute a mask of relevant bits.
629 */
630 bit = 0;
631 mask = ((xfs_rtword_t)1 << lastbit) - 1;
632 /*
633 * Set/clear the active bits.
634 */
635 if (val)
636 *b |= mask;
637 else
638 *b &= ~mask;
639 b++;
640 }
641 /*
642 * Log any remaining changed bytes.
643 */
644 if (b > first)
645 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
646 (uint)((char *)b - (char *)bufp - 1));
647 return 0;
648}
649
650/*
651 * Mark an extent specified by start and len freed.
652 * Updates all the summary information as well as the bitmap.
653 */
654int
655xfs_rtfree_range(
656 xfs_mount_t *mp, /* file system mount point */
657 xfs_trans_t *tp, /* transaction pointer */
658 xfs_rtblock_t start, /* starting block to free */
659 xfs_extlen_t len, /* length to free */
660 xfs_buf_t **rbpp, /* in/out: summary block buffer */
661 xfs_fsblock_t *rsb) /* in/out: summary block number */
662{
663 xfs_rtblock_t end; /* end of the freed extent */
664 int error; /* error value */
665 xfs_rtblock_t postblock; /* first block freed > end */
666 xfs_rtblock_t preblock; /* first block freed < start */
667
668 end = start + len - 1;
669 /*
670 * Modify the bitmap to mark this extent freed.
671 */
672 error = xfs_rtmodify_range(mp, tp, start, len, 1);
673 if (error) {
674 return error;
675 }
676 /*
677 * Assume we're freeing out of the middle of an allocated extent.
678 * We need to find the beginning and end of the extent so we can
679 * properly update the summary.
680 */
681 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
682 if (error) {
683 return error;
684 }
685 /*
686 * Find the next allocated block (end of allocated extent).
687 */
688 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
689 &postblock);
690 if (error)
691 return error;
692 /*
693 * If there are blocks not being freed at the front of the
694 * old extent, add summary data for them to be allocated.
695 */
696 if (preblock < start) {
697 error = xfs_rtmodify_summary(mp, tp,
698 XFS_RTBLOCKLOG(start - preblock),
699 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
700 if (error) {
701 return error;
702 }
703 }
704 /*
705 * If there are blocks not being freed at the end of the
706 * old extent, add summary data for them to be allocated.
707 */
708 if (postblock > end) {
709 error = xfs_rtmodify_summary(mp, tp,
710 XFS_RTBLOCKLOG(postblock - end),
711 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
712 if (error) {
713 return error;
714 }
715 }
716 /*
717 * Increment the summary information corresponding to the entire
718 * (new) free extent.
719 */
720 error = xfs_rtmodify_summary(mp, tp,
721 XFS_RTBLOCKLOG(postblock + 1 - preblock),
722 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
723 return error;
724}
725
726/*
727 * Check that the given range is either all allocated (val = 0) or
728 * all free (val = 1).
729 */
730int
731xfs_rtcheck_range(
732 xfs_mount_t *mp, /* file system mount point */
733 xfs_trans_t *tp, /* transaction pointer */
734 xfs_rtblock_t start, /* starting block number of extent */
735 xfs_extlen_t len, /* length of extent */
736 int val, /* 1 for free, 0 for allocated */
737 xfs_rtblock_t *new, /* out: first block not matching */
738 int *stat) /* out: 1 for matches, 0 for not */
739{
740 xfs_rtword_t *b; /* current word in buffer */
741 int bit; /* bit number in the word */
742 xfs_rtblock_t block; /* bitmap block number */
743 xfs_buf_t *bp; /* buf for the block */
744 xfs_rtword_t *bufp; /* starting word in buffer */
745 int error; /* error value */
746 xfs_rtblock_t i; /* current bit number rel. to start */
747 xfs_rtblock_t lastbit; /* last useful bit in word */
748 xfs_rtword_t mask; /* mask of relevant bits for value */
749 xfs_rtword_t wdiff; /* difference from wanted value */
750 int word; /* word number in the buffer */
751
752 /*
753 * Compute starting bitmap block number
754 */
755 block = XFS_BITTOBLOCK(mp, start);
756 /*
757 * Read the bitmap block.
758 */
759 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
760 if (error) {
761 return error;
762 }
763 bufp = bp->b_addr;
764 /*
765 * Compute the starting word's address, and starting bit.
766 */
767 word = XFS_BITTOWORD(mp, start);
768 b = &bufp[word];
769 bit = (int)(start & (XFS_NBWORD - 1));
770 /*
771 * 0 (allocated) => all zero's; 1 (free) => all one's.
772 */
773 val = -val;
774 /*
775 * If not starting on a word boundary, deal with the first
776 * (partial) word.
777 */
778 if (bit) {
779 /*
780 * Compute first bit not examined.
781 */
782 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
783 /*
784 * Mask of relevant bits.
785 */
786 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
787 /*
788 * Compute difference between actual and desired value.
789 */
790 if ((wdiff = (*b ^ val) & mask)) {
791 /*
792 * Different, compute first wrong bit and return.
793 */
794 xfs_trans_brelse(tp, bp);
795 i = XFS_RTLOBIT(wdiff) - bit;
796 *new = start + i;
797 *stat = 0;
798 return 0;
799 }
800 i = lastbit - bit;
801 /*
802 * Go on to next block if that's where the next word is
803 * and we need the next word.
804 */
805 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
806 /*
807 * If done with this block, get the next one.
808 */
809 xfs_trans_brelse(tp, bp);
810 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
811 if (error) {
812 return error;
813 }
814 b = bufp = bp->b_addr;
815 word = 0;
816 } else {
817 /*
818 * Go on to the next word in the buffer.
819 */
820 b++;
821 }
822 } else {
823 /*
824 * Starting on a word boundary, no partial word.
825 */
826 i = 0;
827 }
828 /*
829 * Loop over whole words in buffers. When we use up one buffer
830 * we move on to the next one.
831 */
832 while (len - i >= XFS_NBWORD) {
833 /*
834 * Compute difference between actual and desired value.
835 */
836 if ((wdiff = *b ^ val)) {
837 /*
838 * Different, compute first wrong bit and return.
839 */
840 xfs_trans_brelse(tp, bp);
841 i += XFS_RTLOBIT(wdiff);
842 *new = start + i;
843 *stat = 0;
844 return 0;
845 }
846 i += XFS_NBWORD;
847 /*
848 * Go on to next block if that's where the next word is
849 * and we need the next word.
850 */
851 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
852 /*
853 * If done with this block, get the next one.
854 */
855 xfs_trans_brelse(tp, bp);
856 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
857 if (error) {
858 return error;
859 }
860 b = bufp = bp->b_addr;
861 word = 0;
862 } else {
863 /*
864 * Go on to the next word in the buffer.
865 */
866 b++;
867 }
868 }
869 /*
870 * If not ending on a word boundary, deal with the last
871 * (partial) word.
872 */
873 if ((lastbit = len - i)) {
874 /*
875 * Mask of relevant bits.
876 */
877 mask = ((xfs_rtword_t)1 << lastbit) - 1;
878 /*
879 * Compute difference between actual and desired value.
880 */
881 if ((wdiff = (*b ^ val) & mask)) {
882 /*
883 * Different, compute first wrong bit and return.
884 */
885 xfs_trans_brelse(tp, bp);
886 i += XFS_RTLOBIT(wdiff);
887 *new = start + i;
888 *stat = 0;
889 return 0;
890 } else
891 i = len;
892 }
893 /*
894 * Successful, return.
895 */
896 xfs_trans_brelse(tp, bp);
897 *new = start + i;
898 *stat = 1;
899 return 0;
900}
901
902#ifdef DEBUG
903/*
904 * Check that the given extent (block range) is allocated already.
905 */
906STATIC int /* error */
907xfs_rtcheck_alloc_range(
908 xfs_mount_t *mp, /* file system mount point */
909 xfs_trans_t *tp, /* transaction pointer */
910 xfs_rtblock_t bno, /* starting block number of extent */
911 xfs_extlen_t len) /* length of extent */
912{
913 xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
914 int stat;
915 int error;
916
917 error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
918 if (error)
919 return error;
920 ASSERT(stat);
921 return 0;
922}
923#else
924#define xfs_rtcheck_alloc_range(m,t,b,l) (0)
925#endif
926/*
927 * Free an extent in the realtime subvolume. Length is expressed in
928 * realtime extents, as is the block number.
929 */
930int /* error */
931xfs_rtfree_extent(
932 xfs_trans_t *tp, /* transaction pointer */
933 xfs_rtblock_t bno, /* starting block number to free */
934 xfs_extlen_t len) /* length of extent freed */
935{
936 int error; /* error value */
937 xfs_mount_t *mp; /* file system mount structure */
938 xfs_fsblock_t sb; /* summary file block number */
939 xfs_buf_t *sumbp = NULL; /* summary file block buffer */
940
941 mp = tp->t_mountp;
942
943 ASSERT(mp->m_rbmip->i_itemp != NULL);
944 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
945
946 error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
947 if (error)
948 return error;
949
950 /*
951 * Free the range of realtime blocks.
952 */
953 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
954 if (error) {
955 return error;
956 }
957 /*
958 * Mark more blocks free in the superblock.
959 */
960 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
961 /*
962 * If we've now freed all the blocks, reset the file sequence
963 * number to 0.
964 */
965 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
966 mp->m_sb.sb_rextents) {
967 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
968 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
969 *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
970 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
971 }
972 return 0;
973}
974
diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c
index a5b59d92eb70..b7c9aea77f8f 100644
--- a/fs/xfs/xfs_sb.c
+++ b/fs/xfs/xfs_sb.c
@@ -17,34 +17,26 @@
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"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
21#include "xfs_bit.h" 24#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_trans_priv.h"
26#include "xfs_sb.h" 25#include "xfs_sb.h"
27#include "xfs_ag.h" 26#include "xfs_ag.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_da_btree.h"
30#include "xfs_dir2_format.h"
31#include "xfs_dir2.h"
32#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h"
35#include "xfs_dinode.h"
36#include "xfs_inode.h" 28#include "xfs_inode.h"
37#include "xfs_btree.h"
38#include "xfs_ialloc.h" 29#include "xfs_ialloc.h"
39#include "xfs_alloc.h" 30#include "xfs_alloc.h"
40#include "xfs_rtalloc.h"
41#include "xfs_bmap.h"
42#include "xfs_error.h" 31#include "xfs_error.h"
43#include "xfs_quota.h"
44#include "xfs_fsops.h"
45#include "xfs_trace.h" 32#include "xfs_trace.h"
46#include "xfs_cksum.h" 33#include "xfs_cksum.h"
34#include "xfs_trans.h"
47#include "xfs_buf_item.h" 35#include "xfs_buf_item.h"
36#include "xfs_dinode.h"
37#include "xfs_bmap_btree.h"
38#include "xfs_alloc_btree.h"
39#include "xfs_ialloc_btree.h"
48 40
49/* 41/*
50 * Physical superblock buffer manipulations. Shared with libxfs in userspace. 42 * Physical superblock buffer manipulations. Shared with libxfs in userspace.
@@ -249,13 +241,13 @@ xfs_mount_validate_sb(
249 if (xfs_sb_version_has_pquotino(sbp)) { 241 if (xfs_sb_version_has_pquotino(sbp)) {
250 if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) { 242 if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
251 xfs_notice(mp, 243 xfs_notice(mp,
252 "Version 5 of Super block has XFS_OQUOTA bits.\n"); 244 "Version 5 of Super block has XFS_OQUOTA bits.");
253 return XFS_ERROR(EFSCORRUPTED); 245 return XFS_ERROR(EFSCORRUPTED);
254 } 246 }
255 } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD | 247 } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
256 XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) { 248 XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
257 xfs_notice(mp, 249 xfs_notice(mp,
258"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n"); 250"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.");
259 return XFS_ERROR(EFSCORRUPTED); 251 return XFS_ERROR(EFSCORRUPTED);
260 } 252 }
261 253
@@ -596,6 +588,11 @@ xfs_sb_verify(
596 * single bit error could clear the feature bit and unused parts of the 588 * single bit error could clear the feature bit and unused parts of the
597 * superblock are supposed to be zero. Hence a non-null crc field indicates that 589 * superblock are supposed to be zero. Hence a non-null crc field indicates that
598 * we've potentially lost a feature bit and we should check it anyway. 590 * we've potentially lost a feature bit and we should check it anyway.
591 *
592 * However, past bugs (i.e. in growfs) left non-zeroed regions beyond the
593 * last field in V4 secondary superblocks. So for secondary superblocks,
594 * we are more forgiving, and ignore CRC failures if the primary doesn't
595 * indicate that the fs version is V5.
599 */ 596 */
600static void 597static void
601xfs_sb_read_verify( 598xfs_sb_read_verify(
@@ -616,16 +613,21 @@ xfs_sb_read_verify(
616 613
617 if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), 614 if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize),
618 offsetof(struct xfs_sb, sb_crc))) { 615 offsetof(struct xfs_sb, sb_crc))) {
619 error = EFSCORRUPTED; 616 /* Only fail bad secondaries on a known V5 filesystem */
620 goto out_error; 617 if (bp->b_bn != XFS_SB_DADDR &&
618 xfs_sb_version_hascrc(&mp->m_sb)) {
619 error = EFSCORRUPTED;
620 goto out_error;
621 }
621 } 622 }
622 } 623 }
623 error = xfs_sb_verify(bp, true); 624 error = xfs_sb_verify(bp, true);
624 625
625out_error: 626out_error:
626 if (error) { 627 if (error) {
627 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, 628 if (error != EWRONGFS)
628 mp, bp->b_addr); 629 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
630 mp, bp->b_addr);
629 xfs_buf_ioerror(bp, error); 631 xfs_buf_ioerror(bp, error);
630 } 632 }
631} 633}
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 6835b44f850e..35061d4b614c 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -699,7 +699,4 @@ extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
699extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t); 699extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t);
700extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp); 700extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp);
701 701
702extern const struct xfs_buf_ops xfs_sb_buf_ops;
703extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
704
705#endif /* __XFS_SB_H__ */ 702#endif /* __XFS_SB_H__ */
diff --git a/fs/xfs/xfs_shared.h b/fs/xfs/xfs_shared.h
new file mode 100644
index 000000000000..8c5035a13df1
--- /dev/null
+++ b/fs/xfs/xfs_shared.h
@@ -0,0 +1,244 @@
1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * Copyright (c) 2013 Red Hat, Inc.
4 * All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#ifndef __XFS_SHARED_H__
20#define __XFS_SHARED_H__
21
22/*
23 * Definitions shared between kernel and userspace that don't fit into any other
24 * header file that is shared with userspace.
25 */
26struct xfs_ifork;
27struct xfs_buf;
28struct xfs_buf_ops;
29struct xfs_mount;
30struct xfs_trans;
31struct xfs_inode;
32
33/*
34 * Buffer verifier operations are widely used, including userspace tools
35 */
36extern const struct xfs_buf_ops xfs_agf_buf_ops;
37extern const struct xfs_buf_ops xfs_agi_buf_ops;
38extern const struct xfs_buf_ops xfs_agf_buf_ops;
39extern const struct xfs_buf_ops xfs_agfl_buf_ops;
40extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
41extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
42extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
43extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
44extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
45extern const struct xfs_buf_ops xfs_dquot_buf_ops;
46extern const struct xfs_buf_ops xfs_symlink_buf_ops;
47extern const struct xfs_buf_ops xfs_agi_buf_ops;
48extern const struct xfs_buf_ops xfs_inobt_buf_ops;
49extern const struct xfs_buf_ops xfs_inode_buf_ops;
50extern const struct xfs_buf_ops xfs_inode_buf_ra_ops;
51extern const struct xfs_buf_ops xfs_dquot_buf_ops;
52extern const struct xfs_buf_ops xfs_sb_buf_ops;
53extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
54extern const struct xfs_buf_ops xfs_symlink_buf_ops;
55
56/*
57 * Transaction types. Used to distinguish types of buffers. These never reach
58 * the log.
59 */
60#define XFS_TRANS_SETATTR_NOT_SIZE 1
61#define XFS_TRANS_SETATTR_SIZE 2
62#define XFS_TRANS_INACTIVE 3
63#define XFS_TRANS_CREATE 4
64#define XFS_TRANS_CREATE_TRUNC 5
65#define XFS_TRANS_TRUNCATE_FILE 6
66#define XFS_TRANS_REMOVE 7
67#define XFS_TRANS_LINK 8
68#define XFS_TRANS_RENAME 9
69#define XFS_TRANS_MKDIR 10
70#define XFS_TRANS_RMDIR 11
71#define XFS_TRANS_SYMLINK 12
72#define XFS_TRANS_SET_DMATTRS 13
73#define XFS_TRANS_GROWFS 14
74#define XFS_TRANS_STRAT_WRITE 15
75#define XFS_TRANS_DIOSTRAT 16
76/* 17 was XFS_TRANS_WRITE_SYNC */
77#define XFS_TRANS_WRITEID 18
78#define XFS_TRANS_ADDAFORK 19
79#define XFS_TRANS_ATTRINVAL 20
80#define XFS_TRANS_ATRUNCATE 21
81#define XFS_TRANS_ATTR_SET 22
82#define XFS_TRANS_ATTR_RM 23
83#define XFS_TRANS_ATTR_FLAG 24
84#define XFS_TRANS_CLEAR_AGI_BUCKET 25
85#define XFS_TRANS_QM_SBCHANGE 26
86/*
87 * Dummy entries since we use the transaction type to index into the
88 * trans_type[] in xlog_recover_print_trans_head()
89 */
90#define XFS_TRANS_DUMMY1 27
91#define XFS_TRANS_DUMMY2 28
92#define XFS_TRANS_QM_QUOTAOFF 29
93#define XFS_TRANS_QM_DQALLOC 30
94#define XFS_TRANS_QM_SETQLIM 31
95#define XFS_TRANS_QM_DQCLUSTER 32
96#define XFS_TRANS_QM_QINOCREATE 33
97#define XFS_TRANS_QM_QUOTAOFF_END 34
98#define XFS_TRANS_SB_UNIT 35
99#define XFS_TRANS_FSYNC_TS 36
100#define XFS_TRANS_GROWFSRT_ALLOC 37
101#define XFS_TRANS_GROWFSRT_ZERO 38
102#define XFS_TRANS_GROWFSRT_FREE 39
103#define XFS_TRANS_SWAPEXT 40
104#define XFS_TRANS_SB_COUNT 41
105#define XFS_TRANS_CHECKPOINT 42
106#define XFS_TRANS_ICREATE 43
107#define XFS_TRANS_TYPE_MAX 43
108/* new transaction types need to be reflected in xfs_logprint(8) */
109
110#define XFS_TRANS_TYPES \
111 { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \
112 { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \
113 { XFS_TRANS_INACTIVE, "INACTIVE" }, \
114 { XFS_TRANS_CREATE, "CREATE" }, \
115 { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \
116 { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \
117 { XFS_TRANS_REMOVE, "REMOVE" }, \
118 { XFS_TRANS_LINK, "LINK" }, \
119 { XFS_TRANS_RENAME, "RENAME" }, \
120 { XFS_TRANS_MKDIR, "MKDIR" }, \
121 { XFS_TRANS_RMDIR, "RMDIR" }, \
122 { XFS_TRANS_SYMLINK, "SYMLINK" }, \
123 { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \
124 { XFS_TRANS_GROWFS, "GROWFS" }, \
125 { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \
126 { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \
127 { XFS_TRANS_WRITEID, "WRITEID" }, \
128 { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \
129 { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \
130 { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \
131 { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \
132 { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \
133 { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \
134 { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \
135 { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \
136 { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \
137 { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \
138 { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \
139 { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \
140 { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \
141 { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \
142 { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \
143 { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \
144 { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \
145 { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \
146 { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \
147 { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \
148 { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \
149 { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \
150 { XFS_TRANS_DUMMY1, "DUMMY1" }, \
151 { XFS_TRANS_DUMMY2, "DUMMY2" }, \
152 { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" }
153
154/*
155 * This structure is used to track log items associated with
156 * a transaction. It points to the log item and keeps some
157 * flags to track the state of the log item. It also tracks
158 * the amount of space needed to log the item it describes
159 * once we get to commit processing (see xfs_trans_commit()).
160 */
161struct xfs_log_item_desc {
162 struct xfs_log_item *lid_item;
163 struct list_head lid_trans;
164 unsigned char lid_flags;
165};
166
167#define XFS_LID_DIRTY 0x1
168
169/* log size calculation functions */
170int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes);
171int xfs_log_calc_minimum_size(struct xfs_mount *);
172
173
174/*
175 * Values for t_flags.
176 */
177#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */
178#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */
179#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */
180#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */
181#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */
182#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */
183#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer
184 count in superblock */
185/*
186 * Values for call flags parameter.
187 */
188#define XFS_TRANS_RELEASE_LOG_RES 0x4
189#define XFS_TRANS_ABORT 0x8
190
191/*
192 * Field values for xfs_trans_mod_sb.
193 */
194#define XFS_TRANS_SB_ICOUNT 0x00000001
195#define XFS_TRANS_SB_IFREE 0x00000002
196#define XFS_TRANS_SB_FDBLOCKS 0x00000004
197#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008
198#define XFS_TRANS_SB_FREXTENTS 0x00000010
199#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020
200#define XFS_TRANS_SB_DBLOCKS 0x00000040
201#define XFS_TRANS_SB_AGCOUNT 0x00000080
202#define XFS_TRANS_SB_IMAXPCT 0x00000100
203#define XFS_TRANS_SB_REXTSIZE 0x00000200
204#define XFS_TRANS_SB_RBMBLOCKS 0x00000400
205#define XFS_TRANS_SB_RBLOCKS 0x00000800
206#define XFS_TRANS_SB_REXTENTS 0x00001000
207#define XFS_TRANS_SB_REXTSLOG 0x00002000
208
209/*
210 * Here we centralize the specification of XFS meta-data buffer reference count
211 * values. This determines how hard the buffer cache tries to hold onto the
212 * buffer.
213 */
214#define XFS_AGF_REF 4
215#define XFS_AGI_REF 4
216#define XFS_AGFL_REF 3
217#define XFS_INO_BTREE_REF 3
218#define XFS_ALLOC_BTREE_REF 2
219#define XFS_BMAP_BTREE_REF 2
220#define XFS_DIR_BTREE_REF 2
221#define XFS_INO_REF 2
222#define XFS_ATTR_BTREE_REF 1
223#define XFS_DQUOT_REF 1
224
225/*
226 * Flags for xfs_trans_ichgtime().
227 */
228#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */
229#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */
230#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */
231
232
233/*
234 * Symlink decoding/encoding functions
235 */
236int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
237int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
238 uint32_t size, struct xfs_buf *bp);
239bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
240 uint32_t size, struct xfs_buf *bp);
241void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
242 struct xfs_inode *ip, struct xfs_ifork *ifp);
243
244#endif /* __XFS_SHARED_H__ */
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 8968f5036fa1..f317488263dd 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -17,34 +17,26 @@
17 */ 17 */
18 18
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_shared.h"
20#include "xfs_format.h" 21#include "xfs_format.h"
21#include "xfs_log.h" 22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
22#include "xfs_inum.h" 24#include "xfs_inum.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_alloc.h"
27#include "xfs_quota.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_bmap_btree.h" 28#include "xfs_da_format.h"
30#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_dinode.h"
33#include "xfs_inode.h" 29#include "xfs_inode.h"
34#include "xfs_btree.h" 30#include "xfs_btree.h"
35#include "xfs_ialloc.h"
36#include "xfs_bmap.h" 31#include "xfs_bmap.h"
37#include "xfs_rtalloc.h" 32#include "xfs_alloc.h"
38#include "xfs_error.h" 33#include "xfs_error.h"
39#include "xfs_itable.h"
40#include "xfs_fsops.h" 34#include "xfs_fsops.h"
41#include "xfs_attr.h" 35#include "xfs_trans.h"
42#include "xfs_buf_item.h" 36#include "xfs_buf_item.h"
37#include "xfs_log.h"
43#include "xfs_log_priv.h" 38#include "xfs_log_priv.h"
44#include "xfs_trans_priv.h"
45#include "xfs_filestream.h"
46#include "xfs_da_btree.h" 39#include "xfs_da_btree.h"
47#include "xfs_dir2_format.h"
48#include "xfs_dir2.h" 40#include "xfs_dir2.h"
49#include "xfs_extfree_item.h" 41#include "xfs_extfree_item.h"
50#include "xfs_mru_cache.h" 42#include "xfs_mru_cache.h"
@@ -52,6 +44,9 @@
52#include "xfs_icache.h" 44#include "xfs_icache.h"
53#include "xfs_trace.h" 45#include "xfs_trace.h"
54#include "xfs_icreate_item.h" 46#include "xfs_icreate_item.h"
47#include "xfs_dinode.h"
48#include "xfs_filestream.h"
49#include "xfs_quota.h"
55 50
56#include <linux/namei.h> 51#include <linux/namei.h>
57#include <linux/init.h> 52#include <linux/init.h>
@@ -946,10 +941,6 @@ xfs_fs_destroy_inode(
946 941
947 XFS_STATS_INC(vn_reclaim); 942 XFS_STATS_INC(vn_reclaim);
948 943
949 /* bad inode, get out here ASAP */
950 if (is_bad_inode(inode))
951 goto out_reclaim;
952
953 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); 944 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
954 945
955 /* 946 /*
@@ -965,7 +956,6 @@ xfs_fs_destroy_inode(
965 * this more efficiently than we can here, so simply let background 956 * this more efficiently than we can here, so simply let background
966 * reclaim tear down all inodes. 957 * reclaim tear down all inodes.
967 */ 958 */
968out_reclaim:
969 xfs_inode_set_reclaim_tag(ip); 959 xfs_inode_set_reclaim_tag(ip);
970} 960}
971 961
@@ -1165,7 +1155,7 @@ xfs_restore_resvblks(struct xfs_mount *mp)
1165 * Note: xfs_log_quiesce() stops background log work - the callers must ensure 1155 * Note: xfs_log_quiesce() stops background log work - the callers must ensure
1166 * it is started again when appropriate. 1156 * it is started again when appropriate.
1167 */ 1157 */
1168void 1158static void
1169xfs_quiesce_attr( 1159xfs_quiesce_attr(
1170 struct xfs_mount *mp) 1160 struct xfs_mount *mp)
1171{ 1161{
@@ -1246,7 +1236,7 @@ xfs_fs_remount(
1246 */ 1236 */
1247#if 0 1237#if 0
1248 xfs_info(mp, 1238 xfs_info(mp,
1249 "mount option \"%s\" not supported for remount\n", p); 1239 "mount option \"%s\" not supported for remount", p);
1250 return -EINVAL; 1240 return -EINVAL;
1251#else 1241#else
1252 break; 1242 break;
@@ -1491,10 +1481,6 @@ xfs_fs_fill_super(
1491 error = ENOENT; 1481 error = ENOENT;
1492 goto out_unmount; 1482 goto out_unmount;
1493 } 1483 }
1494 if (is_bad_inode(root)) {
1495 error = EINVAL;
1496 goto out_unmount;
1497 }
1498 sb->s_root = d_make_root(root); 1484 sb->s_root = d_make_root(root);
1499 if (!sb->s_root) { 1485 if (!sb->s_root) {
1500 error = ENOMEM; 1486 error = ENOMEM;
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index f622a97a7e33..14e58f2c96bd 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -17,31 +17,31 @@
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_shared.h"
20#include "xfs_fs.h" 21#include "xfs_fs.h"
21#include "xfs_format.h" 22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
22#include "xfs_bit.h" 25#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
28#include "xfs_da_btree.h" 29#include "xfs_da_format.h"
29#include "xfs_dir2_format.h"
30#include "xfs_dir2.h" 30#include "xfs_dir2.h"
31#include "xfs_bmap_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_dinode.h"
34#include "xfs_inode.h" 31#include "xfs_inode.h"
35#include "xfs_ialloc.h" 32#include "xfs_ialloc.h"
36#include "xfs_alloc.h" 33#include "xfs_alloc.h"
37#include "xfs_bmap.h" 34#include "xfs_bmap.h"
35#include "xfs_bmap_btree.h"
38#include "xfs_bmap_util.h" 36#include "xfs_bmap_util.h"
39#include "xfs_error.h" 37#include "xfs_error.h"
40#include "xfs_quota.h" 38#include "xfs_quota.h"
41#include "xfs_trans_space.h" 39#include "xfs_trans_space.h"
42#include "xfs_trace.h" 40#include "xfs_trace.h"
43#include "xfs_symlink.h" 41#include "xfs_symlink.h"
44#include "xfs_buf_item.h" 42#include "xfs_trans.h"
43#include "xfs_log.h"
44#include "xfs_dinode.h"
45 45
46/* ----- Kernel only functions below ----- */ 46/* ----- Kernel only functions below ----- */
47STATIC int 47STATIC int
@@ -424,8 +424,7 @@ xfs_symlink(
424 */ 424 */
425STATIC int 425STATIC int
426xfs_inactive_symlink_rmt( 426xfs_inactive_symlink_rmt(
427 xfs_inode_t *ip, 427 struct xfs_inode *ip)
428 xfs_trans_t **tpp)
429{ 428{
430 xfs_buf_t *bp; 429 xfs_buf_t *bp;
431 int committed; 430 int committed;
@@ -437,11 +436,9 @@ xfs_inactive_symlink_rmt(
437 xfs_mount_t *mp; 436 xfs_mount_t *mp;
438 xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; 437 xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
439 int nmaps; 438 int nmaps;
440 xfs_trans_t *ntp;
441 int size; 439 int size;
442 xfs_trans_t *tp; 440 xfs_trans_t *tp;
443 441
444 tp = *tpp;
445 mp = ip->i_mount; 442 mp = ip->i_mount;
446 ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS); 443 ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS);
447 /* 444 /*
@@ -453,6 +450,16 @@ xfs_inactive_symlink_rmt(
453 */ 450 */
454 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); 451 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
455 452
453 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
454 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
455 if (error) {
456 xfs_trans_cancel(tp, 0);
457 return error;
458 }
459
460 xfs_ilock(ip, XFS_ILOCK_EXCL);
461 xfs_trans_ijoin(tp, ip, 0);
462
456 /* 463 /*
457 * Lock the inode, fix the size, and join it to the transaction. 464 * Lock the inode, fix the size, and join it to the transaction.
458 * Hold it so in the normal path, we still have it locked for 465 * Hold it so in the normal path, we still have it locked for
@@ -471,7 +478,7 @@ xfs_inactive_symlink_rmt(
471 error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), 478 error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size),
472 mval, &nmaps, 0); 479 mval, &nmaps, 0);
473 if (error) 480 if (error)
474 goto error0; 481 goto error_trans_cancel;
475 /* 482 /*
476 * Invalidate the block(s). No validation is done. 483 * Invalidate the block(s). No validation is done.
477 */ 484 */
@@ -481,22 +488,24 @@ xfs_inactive_symlink_rmt(
481 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0); 488 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
482 if (!bp) { 489 if (!bp) {
483 error = ENOMEM; 490 error = ENOMEM;
484 goto error1; 491 goto error_bmap_cancel;
485 } 492 }
486 xfs_trans_binval(tp, bp); 493 xfs_trans_binval(tp, bp);
487 } 494 }
488 /* 495 /*
489 * Unmap the dead block(s) to the free_list. 496 * Unmap the dead block(s) to the free_list.
490 */ 497 */
491 if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, 498 error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
492 &first_block, &free_list, &done))) 499 &first_block, &free_list, &done);
493 goto error1; 500 if (error)
501 goto error_bmap_cancel;
494 ASSERT(done); 502 ASSERT(done);
495 /* 503 /*
496 * Commit the first transaction. This logs the EFI and the inode. 504 * Commit the first transaction. This logs the EFI and the inode.
497 */ 505 */
498 if ((error = xfs_bmap_finish(&tp, &free_list, &committed))) 506 error = xfs_bmap_finish(&tp, &free_list, &committed);
499 goto error1; 507 if (error)
508 goto error_bmap_cancel;
500 /* 509 /*
501 * The transaction must have been committed, since there were 510 * The transaction must have been committed, since there were
502 * actually extents freed by xfs_bunmapi. See xfs_bmap_finish. 511 * actually extents freed by xfs_bunmapi. See xfs_bmap_finish.
@@ -511,26 +520,13 @@ xfs_inactive_symlink_rmt(
511 xfs_trans_ijoin(tp, ip, 0); 520 xfs_trans_ijoin(tp, ip, 0);
512 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 521 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
513 /* 522 /*
514 * Get a new, empty transaction to return to our caller.
515 */
516 ntp = xfs_trans_dup(tp);
517 /*
518 * Commit the transaction containing extent freeing and EFDs. 523 * Commit the transaction containing extent freeing and EFDs.
519 * If we get an error on the commit here or on the reserve below,
520 * we need to unlock the inode since the new transaction doesn't
521 * have the inode attached.
522 */ 524 */
523 error = xfs_trans_commit(tp, 0); 525 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
524 tp = ntp;
525 if (error) { 526 if (error) {
526 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 527 ASSERT(XFS_FORCED_SHUTDOWN(mp));
527 goto error0; 528 goto error_unlock;
528 } 529 }
529 /*
530 * transaction commit worked ok so we can drop the extra ticket
531 * reference that we gained in xfs_trans_dup()
532 */
533 xfs_log_ticket_put(tp->t_ticket);
534 530
535 /* 531 /*
536 * Remove the memory for extent descriptions (just bookkeeping). 532 * Remove the memory for extent descriptions (just bookkeeping).
@@ -538,23 +534,16 @@ xfs_inactive_symlink_rmt(
538 if (ip->i_df.if_bytes) 534 if (ip->i_df.if_bytes)
539 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK); 535 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
540 ASSERT(ip->i_df.if_bytes == 0); 536 ASSERT(ip->i_df.if_bytes == 0);
541 /*
542 * Put an itruncate log reservation in the new transaction
543 * for our caller.
544 */
545 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
546 if (error) {
547 ASSERT(XFS_FORCED_SHUTDOWN(mp));
548 goto error0;
549 }
550 537
551 xfs_trans_ijoin(tp, ip, 0); 538 xfs_iunlock(ip, XFS_ILOCK_EXCL);
552 *tpp = tp;
553 return 0; 539 return 0;
554 540
555 error1: 541error_bmap_cancel:
556 xfs_bmap_cancel(&free_list); 542 xfs_bmap_cancel(&free_list);
557 error0: 543error_trans_cancel:
544 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
545error_unlock:
546 xfs_iunlock(ip, XFS_ILOCK_EXCL);
558 return error; 547 return error;
559} 548}
560 549
@@ -563,41 +552,46 @@ xfs_inactive_symlink_rmt(
563 */ 552 */
564int 553int
565xfs_inactive_symlink( 554xfs_inactive_symlink(
566 struct xfs_inode *ip, 555 struct xfs_inode *ip)
567 struct xfs_trans **tp)
568{ 556{
569 struct xfs_mount *mp = ip->i_mount; 557 struct xfs_mount *mp = ip->i_mount;
570 int pathlen; 558 int pathlen;
571 559
572 trace_xfs_inactive_symlink(ip); 560 trace_xfs_inactive_symlink(ip);
573 561
574 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
575
576 if (XFS_FORCED_SHUTDOWN(mp)) 562 if (XFS_FORCED_SHUTDOWN(mp))
577 return XFS_ERROR(EIO); 563 return XFS_ERROR(EIO);
578 564
565 xfs_ilock(ip, XFS_ILOCK_EXCL);
566
579 /* 567 /*
580 * Zero length symlinks _can_ exist. 568 * Zero length symlinks _can_ exist.
581 */ 569 */
582 pathlen = (int)ip->i_d.di_size; 570 pathlen = (int)ip->i_d.di_size;
583 if (!pathlen) 571 if (!pathlen) {
572 xfs_iunlock(ip, XFS_ILOCK_EXCL);
584 return 0; 573 return 0;
574 }
585 575
586 if (pathlen < 0 || pathlen > MAXPATHLEN) { 576 if (pathlen < 0 || pathlen > MAXPATHLEN) {
587 xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", 577 xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)",
588 __func__, (unsigned long long)ip->i_ino, pathlen); 578 __func__, (unsigned long long)ip->i_ino, pathlen);
579 xfs_iunlock(ip, XFS_ILOCK_EXCL);
589 ASSERT(0); 580 ASSERT(0);
590 return XFS_ERROR(EFSCORRUPTED); 581 return XFS_ERROR(EFSCORRUPTED);
591 } 582 }
592 583
593 if (ip->i_df.if_flags & XFS_IFINLINE) { 584 if (ip->i_df.if_flags & XFS_IFINLINE) {
594 if (ip->i_df.if_bytes > 0) 585 if (ip->i_df.if_bytes > 0)
595 xfs_idata_realloc(ip, -(ip->i_df.if_bytes), 586 xfs_idata_realloc(ip, -(ip->i_df.if_bytes),
596 XFS_DATA_FORK); 587 XFS_DATA_FORK);
588 xfs_iunlock(ip, XFS_ILOCK_EXCL);
597 ASSERT(ip->i_df.if_bytes == 0); 589 ASSERT(ip->i_df.if_bytes == 0);
598 return 0; 590 return 0;
599 } 591 }
600 592
593 xfs_iunlock(ip, XFS_ILOCK_EXCL);
594
601 /* remove the remote symlink */ 595 /* remove the remote symlink */
602 return xfs_inactive_symlink_rmt(ip, tp); 596 return xfs_inactive_symlink_rmt(ip);
603} 597}
diff --git a/fs/xfs/xfs_symlink.h b/fs/xfs/xfs_symlink.h
index 99338ba666ac..e75245d09116 100644
--- a/fs/xfs/xfs_symlink.h
+++ b/fs/xfs/xfs_symlink.h
@@ -22,6 +22,6 @@
22int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, 22int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
23 const char *target_path, umode_t mode, struct xfs_inode **ipp); 23 const char *target_path, umode_t mode, struct xfs_inode **ipp);
24int xfs_readlink(struct xfs_inode *ip, char *link); 24int xfs_readlink(struct xfs_inode *ip, char *link);
25int xfs_inactive_symlink(struct xfs_inode *ip, struct xfs_trans **tpp); 25int xfs_inactive_symlink(struct xfs_inode *ip);
26 26
27#endif /* __XFS_SYMLINK_H */ 27#endif /* __XFS_SYMLINK_H */
diff --git a/fs/xfs/xfs_symlink_remote.c b/fs/xfs/xfs_symlink_remote.c
index 01c85e3f6470..bf59a2b45f8c 100644
--- a/fs/xfs/xfs_symlink_remote.c
+++ b/fs/xfs/xfs_symlink_remote.c
@@ -19,8 +19,9 @@
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_format.h" 21#include "xfs_format.h"
22#include "xfs_log.h" 22#include "xfs_log_format.h"
23#include "xfs_trans.h" 23#include "xfs_shared.h"
24#include "xfs_trans_resv.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
@@ -30,6 +31,7 @@
30#include "xfs_trace.h" 31#include "xfs_trace.h"
31#include "xfs_symlink.h" 32#include "xfs_symlink.h"
32#include "xfs_cksum.h" 33#include "xfs_cksum.h"
34#include "xfs_trans.h"
33#include "xfs_buf_item.h" 35#include "xfs_buf_item.h"
34 36
35 37
diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c
index 5d7b3e40705f..dee3279c095e 100644
--- a/fs/xfs/xfs_trace.c
+++ b/fs/xfs/xfs_trace.c
@@ -17,19 +17,16 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_format.h" 21#include "xfs_format.h"
22#include "xfs_log.h" 22#include "xfs_log_format.h"
23#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_bmap_btree.h" 26#include "xfs_mount.h"
27#include "xfs_alloc_btree.h" 27#include "xfs_da_format.h"
28#include "xfs_ialloc_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h" 28#include "xfs_inode.h"
31#include "xfs_btree.h" 29#include "xfs_btree.h"
32#include "xfs_mount.h"
33#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
34#include "xfs_ialloc.h" 31#include "xfs_ialloc.h"
35#include "xfs_itable.h" 32#include "xfs_itable.h"
@@ -37,6 +34,8 @@
37#include "xfs_bmap.h" 34#include "xfs_bmap.h"
38#include "xfs_attr.h" 35#include "xfs_attr.h"
39#include "xfs_attr_leaf.h" 36#include "xfs_attr_leaf.h"
37#include "xfs_trans.h"
38#include "xfs_log.h"
40#include "xfs_log_priv.h" 39#include "xfs_log_priv.h"
41#include "xfs_buf_item.h" 40#include "xfs_buf_item.h"
42#include "xfs_quota.h" 41#include "xfs_quota.h"
@@ -46,6 +45,7 @@
46#include "xfs_dquot.h" 45#include "xfs_dquot.h"
47#include "xfs_log_recover.h" 46#include "xfs_log_recover.h"
48#include "xfs_inode_item.h" 47#include "xfs_inode_item.h"
48#include "xfs_bmap_btree.h"
49 49
50/* 50/*
51 * We include this last to have the helpers above available for the trace 51 * We include this last to have the helpers above available for the trace
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 47910e638c18..425dfa45b9a0 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -31,8 +31,8 @@ struct xfs_da_args;
31struct xfs_da_node_entry; 31struct xfs_da_node_entry;
32struct xfs_dquot; 32struct xfs_dquot;
33struct xfs_log_item; 33struct xfs_log_item;
34struct xlog_ticket;
35struct xlog; 34struct xlog;
35struct xlog_ticket;
36struct xlog_recover; 36struct xlog_recover;
37struct xlog_recover_item; 37struct xlog_recover_item;
38struct xfs_buf_log_format; 38struct xfs_buf_log_format;
@@ -135,6 +135,31 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim);
135DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks); 135DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks);
136DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks); 136DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks);
137 137
138DECLARE_EVENT_CLASS(xfs_ag_class,
139 TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno),
140 TP_ARGS(mp, agno),
141 TP_STRUCT__entry(
142 __field(dev_t, dev)
143 __field(xfs_agnumber_t, agno)
144 ),
145 TP_fast_assign(
146 __entry->dev = mp->m_super->s_dev;
147 __entry->agno = agno;
148 ),
149 TP_printk("dev %d:%d agno %u",
150 MAJOR(__entry->dev), MINOR(__entry->dev),
151 __entry->agno)
152);
153#define DEFINE_AG_EVENT(name) \
154DEFINE_EVENT(xfs_ag_class, name, \
155 TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno), \
156 TP_ARGS(mp, agno))
157
158DEFINE_AG_EVENT(xfs_read_agf);
159DEFINE_AG_EVENT(xfs_alloc_read_agf);
160DEFINE_AG_EVENT(xfs_read_agi);
161DEFINE_AG_EVENT(xfs_ialloc_read_agi);
162
138TRACE_EVENT(xfs_attr_list_node_descend, 163TRACE_EVENT(xfs_attr_list_node_descend,
139 TP_PROTO(struct xfs_attr_list_context *ctx, 164 TP_PROTO(struct xfs_attr_list_context *ctx,
140 struct xfs_da_node_entry *btree), 165 struct xfs_da_node_entry *btree),
@@ -938,6 +963,63 @@ DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned);
938DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); 963DEFINE_LOG_ITEM_EVENT(xfs_ail_locked);
939DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); 964DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing);
940 965
966DECLARE_EVENT_CLASS(xfs_ail_class,
967 TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn),
968 TP_ARGS(lip, old_lsn, new_lsn),
969 TP_STRUCT__entry(
970 __field(dev_t, dev)
971 __field(void *, lip)
972 __field(uint, type)
973 __field(uint, flags)
974 __field(xfs_lsn_t, old_lsn)
975 __field(xfs_lsn_t, new_lsn)
976 ),
977 TP_fast_assign(
978 __entry->dev = lip->li_mountp->m_super->s_dev;
979 __entry->lip = lip;
980 __entry->type = lip->li_type;
981 __entry->flags = lip->li_flags;
982 __entry->old_lsn = old_lsn;
983 __entry->new_lsn = new_lsn;
984 ),
985 TP_printk("dev %d:%d lip 0x%p old lsn %d/%d new lsn %d/%d type %s flags %s",
986 MAJOR(__entry->dev), MINOR(__entry->dev),
987 __entry->lip,
988 CYCLE_LSN(__entry->old_lsn), BLOCK_LSN(__entry->old_lsn),
989 CYCLE_LSN(__entry->new_lsn), BLOCK_LSN(__entry->new_lsn),
990 __print_symbolic(__entry->type, XFS_LI_TYPE_DESC),
991 __print_flags(__entry->flags, "|", XFS_LI_FLAGS))
992)
993
994#define DEFINE_AIL_EVENT(name) \
995DEFINE_EVENT(xfs_ail_class, name, \
996 TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), \
997 TP_ARGS(lip, old_lsn, new_lsn))
998DEFINE_AIL_EVENT(xfs_ail_insert);
999DEFINE_AIL_EVENT(xfs_ail_move);
1000DEFINE_AIL_EVENT(xfs_ail_delete);
1001
1002TRACE_EVENT(xfs_log_assign_tail_lsn,
1003 TP_PROTO(struct xlog *log, xfs_lsn_t new_lsn),
1004 TP_ARGS(log, new_lsn),
1005 TP_STRUCT__entry(
1006 __field(dev_t, dev)
1007 __field(xfs_lsn_t, new_lsn)
1008 __field(xfs_lsn_t, old_lsn)
1009 __field(xfs_lsn_t, last_sync_lsn)
1010 ),
1011 TP_fast_assign(
1012 __entry->dev = log->l_mp->m_super->s_dev;
1013 __entry->new_lsn = new_lsn;
1014 __entry->old_lsn = atomic64_read(&log->l_tail_lsn);
1015 __entry->last_sync_lsn = atomic64_read(&log->l_last_sync_lsn);
1016 ),
1017 TP_printk("dev %d:%d new tail lsn %d/%d, old lsn %d/%d, last sync %d/%d",
1018 MAJOR(__entry->dev), MINOR(__entry->dev),
1019 CYCLE_LSN(__entry->new_lsn), BLOCK_LSN(__entry->new_lsn),
1020 CYCLE_LSN(__entry->old_lsn), BLOCK_LSN(__entry->old_lsn),
1021 CYCLE_LSN(__entry->last_sync_lsn), BLOCK_LSN(__entry->last_sync_lsn))
1022)
941 1023
942DECLARE_EVENT_CLASS(xfs_file_class, 1024DECLARE_EVENT_CLASS(xfs_file_class,
943 TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), 1025 TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags),
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 5411e01ab452..c812c5c060de 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -18,32 +18,21 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_shared.h"
21#include "xfs_format.h" 22#include "xfs_format.h"
22#include "xfs_log.h" 23#include "xfs_log_format.h"
23#include "xfs_trans.h" 24#include "xfs_trans_resv.h"
24#include "xfs_sb.h" 25#include "xfs_sb.h"
25#include "xfs_ag.h" 26#include "xfs_ag.h"
26#include "xfs_mount.h" 27#include "xfs_mount.h"
27#include "xfs_error.h"
28#include "xfs_da_btree.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_dinode.h"
33#include "xfs_inode.h" 28#include "xfs_inode.h"
34#include "xfs_btree.h"
35#include "xfs_ialloc.h"
36#include "xfs_alloc.h"
37#include "xfs_extent_busy.h" 29#include "xfs_extent_busy.h"
38#include "xfs_bmap.h"
39#include "xfs_quota.h" 30#include "xfs_quota.h"
40#include "xfs_qm.h" 31#include "xfs_trans.h"
41#include "xfs_trans_priv.h" 32#include "xfs_trans_priv.h"
42#include "xfs_trans_space.h" 33#include "xfs_log.h"
43#include "xfs_inode_item.h"
44#include "xfs_log_priv.h"
45#include "xfs_buf_item.h"
46#include "xfs_trace.h" 34#include "xfs_trace.h"
35#include "xfs_error.h"
47 36
48kmem_zone_t *xfs_trans_zone; 37kmem_zone_t *xfs_trans_zone;
49kmem_zone_t *xfs_log_item_desc_zone; 38kmem_zone_t *xfs_log_item_desc_zone;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 09cf40b89e8c..9b96d35e483d 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -18,10 +18,6 @@
18#ifndef __XFS_TRANS_H__ 18#ifndef __XFS_TRANS_H__
19#define __XFS_TRANS_H__ 19#define __XFS_TRANS_H__
20 20
21struct xfs_log_item;
22
23#include "xfs_trans_resv.h"
24
25/* kernel only transaction subsystem defines */ 21/* kernel only transaction subsystem defines */
26 22
27struct xfs_buf; 23struct xfs_buf;
@@ -77,6 +73,9 @@ struct xfs_item_ops {
77 void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t); 73 void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
78}; 74};
79 75
76void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
77 int type, const struct xfs_item_ops *ops);
78
80/* 79/*
81 * Return values for the iop_push() routines. 80 * Return values for the iop_push() routines.
82 */ 81 */
@@ -85,18 +84,12 @@ struct xfs_item_ops {
85#define XFS_ITEM_LOCKED 2 84#define XFS_ITEM_LOCKED 2
86#define XFS_ITEM_FLUSHING 3 85#define XFS_ITEM_FLUSHING 3
87 86
88/*
89 * This is the type of function which can be given to xfs_trans_callback()
90 * to be called upon the transaction's commit to disk.
91 */
92typedef void (*xfs_trans_callback_t)(struct xfs_trans *, void *);
93 87
94/* 88/*
95 * This is the structure maintained for every active transaction. 89 * This is the structure maintained for every active transaction.
96 */ 90 */
97typedef struct xfs_trans { 91typedef struct xfs_trans {
98 unsigned int t_magic; /* magic number */ 92 unsigned int t_magic; /* magic number */
99 xfs_log_callback_t t_logcb; /* log callback struct */
100 unsigned int t_type; /* transaction type */ 93 unsigned int t_type; /* transaction type */
101 unsigned int t_log_res; /* amt of log space resvd */ 94 unsigned int t_log_res; /* amt of log space resvd */
102 unsigned int t_log_count; /* count for perm log res */ 95 unsigned int t_log_count; /* count for perm log res */
@@ -132,7 +125,6 @@ typedef struct xfs_trans {
132 int64_t t_rextents_delta;/* superblocks rextents chg */ 125 int64_t t_rextents_delta;/* superblocks rextents chg */
133 int64_t t_rextslog_delta;/* superblocks rextslog chg */ 126 int64_t t_rextslog_delta;/* superblocks rextslog chg */
134 struct list_head t_items; /* log item descriptors */ 127 struct list_head t_items; /* log item descriptors */
135 xfs_trans_header_t t_header; /* header for in-log trans */
136 struct list_head t_busy; /* list of busy extents */ 128 struct list_head t_busy; /* list of busy extents */
137 unsigned long t_pflags; /* saved process flags state */ 129 unsigned long t_pflags; /* saved process flags state */
138} xfs_trans_t; 130} xfs_trans_t;
@@ -237,10 +229,16 @@ void xfs_trans_log_efd_extent(xfs_trans_t *,
237 xfs_fsblock_t, 229 xfs_fsblock_t,
238 xfs_extlen_t); 230 xfs_extlen_t);
239int xfs_trans_commit(xfs_trans_t *, uint flags); 231int xfs_trans_commit(xfs_trans_t *, uint flags);
232int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *);
240void xfs_trans_cancel(xfs_trans_t *, int); 233void xfs_trans_cancel(xfs_trans_t *, int);
241int xfs_trans_ail_init(struct xfs_mount *); 234int xfs_trans_ail_init(struct xfs_mount *);
242void xfs_trans_ail_destroy(struct xfs_mount *); 235void xfs_trans_ail_destroy(struct xfs_mount *);
243 236
237void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *,
238 enum xfs_blft);
239void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp,
240 struct xfs_buf *src_bp);
241
244extern kmem_zone_t *xfs_trans_zone; 242extern kmem_zone_t *xfs_trans_zone;
245extern kmem_zone_t *xfs_log_item_desc_zone; 243extern kmem_zone_t *xfs_log_item_desc_zone;
246 244
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 21c6d7ddbc06..a7287354e535 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -18,15 +18,16 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_types.h" 21#include "xfs_log_format.h"
22#include "xfs_log.h" 22#include "xfs_trans_resv.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h" 23#include "xfs_sb.h"
25#include "xfs_ag.h" 24#include "xfs_ag.h"
26#include "xfs_mount.h" 25#include "xfs_mount.h"
26#include "xfs_trans.h"
27#include "xfs_trans_priv.h" 27#include "xfs_trans_priv.h"
28#include "xfs_trace.h" 28#include "xfs_trace.h"
29#include "xfs_error.h" 29#include "xfs_error.h"
30#include "xfs_log.h"
30 31
31#ifdef DEBUG 32#ifdef DEBUG
32/* 33/*
@@ -658,11 +659,13 @@ xfs_trans_ail_update_bulk(
658 if (XFS_LSN_CMP(lsn, lip->li_lsn) <= 0) 659 if (XFS_LSN_CMP(lsn, lip->li_lsn) <= 0)
659 continue; 660 continue;
660 661
662 trace_xfs_ail_move(lip, lip->li_lsn, lsn);
661 xfs_ail_delete(ailp, lip); 663 xfs_ail_delete(ailp, lip);
662 if (mlip == lip) 664 if (mlip == lip)
663 mlip_changed = 1; 665 mlip_changed = 1;
664 } else { 666 } else {
665 lip->li_flags |= XFS_LI_IN_AIL; 667 lip->li_flags |= XFS_LI_IN_AIL;
668 trace_xfs_ail_insert(lip, 0, lsn);
666 } 669 }
667 lip->li_lsn = lsn; 670 lip->li_lsn = lsn;
668 list_add(&lip->li_ail, &tmp); 671 list_add(&lip->li_ail, &tmp);
@@ -731,6 +734,7 @@ xfs_trans_ail_delete_bulk(
731 return; 734 return;
732 } 735 }
733 736
737 trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn);
734 xfs_ail_delete(ailp, lip); 738 xfs_ail_delete(ailp, lip);
735 lip->li_flags &= ~XFS_LI_IN_AIL; 739 lip->li_flags &= ~XFS_LI_IN_AIL;
736 lip->li_lsn = 0; 740 lip->li_lsn = 0;
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 8c75b8f67270..c035d11b7734 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -17,17 +17,15 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log.h" 21#include "xfs_format.h"
22#include "xfs_trans.h" 22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_mount.h" 26#include "xfs_mount.h"
26#include "xfs_bmap_btree.h"
27#include "xfs_alloc_btree.h"
28#include "xfs_ialloc_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h" 27#include "xfs_inode.h"
28#include "xfs_trans.h"
31#include "xfs_buf_item.h" 29#include "xfs_buf_item.h"
32#include "xfs_trans_priv.h" 30#include "xfs_trans_priv.h"
33#include "xfs_error.h" 31#include "xfs_error.h"
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 54ee3c5dee76..cd2a10e15d3a 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -17,23 +17,18 @@
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_log.h" 22#include "xfs_log_format.h"
22#include "xfs_trans.h" 23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_alloc.h"
26#include "xfs_quota.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_inode.h" 27#include "xfs_inode.h"
30#include "xfs_itable.h"
31#include "xfs_bmap.h"
32#include "xfs_rtalloc.h"
33#include "xfs_error.h" 28#include "xfs_error.h"
34#include "xfs_attr.h" 29#include "xfs_trans.h"
35#include "xfs_buf_item.h"
36#include "xfs_trans_priv.h" 30#include "xfs_trans_priv.h"
31#include "xfs_quota.h"
37#include "xfs_qm.h" 32#include "xfs_qm.h"
38 33
39STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *); 34STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *);
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index 8d71b16eccae..47978ba89dae 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -17,12 +17,13 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log.h" 21#include "xfs_log_format.h"
22#include "xfs_trans.h" 22#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_ag.h" 24#include "xfs_ag.h"
25#include "xfs_mount.h" 25#include "xfs_mount.h"
26#include "xfs_trans.h"
26#include "xfs_trans_priv.h" 27#include "xfs_trans_priv.h"
27#include "xfs_extfree_item.h" 28#include "xfs_extfree_item.h"
28 29
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 53dfe46f3680..1bba7f60d94c 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -17,18 +17,15 @@
17 */ 17 */
18#include "xfs.h" 18#include "xfs.h"
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_shared.h"
21#include "xfs_log.h" 21#include "xfs_format.h"
22#include "xfs_trans.h" 22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
23#include "xfs_sb.h" 24#include "xfs_sb.h"
24#include "xfs_ag.h" 25#include "xfs_ag.h"
25#include "xfs_mount.h" 26#include "xfs_mount.h"
26#include "xfs_bmap_btree.h"
27#include "xfs_alloc_btree.h"
28#include "xfs_ialloc_btree.h"
29#include "xfs_dinode.h"
30#include "xfs_inode.h" 27#include "xfs_inode.h"
31#include "xfs_btree.h" 28#include "xfs_trans.h"
32#include "xfs_trans_priv.h" 29#include "xfs_trans_priv.h"
33#include "xfs_inode_item.h" 30#include "xfs_inode_item.h"
34#include "xfs_trace.h" 31#include "xfs_trace.h"
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index c52def0b441c..12e86af9d9b9 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -27,7 +27,6 @@ struct xfs_log_vec;
27 27
28 28
29void xfs_trans_init(struct xfs_mount *); 29void xfs_trans_init(struct xfs_mount *);
30int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *);
31void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *); 30void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *);
32void xfs_trans_del_item(struct xfs_log_item *); 31void xfs_trans_del_item(struct xfs_log_item *);
33void xfs_trans_free_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn, 32void xfs_trans_free_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn,
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c
index a65a3cc40610..d53d9f0627a7 100644
--- a/fs/xfs/xfs_trans_resv.c
+++ b/fs/xfs/xfs_trans_resv.c
@@ -18,27 +18,19 @@
18 */ 18 */
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_fs.h" 20#include "xfs_fs.h"
21#include "xfs_shared.h"
21#include "xfs_format.h" 22#include "xfs_format.h"
22#include "xfs_log.h" 23#include "xfs_log_format.h"
23#include "xfs_trans_resv.h" 24#include "xfs_trans_resv.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_mount.h" 27#include "xfs_mount.h"
28#include "xfs_error.h" 28#include "xfs_da_format.h"
29#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_dinode.h"
34#include "xfs_inode.h" 29#include "xfs_inode.h"
35#include "xfs_btree.h" 30#include "xfs_bmap_btree.h"
36#include "xfs_ialloc.h" 31#include "xfs_ialloc.h"
37#include "xfs_alloc.h"
38#include "xfs_extent_busy.h"
39#include "xfs_bmap.h"
40#include "xfs_bmap_util.h"
41#include "xfs_quota.h" 32#include "xfs_quota.h"
33#include "xfs_trans.h"
42#include "xfs_qm.h" 34#include "xfs_qm.h"
43#include "xfs_trans_space.h" 35#include "xfs_trans_space.h"
44#include "xfs_trace.h" 36#include "xfs_trace.h"
diff --git a/fs/xfs/xfs_vnode.h b/fs/xfs/xfs_vnode.h
index db14d0c08682..3e8e797c6d11 100644
--- a/fs/xfs/xfs_vnode.h
+++ b/fs/xfs/xfs_vnode.h
@@ -25,14 +25,6 @@ struct xfs_inode;
25struct attrlist_cursor_kern; 25struct attrlist_cursor_kern;
26 26
27/* 27/*
28 * Return values for xfs_inactive. A return value of
29 * VN_INACTIVE_NOCACHE implies that the file system behavior
30 * has disassociated its state and bhv_desc_t from the vnode.
31 */
32#define VN_INACTIVE_CACHE 0
33#define VN_INACTIVE_NOCACHE 1
34
35/*
36 * Flags for read/write calls - same values as IRIX 28 * Flags for read/write calls - same values as IRIX
37 */ 29 */
38#define IO_ISDIRECT 0x00004 /* bypass page cache */ 30#define IO_ISDIRECT 0x00004 /* bypass page cache */
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index e01f35ea76ba..9d479073ba41 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -17,9 +17,13 @@
17 */ 17 */
18 18
19#include "xfs.h" 19#include "xfs.h"
20#include "xfs_format.h"
20#include "xfs_log_format.h" 21#include "xfs_log_format.h"
21#include "xfs_da_btree.h" 22#include "xfs_trans_resv.h"
22#include "xfs_bmap_btree.h" 23#include "xfs_sb.h"
24#include "xfs_ag.h"
25#include "xfs_mount.h"
26#include "xfs_da_format.h"
23#include "xfs_inode.h" 27#include "xfs_inode.h"
24#include "xfs_attr.h" 28#include "xfs_attr.h"
25#include "xfs_attr_leaf.h" 29#include "xfs_attr_leaf.h"