aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs')
-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.c10
-rw-r--r--fs/xfs/xfs_buf_item.h4
-rw-r--r--fs/xfs/xfs_da_btree.c267
-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)692
-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.c152
-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.h6
-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.c29
-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.c245
-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.c40
-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, 5294 insertions, 4717 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 88c5ea75ebf6..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;
@@ -628,6 +629,7 @@ xfs_buf_item_unlock(
628 else if (aborted) { 629 else if (aborted) {
629 ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp)); 630 ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
630 if (lip->li_flags & XFS_LI_IN_AIL) { 631 if (lip->li_flags & XFS_LI_IN_AIL) {
632 spin_lock(&lip->li_ailp->xa_lock);
631 xfs_trans_ail_delete(lip->li_ailp, lip, 633 xfs_trans_ail_delete(lip->li_ailp, lip,
632 SHUTDOWN_LOG_IO_ERROR); 634 SHUTDOWN_LOG_IO_ERROR);
633 } 635 }
@@ -807,7 +809,7 @@ xfs_buf_item_init(
807 * Mark bytes first through last inclusive as dirty in the buf 809 * Mark bytes first through last inclusive as dirty in the buf
808 * item's bitmap. 810 * item's bitmap.
809 */ 811 */
810void 812static void
811xfs_buf_item_log_segment( 813xfs_buf_item_log_segment(
812 struct xfs_buf_log_item *bip, 814 struct xfs_buf_log_item *bip,
813 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 069537c845e5..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 */
@@ -1224,22 +1182,23 @@ xfs_da3_node_toosmall(
1224 /* start with smaller blk num */ 1182 /* start with smaller blk num */
1225 forward = nodehdr.forw < nodehdr.back; 1183 forward = nodehdr.forw < nodehdr.back;
1226 for (i = 0; i < 2; forward = !forward, i++) { 1184 for (i = 0; i < 2; forward = !forward, i++) {
1185 struct xfs_da3_icnode_hdr thdr;
1227 if (forward) 1186 if (forward)
1228 blkno = nodehdr.forw; 1187 blkno = nodehdr.forw;
1229 else 1188 else
1230 blkno = nodehdr.back; 1189 blkno = nodehdr.back;
1231 if (blkno == 0) 1190 if (blkno == 0)
1232 continue; 1191 continue;
1233 error = xfs_da3_node_read(state->args->trans, state->args->dp, 1192 error = xfs_da3_node_read(state->args->trans, dp,
1234 blkno, -1, &bp, state->args->whichfork); 1193 blkno, -1, &bp, state->args->whichfork);
1235 if (error) 1194 if (error)
1236 return(error); 1195 return(error);
1237 1196
1238 node = bp->b_addr; 1197 node = bp->b_addr;
1239 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1198 dp->d_ops->node_hdr_from_disk(&thdr, node);
1240 xfs_trans_brelse(state->args->trans, bp); 1199 xfs_trans_brelse(state->args->trans, bp);
1241 1200
1242 if (count - nodehdr.count >= 0) 1201 if (count - thdr.count >= 0)
1243 break; /* fits with at least 25% to spare */ 1202 break; /* fits with at least 25% to spare */
1244 } 1203 }
1245 if (i >= 2) { 1204 if (i >= 2) {
@@ -1274,6 +1233,7 @@ xfs_da3_node_toosmall(
1274 */ 1233 */
1275STATIC uint 1234STATIC uint
1276xfs_da3_node_lasthash( 1235xfs_da3_node_lasthash(
1236 struct xfs_inode *dp,
1277 struct xfs_buf *bp, 1237 struct xfs_buf *bp,
1278 int *count) 1238 int *count)
1279{ 1239{
@@ -1282,12 +1242,12 @@ xfs_da3_node_lasthash(
1282 struct xfs_da3_icnode_hdr nodehdr; 1242 struct xfs_da3_icnode_hdr nodehdr;
1283 1243
1284 node = bp->b_addr; 1244 node = bp->b_addr;
1285 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1245 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1286 if (count) 1246 if (count)
1287 *count = nodehdr.count; 1247 *count = nodehdr.count;
1288 if (!nodehdr.count) 1248 if (!nodehdr.count)
1289 return 0; 1249 return 0;
1290 btree = xfs_da3_node_tree_p(node); 1250 btree = dp->d_ops->node_tree_p(node);
1291 return be32_to_cpu(btree[nodehdr.count - 1].hashval); 1251 return be32_to_cpu(btree[nodehdr.count - 1].hashval);
1292} 1252}
1293 1253
@@ -1306,6 +1266,7 @@ xfs_da3_fixhashpath(
1306 xfs_dahash_t lasthash=0; 1266 xfs_dahash_t lasthash=0;
1307 int level; 1267 int level;
1308 int count; 1268 int count;
1269 struct xfs_inode *dp = state->args->dp;
1309 1270
1310 trace_xfs_da_fixhashpath(state->args); 1271 trace_xfs_da_fixhashpath(state->args);
1311 1272
@@ -1318,12 +1279,12 @@ xfs_da3_fixhashpath(
1318 return; 1279 return;
1319 break; 1280 break;
1320 case XFS_DIR2_LEAFN_MAGIC: 1281 case XFS_DIR2_LEAFN_MAGIC:
1321 lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); 1282 lasthash = xfs_dir2_leafn_lasthash(dp, blk->bp, &count);
1322 if (count == 0) 1283 if (count == 0)
1323 return; 1284 return;
1324 break; 1285 break;
1325 case XFS_DA_NODE_MAGIC: 1286 case XFS_DA_NODE_MAGIC:
1326 lasthash = xfs_da3_node_lasthash(blk->bp, &count); 1287 lasthash = xfs_da3_node_lasthash(dp, blk->bp, &count);
1327 if (count == 0) 1288 if (count == 0)
1328 return; 1289 return;
1329 break; 1290 break;
@@ -1332,8 +1293,8 @@ xfs_da3_fixhashpath(
1332 struct xfs_da3_icnode_hdr nodehdr; 1293 struct xfs_da3_icnode_hdr nodehdr;
1333 1294
1334 node = blk->bp->b_addr; 1295 node = blk->bp->b_addr;
1335 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1296 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1336 btree = xfs_da3_node_tree_p(node); 1297 btree = dp->d_ops->node_tree_p(node);
1337 if (be32_to_cpu(btree->hashval) == lasthash) 1298 if (be32_to_cpu(btree->hashval) == lasthash)
1338 break; 1299 break;
1339 blk->hashval = lasthash; 1300 blk->hashval = lasthash;
@@ -1359,11 +1320,12 @@ xfs_da3_node_remove(
1359 struct xfs_da_node_entry *btree; 1320 struct xfs_da_node_entry *btree;
1360 int index; 1321 int index;
1361 int tmp; 1322 int tmp;
1323 struct xfs_inode *dp = state->args->dp;
1362 1324
1363 trace_xfs_da_node_remove(state->args); 1325 trace_xfs_da_node_remove(state->args);
1364 1326
1365 node = drop_blk->bp->b_addr; 1327 node = drop_blk->bp->b_addr;
1366 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1328 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1367 ASSERT(drop_blk->index < nodehdr.count); 1329 ASSERT(drop_blk->index < nodehdr.count);
1368 ASSERT(drop_blk->index >= 0); 1330 ASSERT(drop_blk->index >= 0);
1369 1331
@@ -1371,7 +1333,7 @@ xfs_da3_node_remove(
1371 * Copy over the offending entry, or just zero it out. 1333 * Copy over the offending entry, or just zero it out.
1372 */ 1334 */
1373 index = drop_blk->index; 1335 index = drop_blk->index;
1374 btree = xfs_da3_node_tree_p(node); 1336 btree = dp->d_ops->node_tree_p(node);
1375 if (index < nodehdr.count - 1) { 1337 if (index < nodehdr.count - 1) {
1376 tmp = nodehdr.count - index - 1; 1338 tmp = nodehdr.count - index - 1;
1377 tmp *= (uint)sizeof(xfs_da_node_entry_t); 1339 tmp *= (uint)sizeof(xfs_da_node_entry_t);
@@ -1384,9 +1346,9 @@ xfs_da3_node_remove(
1384 xfs_trans_log_buf(state->args->trans, drop_blk->bp, 1346 xfs_trans_log_buf(state->args->trans, drop_blk->bp,
1385 XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index]))); 1347 XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index])));
1386 nodehdr.count -= 1; 1348 nodehdr.count -= 1;
1387 xfs_da3_node_hdr_to_disk(node, &nodehdr); 1349 dp->d_ops->node_hdr_to_disk(node, &nodehdr);
1388 xfs_trans_log_buf(state->args->trans, drop_blk->bp, 1350 xfs_trans_log_buf(state->args->trans, drop_blk->bp,
1389 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));
1390 1352
1391 /* 1353 /*
1392 * Copy the last hash value from the block to propagate upwards. 1354 * Copy the last hash value from the block to propagate upwards.
@@ -1413,15 +1375,16 @@ xfs_da3_node_unbalance(
1413 struct xfs_trans *tp; 1375 struct xfs_trans *tp;
1414 int sindex; 1376 int sindex;
1415 int tmp; 1377 int tmp;
1378 struct xfs_inode *dp = state->args->dp;
1416 1379
1417 trace_xfs_da_node_unbalance(state->args); 1380 trace_xfs_da_node_unbalance(state->args);
1418 1381
1419 drop_node = drop_blk->bp->b_addr; 1382 drop_node = drop_blk->bp->b_addr;
1420 save_node = save_blk->bp->b_addr; 1383 save_node = save_blk->bp->b_addr;
1421 xfs_da3_node_hdr_from_disk(&drop_hdr, drop_node); 1384 dp->d_ops->node_hdr_from_disk(&drop_hdr, drop_node);
1422 xfs_da3_node_hdr_from_disk(&save_hdr, save_node); 1385 dp->d_ops->node_hdr_from_disk(&save_hdr, save_node);
1423 drop_btree = xfs_da3_node_tree_p(drop_node); 1386 drop_btree = dp->d_ops->node_tree_p(drop_node);
1424 save_btree = xfs_da3_node_tree_p(save_node); 1387 save_btree = dp->d_ops->node_tree_p(save_node);
1425 tp = state->args->trans; 1388 tp = state->args->trans;
1426 1389
1427 /* 1390 /*
@@ -1455,10 +1418,10 @@ xfs_da3_node_unbalance(
1455 memcpy(&save_btree[sindex], &drop_btree[0], tmp); 1418 memcpy(&save_btree[sindex], &drop_btree[0], tmp);
1456 save_hdr.count += drop_hdr.count; 1419 save_hdr.count += drop_hdr.count;
1457 1420
1458 xfs_da3_node_hdr_to_disk(save_node, &save_hdr); 1421 dp->d_ops->node_hdr_to_disk(save_node, &save_hdr);
1459 xfs_trans_log_buf(tp, save_blk->bp, 1422 xfs_trans_log_buf(tp, save_blk->bp,
1460 XFS_DA_LOGRANGE(save_node, &save_node->hdr, 1423 XFS_DA_LOGRANGE(save_node, &save_node->hdr,
1461 xfs_da3_node_hdr_size(save_node))); 1424 dp->d_ops->node_hdr_size));
1462 1425
1463 /* 1426 /*
1464 * Save the last hashval in the remaining block for upward propagation. 1427 * Save the last hashval in the remaining block for upward propagation.
@@ -1500,6 +1463,7 @@ xfs_da3_node_lookup_int(
1500 int max; 1463 int max;
1501 int error; 1464 int error;
1502 int retval; 1465 int retval;
1466 struct xfs_inode *dp = state->args->dp;
1503 1467
1504 args = state->args; 1468 args = state->args;
1505 1469
@@ -1535,7 +1499,8 @@ xfs_da3_node_lookup_int(
1535 if (blk->magic == XFS_DIR2_LEAFN_MAGIC || 1499 if (blk->magic == XFS_DIR2_LEAFN_MAGIC ||
1536 blk->magic == XFS_DIR3_LEAFN_MAGIC) { 1500 blk->magic == XFS_DIR3_LEAFN_MAGIC) {
1537 blk->magic = XFS_DIR2_LEAFN_MAGIC; 1501 blk->magic = XFS_DIR2_LEAFN_MAGIC;
1538 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); 1502 blk->hashval = xfs_dir2_leafn_lasthash(args->dp,
1503 blk->bp, NULL);
1539 break; 1504 break;
1540 } 1505 }
1541 1506
@@ -1546,8 +1511,8 @@ xfs_da3_node_lookup_int(
1546 * Search an intermediate node for a match. 1511 * Search an intermediate node for a match.
1547 */ 1512 */
1548 node = blk->bp->b_addr; 1513 node = blk->bp->b_addr;
1549 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1514 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1550 btree = xfs_da3_node_tree_p(node); 1515 btree = dp->d_ops->node_tree_p(node);
1551 1516
1552 max = nodehdr.count; 1517 max = nodehdr.count;
1553 blk->hashval = be32_to_cpu(btree[max - 1].hashval); 1518 blk->hashval = be32_to_cpu(btree[max - 1].hashval);
@@ -1642,6 +1607,7 @@ xfs_da3_node_lookup_int(
1642 */ 1607 */
1643STATIC int 1608STATIC int
1644xfs_da3_node_order( 1609xfs_da3_node_order(
1610 struct xfs_inode *dp,
1645 struct xfs_buf *node1_bp, 1611 struct xfs_buf *node1_bp,
1646 struct xfs_buf *node2_bp) 1612 struct xfs_buf *node2_bp)
1647{ 1613{
@@ -1654,10 +1620,10 @@ xfs_da3_node_order(
1654 1620
1655 node1 = node1_bp->b_addr; 1621 node1 = node1_bp->b_addr;
1656 node2 = node2_bp->b_addr; 1622 node2 = node2_bp->b_addr;
1657 xfs_da3_node_hdr_from_disk(&node1hdr, node1); 1623 dp->d_ops->node_hdr_from_disk(&node1hdr, node1);
1658 xfs_da3_node_hdr_from_disk(&node2hdr, node2); 1624 dp->d_ops->node_hdr_from_disk(&node2hdr, node2);
1659 btree1 = xfs_da3_node_tree_p(node1); 1625 btree1 = dp->d_ops->node_tree_p(node1);
1660 btree2 = xfs_da3_node_tree_p(node2); 1626 btree2 = dp->d_ops->node_tree_p(node2);
1661 1627
1662 if (node1hdr.count > 0 && node2hdr.count > 0 && 1628 if (node1hdr.count > 0 && node2hdr.count > 0 &&
1663 ((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)) ||
@@ -1684,6 +1650,7 @@ xfs_da3_blk_link(
1684 struct xfs_buf *bp; 1650 struct xfs_buf *bp;
1685 int before = 0; 1651 int before = 0;
1686 int error; 1652 int error;
1653 struct xfs_inode *dp = state->args->dp;
1687 1654
1688 /* 1655 /*
1689 * Set up environment. 1656 * Set up environment.
@@ -1701,10 +1668,10 @@ xfs_da3_blk_link(
1701 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); 1668 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
1702 break; 1669 break;
1703 case XFS_DIR2_LEAFN_MAGIC: 1670 case XFS_DIR2_LEAFN_MAGIC:
1704 before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); 1671 before = xfs_dir2_leafn_order(dp, old_blk->bp, new_blk->bp);
1705 break; 1672 break;
1706 case XFS_DA_NODE_MAGIC: 1673 case XFS_DA_NODE_MAGIC:
1707 before = xfs_da3_node_order(old_blk->bp, new_blk->bp); 1674 before = xfs_da3_node_order(dp, old_blk->bp, new_blk->bp);
1708 break; 1675 break;
1709 } 1676 }
1710 1677
@@ -1719,7 +1686,7 @@ xfs_da3_blk_link(
1719 new_info->forw = cpu_to_be32(old_blk->blkno); 1686 new_info->forw = cpu_to_be32(old_blk->blkno);
1720 new_info->back = old_info->back; 1687 new_info->back = old_info->back;
1721 if (old_info->back) { 1688 if (old_info->back) {
1722 error = xfs_da3_node_read(args->trans, args->dp, 1689 error = xfs_da3_node_read(args->trans, dp,
1723 be32_to_cpu(old_info->back), 1690 be32_to_cpu(old_info->back),
1724 -1, &bp, args->whichfork); 1691 -1, &bp, args->whichfork);
1725 if (error) 1692 if (error)
@@ -1740,7 +1707,7 @@ xfs_da3_blk_link(
1740 new_info->forw = old_info->forw; 1707 new_info->forw = old_info->forw;
1741 new_info->back = cpu_to_be32(old_blk->blkno); 1708 new_info->back = cpu_to_be32(old_blk->blkno);
1742 if (old_info->forw) { 1709 if (old_info->forw) {
1743 error = xfs_da3_node_read(args->trans, args->dp, 1710 error = xfs_da3_node_read(args->trans, dp,
1744 be32_to_cpu(old_info->forw), 1711 be32_to_cpu(old_info->forw),
1745 -1, &bp, args->whichfork); 1712 -1, &bp, args->whichfork);
1746 if (error) 1713 if (error)
@@ -1860,6 +1827,7 @@ xfs_da3_path_shift(
1860 xfs_dablk_t blkno = 0; 1827 xfs_dablk_t blkno = 0;
1861 int level; 1828 int level;
1862 int error; 1829 int error;
1830 struct xfs_inode *dp = state->args->dp;
1863 1831
1864 trace_xfs_da_path_shift(state->args); 1832 trace_xfs_da_path_shift(state->args);
1865 1833
@@ -1875,8 +1843,8 @@ xfs_da3_path_shift(
1875 level = (path->active-1) - 1; /* skip bottom layer in path */ 1843 level = (path->active-1) - 1; /* skip bottom layer in path */
1876 for (blk = &path->blk[level]; level >= 0; blk--, level--) { 1844 for (blk = &path->blk[level]; level >= 0; blk--, level--) {
1877 node = blk->bp->b_addr; 1845 node = blk->bp->b_addr;
1878 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1846 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1879 btree = xfs_da3_node_tree_p(node); 1847 btree = dp->d_ops->node_tree_p(node);
1880 1848
1881 if (forward && (blk->index < nodehdr.count - 1)) { 1849 if (forward && (blk->index < nodehdr.count - 1)) {
1882 blk->index++; 1850 blk->index++;
@@ -1910,7 +1878,7 @@ xfs_da3_path_shift(
1910 * Read the next child block. 1878 * Read the next child block.
1911 */ 1879 */
1912 blk->blkno = blkno; 1880 blk->blkno = blkno;
1913 error = xfs_da3_node_read(args->trans, args->dp, blkno, -1, 1881 error = xfs_da3_node_read(args->trans, dp, blkno, -1,
1914 &blk->bp, args->whichfork); 1882 &blk->bp, args->whichfork);
1915 if (error) 1883 if (error)
1916 return(error); 1884 return(error);
@@ -1932,8 +1900,8 @@ xfs_da3_path_shift(
1932 case XFS_DA3_NODE_MAGIC: 1900 case XFS_DA3_NODE_MAGIC:
1933 blk->magic = XFS_DA_NODE_MAGIC; 1901 blk->magic = XFS_DA_NODE_MAGIC;
1934 node = (xfs_da_intnode_t *)info; 1902 node = (xfs_da_intnode_t *)info;
1935 xfs_da3_node_hdr_from_disk(&nodehdr, node); 1903 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
1936 btree = xfs_da3_node_tree_p(node); 1904 btree = dp->d_ops->node_tree_p(node);
1937 blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); 1905 blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval);
1938 if (forward) 1906 if (forward)
1939 blk->index = 0; 1907 blk->index = 0;
@@ -1946,16 +1914,15 @@ xfs_da3_path_shift(
1946 blk->magic = XFS_ATTR_LEAF_MAGIC; 1914 blk->magic = XFS_ATTR_LEAF_MAGIC;
1947 ASSERT(level == path->active-1); 1915 ASSERT(level == path->active-1);
1948 blk->index = 0; 1916 blk->index = 0;
1949 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, 1917 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
1950 NULL);
1951 break; 1918 break;
1952 case XFS_DIR2_LEAFN_MAGIC: 1919 case XFS_DIR2_LEAFN_MAGIC:
1953 case XFS_DIR3_LEAFN_MAGIC: 1920 case XFS_DIR3_LEAFN_MAGIC:
1954 blk->magic = XFS_DIR2_LEAFN_MAGIC; 1921 blk->magic = XFS_DIR2_LEAFN_MAGIC;
1955 ASSERT(level == path->active-1); 1922 ASSERT(level == path->active-1);
1956 blk->index = 0; 1923 blk->index = 0;
1957 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, 1924 blk->hashval = xfs_dir2_leafn_lasthash(args->dp,
1958 NULL); 1925 blk->bp, NULL);
1959 break; 1926 break;
1960 default: 1927 default:
1961 ASSERT(0); 1928 ASSERT(0);
@@ -2162,7 +2129,7 @@ xfs_da3_swap_lastblock(
2162 struct xfs_dir2_leaf *dead_leaf2; 2129 struct xfs_dir2_leaf *dead_leaf2;
2163 struct xfs_da_node_entry *btree; 2130 struct xfs_da_node_entry *btree;
2164 struct xfs_da3_icnode_hdr par_hdr; 2131 struct xfs_da3_icnode_hdr par_hdr;
2165 struct xfs_inode *ip; 2132 struct xfs_inode *dp;
2166 struct xfs_trans *tp; 2133 struct xfs_trans *tp;
2167 struct xfs_mount *mp; 2134 struct xfs_mount *mp;
2168 struct xfs_buf *dead_buf; 2135 struct xfs_buf *dead_buf;
@@ -2186,12 +2153,12 @@ xfs_da3_swap_lastblock(
2186 dead_buf = *dead_bufp; 2153 dead_buf = *dead_bufp;
2187 dead_blkno = *dead_blknop; 2154 dead_blkno = *dead_blknop;
2188 tp = args->trans; 2155 tp = args->trans;
2189 ip = args->dp; 2156 dp = args->dp;
2190 w = args->whichfork; 2157 w = args->whichfork;
2191 ASSERT(w == XFS_DATA_FORK); 2158 ASSERT(w == XFS_DATA_FORK);
2192 mp = ip->i_mount; 2159 mp = dp->i_mount;
2193 lastoff = mp->m_dirfreeblk; 2160 lastoff = mp->m_dirfreeblk;
2194 error = xfs_bmap_last_before(tp, ip, &lastoff, w); 2161 error = xfs_bmap_last_before(tp, dp, &lastoff, w);
2195 if (error) 2162 if (error)
2196 return error; 2163 return error;
2197 if (unlikely(lastoff == 0)) { 2164 if (unlikely(lastoff == 0)) {
@@ -2203,7 +2170,7 @@ xfs_da3_swap_lastblock(
2203 * Read the last block in the btree space. 2170 * Read the last block in the btree space.
2204 */ 2171 */
2205 last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs; 2172 last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs;
2206 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);
2207 if (error) 2174 if (error)
2208 return error; 2175 return error;
2209 /* 2176 /*
@@ -2221,16 +2188,16 @@ xfs_da3_swap_lastblock(
2221 struct xfs_dir2_leaf_entry *ents; 2188 struct xfs_dir2_leaf_entry *ents;
2222 2189
2223 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; 2190 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
2224 xfs_dir3_leaf_hdr_from_disk(&leafhdr, dead_leaf2); 2191 dp->d_ops->leaf_hdr_from_disk(&leafhdr, dead_leaf2);
2225 ents = xfs_dir3_leaf_ents_p(dead_leaf2); 2192 ents = dp->d_ops->leaf_ents_p(dead_leaf2);
2226 dead_level = 0; 2193 dead_level = 0;
2227 dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); 2194 dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval);
2228 } else { 2195 } else {
2229 struct xfs_da3_icnode_hdr deadhdr; 2196 struct xfs_da3_icnode_hdr deadhdr;
2230 2197
2231 dead_node = (xfs_da_intnode_t *)dead_info; 2198 dead_node = (xfs_da_intnode_t *)dead_info;
2232 xfs_da3_node_hdr_from_disk(&deadhdr, dead_node); 2199 dp->d_ops->node_hdr_from_disk(&deadhdr, dead_node);
2233 btree = xfs_da3_node_tree_p(dead_node); 2200 btree = dp->d_ops->node_tree_p(dead_node);
2234 dead_level = deadhdr.level; 2201 dead_level = deadhdr.level;
2235 dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval); 2202 dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval);
2236 } 2203 }
@@ -2239,7 +2206,7 @@ xfs_da3_swap_lastblock(
2239 * 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.
2240 */ 2207 */
2241 if ((sib_blkno = be32_to_cpu(dead_info->back))) { 2208 if ((sib_blkno = be32_to_cpu(dead_info->back))) {
2242 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);
2243 if (error) 2210 if (error)
2244 goto done; 2211 goto done;
2245 sib_info = sib_buf->b_addr; 2212 sib_info = sib_buf->b_addr;
@@ -2261,7 +2228,7 @@ xfs_da3_swap_lastblock(
2261 * 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.
2262 */ 2229 */
2263 if ((sib_blkno = be32_to_cpu(dead_info->forw))) { 2230 if ((sib_blkno = be32_to_cpu(dead_info->forw))) {
2264 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);
2265 if (error) 2232 if (error)
2266 goto done; 2233 goto done;
2267 sib_info = sib_buf->b_addr; 2234 sib_info = sib_buf->b_addr;
@@ -2285,11 +2252,11 @@ xfs_da3_swap_lastblock(
2285 * 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.
2286 */ 2253 */
2287 for (;;) { 2254 for (;;) {
2288 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);
2289 if (error) 2256 if (error)
2290 goto done; 2257 goto done;
2291 par_node = par_buf->b_addr; 2258 par_node = par_buf->b_addr;
2292 xfs_da3_node_hdr_from_disk(&par_hdr, par_node); 2259 dp->d_ops->node_hdr_from_disk(&par_hdr, par_node);
2293 if (level >= 0 && level != par_hdr.level + 1) { 2260 if (level >= 0 && level != par_hdr.level + 1) {
2294 XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", 2261 XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)",
2295 XFS_ERRLEVEL_LOW, mp); 2262 XFS_ERRLEVEL_LOW, mp);
@@ -2297,7 +2264,7 @@ xfs_da3_swap_lastblock(
2297 goto done; 2264 goto done;
2298 } 2265 }
2299 level = par_hdr.level; 2266 level = par_hdr.level;
2300 btree = xfs_da3_node_tree_p(par_node); 2267 btree = dp->d_ops->node_tree_p(par_node);
2301 for (entno = 0; 2268 for (entno = 0;
2302 entno < par_hdr.count && 2269 entno < par_hdr.count &&
2303 be32_to_cpu(btree[entno].hashval) < dead_hash; 2270 be32_to_cpu(btree[entno].hashval) < dead_hash;
@@ -2336,18 +2303,18 @@ xfs_da3_swap_lastblock(
2336 error = XFS_ERROR(EFSCORRUPTED); 2303 error = XFS_ERROR(EFSCORRUPTED);
2337 goto done; 2304 goto done;
2338 } 2305 }
2339 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);
2340 if (error) 2307 if (error)
2341 goto done; 2308 goto done;
2342 par_node = par_buf->b_addr; 2309 par_node = par_buf->b_addr;
2343 xfs_da3_node_hdr_from_disk(&par_hdr, par_node); 2310 dp->d_ops->node_hdr_from_disk(&par_hdr, par_node);
2344 if (par_hdr.level != level) { 2311 if (par_hdr.level != level) {
2345 XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", 2312 XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)",
2346 XFS_ERRLEVEL_LOW, mp); 2313 XFS_ERRLEVEL_LOW, mp);
2347 error = XFS_ERROR(EFSCORRUPTED); 2314 error = XFS_ERROR(EFSCORRUPTED);
2348 goto done; 2315 goto done;
2349 } 2316 }
2350 btree = xfs_da3_node_tree_p(par_node); 2317 btree = dp->d_ops->node_tree_p(par_node);
2351 entno = 0; 2318 entno = 0;
2352 } 2319 }
2353 /* 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 a0961a61ac1a..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,104 +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 * The macros are used for shortform directories as they have no headers to read
501 * the magic number out of. Shortform directories need to know the size of the
502 * data block header because the sfe embeds the block offset of the entry into
503 * it so that it doesn't change when format conversion occurs. Bad Things Happen
504 * if we don't follow this rule.
505 *
506 * XXX: there is scope for significant optimisation of the logic here. Right
507 * now we are checking for "dir3 format" over and over again. Ideally we should
508 * only do it once for each operation.
509 */
510#define XFS_DIR3_DATA_DOT_OFFSET(mp) \
511 xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb))
512#define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \
513 (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 1))
514#define XFS_DIR3_DATA_FIRST_OFFSET(mp) \
515 (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 2))
516
517static inline xfs_dir2_data_aoff_t
518xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr)
519{
520 return xfs_dir3_data_entry_offset(hdr);
521}
522
523static inline xfs_dir2_data_aoff_t
524xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr)
525{
526 bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
527 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
528 return xfs_dir3_data_dot_offset(hdr) +
529 __xfs_dir3_data_entsize(dir3, 1);
530}
531
532static inline xfs_dir2_data_aoff_t
533xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr)
534{
535 bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
536 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
537 return xfs_dir3_data_dotdot_offset(hdr) +
538 __xfs_dir3_data_entsize(dir3, 2);
539}
540
541/*
542 * location of . and .. in data space (always block 0)
543 */
544static inline struct xfs_dir2_data_entry *
545xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr)
546{
547 return (struct xfs_dir2_data_entry *)
548 ((char *)hdr + xfs_dir3_data_dot_offset(hdr));
549}
550
551static inline struct xfs_dir2_data_entry *
552xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr)
553{
554 return (struct xfs_dir2_data_entry *)
555 ((char *)hdr + xfs_dir3_data_dotdot_offset(hdr));
556}
557
558static inline struct xfs_dir2_data_entry *
559xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr)
560{
561 return (struct xfs_dir2_data_entry *)
562 ((char *)hdr + xfs_dir3_data_first_offset(hdr));
563}
564
565/* 422/*
566 * Leaf block structures. 423 * Leaf block structures.
567 * 424 *
@@ -656,39 +513,6 @@ struct xfs_dir3_leaf {
656 513
657#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)
658 515
659extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
660 struct xfs_dir2_leaf *from);
661
662static inline int
663xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp)
664{
665 if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
666 lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
667 return sizeof(struct xfs_dir3_leaf_hdr);
668 return sizeof(struct xfs_dir2_leaf_hdr);
669}
670
671static inline int
672xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
673{
674 return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) /
675 (uint)sizeof(struct xfs_dir2_leaf_entry);
676}
677
678/*
679 * Get address of the bestcount field in the single-leaf block.
680 */
681static inline struct xfs_dir2_leaf_entry *
682xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
683{
684 if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
685 lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
686 struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp;
687 return lp3->__ents;
688 }
689 return lp->__ents;
690}
691
692/* 516/*
693 * Get address of the bestcount field in the single-leaf block. 517 * Get address of the bestcount field in the single-leaf block.
694 */ 518 */
@@ -880,48 +704,6 @@ struct xfs_dir3_icfree_hdr {
880 704
881}; 705};
882 706
883void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
884 struct xfs_dir2_free *from);
885
886static inline int
887xfs_dir3_free_hdr_size(struct xfs_mount *mp)
888{
889 if (xfs_sb_version_hascrc(&mp->m_sb))
890 return sizeof(struct xfs_dir3_free_hdr);
891 return sizeof(struct xfs_dir2_free_hdr);
892}
893
894static inline int
895xfs_dir3_free_max_bests(struct xfs_mount *mp)
896{
897 return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
898 sizeof(xfs_dir2_data_off_t);
899}
900
901static inline __be16 *
902xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
903{
904 return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
905}
906
907/*
908 * Convert data space db to the corresponding free db.
909 */
910static inline xfs_dir2_db_t
911xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
912{
913 return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
914}
915
916/*
917 * Convert data space db to the corresponding index in a free db.
918 */
919static inline int
920xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
921{
922 return db % xfs_dir3_free_max_bests(mp);
923}
924
925/* 707/*
926 * Single block format. 708 * Single block format.
927 * 709 *
@@ -972,4 +754,262 @@ xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
972 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);
973} 755}
974 756
975#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 0957aa98b6c0..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(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(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(hdr); 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 8993ec17452c..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 bb6e2848f473..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 71520e6e5d65..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:
@@ -64,7 +64,8 @@ int xfs_dqerror_mod = 33;
64struct kmem_zone *xfs_qm_dqtrxzone; 64struct kmem_zone *xfs_qm_dqtrxzone;
65static struct kmem_zone *xfs_qm_dqzone; 65static struct kmem_zone *xfs_qm_dqzone;
66 66
67static struct lock_class_key xfs_dquot_other_class; 67static struct lock_class_key xfs_dquot_group_class;
68static struct lock_class_key xfs_dquot_project_class;
68 69
69/* 70/*
70 * This is called to free all the memory associated with a dquot 71 * This is called to free all the memory associated with a dquot
@@ -291,118 +292,6 @@ xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
291 dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5; 292 dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
292} 293}
293 294
294STATIC bool
295xfs_dquot_buf_verify_crc(
296 struct xfs_mount *mp,
297 struct xfs_buf *bp)
298{
299 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
300 int ndquots;
301 int i;
302
303 if (!xfs_sb_version_hascrc(&mp->m_sb))
304 return true;
305
306 /*
307 * if we are in log recovery, the quota subsystem has not been
308 * initialised so we have no quotainfo structure. In that case, we need
309 * to manually calculate the number of dquots in the buffer.
310 */
311 if (mp->m_quotainfo)
312 ndquots = mp->m_quotainfo->qi_dqperchunk;
313 else
314 ndquots = xfs_qm_calc_dquots_per_chunk(mp,
315 XFS_BB_TO_FSB(mp, bp->b_length));
316
317 for (i = 0; i < ndquots; i++, d++) {
318 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
319 XFS_DQUOT_CRC_OFF))
320 return false;
321 if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
322 return false;
323 }
324 return true;
325}
326
327STATIC bool
328xfs_dquot_buf_verify(
329 struct xfs_mount *mp,
330 struct xfs_buf *bp)
331{
332 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
333 xfs_dqid_t id = 0;
334 int ndquots;
335 int i;
336
337 /*
338 * if we are in log recovery, the quota subsystem has not been
339 * initialised so we have no quotainfo structure. In that case, we need
340 * to manually calculate the number of dquots in the buffer.
341 */
342 if (mp->m_quotainfo)
343 ndquots = mp->m_quotainfo->qi_dqperchunk;
344 else
345 ndquots = xfs_qm_calc_dquots_per_chunk(mp, bp->b_length);
346
347 /*
348 * On the first read of the buffer, verify that each dquot is valid.
349 * We don't know what the id of the dquot is supposed to be, just that
350 * they should be increasing monotonically within the buffer. If the
351 * first id is corrupt, then it will fail on the second dquot in the
352 * buffer so corruptions could point to the wrong dquot in this case.
353 */
354 for (i = 0; i < ndquots; i++) {
355 struct xfs_disk_dquot *ddq;
356 int error;
357
358 ddq = &d[i].dd_diskdq;
359
360 if (i == 0)
361 id = be32_to_cpu(ddq->d_id);
362
363 error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
364 "xfs_dquot_buf_verify");
365 if (error)
366 return false;
367 }
368 return true;
369}
370
371static void
372xfs_dquot_buf_read_verify(
373 struct xfs_buf *bp)
374{
375 struct xfs_mount *mp = bp->b_target->bt_mount;
376
377 if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) {
378 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
379 xfs_buf_ioerror(bp, EFSCORRUPTED);
380 }
381}
382
383/*
384 * we don't calculate the CRC here as that is done when the dquot is flushed to
385 * the buffer after the update is done. This ensures that the dquot in the
386 * buffer always has an up-to-date CRC value.
387 */
388void
389xfs_dquot_buf_write_verify(
390 struct xfs_buf *bp)
391{
392 struct xfs_mount *mp = bp->b_target->bt_mount;
393
394 if (!xfs_dquot_buf_verify(mp, bp)) {
395 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
396 xfs_buf_ioerror(bp, EFSCORRUPTED);
397 return;
398 }
399}
400
401const struct xfs_buf_ops xfs_dquot_buf_ops = {
402 .verify_read = xfs_dquot_buf_read_verify,
403 .verify_write = xfs_dquot_buf_write_verify,
404};
405
406/* 295/*
407 * Allocate a block and fill it with dquots. 296 * Allocate a block and fill it with dquots.
408 * This is called when the bmapi finds a hole. 297 * This is called when the bmapi finds a hole.
@@ -513,6 +402,7 @@ xfs_qm_dqalloc(
513 402
514 return (error); 403 return (error);
515} 404}
405
516STATIC int 406STATIC int
517xfs_qm_dqrepair( 407xfs_qm_dqrepair(
518 struct xfs_mount *mp, 408 struct xfs_mount *mp,
@@ -546,7 +436,7 @@ xfs_qm_dqrepair(
546 /* Do the actual repair of dquots in this buffer */ 436 /* Do the actual repair of dquots in this buffer */
547 for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) { 437 for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) {
548 ddq = &d[i].dd_diskdq; 438 ddq = &d[i].dd_diskdq;
549 error = xfs_qm_dqcheck(mp, ddq, firstid + i, 439 error = xfs_dqcheck(mp, ddq, firstid + i,
550 dqp->dq_flags & XFS_DQ_ALLTYPES, 440 dqp->dq_flags & XFS_DQ_ALLTYPES,
551 XFS_QMOPT_DQREPAIR, "xfs_qm_dqrepair"); 441 XFS_QMOPT_DQREPAIR, "xfs_qm_dqrepair");
552 if (error) { 442 if (error) {
@@ -703,8 +593,20 @@ xfs_qm_dqread(
703 * Make sure group quotas have a different lock class than user 593 * Make sure group quotas have a different lock class than user
704 * quotas. 594 * quotas.
705 */ 595 */
706 if (!(type & XFS_DQ_USER)) 596 switch (type) {
707 lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); 597 case XFS_DQ_USER:
598 /* uses the default lock class */
599 break;
600 case XFS_DQ_GROUP:
601 lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class);
602 break;
603 case XFS_DQ_PROJ:
604 lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class);
605 break;
606 default:
607 ASSERT(0);
608 break;
609 }
708 610
709 XFS_STATS_INC(xs_qm_dquot); 611 XFS_STATS_INC(xs_qm_dquot);
710 612
@@ -1120,7 +1022,7 @@ xfs_qm_dqflush(
1120 /* 1022 /*
1121 * A simple sanity check in case we got a corrupted dquot.. 1023 * A simple sanity check in case we got a corrupted dquot..
1122 */ 1024 */
1123 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,
1124 XFS_QMOPT_DOWARN, "dqflush (incore copy)"); 1026 XFS_QMOPT_DOWARN, "dqflush (incore copy)");
1125 if (error) { 1027 if (error) {
1126 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 1edb5cc3e5f4..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.
@@ -515,7 +515,7 @@ typedef struct xfs_swapext
515/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */ 515/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */
516#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap) 516#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)
517#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64) 517#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64)
518#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_eofblocks) 518#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
519 519
520/* 520/*
521 * ioctl commands that replace IRIX syssgi()'s 521 * ioctl commands that replace IRIX syssgi()'s
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 193206ba4358..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
@@ -119,11 +114,6 @@ xfs_inode_free(
119 ip->i_itemp = NULL; 114 ip->i_itemp = NULL;
120 } 115 }
121 116
122 /* asserts to verify all state is correct here */
123 ASSERT(atomic_read(&ip->i_pincount) == 0);
124 ASSERT(!spin_is_locked(&ip->i_flags_lock));
125 ASSERT(!xfs_isiflocked(ip));
126
127 /* 117 /*
128 * Because we use RCU freeing we need to ensure the inode always 118 * Because we use RCU freeing we need to ensure the inode always
129 * appears to be reclaimed with an invalid inode number when in the 119 * appears to be reclaimed with an invalid inode number when in the
@@ -135,6 +125,10 @@ xfs_inode_free(
135 ip->i_ino = 0; 125 ip->i_ino = 0;
136 spin_unlock(&ip->i_flags_lock); 126 spin_unlock(&ip->i_flags_lock);
137 127
128 /* asserts to verify all state is correct here */
129 ASSERT(atomic_read(&ip->i_pincount) == 0);
130 ASSERT(!xfs_isiflocked(ip));
131
138 call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback); 132 call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
139} 133}
140 134
@@ -501,11 +495,6 @@ xfs_inode_ag_walk_grab(
501 if (!igrab(inode)) 495 if (!igrab(inode))
502 return ENOENT; 496 return ENOENT;
503 497
504 if (is_bad_inode(inode)) {
505 IRELE(ip);
506 return ENOENT;
507 }
508
509 /* inode is valid */ 498 /* inode is valid */
510 return 0; 499 return 0;
511 500
@@ -919,8 +908,6 @@ restart:
919 xfs_iflock(ip); 908 xfs_iflock(ip);
920 } 909 }
921 910
922 if (is_bad_inode(VFS_I(ip)))
923 goto reclaim;
924 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { 911 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
925 xfs_iunpin_wait(ip); 912 xfs_iunpin_wait(ip);
926 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 dabda9521b4b..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
@@ -1585,6 +1577,7 @@ xlog_recover_add_to_trans(
1585 "bad number of regions (%d) in inode log format", 1577 "bad number of regions (%d) in inode log format",
1586 in_f->ilf_size); 1578 in_f->ilf_size);
1587 ASSERT(0); 1579 ASSERT(0);
1580 kmem_free(ptr);
1588 return XFS_ERROR(EIO); 1581 return XFS_ERROR(EIO);
1589 } 1582 }
1590 1583
@@ -1970,6 +1963,13 @@ xlog_recover_do_inode_buffer(
1970 * magic number. If we don't recognise the magic number in the buffer, then 1963 * magic number. If we don't recognise the magic number in the buffer, then
1971 * return a LSN of -1 so that the caller knows it was an unrecognised block and 1964 * return a LSN of -1 so that the caller knows it was an unrecognised block and
1972 * so can recover the buffer. 1965 * so can recover the buffer.
1966 *
1967 * Note: we cannot rely solely on magic number matches to determine that the
1968 * buffer has a valid LSN - we also need to verify that it belongs to this
1969 * filesystem, so we need to extract the object's LSN and compare it to that
1970 * which we read from the superblock. If the UUIDs don't match, then we've got a
1971 * stale metadata block from an old filesystem instance that we need to recover
1972 * over the top of.
1973 */ 1973 */
1974static xfs_lsn_t 1974static xfs_lsn_t
1975xlog_recover_get_buf_lsn( 1975xlog_recover_get_buf_lsn(
@@ -1980,6 +1980,8 @@ xlog_recover_get_buf_lsn(
1980 __uint16_t magic16; 1980 __uint16_t magic16;
1981 __uint16_t magicda; 1981 __uint16_t magicda;
1982 void *blk = bp->b_addr; 1982 void *blk = bp->b_addr;
1983 uuid_t *uuid;
1984 xfs_lsn_t lsn = -1;
1983 1985
1984 /* v4 filesystems always recover immediately */ 1986 /* v4 filesystems always recover immediately */
1985 if (!xfs_sb_version_hascrc(&mp->m_sb)) 1987 if (!xfs_sb_version_hascrc(&mp->m_sb))
@@ -1992,43 +1994,79 @@ xlog_recover_get_buf_lsn(
1992 case XFS_ABTB_MAGIC: 1994 case XFS_ABTB_MAGIC:
1993 case XFS_ABTC_MAGIC: 1995 case XFS_ABTC_MAGIC:
1994 case XFS_IBT_CRC_MAGIC: 1996 case XFS_IBT_CRC_MAGIC:
1995 case XFS_IBT_MAGIC: 1997 case XFS_IBT_MAGIC: {
1996 return be64_to_cpu( 1998 struct xfs_btree_block *btb = blk;
1997 ((struct xfs_btree_block *)blk)->bb_u.s.bb_lsn); 1999
2000 lsn = be64_to_cpu(btb->bb_u.s.bb_lsn);
2001 uuid = &btb->bb_u.s.bb_uuid;
2002 break;
2003 }
1998 case XFS_BMAP_CRC_MAGIC: 2004 case XFS_BMAP_CRC_MAGIC:
1999 case XFS_BMAP_MAGIC: 2005 case XFS_BMAP_MAGIC: {
2000 return be64_to_cpu( 2006 struct xfs_btree_block *btb = blk;
2001 ((struct xfs_btree_block *)blk)->bb_u.l.bb_lsn); 2007
2008 lsn = be64_to_cpu(btb->bb_u.l.bb_lsn);
2009 uuid = &btb->bb_u.l.bb_uuid;
2010 break;
2011 }
2002 case XFS_AGF_MAGIC: 2012 case XFS_AGF_MAGIC:
2003 return be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn); 2013 lsn = be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn);
2014 uuid = &((struct xfs_agf *)blk)->agf_uuid;
2015 break;
2004 case XFS_AGFL_MAGIC: 2016 case XFS_AGFL_MAGIC:
2005 return be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn); 2017 lsn = be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn);
2018 uuid = &((struct xfs_agfl *)blk)->agfl_uuid;
2019 break;
2006 case XFS_AGI_MAGIC: 2020 case XFS_AGI_MAGIC:
2007 return be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn); 2021 lsn = be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn);
2022 uuid = &((struct xfs_agi *)blk)->agi_uuid;
2023 break;
2008 case XFS_SYMLINK_MAGIC: 2024 case XFS_SYMLINK_MAGIC:
2009 return be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn); 2025 lsn = be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn);
2026 uuid = &((struct xfs_dsymlink_hdr *)blk)->sl_uuid;
2027 break;
2010 case XFS_DIR3_BLOCK_MAGIC: 2028 case XFS_DIR3_BLOCK_MAGIC:
2011 case XFS_DIR3_DATA_MAGIC: 2029 case XFS_DIR3_DATA_MAGIC:
2012 case XFS_DIR3_FREE_MAGIC: 2030 case XFS_DIR3_FREE_MAGIC:
2013 return be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn); 2031 lsn = be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn);
2032 uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid;
2033 break;
2014 case XFS_ATTR3_RMT_MAGIC: 2034 case XFS_ATTR3_RMT_MAGIC:
2015 return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); 2035 lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
2036 uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid;
2037 break;
2016 case XFS_SB_MAGIC: 2038 case XFS_SB_MAGIC:
2017 return be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); 2039 lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
2040 uuid = &((struct xfs_dsb *)blk)->sb_uuid;
2041 break;
2018 default: 2042 default:
2019 break; 2043 break;
2020 } 2044 }
2021 2045
2046 if (lsn != (xfs_lsn_t)-1) {
2047 if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
2048 goto recover_immediately;
2049 return lsn;
2050 }
2051
2022 magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic); 2052 magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic);
2023 switch (magicda) { 2053 switch (magicda) {
2024 case XFS_DIR3_LEAF1_MAGIC: 2054 case XFS_DIR3_LEAF1_MAGIC:
2025 case XFS_DIR3_LEAFN_MAGIC: 2055 case XFS_DIR3_LEAFN_MAGIC:
2026 case XFS_DA3_NODE_MAGIC: 2056 case XFS_DA3_NODE_MAGIC:
2027 return be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn); 2057 lsn = be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn);
2058 uuid = &((struct xfs_da3_blkinfo *)blk)->uuid;
2059 break;
2028 default: 2060 default:
2029 break; 2061 break;
2030 } 2062 }
2031 2063
2064 if (lsn != (xfs_lsn_t)-1) {
2065 if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
2066 goto recover_immediately;
2067 return lsn;
2068 }
2069
2032 /* 2070 /*
2033 * We do individual object checks on dquot and inode buffers as they 2071 * We do individual object checks on dquot and inode buffers as they
2034 * have their own individual LSN records. Also, we could have a stale 2072 * have their own individual LSN records. Also, we could have a stale
@@ -2316,7 +2354,7 @@ xlog_recover_do_reg_buffer(
2316 item->ri_buf[i].i_len, __func__); 2354 item->ri_buf[i].i_len, __func__);
2317 goto next; 2355 goto next;
2318 } 2356 }
2319 error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr, 2357 error = xfs_dqcheck(mp, item->ri_buf[i].i_addr,
2320 -1, 0, XFS_QMOPT_DOWARN, 2358 -1, 0, XFS_QMOPT_DOWARN,
2321 "dquot_buf_recover"); 2359 "dquot_buf_recover");
2322 if (error) 2360 if (error)
@@ -2348,133 +2386,6 @@ xlog_recover_do_reg_buffer(
2348} 2386}
2349 2387
2350/* 2388/*
2351 * Do some primitive error checking on ondisk dquot data structures.
2352 */
2353int
2354xfs_qm_dqcheck(
2355 struct xfs_mount *mp,
2356 xfs_disk_dquot_t *ddq,
2357 xfs_dqid_t id,
2358 uint type, /* used only when IO_dorepair is true */
2359 uint flags,
2360 char *str)
2361{
2362 xfs_dqblk_t *d = (xfs_dqblk_t *)ddq;
2363 int errs = 0;
2364
2365 /*
2366 * We can encounter an uninitialized dquot buffer for 2 reasons:
2367 * 1. If we crash while deleting the quotainode(s), and those blks got
2368 * used for user data. This is because we take the path of regular
2369 * file deletion; however, the size field of quotainodes is never
2370 * updated, so all the tricks that we play in itruncate_finish
2371 * don't quite matter.
2372 *
2373 * 2. We don't play the quota buffers when there's a quotaoff logitem.
2374 * But the allocation will be replayed so we'll end up with an
2375 * uninitialized quota block.
2376 *
2377 * This is all fine; things are still consistent, and we haven't lost
2378 * any quota information. Just don't complain about bad dquot blks.
2379 */
2380 if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) {
2381 if (flags & XFS_QMOPT_DOWARN)
2382 xfs_alert(mp,
2383 "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
2384 str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
2385 errs++;
2386 }
2387 if (ddq->d_version != XFS_DQUOT_VERSION) {
2388 if (flags & XFS_QMOPT_DOWARN)
2389 xfs_alert(mp,
2390 "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
2391 str, id, ddq->d_version, XFS_DQUOT_VERSION);
2392 errs++;
2393 }
2394
2395 if (ddq->d_flags != XFS_DQ_USER &&
2396 ddq->d_flags != XFS_DQ_PROJ &&
2397 ddq->d_flags != XFS_DQ_GROUP) {
2398 if (flags & XFS_QMOPT_DOWARN)
2399 xfs_alert(mp,
2400 "%s : XFS dquot ID 0x%x, unknown flags 0x%x",
2401 str, id, ddq->d_flags);
2402 errs++;
2403 }
2404
2405 if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
2406 if (flags & XFS_QMOPT_DOWARN)
2407 xfs_alert(mp,
2408 "%s : ondisk-dquot 0x%p, ID mismatch: "
2409 "0x%x expected, found id 0x%x",
2410 str, ddq, id, be32_to_cpu(ddq->d_id));
2411 errs++;
2412 }
2413
2414 if (!errs && ddq->d_id) {
2415 if (ddq->d_blk_softlimit &&
2416 be64_to_cpu(ddq->d_bcount) >
2417 be64_to_cpu(ddq->d_blk_softlimit)) {
2418 if (!ddq->d_btimer) {
2419 if (flags & XFS_QMOPT_DOWARN)
2420 xfs_alert(mp,
2421 "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",
2422 str, (int)be32_to_cpu(ddq->d_id), ddq);
2423 errs++;
2424 }
2425 }
2426 if (ddq->d_ino_softlimit &&
2427 be64_to_cpu(ddq->d_icount) >
2428 be64_to_cpu(ddq->d_ino_softlimit)) {
2429 if (!ddq->d_itimer) {
2430 if (flags & XFS_QMOPT_DOWARN)
2431 xfs_alert(mp,
2432 "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",
2433 str, (int)be32_to_cpu(ddq->d_id), ddq);
2434 errs++;
2435 }
2436 }
2437 if (ddq->d_rtb_softlimit &&
2438 be64_to_cpu(ddq->d_rtbcount) >
2439 be64_to_cpu(ddq->d_rtb_softlimit)) {
2440 if (!ddq->d_rtbtimer) {
2441 if (flags & XFS_QMOPT_DOWARN)
2442 xfs_alert(mp,
2443 "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",
2444 str, (int)be32_to_cpu(ddq->d_id), ddq);
2445 errs++;
2446 }
2447 }
2448 }
2449
2450 if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
2451 return errs;
2452
2453 if (flags & XFS_QMOPT_DOWARN)
2454 xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);
2455
2456 /*
2457 * Typically, a repair is only requested by quotacheck.
2458 */
2459 ASSERT(id != -1);
2460 ASSERT(flags & XFS_QMOPT_DQREPAIR);
2461 memset(d, 0, sizeof(xfs_dqblk_t));
2462
2463 d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
2464 d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
2465 d->dd_diskdq.d_flags = type;
2466 d->dd_diskdq.d_id = cpu_to_be32(id);
2467
2468 if (xfs_sb_version_hascrc(&mp->m_sb)) {
2469 uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
2470 xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
2471 XFS_DQUOT_CRC_OFF);
2472 }
2473
2474 return errs;
2475}
2476
2477/*
2478 * Perform a dquot buffer recovery. 2389 * Perform a dquot buffer recovery.
2479 * 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
2480 * (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.
@@ -3079,7 +2990,7 @@ xlog_recover_dquot_pass2(
3079 */ 2990 */
3080 dq_f = item->ri_buf[0].i_addr; 2991 dq_f = item->ri_buf[0].i_addr;
3081 ASSERT(dq_f); 2992 ASSERT(dq_f);
3082 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,
3083 "xlog_recover_dquot_pass2 (log copy)"); 2994 "xlog_recover_dquot_pass2 (log copy)");
3084 if (error) 2995 if (error)
3085 return XFS_ERROR(EIO); 2996 return XFS_ERROR(EIO);
@@ -3099,7 +3010,7 @@ xlog_recover_dquot_pass2(
3099 * 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
3100 * minimal initialization then. 3011 * minimal initialization then.
3101 */ 3012 */
3102 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,
3103 "xlog_recover_dquot_pass2"); 3014 "xlog_recover_dquot_pass2");
3104 if (error) { 3015 if (error) {
3105 xfs_buf_relse(bp); 3016 xfs_buf_relse(bp);
@@ -4031,7 +3942,7 @@ xlog_unpack_data_crc(
4031 if (crc != rhead->h_crc) { 3942 if (crc != rhead->h_crc) {
4032 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)) {
4033 xfs_alert(log->l_mp, 3944 xfs_alert(log->l_mp,
4034 "log record CRC mismatch: found 0x%x, expected 0x%x.\n", 3945 "log record CRC mismatch: found 0x%x, expected 0x%x.",
4035 le32_to_cpu(rhead->h_crc), 3946 le32_to_cpu(rhead->h_crc),
4036 le32_to_cpu(crc)); 3947 le32_to_cpu(crc));
4037 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 15188cc99449..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>
@@ -918,7 +913,7 @@ xfs_flush_inodes(
918 struct super_block *sb = mp->m_super; 913 struct super_block *sb = mp->m_super;
919 914
920 if (down_read_trylock(&sb->s_umount)) { 915 if (down_read_trylock(&sb->s_umount)) {
921 sync_inodes_sb(sb); 916 sync_inodes_sb(sb, jiffies);
922 up_read(&sb->s_umount); 917 up_read(&sb->s_umount);
923 } 918 }
924} 919}
@@ -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"