diff options
Diffstat (limited to 'fs/xfs')
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 |
106 | xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o | 108 | |
109 | # xfs_rtbitmap is shared with libxfs | ||
110 | xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o \ | ||
111 | xfs_rtbitmap.o | ||
112 | |||
107 | xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o | 113 | xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o |
108 | xfs-$(CONFIG_PROC_FS) += xfs_stats.o | 114 | xfs-$(CONFIG_PROC_FS) += xfs_stats.o |
109 | xfs-$(CONFIG_SYSCTL) += xfs_sysctl.o | 115 | xfs-$(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 | ||
65 | void * | 65 | void * |
66 | kmem_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 | |||
76 | void * | ||
77 | kmem_zalloc_large(size_t size, xfs_km_flags_t flags) | 66 | kmem_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 | |||
132 | void * | ||
133 | kmem_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 | ||
58 | extern void *kmem_alloc(size_t, xfs_km_flags_t); | 63 | extern void *kmem_alloc(size_t, xfs_km_flags_t); |
59 | extern void *kmem_zalloc(size_t, xfs_km_flags_t); | ||
60 | extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t); | 64 | extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t); |
61 | extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); | 65 | extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); |
62 | extern void kmem_free(const void *); | 66 | extern void kmem_free(const void *); |
@@ -64,6 +68,12 @@ extern void kmem_free(const void *); | |||
64 | 68 | ||
65 | extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); | 69 | extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); |
66 | 70 | ||
71 | static inline void * | ||
72 | kmem_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 | ||
104 | extern void *kmem_zone_alloc(kmem_zone_t *, xfs_km_flags_t); | 114 | extern void *kmem_zone_alloc(kmem_zone_t *, xfs_km_flags_t); |
105 | extern void *kmem_zone_zalloc(kmem_zone_t *, xfs_km_flags_t); | 115 | |
116 | static inline void * | ||
117 | kmem_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 { | |||
128 | extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, | 128 | extern 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 | ||
131 | extern 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 { | |||
191 | extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, | 189 | extern 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 | ||
194 | extern 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 | ||
40 | struct workqueue_struct *xfs_alloc_wq; | 40 | struct 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 | ||
234 | extern const struct xfs_buf_ops xfs_agf_buf_ops; | ||
235 | extern 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 | ||
39 | STATIC struct xfs_btree_cur * | 37 | STATIC 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; | |||
27 | struct xfs_mount; | 27 | struct 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 | */ | ||
42 | typedef 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 | |||
47 | typedef 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 */ | ||
53 | typedef __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); |
96 | extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); | 63 | extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); |
97 | 64 | ||
98 | extern 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; |
935 | out: | 934 | out: |
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 | |||
32 | struct attrlist; | 22 | struct attrlist; |
33 | struct attrlist_cursor_kern; | 23 | struct attrlist_cursor_kern; |
34 | struct xfs_attr_list_context; | 24 | struct xfs_attr_list_context; |
@@ -38,226 +28,6 @@ struct xfs_da_state_blk; | |||
38 | struct xfs_inode; | 28 | struct xfs_inode; |
39 | struct xfs_trans; | 29 | struct 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 | |||
75 | typedef 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 | |||
80 | typedef 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 | |||
91 | typedef 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 | |||
98 | typedef 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 | |||
104 | typedef 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 | |||
111 | typedef 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 | */ | ||
123 | struct 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 | |||
136 | struct 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 | */ | ||
153 | struct 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 | |||
200 | static inline int | ||
201 | xfs_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 | |||
208 | static inline struct xfs_attr_leaf_entry * | ||
209 | xfs_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 | */ | ||
219 | static inline char * | ||
220 | xfs_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 | |||
227 | static inline xfs_attr_leaf_name_remote_t * | ||
228 | xfs_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 | |||
233 | static inline xfs_attr_leaf_name_local_t * | ||
234 | xfs_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 | */ | ||
244 | static 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 | |||
250 | static 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 | |||
256 | static 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, | |||
336 | void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to, | 106 | void 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 | ||
339 | extern 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 | ||
47 | STATIC int | 45 | STATIC int |
48 | xfs_attr_shortform_compare(const void *a, const void *b) | 46 | xfs_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 | */ | ||
31 | struct 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 | |||
48 | extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; | ||
49 | |||
50 | int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); | 21 | int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); |
51 | 22 | ||
52 | int xfs_attr_rmtval_get(struct xfs_da_args *args); | 23 | int 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 | ||
55 | kmem_zone_t *xfs_bmap_free_item_zone; | 53 | kmem_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 | |||
24 | struct xfs_btree_cur; | 21 | struct xfs_btree_cur; |
25 | struct xfs_btree_block; | 22 | struct xfs_btree_block; |
26 | struct xfs_mount; | 23 | struct xfs_mount; |
@@ -28,85 +25,6 @@ struct xfs_inode; | |||
28 | struct xfs_trans; | 25 | struct xfs_trans; |
29 | 26 | ||
30 | /* | 27 | /* |
31 | * Bmap root header, on-disk form only. | ||
32 | */ | ||
33 | typedef 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 | |||
50 | typedef struct xfs_bmbt_rec { | ||
51 | __be64 l0, l1; | ||
52 | } xfs_bmbt_rec_t; | ||
53 | |||
54 | typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ | ||
55 | typedef xfs_bmbt_rec_t xfs_bmdr_rec_t; | ||
56 | |||
57 | typedef 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 | |||
72 | static inline int isnullstartblock(xfs_fsblock_t x) | ||
73 | { | ||
74 | return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK; | ||
75 | } | ||
76 | |||
77 | static inline int isnulldstartblock(xfs_dfsbno_t x) | ||
78 | { | ||
79 | return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK; | ||
80 | } | ||
81 | |||
82 | static inline xfs_fsblock_t nullstartblock(int k) | ||
83 | { | ||
84 | ASSERT(k < (1 << STARTBLOCKVALBITS)); | ||
85 | return STARTBLOCKMASK | (k); | ||
86 | } | ||
87 | |||
88 | static 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 | */ | ||
96 | typedef enum { | ||
97 | XFS_EXTFMT_NOSTATE = 0, | ||
98 | XFS_EXTFMT_HASSTATE | ||
99 | } xfs_exntfmt_t; | ||
100 | |||
101 | /* | ||
102 | * Possible extent states. | ||
103 | */ | ||
104 | typedef 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 | */ | ||
120 | typedef 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 | */ | ||
131 | typedef 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 */ | ||
136 | typedef __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, | |||
243 | extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, | 140 | extern 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 | ||
246 | extern 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 | /* | 968 | int |
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 | */ | ||
987 | STATIC int | ||
988 | xfs_alloc_file_space( | 969 | xfs_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 | /* | 1215 | int |
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 | */ | ||
1247 | STATIC int | ||
1248 | xfs_free_file_space( | 1216 | xfs_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 | ||
1430 | STATIC int | 1388 | int |
1431 | xfs_zero_file_space( | 1389 | xfs_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 | ||
1489 | out_unlock: | 1443 | out: |
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 | */ | ||
1507 | int | ||
1508 | xfs_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 */ |
96 | int xfs_change_file_space(struct xfs_inode *ip, int cmd, | 96 | int 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); | 98 | int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, |
99 | xfs_off_t len); | ||
100 | int 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 */ |
101 | bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); | 104 | bool 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; | |||
27 | extern kmem_zone_t *xfs_btree_cur_zone; | 27 | extern 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 | */ | ||
55 | struct 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 | ||
44 | static kmem_zone_t *xfs_buf_zone; | 45 | static 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 | ||
33 | kmem_zone_t *xfs_buf_item_zone; | 34 | kmem_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 | */ |
810 | void | 812 | static void |
811 | xfs_buf_item_log_segment( | 813 | xfs_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 *, | |||
71 | void xfs_buf_iodone_callbacks(struct xfs_buf *); | 71 | void xfs_buf_iodone_callbacks(struct xfs_buf *); |
72 | void xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *); | 72 | void xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *); |
73 | 73 | ||
74 | void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *, | ||
75 | enum xfs_blft); | ||
76 | void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp, struct xfs_buf *src_bp); | ||
77 | |||
78 | extern kmem_zone_t *xfs_buf_item_zone; | 74 | extern 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 | ||
132 | void | ||
133 | xfs_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 | |||
157 | void | ||
158 | xfs_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 | |||
182 | static bool | 132 | static bool |
183 | xfs_da3_node_verify( | 133 | xfs_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 | */ |
1275 | STATIC uint | 1234 | STATIC uint |
1276 | xfs_da3_node_lasthash( | 1235 | xfs_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 | */ |
1643 | STATIC int | 1608 | STATIC int |
1644 | xfs_da3_node_order( | 1609 | xfs_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; | |||
23 | struct xfs_inode; | 23 | struct xfs_inode; |
24 | struct xfs_trans; | 24 | struct xfs_trans; |
25 | struct zone; | 25 | struct zone; |
26 | 26 | struct 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 | |||
42 | typedef 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 | |||
62 | struct 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 | |||
87 | typedef 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 | |||
93 | struct 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 | |||
102 | typedef 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 | |||
107 | typedef struct xfs_da_intnode { | ||
108 | struct xfs_da_node_hdr hdr; | ||
109 | struct xfs_da_node_entry __btree[]; | ||
110 | } xfs_da_intnode_t; | ||
111 | |||
112 | struct 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 | */ | ||
122 | struct 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 | |||
130 | extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to, | ||
131 | struct xfs_da_intnode *from); | ||
132 | extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to, | ||
133 | struct xfs_da3_icnode_hdr *from); | ||
134 | |||
135 | static 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 | } | ||
142 | static inline int | ||
143 | xfs_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 | |||
150 | static inline struct xfs_da_node_entry * | ||
151 | xfs_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 | |||
160 | extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to, | ||
161 | struct xfs_da_intnode *from); | ||
162 | extern 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 | ||
312 | extern 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 | */ | ||
35 | static int | ||
36 | xfs_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 | |||
48 | static int | ||
49 | xfs_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 | |||
56 | static struct xfs_dir2_sf_entry * | ||
57 | xfs_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 | |||
65 | static struct xfs_dir2_sf_entry * | ||
66 | xfs_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 | */ | ||
81 | static __uint8_t | ||
82 | xfs_dir2_sfe_get_ftype( | ||
83 | struct xfs_dir2_sf_entry *sfep) | ||
84 | { | ||
85 | return XFS_DIR3_FT_UNKNOWN; | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | xfs_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 | |||
96 | static __uint8_t | ||
97 | xfs_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 | |||
108 | static void | ||
109 | xfs_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 | */ | ||
125 | static xfs_ino_t | ||
126 | xfs_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 | |||
136 | static void | ||
137 | xfs_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 | |||
150 | static xfs_ino_t | ||
151 | xfs_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 | |||
157 | static void | ||
158 | xfs_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 | */ | ||
171 | static xfs_ino_t | ||
172 | xfs_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 | |||
180 | static void | ||
181 | xfs_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 | |||
190 | static xfs_ino_t | ||
191 | xfs_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 | |||
199 | static void | ||
200 | xfs_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 | |||
236 | static int | ||
237 | xfs_dir2_data_entsize( | ||
238 | int n) | ||
239 | { | ||
240 | return XFS_DIR2_DATA_ENTSIZE(n); | ||
241 | } | ||
242 | |||
243 | static int | ||
244 | xfs_dir3_data_entsize( | ||
245 | int n) | ||
246 | { | ||
247 | return XFS_DIR3_DATA_ENTSIZE(n); | ||
248 | } | ||
249 | |||
250 | static __uint8_t | ||
251 | xfs_dir2_data_get_ftype( | ||
252 | struct xfs_dir2_data_entry *dep) | ||
253 | { | ||
254 | return XFS_DIR3_FT_UNKNOWN; | ||
255 | } | ||
256 | |||
257 | static void | ||
258 | xfs_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 | |||
265 | static __uint8_t | ||
266 | xfs_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 | |||
277 | static void | ||
278 | xfs_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 | */ | ||
291 | static __be16 * | ||
292 | xfs_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 | |||
299 | static __be16 * | ||
300 | xfs_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 | */ | ||
310 | static struct xfs_dir2_data_entry * | ||
311 | xfs_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 | |||
318 | static struct xfs_dir2_data_entry * | ||
319 | xfs_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 | |||
327 | static struct xfs_dir2_data_entry * | ||
328 | xfs_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 | |||
337 | static struct xfs_dir2_data_entry * | ||
338 | xfs_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 | |||
346 | static struct xfs_dir2_data_entry * | ||
347 | xfs_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 | |||
356 | static struct xfs_dir2_data_entry * | ||
357 | xfs_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 | |||
364 | static struct xfs_dir2_data_entry * | ||
365 | xfs_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 | |||
373 | static struct xfs_dir2_data_entry * | ||
374 | xfs_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 | |||
383 | static struct xfs_dir2_data_free * | ||
384 | xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) | ||
385 | { | ||
386 | return hdr->bestfree; | ||
387 | } | ||
388 | |||
389 | static struct xfs_dir2_data_free * | ||
390 | xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) | ||
391 | { | ||
392 | return ((struct xfs_dir3_data_hdr *)hdr)->best_free; | ||
393 | } | ||
394 | |||
395 | static struct xfs_dir2_data_entry * | ||
396 | xfs_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 | |||
402 | static struct xfs_dir2_data_unused * | ||
403 | xfs_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 | |||
409 | static struct xfs_dir2_data_entry * | ||
410 | xfs_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 | |||
416 | static struct xfs_dir2_data_unused * | ||
417 | xfs_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 | */ | ||
427 | static int | ||
428 | xfs_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 | |||
434 | static struct xfs_dir2_leaf_entry * | ||
435 | xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp) | ||
436 | { | ||
437 | return lp->__ents; | ||
438 | } | ||
439 | |||
440 | static int | ||
441 | xfs_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 | |||
447 | static struct xfs_dir2_leaf_entry * | ||
448 | xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) | ||
449 | { | ||
450 | return ((struct xfs_dir3_leaf *)lp)->__ents; | ||
451 | } | ||
452 | |||
453 | static void | ||
454 | xfs_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 | |||
468 | static void | ||
469 | xfs_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 | |||
483 | static void | ||
484 | xfs_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 | |||
500 | static void | ||
501 | xfs_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 | */ | ||
521 | static struct xfs_da_node_entry * | ||
522 | xfs_da2_node_tree_p(struct xfs_da_intnode *dap) | ||
523 | { | ||
524 | return dap->__btree; | ||
525 | } | ||
526 | |||
527 | static struct xfs_da_node_entry * | ||
528 | xfs_da3_node_tree_p(struct xfs_da_intnode *dap) | ||
529 | { | ||
530 | return ((struct xfs_da3_intnode *)dap)->__btree; | ||
531 | } | ||
532 | |||
533 | static void | ||
534 | xfs_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 | |||
546 | static void | ||
547 | xfs_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 | |||
559 | static void | ||
560 | xfs_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 | |||
574 | static void | ||
575 | xfs_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 | */ | ||
593 | static int | ||
594 | xfs_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 | |||
600 | static __be16 * | ||
601 | xfs_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 | */ | ||
609 | static xfs_dir2_db_t | ||
610 | xfs_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 | */ | ||
618 | static int | ||
619 | xfs_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 | |||
624 | static int | ||
625 | xfs_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 | |||
631 | static __be16 * | ||
632 | xfs_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 | */ | ||
640 | static xfs_dir2_db_t | ||
641 | xfs_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 | */ | ||
649 | static int | ||
650 | xfs_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 | |||
655 | static void | ||
656 | xfs_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 | |||
667 | static void | ||
668 | xfs_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 | |||
680 | static void | ||
681 | xfs_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 | |||
695 | static void | ||
696 | xfs_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 | |||
710 | static 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 | |||
760 | static 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 | |||
810 | static 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 | |||
860 | static 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 | |||
867 | static 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 | */ | ||
879 | const struct xfs_dir_ops * | ||
880 | xfs_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 | |||
895 | const struct xfs_dir_ops * | ||
896 | xfs_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 | |||
37 | typedef 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 | |||
57 | struct 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 | |||
82 | typedef 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 | |||
88 | struct 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 | |||
97 | typedef 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 | |||
102 | typedef struct xfs_da_intnode { | ||
103 | struct xfs_da_node_hdr hdr; | ||
104 | struct xfs_da_node_entry __btree[]; | ||
105 | } xfs_da_intnode_t; | ||
106 | |||
107 | struct 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 | */ | ||
117 | struct 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 | ||
192 | static inline int | ||
193 | xfs_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 | |||
208 | static inline struct xfs_dir2_sf_entry * | ||
209 | xfs_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 | */ | ||
223 | static inline __uint8_t * | ||
224 | xfs_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 | |||
231 | static inline __uint8_t | ||
232 | xfs_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 | |||
248 | static inline void | ||
249 | xfs_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 | ||
348 | static inline struct xfs_dir2_data_free * | ||
349 | xfs_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 | */ | ||
394 | static 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 | } | ||
407 | static inline int | ||
408 | xfs_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 | |||
416 | static inline __uint8_t | ||
417 | xfs_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 | |||
432 | static inline void | ||
433 | xfs_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 | */ | ||
448 | static inline __be16 * | ||
449 | xfs_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 | */ |
460 | static inline __be16 * | 415 | static 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 | ||
467 | static inline size_t | ||
468 | xfs_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 | |||
475 | static inline size_t | ||
476 | xfs_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 | |||
483 | static inline struct xfs_dir2_data_entry * | ||
484 | xfs_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 | |||
490 | static inline struct xfs_dir2_data_unused * | ||
491 | xfs_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 | |||
517 | static inline xfs_dir2_data_aoff_t | ||
518 | xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) | ||
519 | { | ||
520 | return xfs_dir3_data_entry_offset(hdr); | ||
521 | } | ||
522 | |||
523 | static inline xfs_dir2_data_aoff_t | ||
524 | xfs_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 | |||
532 | static inline xfs_dir2_data_aoff_t | ||
533 | xfs_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 | */ | ||
544 | static inline struct xfs_dir2_data_entry * | ||
545 | xfs_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 | |||
551 | static inline struct xfs_dir2_data_entry * | ||
552 | xfs_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 | |||
558 | static inline struct xfs_dir2_data_entry * | ||
559 | xfs_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 | ||
659 | extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, | ||
660 | struct xfs_dir2_leaf *from); | ||
661 | |||
662 | static inline int | ||
663 | xfs_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 | |||
671 | static inline int | ||
672 | xfs_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 | */ | ||
681 | static inline struct xfs_dir2_leaf_entry * | ||
682 | xfs_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 | ||
883 | void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to, | ||
884 | struct xfs_dir2_free *from); | ||
885 | |||
886 | static inline int | ||
887 | xfs_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 | |||
894 | static inline int | ||
895 | xfs_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 | |||
901 | static inline __be16 * | ||
902 | xfs_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 | */ | ||
910 | static inline xfs_dir2_db_t | ||
911 | xfs_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 | */ | ||
919 | static inline int | ||
920 | xfs_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 | |||
798 | typedef 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 | |||
803 | typedef 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 | |||
814 | typedef 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 | |||
821 | typedef 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 | |||
827 | typedef 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 | |||
834 | typedef 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 | */ | ||
846 | struct 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 | |||
859 | struct 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 | */ | ||
876 | struct 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 | |||
923 | static inline int | ||
924 | xfs_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 | |||
931 | static inline struct xfs_attr_leaf_entry * | ||
932 | xfs_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 | */ | ||
942 | static inline char * | ||
943 | xfs_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 | |||
950 | static inline xfs_attr_leaf_name_remote_t * | ||
951 | xfs_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 | |||
956 | static inline xfs_attr_leaf_name_local_t * | ||
957 | xfs_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 | */ | ||
967 | static 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 | |||
973 | static 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 | |||
979 | static 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 | |||
998 | struct 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 | ||
40 | struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; | 39 | struct 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; | |||
32 | extern struct xfs_name xfs_name_dotdot; | 32 | extern struct xfs_name xfs_name_dotdot; |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * directory operations vector for encode/decode routines | ||
36 | */ | ||
37 | struct 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 | |||
106 | extern const struct xfs_dir_ops * | ||
107 | xfs_dir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); | ||
108 | extern 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 | */ |
37 | extern void xfs_dir_startup(void); | 114 | extern 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 | */ |
68 | extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); | ||
69 | extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp, | ||
70 | xfs_ino_t ino); | ||
71 | extern 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); | ||
73 | extern 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 | |||
77 | extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r); | 145 | extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r); |
78 | extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r); | 146 | extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r); |
79 | extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, | 147 | extern 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 | ||
82 | extern void xfs_dir2_data_freescan(struct xfs_mount *mp, | 150 | extern 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); |
84 | extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp, | 152 | extern 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); |
86 | extern void xfs_dir2_data_log_header(struct xfs_trans *tp, | 154 | extern void xfs_dir2_data_log_header(struct xfs_trans *tp, struct xfs_inode *dp, |
87 | struct xfs_buf *bp); | 155 | struct xfs_buf *bp); |
88 | extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp, | 156 | extern 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); |
90 | extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_buf *bp, | 158 | extern 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); | ||
161 | extern 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); |
93 | extern 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 | ||
97 | extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( | 166 | extern 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 | ||
100 | extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; | 170 | extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; |
101 | extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; | 171 | extern 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 | ||
169 | static void | 169 | static void |
170 | xfs_dir2_block_need_space( | 170 | xfs_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: | |||
280 | static void | 281 | static void |
281 | xfs_dir2_block_compact( | 282 | xfs_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 | */ |
328 | xfs_dir2_data_free_t * | 345 | xfs_dir2_data_free_t * |
329 | xfs_dir2_data_freefind( | 346 | xfs_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 | */ |
400 | xfs_dir2_data_free_t * /* entry inserted */ | 416 | xfs_dir2_data_free_t * /* entry inserted */ |
401 | xfs_dir2_data_freeinsert( | 417 | xfs_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 | */ |
445 | STATIC void | 460 | STATIC void |
446 | xfs_dir2_data_freeremove( | 461 | xfs_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 | */ |
487 | void | 501 | void |
488 | xfs_dir2_data_freescan( | 502 | xfs_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( | |||
626 | void | 640 | void |
627 | xfs_dir2_data_log_entry( | 641 | xfs_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( | |||
648 | void | 662 | void |
649 | xfs_dir2_data_log_header( | 663 | xfs_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( | |||
698 | void | 715 | void |
699 | xfs_dir2_data_make_free( | 716 | xfs_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( | |||
884 | void | 903 | void |
885 | xfs_dir2_data_use_free( | 904 | xfs_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) \ |
56 | do { \ | 54 | do { \ |
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 | ||
61 | STATIC bool | 59 | STATIC bool |
62 | xfs_dir3_leaf1_check( | 60 | xfs_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 | ||
84 | void | ||
85 | xfs_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 | |||
112 | void | ||
113 | xfs_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 | |||
140 | bool | 82 | bool |
141 | xfs_dir3_leaf_check_int( | 83 | xfs_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 | ||
221 | static void | 175 | static 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 | */ |
1122 | void | 1077 | void |
1123 | xfs_dir3_leaf_log_ents( | 1078 | xfs_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( | |||
1149 | void | 1105 | void |
1150 | xfs_dir3_leaf_log_header( | 1106 | xfs_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) \ |
59 | do { \ | 58 | do { \ |
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 | ||
64 | static bool | 63 | static bool |
65 | xfs_dir3_leafn_check( | 64 | xfs_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 | ||
87 | static bool | 86 | static 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 | |||
197 | void | ||
198 | xfs_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 | |||
220 | static void | ||
221 | xfs_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 | |||
243 | static int | 195 | static int |
244 | xfs_dir3_free_get_buf( | 196 | xfs_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( | |||
288 | STATIC void | 240 | STATIC void |
289 | xfs_dir2_free_log_bests( | 241 | xfs_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( | |||
311 | static void | 264 | static void |
312 | xfs_dir2_free_log_header( | 265 | xfs_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 |
509 | static void | 463 | static void |
510 | xfs_dir2_free_hdr_check( | 464 | xfs_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 | */ |
531 | xfs_dahash_t /* hash value */ | 485 | xfs_dahash_t /* hash value */ |
532 | xfs_dir2_leafn_lasthash( | 486 | xfs_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 | */ |
957 | int /* sort order */ | 914 | int /* sort order */ |
958 | xfs_dir2_leafn_order( | 915 | xfs_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 | ||
60 | extern struct xfs_dir2_data_free * | 60 | extern struct xfs_dir2_data_free * |
61 | xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, | 61 | xfs_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); | ||
63 | extern int xfs_dir3_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno, | 64 | extern 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); |
77 | extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, | 78 | extern 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); |
79 | extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, | 80 | extern 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); |
81 | extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, | 82 | extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, struct xfs_inode *dp, |
82 | struct xfs_buf *bp); | 83 | struct xfs_buf *bp); |
83 | extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); | 84 | extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); |
84 | extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); | 85 | extern 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); |
94 | extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); | 95 | extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); |
95 | 96 | ||
96 | extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, | 97 | extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, struct xfs_inode *dp, |
97 | struct xfs_dir2_leaf *from); | ||
98 | extern void xfs_dir3_leaf_hdr_to_disk(struct xfs_dir2_leaf *to, | ||
99 | struct xfs_dir3_icleaf_hdr *from); | ||
100 | extern 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 */ |
104 | extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, | 101 | extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, |
105 | struct xfs_buf *lbp); | 102 | struct xfs_buf *lbp); |
106 | extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_buf *bp, int *count); | 103 | extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_inode *dp, |
104 | struct xfs_buf *bp, int *count); | ||
107 | extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp, | 105 | extern 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); |
110 | extern int xfs_dir2_leafn_order(struct xfs_buf *leaf1_bp, | 108 | extern 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); |
112 | extern int xfs_dir2_leafn_split(struct xfs_da_state *state, | 110 | extern 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 | */ | ||
66 | static xfs_ino_t | ||
67 | xfs_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 | |||
77 | static void | ||
78 | xfs_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 | |||
91 | xfs_ino_t | ||
92 | xfs_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 | |||
98 | void | ||
99 | xfs_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 | */ | ||
112 | static xfs_dir2_inou_t * | ||
113 | xfs_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 | |||
123 | xfs_ino_t | ||
124 | xfs_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 | |||
132 | void | ||
133 | xfs_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 | ||
37 | STATIC int | 36 | STATIC int |
38 | xfs_trim_extents( | 37 | xfs_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; | |||
64 | struct kmem_zone *xfs_qm_dqtrxzone; | 64 | struct kmem_zone *xfs_qm_dqtrxzone; |
65 | static struct kmem_zone *xfs_qm_dqzone; | 65 | static struct kmem_zone *xfs_qm_dqzone; |
66 | 66 | ||
67 | static struct lock_class_key xfs_dquot_other_class; | 67 | static struct lock_class_key xfs_dquot_group_class; |
68 | static 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 | ||
294 | STATIC bool | ||
295 | xfs_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 | |||
327 | STATIC bool | ||
328 | xfs_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 | |||
371 | static void | ||
372 | xfs_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 | */ | ||
388 | void | ||
389 | xfs_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 | |||
401 | const 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 | |||
516 | STATIC int | 406 | STATIC int |
517 | xfs_qm_dqrepair( | 407 | xfs_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 | ||
175 | extern 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 | |||
36 | int | ||
37 | xfs_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 | */ | ||
53 | int | ||
54 | xfs_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 | |||
177 | STATIC bool | ||
178 | xfs_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 | |||
210 | STATIC bool | ||
211 | xfs_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 | |||
254 | static void | ||
255 | xfs_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 | */ | ||
271 | static void | ||
272 | xfs_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 | |||
284 | const 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 | ||
39 | static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip) | 35 | static 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 | ||
34 | void | 35 | void |
35 | xfs_extent_busy_insert( | 36 | xfs_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 | ||
23 | struct xfs_mount; | ||
24 | struct xfs_trans; | ||
25 | struct 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 | ||
806 | STATIC long | 808 | STATIC long |
807 | xfs_file_fallocate( | 809 | xfs_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 | ||
858 | out_unlock: | 880 | out_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 | ||
159 | int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); | 159 | |
160 | int 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 |
162 | bool 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 |
164 | void 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 | */ | |
167 | extern 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 | */ | ||
175 | typedef 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 | |||
180 | typedef 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 */ | ||
186 | typedef __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 | |||
204 | typedef __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 | |||
210 | static 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 | */ | ||
218 | typedef 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 | |||
224 | typedef 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 | */ | ||
234 | typedef struct xfs_inobt_key { | ||
235 | __be32 ir_startino; /* starting inode number */ | ||
236 | } xfs_inobt_key_t; | ||
237 | |||
238 | /* btree pointer type */ | ||
239 | typedef __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 | */ | ||
261 | typedef 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 | |||
278 | typedef struct xfs_bmbt_rec { | ||
279 | __be64 l0, l1; | ||
280 | } xfs_bmbt_rec_t; | ||
281 | |||
282 | typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ | ||
283 | typedef xfs_bmbt_rec_t xfs_bmdr_rec_t; | ||
284 | |||
285 | typedef 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 | |||
300 | static inline int isnullstartblock(xfs_fsblock_t x) | ||
301 | { | ||
302 | return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK; | ||
303 | } | ||
304 | |||
305 | static inline int isnulldstartblock(xfs_dfsbno_t x) | ||
306 | { | ||
307 | return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK; | ||
308 | } | ||
309 | |||
310 | static inline xfs_fsblock_t nullstartblock(int k) | ||
311 | { | ||
312 | ASSERT(k < (1 << STARTBLOCKVALBITS)); | ||
313 | return STARTBLOCKMASK | (k); | ||
314 | } | ||
315 | |||
316 | static 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 | */ | ||
324 | typedef enum { | ||
325 | XFS_EXTFMT_NOSTATE = 0, | ||
326 | XFS_EXTFMT_HASSTATE | ||
327 | } xfs_exntfmt_t; | ||
328 | |||
329 | /* | ||
330 | * Possible extent states. | ||
331 | */ | ||
332 | typedef 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 | */ | ||
340 | typedef 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 | */ | ||
351 | typedef 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 */ | ||
356 | typedef __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 | */ | ||
373 | struct 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; | |||
23 | struct xfs_imap; | 23 | struct xfs_imap; |
24 | struct xfs_mount; | 24 | struct xfs_mount; |
25 | struct xfs_trans; | 25 | struct xfs_trans; |
26 | struct 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; | |||
42 | static inline struct xfs_dinode * | 43 | static inline struct xfs_dinode * |
43 | xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) | 44 | xfs_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 | ||
161 | extern 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 | ||
40 | STATIC int | 39 | STATIC 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; | |||
27 | struct xfs_mount; | 27 | struct 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 | |||
35 | typedef __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 | |||
41 | static 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 | */ | ||
49 | typedef 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 | |||
55 | typedef 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 | */ | ||
65 | typedef struct xfs_inobt_key { | ||
66 | __be32 ir_startino; /* starting inode number */ | ||
67 | } xfs_inobt_key_t; | ||
68 | |||
69 | /* btree pointer type */ | ||
70 | typedef __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); |
111 | extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); | 62 | extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); |
112 | 63 | ||
113 | extern 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 | ||
56 | kmem_zone_t *xfs_inode_zone; | 55 | kmem_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 | */ | ||
1669 | STATIC int | ||
1670 | xfs_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 | |||
1709 | error_trans_cancel: | ||
1710 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
1711 | error_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 | */ | ||
1721 | STATIC int | ||
1722 | xfs_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 | */ |
1673 | int | 1792 | void |
1674 | xfs_inactive( | 1793 | xfs_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); |
1833 | out_unlock: | ||
1834 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1835 | out: | ||
1836 | return VN_INACTIVE_CACHE; | ||
1837 | out_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 | */ | ||
2373 | int | 2434 | int |
2374 | xfs_remove( | 2435 | xfs_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 | |||
28 | struct xfs_dinode; | 27 | struct xfs_dinode; |
29 | struct xfs_inode; | 28 | struct xfs_inode; |
30 | struct xfs_buf; | 29 | struct 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 | ||
318 | int xfs_release(struct xfs_inode *ip); | 320 | int xfs_release(struct xfs_inode *ip); |
319 | int xfs_inactive(struct xfs_inode *ip); | 321 | void xfs_inactive(struct xfs_inode *ip); |
320 | int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, | 322 | int 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); |
322 | int xfs_create(struct xfs_inode *dp, struct xfs_name *name, | 324 | int 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 | ||
50 | extern const struct xfs_buf_ops xfs_inode_buf_ops; | ||
51 | extern 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 | ||
49 | kmem_zone_t *xfs_ifork_zone; | 39 | kmem_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( | |||
1359 | void | 1348 | void |
1360 | xfs_iext_realloc_direct( | 1349 | xfs_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 | ||
21 | struct xfs_inode_log_item; | 21 | struct xfs_inode_log_item; |
22 | struct 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 | ||
35 | kmem_zone_t *xfs_ili_zone; /* inode log item zone */ | 35 | kmem_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 | |||
787 | out_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 | |||
655 | xfs_iomap_write_allocate( | 649 | xfs_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 @@ | |||
21 | struct xfs_inode; | 21 | struct xfs_inode; |
22 | struct xfs_bmbt_irec; | 22 | struct xfs_bmbt_irec; |
23 | 23 | ||
24 | extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, | 24 | int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, |
25 | struct xfs_bmbt_irec *, int); | 25 | struct xfs_bmbt_irec *, int); |
26 | extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, | 26 | int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, |
27 | struct xfs_bmbt_irec *); | 27 | struct xfs_bmbt_irec *); |
28 | extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t, | 28 | int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, |
29 | struct xfs_bmbt_irec *); | 29 | struct xfs_bmbt_irec *); |
30 | extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t); | 30 | int 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: | |||
709 | int | 705 | int |
710 | xfs_setattr_size( | 706 | xfs_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 | ||
917 | STATIC int | 907 | STATIC int |
918 | xfs_vn_setattr( | 908 | xfs_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 | ||
927 | STATIC int | 926 | STATIC 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 | ||
39 | extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, | 35 | extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, |
40 | int flags); | 36 | int flags); |
41 | extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap, int flags); | 37 | extern 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 | ||
39 | STATIC int | 38 | STATIC int |
40 | xfs_internal_inum( | 39 | xfs_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 | */ |
1015 | int | 1017 | int |
1016 | xfs_log_need_covered(xfs_mount_t *mp) | 1018 | xfs_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 | |||
23 | struct xfs_log_vec { | 21 | struct 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; | |||
82 | struct xfs_log_item; | 80 | struct xfs_log_item; |
83 | struct xfs_item_ops; | 81 | struct xfs_item_ops; |
84 | struct xfs_trans; | 82 | struct xfs_trans; |
85 | 83 | struct xfs_log_callback; | |
86 | void 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 | ||
91 | xfs_lsn_t xfs_log_done(struct xfs_mount *mp, | 85 | xfs_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); | |||
114 | void xfs_log_space_wake(struct xfs_mount *mp); | 108 | void xfs_log_space_wake(struct xfs_mount *mp); |
115 | int xfs_log_notify(struct xfs_mount *mp, | 109 | int 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); |
118 | int xfs_log_release_iclog(struct xfs_mount *mp, | 112 | int xfs_log_release_iclog(struct xfs_mount *mp, |
119 | struct xlog_in_core *iclog); | 113 | struct xlog_in_core *iclog); |
120 | int xfs_log_reserve(struct xfs_mount *mp, | 114 | int 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 | ||
716 | bool | ||
717 | xlog_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 | */ | ||
340 | struct 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 | ||
852 | int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes); | ||
853 | int 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; | |||
22 | struct xlog; | 22 | struct xlog; |
23 | struct xlog_ticket; | 23 | struct xlog_ticket; |
24 | struct xfs_mount; | 24 | struct xfs_mount; |
25 | struct 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 | */ |
517 | int | 518 | int xlog_cil_init(struct xlog *log); |
518 | xlog_cil_init(struct xlog *log); | 519 | void xlog_cil_init_post_recovery(struct xlog *log); |
519 | void | 520 | void xlog_cil_destroy(struct xlog *log); |
520 | xlog_cil_init_post_recovery(struct xlog *log); | 521 | bool xlog_cil_empty(struct xlog *log); |
521 | void | ||
522 | xlog_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 | */ |
1974 | static xfs_lsn_t | 1974 | static xfs_lsn_t |
1975 | xlog_recover_get_buf_lsn( | 1975 | xlog_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 | */ | ||
2353 | int | ||
2354 | xfs_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; | |||
26 | struct xfs_nameops; | 26 | struct xfs_nameops; |
27 | struct xfs_ail; | 27 | struct xfs_ail; |
28 | struct xfs_quotainfo; | 28 | struct xfs_quotainfo; |
29 | struct 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 | ||
667 | int | ||
668 | xfs_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 | |||
681 | struct xfs_qm_isolate { | 664 | struct 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 | ||
106 | extern int xfs_qm_calc_dquots_per_chunk(struct xfs_mount *mp, | ||
107 | unsigned int nbblks); | ||
108 | extern void xfs_trans_mod_dquot(struct xfs_trans *, | 106 | extern void xfs_trans_mod_dquot(struct xfs_trans *, |
109 | struct xfs_dquot *, uint, long); | 107 | struct xfs_dquot *, uint, long); |
110 | extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, | 108 | extern 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 | ||
153 | extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, | ||
154 | xfs_dqid_t, uint, uint, char *); | ||
155 | extern int xfs_mount_reset_sbqflags(struct xfs_mount *); | 153 | extern int xfs_mount_reset_sbqflags(struct xfs_mount *); |
156 | 154 | ||
157 | extern 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 | ||
157 | extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq, | ||
158 | xfs_dqid_t id, uint type, uint flags, char *str); | ||
159 | extern 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 | */ |
49 | STATIC int /* error */ | ||
50 | xfs_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 | ||
48 | STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, | ||
49 | xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *); | ||
50 | STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int, | ||
51 | xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *); | ||
52 | STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, | ||
53 | xfs_extlen_t, int, xfs_rtblock_t *, int *); | ||
54 | STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, | ||
55 | xfs_rtblock_t, xfs_rtblock_t *); | ||
56 | STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, | ||
57 | xfs_rtblock_t, xfs_rtblock_t *); | ||
58 | STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int, | ||
59 | xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *); | ||
60 | STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, | ||
61 | xfs_extlen_t, int); | ||
62 | STATIC 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 | */ |
72 | STATIC int /* error */ | 117 | STATIC int /* error */ |
73 | xfs_growfs_rt_alloc( | 118 | xfs_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; | 163 | STATIC int /* error */ |
120 | error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, | 164 | xfs_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); | ||
165 | error_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 | */ | ||
204 | STATIC int /* error */ | ||
205 | xfs_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 | ||
185 | error: | 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 | */ |
727 | STATIC int /* error */ | 814 | STATIC int /* error */ |
728 | xfs_rtallocate_range( | 815 | xfs_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 | */ | ||
804 | STATIC int /* error */ | ||
805 | xfs_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 | */ | ||
849 | STATIC int /* error */ | ||
850 | xfs_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 | */ | ||
884 | STATIC int /* error */ | ||
885 | xfs_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 | */ | ||
902 | STATIC int /* error */ | ||
903 | xfs_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 | */ | ||
1078 | STATIC int /* error */ | ||
1079 | xfs_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 | */ | ||
1120 | STATIC int /* error */ | ||
1121 | xfs_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 | */ | ||
1295 | STATIC int /* error */ | ||
1296 | xfs_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); | ||
907 | error_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 | /* | 927 | error: |
1462 | * Mark an extent specified by start and len freed. | ||
1463 | * Updates all the summary information as well as the bitmap. | ||
1464 | */ | ||
1465 | STATIC int /* error */ | ||
1466 | xfs_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 | */ | ||
1543 | STATIC int /* error */ | ||
1544 | xfs_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 | */ | ||
1610 | STATIC int /* error */ | ||
1611 | xfs_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 | */ | ||
1769 | STATIC int /* error */ | ||
1770 | xfs_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 | */ | ||
2135 | int /* error */ | ||
2136 | xfs_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 | */ |
2194 | int /* error */ | 1236 | int /* 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 | */ | ||
101 | int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp, | ||
102 | xfs_rtblock_t block, int issum, struct xfs_buf **bpp); | ||
103 | int 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); | ||
106 | int 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); | ||
109 | int 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); | ||
112 | int xfs_rtmodify_range(struct xfs_mount *mp, struct xfs_trans *tp, | ||
113 | xfs_rtblock_t start, xfs_extlen_t len, int val); | ||
114 | int 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); | ||
117 | int 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 | */ | ||
51 | int | ||
52 | xfs_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 | */ | ||
86 | int | ||
87 | xfs_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 | */ | ||
261 | int | ||
262 | xfs_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 | */ | ||
433 | int | ||
434 | xfs_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 | */ | ||
497 | int | ||
498 | xfs_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 | */ | ||
654 | int | ||
655 | xfs_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 | */ | ||
730 | int | ||
731 | xfs_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 | */ | ||
906 | STATIC int /* error */ | ||
907 | xfs_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 | */ | ||
930 | int /* error */ | ||
931 | xfs_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 | */ |
600 | static void | 597 | static void |
601 | xfs_sb_read_verify( | 598 | xfs_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 | ||
625 | out_error: | 626 | out_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 *); | |||
699 | extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t); | 699 | extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t); |
700 | extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp); | 700 | extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp); |
701 | 701 | ||
702 | extern const struct xfs_buf_ops xfs_sb_buf_ops; | ||
703 | extern 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 | */ | ||
26 | struct xfs_ifork; | ||
27 | struct xfs_buf; | ||
28 | struct xfs_buf_ops; | ||
29 | struct xfs_mount; | ||
30 | struct xfs_trans; | ||
31 | struct xfs_inode; | ||
32 | |||
33 | /* | ||
34 | * Buffer verifier operations are widely used, including userspace tools | ||
35 | */ | ||
36 | extern const struct xfs_buf_ops xfs_agf_buf_ops; | ||
37 | extern const struct xfs_buf_ops xfs_agi_buf_ops; | ||
38 | extern const struct xfs_buf_ops xfs_agf_buf_ops; | ||
39 | extern const struct xfs_buf_ops xfs_agfl_buf_ops; | ||
40 | extern const struct xfs_buf_ops xfs_allocbt_buf_ops; | ||
41 | extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; | ||
42 | extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; | ||
43 | extern const struct xfs_buf_ops xfs_bmbt_buf_ops; | ||
44 | extern const struct xfs_buf_ops xfs_da3_node_buf_ops; | ||
45 | extern const struct xfs_buf_ops xfs_dquot_buf_ops; | ||
46 | extern const struct xfs_buf_ops xfs_symlink_buf_ops; | ||
47 | extern const struct xfs_buf_ops xfs_agi_buf_ops; | ||
48 | extern const struct xfs_buf_ops xfs_inobt_buf_ops; | ||
49 | extern const struct xfs_buf_ops xfs_inode_buf_ops; | ||
50 | extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; | ||
51 | extern const struct xfs_buf_ops xfs_dquot_buf_ops; | ||
52 | extern const struct xfs_buf_ops xfs_sb_buf_ops; | ||
53 | extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops; | ||
54 | extern 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 | */ | ||
161 | struct 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 */ | ||
170 | int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes); | ||
171 | int 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 | */ | ||
236 | int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); | ||
237 | int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, | ||
238 | uint32_t size, struct xfs_buf *bp); | ||
239 | bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, | ||
240 | uint32_t size, struct xfs_buf *bp); | ||
241 | void 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 | */ |
968 | out_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 | */ |
1168 | void | 1158 | static void |
1169 | xfs_quiesce_attr( | 1159 | xfs_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 ----- */ |
47 | STATIC int | 47 | STATIC int |
@@ -424,8 +424,7 @@ xfs_symlink( | |||
424 | */ | 424 | */ |
425 | STATIC int | 425 | STATIC int |
426 | xfs_inactive_symlink_rmt( | 426 | xfs_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: | 541 | error_bmap_cancel: |
556 | xfs_bmap_cancel(&free_list); | 542 | xfs_bmap_cancel(&free_list); |
557 | error0: | 543 | error_trans_cancel: |
544 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
545 | error_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 | */ |
564 | int | 553 | int |
565 | xfs_inactive_symlink( | 554 | xfs_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 @@ | |||
22 | int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, | 22 | int 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); |
24 | int xfs_readlink(struct xfs_inode *ip, char *link); | 24 | int xfs_readlink(struct xfs_inode *ip, char *link); |
25 | int xfs_inactive_symlink(struct xfs_inode *ip, struct xfs_trans **tpp); | 25 | int 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; | |||
31 | struct xfs_da_node_entry; | 31 | struct xfs_da_node_entry; |
32 | struct xfs_dquot; | 32 | struct xfs_dquot; |
33 | struct xfs_log_item; | 33 | struct xfs_log_item; |
34 | struct xlog_ticket; | ||
35 | struct xlog; | 34 | struct xlog; |
35 | struct xlog_ticket; | ||
36 | struct xlog_recover; | 36 | struct xlog_recover; |
37 | struct xlog_recover_item; | 37 | struct xlog_recover_item; |
38 | struct xfs_buf_log_format; | 38 | struct xfs_buf_log_format; |
@@ -135,6 +135,31 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim); | |||
135 | DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks); | 135 | DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks); |
136 | DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks); | 136 | DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks); |
137 | 137 | ||
138 | DECLARE_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) \ | ||
154 | DEFINE_EVENT(xfs_ag_class, name, \ | ||
155 | TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno), \ | ||
156 | TP_ARGS(mp, agno)) | ||
157 | |||
158 | DEFINE_AG_EVENT(xfs_read_agf); | ||
159 | DEFINE_AG_EVENT(xfs_alloc_read_agf); | ||
160 | DEFINE_AG_EVENT(xfs_read_agi); | ||
161 | DEFINE_AG_EVENT(xfs_ialloc_read_agi); | ||
162 | |||
138 | TRACE_EVENT(xfs_attr_list_node_descend, | 163 | TRACE_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); | |||
938 | DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); | 963 | DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); |
939 | DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); | 964 | DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); |
940 | 965 | ||
966 | DECLARE_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) \ | ||
995 | DEFINE_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)) | ||
998 | DEFINE_AIL_EVENT(xfs_ail_insert); | ||
999 | DEFINE_AIL_EVENT(xfs_ail_move); | ||
1000 | DEFINE_AIL_EVENT(xfs_ail_delete); | ||
1001 | |||
1002 | TRACE_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 | ||
942 | DECLARE_EVENT_CLASS(xfs_file_class, | 1024 | DECLARE_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 | ||
48 | kmem_zone_t *xfs_trans_zone; | 37 | kmem_zone_t *xfs_trans_zone; |
49 | kmem_zone_t *xfs_log_item_desc_zone; | 38 | kmem_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 | ||
21 | struct 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 | ||
27 | struct xfs_buf; | 23 | struct 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 | ||
76 | void 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 | */ | ||
92 | typedef 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 | */ |
97 | typedef struct xfs_trans { | 91 | typedef 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); |
239 | int xfs_trans_commit(xfs_trans_t *, uint flags); | 231 | int xfs_trans_commit(xfs_trans_t *, uint flags); |
232 | int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); | ||
240 | void xfs_trans_cancel(xfs_trans_t *, int); | 233 | void xfs_trans_cancel(xfs_trans_t *, int); |
241 | int xfs_trans_ail_init(struct xfs_mount *); | 234 | int xfs_trans_ail_init(struct xfs_mount *); |
242 | void xfs_trans_ail_destroy(struct xfs_mount *); | 235 | void xfs_trans_ail_destroy(struct xfs_mount *); |
243 | 236 | ||
237 | void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *, | ||
238 | enum xfs_blft); | ||
239 | void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp, | ||
240 | struct xfs_buf *src_bp); | ||
241 | |||
244 | extern kmem_zone_t *xfs_trans_zone; | 242 | extern kmem_zone_t *xfs_trans_zone; |
245 | extern kmem_zone_t *xfs_log_item_desc_zone; | 243 | extern 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 | ||
39 | STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *); | 34 | STATIC 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 | ||
29 | void xfs_trans_init(struct xfs_mount *); | 29 | void xfs_trans_init(struct xfs_mount *); |
30 | int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); | ||
31 | void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *); | 30 | void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *); |
32 | void xfs_trans_del_item(struct xfs_log_item *); | 31 | void xfs_trans_del_item(struct xfs_log_item *); |
33 | void xfs_trans_free_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn, | 32 | void 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; | |||
25 | struct attrlist_cursor_kern; | 25 | struct 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" |