diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-11 12:03:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-11 12:03:47 -0400 |
commit | 412dd3a6daf0cadce1b2d6a34fa3713f40255579 (patch) | |
tree | bb2518c00c9d56acc8d36f87ed9c3144d8cf8201 /fs/xfs | |
parent | 23d4ed53b7342bf5999b3ea227d9f69e75e5a625 (diff) | |
parent | 7691283d0561a350b7517be94818669fb5e3d910 (diff) |
Merge tag 'xfs-for-linus-3.16-rc1' of git://oss.sgi.com/xfs/xfs
Pull xfs updates from Dave Chinner:
"This update contains:
- cleanup removing unused function args
- rework of the filestreams allocator to use dentry cache parent
lookups
- new on-disk free inode btree and optimised inode allocator
- various bug fixes
- rework of internal attribute API
- cleanup of superblock feature bit support to remove historic cruft
- more fixes and minor cleanups
- added a new directory/attribute geometry abstraction
- yet more fixes and minor cleanups"
* tag 'xfs-for-linus-3.16-rc1' of git://oss.sgi.com/xfs/xfs: (86 commits)
xfs: fix xfs_da_args sparse warning in xfs_readdir
xfs: Fix rounding in xfs_alloc_fix_len()
xfs: tone down writepage/releasepage WARN_ONs
xfs: small cleanup in xfs_lowbit64()
xfs: kill xfs_buf_geterror()
xfs: xfs_readsb needs to check for magic numbers
xfs: block allocation work needs to be kswapd aware
xfs: remove redundant geometry information from xfs_da_state
xfs: replace attr LBSIZE with xfs_da_geometry
xfs: pass xfs_da_args to xfs_attr_leaf_newentsize
xfs: use xfs_da_geometry for block size in attr code
xfs: remove mp->m_dir_geo from directory logging
xfs: reduce direct usage of mp->m_dir_geo
xfs: move node entry counts to xfs_da_geometry
xfs: convert dir/attr btree threshold to xfs_da_geometry
xfs: convert m_dirblksize to xfs_da_geometry
xfs: convert m_dirblkfsbs to xfs_da_geometry
xfs: convert directory segment limits to xfs_da_geometry
xfs: convert directory db conversion to xfs_da_geometry
xfs: convert directory dablk conversion to xfs_da_geometry
...
Diffstat (limited to 'fs/xfs')
90 files changed, 2634 insertions, 2784 deletions
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index 0fdd4109c624..6e247a99f5db 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h | |||
@@ -160,30 +160,38 @@ typedef struct xfs_agi { | |||
160 | * still being referenced. | 160 | * still being referenced. |
161 | */ | 161 | */ |
162 | __be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS]; | 162 | __be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS]; |
163 | 163 | /* | |
164 | * This marks the end of logging region 1 and start of logging region 2. | ||
165 | */ | ||
164 | uuid_t agi_uuid; /* uuid of filesystem */ | 166 | uuid_t agi_uuid; /* uuid of filesystem */ |
165 | __be32 agi_crc; /* crc of agi sector */ | 167 | __be32 agi_crc; /* crc of agi sector */ |
166 | __be32 agi_pad32; | 168 | __be32 agi_pad32; |
167 | __be64 agi_lsn; /* last write sequence */ | 169 | __be64 agi_lsn; /* last write sequence */ |
168 | 170 | ||
171 | __be32 agi_free_root; /* root of the free inode btree */ | ||
172 | __be32 agi_free_level;/* levels in free inode btree */ | ||
173 | |||
169 | /* structure must be padded to 64 bit alignment */ | 174 | /* structure must be padded to 64 bit alignment */ |
170 | } xfs_agi_t; | 175 | } xfs_agi_t; |
171 | 176 | ||
172 | #define XFS_AGI_CRC_OFF offsetof(struct xfs_agi, agi_crc) | 177 | #define XFS_AGI_CRC_OFF offsetof(struct xfs_agi, agi_crc) |
173 | 178 | ||
174 | #define XFS_AGI_MAGICNUM 0x00000001 | 179 | #define XFS_AGI_MAGICNUM (1 << 0) |
175 | #define XFS_AGI_VERSIONNUM 0x00000002 | 180 | #define XFS_AGI_VERSIONNUM (1 << 1) |
176 | #define XFS_AGI_SEQNO 0x00000004 | 181 | #define XFS_AGI_SEQNO (1 << 2) |
177 | #define XFS_AGI_LENGTH 0x00000008 | 182 | #define XFS_AGI_LENGTH (1 << 3) |
178 | #define XFS_AGI_COUNT 0x00000010 | 183 | #define XFS_AGI_COUNT (1 << 4) |
179 | #define XFS_AGI_ROOT 0x00000020 | 184 | #define XFS_AGI_ROOT (1 << 5) |
180 | #define XFS_AGI_LEVEL 0x00000040 | 185 | #define XFS_AGI_LEVEL (1 << 6) |
181 | #define XFS_AGI_FREECOUNT 0x00000080 | 186 | #define XFS_AGI_FREECOUNT (1 << 7) |
182 | #define XFS_AGI_NEWINO 0x00000100 | 187 | #define XFS_AGI_NEWINO (1 << 8) |
183 | #define XFS_AGI_DIRINO 0x00000200 | 188 | #define XFS_AGI_DIRINO (1 << 9) |
184 | #define XFS_AGI_UNLINKED 0x00000400 | 189 | #define XFS_AGI_UNLINKED (1 << 10) |
185 | #define XFS_AGI_NUM_BITS 11 | 190 | #define XFS_AGI_NUM_BITS_R1 11 /* end of the 1st agi logging region */ |
186 | #define XFS_AGI_ALL_BITS ((1 << XFS_AGI_NUM_BITS) - 1) | 191 | #define XFS_AGI_ALL_BITS_R1 ((1 << XFS_AGI_NUM_BITS_R1) - 1) |
192 | #define XFS_AGI_FREE_ROOT (1 << 11) | ||
193 | #define XFS_AGI_FREE_LEVEL (1 << 12) | ||
194 | #define XFS_AGI_NUM_BITS_R2 13 | ||
187 | 195 | ||
188 | /* disk block (xfs_daddr_t) in the AG */ | 196 | /* disk block (xfs_daddr_t) in the AG */ |
189 | #define XFS_AGI_DADDR(mp) ((xfs_daddr_t)(2 << (mp)->m_sectbb_log)) | 197 | #define XFS_AGI_DADDR(mp) ((xfs_daddr_t)(2 << (mp)->m_sectbb_log)) |
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index c1cf6a336a72..d43813267a80 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -257,16 +257,14 @@ xfs_alloc_fix_len( | |||
257 | k = rlen % args->prod; | 257 | k = rlen % args->prod; |
258 | if (k == args->mod) | 258 | if (k == args->mod) |
259 | return; | 259 | return; |
260 | if (k > args->mod) { | 260 | if (k > args->mod) |
261 | if ((int)(rlen = rlen - k - args->mod) < (int)args->minlen) | 261 | rlen = rlen - (k - args->mod); |
262 | return; | 262 | else |
263 | } else { | 263 | rlen = rlen - args->prod + (args->mod - k); |
264 | if ((int)(rlen = rlen - args->prod - (args->mod - k)) < | 264 | if ((int)rlen < (int)args->minlen) |
265 | (int)args->minlen) | 265 | return; |
266 | return; | 266 | ASSERT(rlen >= args->minlen && rlen <= args->maxlen); |
267 | } | 267 | ASSERT(rlen % args->prod == args->mod); |
268 | ASSERT(rlen >= args->minlen); | ||
269 | ASSERT(rlen <= args->maxlen); | ||
270 | args->len = rlen; | 268 | args->len = rlen; |
271 | } | 269 | } |
272 | 270 | ||
@@ -541,7 +539,6 @@ xfs_alloc_read_agfl( | |||
541 | XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops); | 539 | XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops); |
542 | if (error) | 540 | if (error) |
543 | return error; | 541 | return error; |
544 | ASSERT(!xfs_buf_geterror(bp)); | ||
545 | xfs_buf_set_ref(bp, XFS_AGFL_REF); | 542 | xfs_buf_set_ref(bp, XFS_AGFL_REF); |
546 | *bpp = bp; | 543 | *bpp = bp; |
547 | return 0; | 544 | return 0; |
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index cc1eadcbb049..8358f1ded94d 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c | |||
@@ -70,7 +70,6 @@ xfs_allocbt_alloc_block( | |||
70 | struct xfs_btree_cur *cur, | 70 | struct xfs_btree_cur *cur, |
71 | union xfs_btree_ptr *start, | 71 | union xfs_btree_ptr *start, |
72 | union xfs_btree_ptr *new, | 72 | union xfs_btree_ptr *new, |
73 | int length, | ||
74 | int *stat) | 73 | int *stat) |
75 | { | 74 | { |
76 | int error; | 75 | int error; |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 0479c32c5eb1..e32640eedea6 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -975,14 +975,39 @@ xfs_vm_writepage( | |||
975 | * Given that we do not allow direct reclaim to call us, we should | 975 | * Given that we do not allow direct reclaim to call us, we should |
976 | * never be called while in a filesystem transaction. | 976 | * never be called while in a filesystem transaction. |
977 | */ | 977 | */ |
978 | if (WARN_ON(current->flags & PF_FSTRANS)) | 978 | if (WARN_ON_ONCE(current->flags & PF_FSTRANS)) |
979 | goto redirty; | 979 | goto redirty; |
980 | 980 | ||
981 | /* Is this page beyond the end of the file? */ | 981 | /* Is this page beyond the end of the file? */ |
982 | offset = i_size_read(inode); | 982 | offset = i_size_read(inode); |
983 | end_index = offset >> PAGE_CACHE_SHIFT; | 983 | end_index = offset >> PAGE_CACHE_SHIFT; |
984 | last_index = (offset - 1) >> PAGE_CACHE_SHIFT; | 984 | last_index = (offset - 1) >> PAGE_CACHE_SHIFT; |
985 | if (page->index >= end_index) { | 985 | |
986 | /* | ||
987 | * The page index is less than the end_index, adjust the end_offset | ||
988 | * to the highest offset that this page should represent. | ||
989 | * ----------------------------------------------------- | ||
990 | * | file mapping | <EOF> | | ||
991 | * ----------------------------------------------------- | ||
992 | * | Page ... | Page N-2 | Page N-1 | Page N | | | ||
993 | * ^--------------------------------^----------|-------- | ||
994 | * | desired writeback range | see else | | ||
995 | * ---------------------------------^------------------| | ||
996 | */ | ||
997 | if (page->index < end_index) | ||
998 | end_offset = (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT; | ||
999 | else { | ||
1000 | /* | ||
1001 | * Check whether the page to write out is beyond or straddles | ||
1002 | * i_size or not. | ||
1003 | * ------------------------------------------------------- | ||
1004 | * | file mapping | <EOF> | | ||
1005 | * ------------------------------------------------------- | ||
1006 | * | Page ... | Page N-2 | Page N-1 | Page N | Beyond | | ||
1007 | * ^--------------------------------^-----------|--------- | ||
1008 | * | | Straddles | | ||
1009 | * ---------------------------------^-----------|--------| | ||
1010 | */ | ||
986 | unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1); | 1011 | unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1); |
987 | 1012 | ||
988 | /* | 1013 | /* |
@@ -990,24 +1015,36 @@ xfs_vm_writepage( | |||
990 | * truncate operation that is in progress. We must redirty the | 1015 | * truncate operation that is in progress. We must redirty the |
991 | * page so that reclaim stops reclaiming it. Otherwise | 1016 | * page so that reclaim stops reclaiming it. Otherwise |
992 | * xfs_vm_releasepage() is called on it and gets confused. | 1017 | * xfs_vm_releasepage() is called on it and gets confused. |
1018 | * | ||
1019 | * Note that the end_index is unsigned long, it would overflow | ||
1020 | * if the given offset is greater than 16TB on 32-bit system | ||
1021 | * and if we do check the page is fully outside i_size or not | ||
1022 | * via "if (page->index >= end_index + 1)" as "end_index + 1" | ||
1023 | * will be evaluated to 0. Hence this page will be redirtied | ||
1024 | * and be written out repeatedly which would result in an | ||
1025 | * infinite loop, the user program that perform this operation | ||
1026 | * will hang. Instead, we can verify this situation by checking | ||
1027 | * if the page to write is totally beyond the i_size or if it's | ||
1028 | * offset is just equal to the EOF. | ||
993 | */ | 1029 | */ |
994 | if (page->index >= end_index + 1 || offset_into_page == 0) | 1030 | if (page->index > end_index || |
1031 | (page->index == end_index && offset_into_page == 0)) | ||
995 | goto redirty; | 1032 | goto redirty; |
996 | 1033 | ||
997 | /* | 1034 | /* |
998 | * The page straddles i_size. It must be zeroed out on each | 1035 | * The page straddles i_size. It must be zeroed out on each |
999 | * and every writepage invocation because it may be mmapped. | 1036 | * and every writepage invocation because it may be mmapped. |
1000 | * "A file is mapped in multiples of the page size. For a file | 1037 | * "A file is mapped in multiples of the page size. For a file |
1001 | * that is not a multiple of the page size, the remaining | 1038 | * that is not a multiple of the page size, the remaining |
1002 | * memory is zeroed when mapped, and writes to that region are | 1039 | * memory is zeroed when mapped, and writes to that region are |
1003 | * not written out to the file." | 1040 | * not written out to the file." |
1004 | */ | 1041 | */ |
1005 | zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE); | 1042 | zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE); |
1043 | |||
1044 | /* Adjust the end_offset to the end of file */ | ||
1045 | end_offset = offset; | ||
1006 | } | 1046 | } |
1007 | 1047 | ||
1008 | end_offset = min_t(unsigned long long, | ||
1009 | (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, | ||
1010 | offset); | ||
1011 | len = 1 << inode->i_blkbits; | 1048 | len = 1 << inode->i_blkbits; |
1012 | 1049 | ||
1013 | bh = head = page_buffers(page); | 1050 | bh = head = page_buffers(page); |
@@ -1188,9 +1225,9 @@ xfs_vm_releasepage( | |||
1188 | 1225 | ||
1189 | xfs_count_page_state(page, &delalloc, &unwritten); | 1226 | xfs_count_page_state(page, &delalloc, &unwritten); |
1190 | 1227 | ||
1191 | if (WARN_ON(delalloc)) | 1228 | if (WARN_ON_ONCE(delalloc)) |
1192 | return 0; | 1229 | return 0; |
1193 | if (WARN_ON(unwritten)) | 1230 | if (WARN_ON_ONCE(unwritten)) |
1194 | return 0; | 1231 | return 0; |
1195 | 1232 | ||
1196 | return try_to_free_buffers(page); | 1233 | return try_to_free_buffers(page); |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index abda1124a70f..bfe36fc2cdc2 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -77,17 +77,27 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state); | |||
77 | 77 | ||
78 | 78 | ||
79 | STATIC int | 79 | STATIC int |
80 | xfs_attr_name_to_xname( | 80 | xfs_attr_args_init( |
81 | struct xfs_name *xname, | 81 | struct xfs_da_args *args, |
82 | const unsigned char *aname) | 82 | struct xfs_inode *dp, |
83 | const unsigned char *name, | ||
84 | int flags) | ||
83 | { | 85 | { |
84 | if (!aname) | 86 | |
87 | if (!name) | ||
85 | return EINVAL; | 88 | return EINVAL; |
86 | xname->name = aname; | 89 | |
87 | xname->len = strlen((char *)aname); | 90 | memset(args, 0, sizeof(*args)); |
88 | if (xname->len >= MAXNAMELEN) | 91 | args->geo = dp->i_mount->m_attr_geo; |
92 | args->whichfork = XFS_ATTR_FORK; | ||
93 | args->dp = dp; | ||
94 | args->flags = flags; | ||
95 | args->name = name; | ||
96 | args->namelen = strlen((const char *)name); | ||
97 | if (args->namelen >= MAXNAMELEN) | ||
89 | return EFAULT; /* match IRIX behaviour */ | 98 | return EFAULT; /* match IRIX behaviour */ |
90 | 99 | ||
100 | args->hashval = xfs_da_hashname(args->name, args->namelen); | ||
91 | return 0; | 101 | return 0; |
92 | } | 102 | } |
93 | 103 | ||
@@ -106,79 +116,46 @@ xfs_inode_hasattr( | |||
106 | * Overall external interface routines. | 116 | * Overall external interface routines. |
107 | *========================================================================*/ | 117 | *========================================================================*/ |
108 | 118 | ||
109 | STATIC int | 119 | int |
110 | xfs_attr_get_int( | 120 | xfs_attr_get( |
111 | struct xfs_inode *ip, | 121 | struct xfs_inode *ip, |
112 | struct xfs_name *name, | 122 | const unsigned char *name, |
113 | unsigned char *value, | 123 | unsigned char *value, |
114 | int *valuelenp, | 124 | int *valuelenp, |
115 | int flags) | 125 | int flags) |
116 | { | 126 | { |
117 | xfs_da_args_t args; | 127 | struct xfs_da_args args; |
118 | int error; | 128 | uint lock_mode; |
129 | int error; | ||
130 | |||
131 | XFS_STATS_INC(xs_attr_get); | ||
132 | |||
133 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
134 | return EIO; | ||
119 | 135 | ||
120 | if (!xfs_inode_hasattr(ip)) | 136 | if (!xfs_inode_hasattr(ip)) |
121 | return ENOATTR; | 137 | return ENOATTR; |
122 | 138 | ||
123 | /* | 139 | error = xfs_attr_args_init(&args, ip, name, flags); |
124 | * Fill in the arg structure for this request. | 140 | if (error) |
125 | */ | 141 | return error; |
126 | memset((char *)&args, 0, sizeof(args)); | 142 | |
127 | args.name = name->name; | ||
128 | args.namelen = name->len; | ||
129 | args.value = value; | 143 | args.value = value; |
130 | args.valuelen = *valuelenp; | 144 | args.valuelen = *valuelenp; |
131 | args.flags = flags; | ||
132 | args.hashval = xfs_da_hashname(args.name, args.namelen); | ||
133 | args.dp = ip; | ||
134 | args.whichfork = XFS_ATTR_FORK; | ||
135 | 145 | ||
136 | /* | 146 | lock_mode = xfs_ilock_attr_map_shared(ip); |
137 | * Decide on what work routines to call based on the inode size. | 147 | if (!xfs_inode_hasattr(ip)) |
138 | */ | 148 | error = ENOATTR; |
139 | if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | 149 | else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) |
140 | error = xfs_attr_shortform_getvalue(&args); | 150 | error = xfs_attr_shortform_getvalue(&args); |
141 | } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { | 151 | else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) |
142 | error = xfs_attr_leaf_get(&args); | 152 | error = xfs_attr_leaf_get(&args); |
143 | } else { | 153 | else |
144 | error = xfs_attr_node_get(&args); | 154 | error = xfs_attr_node_get(&args); |
145 | } | 155 | xfs_iunlock(ip, lock_mode); |
146 | 156 | ||
147 | /* | ||
148 | * Return the number of bytes in the value to the caller. | ||
149 | */ | ||
150 | *valuelenp = args.valuelen; | 157 | *valuelenp = args.valuelen; |
151 | 158 | return error == EEXIST ? 0 : error; | |
152 | if (error == EEXIST) | ||
153 | error = 0; | ||
154 | return(error); | ||
155 | } | ||
156 | |||
157 | int | ||
158 | xfs_attr_get( | ||
159 | xfs_inode_t *ip, | ||
160 | const unsigned char *name, | ||
161 | unsigned char *value, | ||
162 | int *valuelenp, | ||
163 | int flags) | ||
164 | { | ||
165 | int error; | ||
166 | struct xfs_name xname; | ||
167 | uint lock_mode; | ||
168 | |||
169 | XFS_STATS_INC(xs_attr_get); | ||
170 | |||
171 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
172 | return(EIO); | ||
173 | |||
174 | error = xfs_attr_name_to_xname(&xname, name); | ||
175 | if (error) | ||
176 | return error; | ||
177 | |||
178 | lock_mode = xfs_ilock_attr_map_shared(ip); | ||
179 | error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags); | ||
180 | xfs_iunlock(ip, lock_mode); | ||
181 | return(error); | ||
182 | } | 159 | } |
183 | 160 | ||
184 | /* | 161 | /* |
@@ -186,12 +163,10 @@ xfs_attr_get( | |||
186 | */ | 163 | */ |
187 | STATIC int | 164 | STATIC int |
188 | xfs_attr_calc_size( | 165 | xfs_attr_calc_size( |
189 | struct xfs_inode *ip, | 166 | struct xfs_da_args *args, |
190 | int namelen, | ||
191 | int valuelen, | ||
192 | int *local) | 167 | int *local) |
193 | { | 168 | { |
194 | struct xfs_mount *mp = ip->i_mount; | 169 | struct xfs_mount *mp = args->dp->i_mount; |
195 | int size; | 170 | int size; |
196 | int nblks; | 171 | int nblks; |
197 | 172 | ||
@@ -199,12 +174,10 @@ xfs_attr_calc_size( | |||
199 | * Determine space new attribute will use, and if it would be | 174 | * Determine space new attribute will use, and if it would be |
200 | * "local" or "remote" (note: local != inline). | 175 | * "local" or "remote" (note: local != inline). |
201 | */ | 176 | */ |
202 | size = xfs_attr_leaf_newentsize(namelen, valuelen, | 177 | size = xfs_attr_leaf_newentsize(args, local); |
203 | mp->m_sb.sb_blocksize, local); | ||
204 | |||
205 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); | 178 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); |
206 | if (*local) { | 179 | if (*local) { |
207 | if (size > (mp->m_sb.sb_blocksize >> 1)) { | 180 | if (size > (args->geo->blksize / 2)) { |
208 | /* Double split possible */ | 181 | /* Double split possible */ |
209 | nblks *= 2; | 182 | nblks *= 2; |
210 | } | 183 | } |
@@ -213,7 +186,7 @@ xfs_attr_calc_size( | |||
213 | * Out of line attribute, cannot double split, but | 186 | * Out of line attribute, cannot double split, but |
214 | * make room for the attribute value itself. | 187 | * make room for the attribute value itself. |
215 | */ | 188 | */ |
216 | uint dblocks = xfs_attr3_rmt_blocks(mp, valuelen); | 189 | uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen); |
217 | nblks += dblocks; | 190 | nblks += dblocks; |
218 | nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); | 191 | nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); |
219 | } | 192 | } |
@@ -221,26 +194,38 @@ xfs_attr_calc_size( | |||
221 | return nblks; | 194 | return nblks; |
222 | } | 195 | } |
223 | 196 | ||
224 | STATIC int | 197 | int |
225 | xfs_attr_set_int( | 198 | xfs_attr_set( |
226 | struct xfs_inode *dp, | 199 | struct xfs_inode *dp, |
227 | struct xfs_name *name, | 200 | const unsigned char *name, |
228 | unsigned char *value, | 201 | unsigned char *value, |
229 | int valuelen, | 202 | int valuelen, |
230 | int flags) | 203 | int flags) |
231 | { | 204 | { |
232 | xfs_da_args_t args; | ||
233 | xfs_fsblock_t firstblock; | ||
234 | xfs_bmap_free_t flist; | ||
235 | int error, err2, committed; | ||
236 | struct xfs_mount *mp = dp->i_mount; | 205 | struct xfs_mount *mp = dp->i_mount; |
206 | struct xfs_da_args args; | ||
207 | struct xfs_bmap_free flist; | ||
237 | struct xfs_trans_res tres; | 208 | struct xfs_trans_res tres; |
209 | xfs_fsblock_t firstblock; | ||
238 | int rsvd = (flags & ATTR_ROOT) != 0; | 210 | int rsvd = (flags & ATTR_ROOT) != 0; |
239 | int local; | 211 | int error, err2, committed, local; |
212 | |||
213 | XFS_STATS_INC(xs_attr_set); | ||
214 | |||
215 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
216 | return EIO; | ||
217 | |||
218 | error = xfs_attr_args_init(&args, dp, name, flags); | ||
219 | if (error) | ||
220 | return error; | ||
221 | |||
222 | args.value = value; | ||
223 | args.valuelen = valuelen; | ||
224 | args.firstblock = &firstblock; | ||
225 | args.flist = &flist; | ||
226 | args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; | ||
227 | args.total = xfs_attr_calc_size(&args, &local); | ||
240 | 228 | ||
241 | /* | ||
242 | * Attach the dquots to the inode. | ||
243 | */ | ||
244 | error = xfs_qm_dqattach(dp, 0); | 229 | error = xfs_qm_dqattach(dp, 0); |
245 | if (error) | 230 | if (error) |
246 | return error; | 231 | return error; |
@@ -251,32 +236,14 @@ xfs_attr_set_int( | |||
251 | */ | 236 | */ |
252 | if (XFS_IFORK_Q(dp) == 0) { | 237 | if (XFS_IFORK_Q(dp) == 0) { |
253 | int sf_size = sizeof(xfs_attr_sf_hdr_t) + | 238 | int sf_size = sizeof(xfs_attr_sf_hdr_t) + |
254 | XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen); | 239 | XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen); |
255 | 240 | ||
256 | if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd))) | 241 | error = xfs_bmap_add_attrfork(dp, sf_size, rsvd); |
257 | return(error); | 242 | if (error) |
243 | return error; | ||
258 | } | 244 | } |
259 | 245 | ||
260 | /* | 246 | /* |
261 | * Fill in the arg structure for this request. | ||
262 | */ | ||
263 | memset((char *)&args, 0, sizeof(args)); | ||
264 | args.name = name->name; | ||
265 | args.namelen = name->len; | ||
266 | args.value = value; | ||
267 | args.valuelen = valuelen; | ||
268 | args.flags = flags; | ||
269 | args.hashval = xfs_da_hashname(args.name, args.namelen); | ||
270 | args.dp = dp; | ||
271 | args.firstblock = &firstblock; | ||
272 | args.flist = &flist; | ||
273 | args.whichfork = XFS_ATTR_FORK; | ||
274 | args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; | ||
275 | |||
276 | /* Size is now blocks for attribute data */ | ||
277 | args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local); | ||
278 | |||
279 | /* | ||
280 | * Start our first transaction of the day. | 247 | * Start our first transaction of the day. |
281 | * | 248 | * |
282 | * All future transactions during this code must be "chained" off | 249 | * All future transactions during this code must be "chained" off |
@@ -303,7 +270,7 @@ xfs_attr_set_int( | |||
303 | error = xfs_trans_reserve(args.trans, &tres, args.total, 0); | 270 | error = xfs_trans_reserve(args.trans, &tres, args.total, 0); |
304 | if (error) { | 271 | if (error) { |
305 | xfs_trans_cancel(args.trans, 0); | 272 | xfs_trans_cancel(args.trans, 0); |
306 | return(error); | 273 | return error; |
307 | } | 274 | } |
308 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 275 | xfs_ilock(dp, XFS_ILOCK_EXCL); |
309 | 276 | ||
@@ -313,7 +280,7 @@ xfs_attr_set_int( | |||
313 | if (error) { | 280 | if (error) { |
314 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 281 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
315 | xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); | 282 | xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); |
316 | return (error); | 283 | return error; |
317 | } | 284 | } |
318 | 285 | ||
319 | xfs_trans_ijoin(args.trans, dp, 0); | 286 | xfs_trans_ijoin(args.trans, dp, 0); |
@@ -322,9 +289,9 @@ xfs_attr_set_int( | |||
322 | * If the attribute list is non-existent or a shortform list, | 289 | * If the attribute list is non-existent or a shortform list, |
323 | * upgrade it to a single-leaf-block attribute list. | 290 | * upgrade it to a single-leaf-block attribute list. |
324 | */ | 291 | */ |
325 | if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || | 292 | if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL || |
326 | ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) && | 293 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && |
327 | (dp->i_d.di_anextents == 0))) { | 294 | dp->i_d.di_anextents == 0)) { |
328 | 295 | ||
329 | /* | 296 | /* |
330 | * Build initial attribute list (if required). | 297 | * Build initial attribute list (if required). |
@@ -349,9 +316,8 @@ xfs_attr_set_int( | |||
349 | * the transaction goes to disk before returning | 316 | * the transaction goes to disk before returning |
350 | * to the user. | 317 | * to the user. |
351 | */ | 318 | */ |
352 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 319 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
353 | xfs_trans_set_sync(args.trans); | 320 | xfs_trans_set_sync(args.trans); |
354 | } | ||
355 | 321 | ||
356 | if (!error && (flags & ATTR_KERNOTIME) == 0) { | 322 | if (!error && (flags & ATTR_KERNOTIME) == 0) { |
357 | xfs_trans_ichgtime(args.trans, dp, | 323 | xfs_trans_ichgtime(args.trans, dp, |
@@ -361,7 +327,7 @@ xfs_attr_set_int( | |||
361 | XFS_TRANS_RELEASE_LOG_RES); | 327 | XFS_TRANS_RELEASE_LOG_RES); |
362 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 328 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
363 | 329 | ||
364 | return(error == 0 ? err2 : error); | 330 | return error ? error : err2; |
365 | } | 331 | } |
366 | 332 | ||
367 | /* | 333 | /* |
@@ -399,22 +365,19 @@ xfs_attr_set_int( | |||
399 | 365 | ||
400 | } | 366 | } |
401 | 367 | ||
402 | if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { | 368 | if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) |
403 | error = xfs_attr_leaf_addname(&args); | 369 | error = xfs_attr_leaf_addname(&args); |
404 | } else { | 370 | else |
405 | error = xfs_attr_node_addname(&args); | 371 | error = xfs_attr_node_addname(&args); |
406 | } | 372 | if (error) |
407 | if (error) { | ||
408 | goto out; | 373 | goto out; |
409 | } | ||
410 | 374 | ||
411 | /* | 375 | /* |
412 | * If this is a synchronous mount, make sure that the | 376 | * If this is a synchronous mount, make sure that the |
413 | * transaction goes to disk before returning to the user. | 377 | * transaction goes to disk before returning to the user. |
414 | */ | 378 | */ |
415 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 379 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
416 | xfs_trans_set_sync(args.trans); | 380 | xfs_trans_set_sync(args.trans); |
417 | } | ||
418 | 381 | ||
419 | if ((flags & ATTR_KERNOTIME) == 0) | 382 | if ((flags & ATTR_KERNOTIME) == 0) |
420 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); | 383 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); |
@@ -426,65 +389,47 @@ xfs_attr_set_int( | |||
426 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); | 389 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); |
427 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 390 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
428 | 391 | ||
429 | return(error); | 392 | return error; |
430 | 393 | ||
431 | out: | 394 | out: |
432 | if (args.trans) | 395 | if (args.trans) { |
433 | xfs_trans_cancel(args.trans, | 396 | xfs_trans_cancel(args.trans, |
434 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); | 397 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); |
398 | } | ||
435 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 399 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
436 | return(error); | 400 | return error; |
437 | } | 401 | } |
438 | 402 | ||
403 | /* | ||
404 | * Generic handler routine to remove a name from an attribute list. | ||
405 | * Transitions attribute list from Btree to shortform as necessary. | ||
406 | */ | ||
439 | int | 407 | int |
440 | xfs_attr_set( | 408 | xfs_attr_remove( |
441 | xfs_inode_t *dp, | 409 | struct xfs_inode *dp, |
442 | const unsigned char *name, | 410 | const unsigned char *name, |
443 | unsigned char *value, | 411 | int flags) |
444 | int valuelen, | ||
445 | int flags) | ||
446 | { | 412 | { |
447 | int error; | 413 | struct xfs_mount *mp = dp->i_mount; |
448 | struct xfs_name xname; | 414 | struct xfs_da_args args; |
415 | struct xfs_bmap_free flist; | ||
416 | xfs_fsblock_t firstblock; | ||
417 | int error; | ||
449 | 418 | ||
450 | XFS_STATS_INC(xs_attr_set); | 419 | XFS_STATS_INC(xs_attr_remove); |
451 | 420 | ||
452 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 421 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
453 | return (EIO); | 422 | return EIO; |
423 | |||
424 | if (!xfs_inode_hasattr(dp)) | ||
425 | return ENOATTR; | ||
454 | 426 | ||
455 | error = xfs_attr_name_to_xname(&xname, name); | 427 | error = xfs_attr_args_init(&args, dp, name, flags); |
456 | if (error) | 428 | if (error) |
457 | return error; | 429 | return error; |
458 | 430 | ||
459 | return xfs_attr_set_int(dp, &xname, value, valuelen, flags); | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * Generic handler routine to remove a name from an attribute list. | ||
464 | * Transitions attribute list from Btree to shortform as necessary. | ||
465 | */ | ||
466 | STATIC int | ||
467 | xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | ||
468 | { | ||
469 | xfs_da_args_t args; | ||
470 | xfs_fsblock_t firstblock; | ||
471 | xfs_bmap_free_t flist; | ||
472 | int error; | ||
473 | xfs_mount_t *mp = dp->i_mount; | ||
474 | |||
475 | /* | ||
476 | * Fill in the arg structure for this request. | ||
477 | */ | ||
478 | memset((char *)&args, 0, sizeof(args)); | ||
479 | args.name = name->name; | ||
480 | args.namelen = name->len; | ||
481 | args.flags = flags; | ||
482 | args.hashval = xfs_da_hashname(args.name, args.namelen); | ||
483 | args.dp = dp; | ||
484 | args.firstblock = &firstblock; | 431 | args.firstblock = &firstblock; |
485 | args.flist = &flist; | 432 | args.flist = &flist; |
486 | args.total = 0; | ||
487 | args.whichfork = XFS_ATTR_FORK; | ||
488 | 433 | ||
489 | /* | 434 | /* |
490 | * we have no control over the attribute names that userspace passes us | 435 | * we have no control over the attribute names that userspace passes us |
@@ -493,9 +438,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
493 | */ | 438 | */ |
494 | args.op_flags = XFS_DA_OP_OKNOENT; | 439 | args.op_flags = XFS_DA_OP_OKNOENT; |
495 | 440 | ||
496 | /* | ||
497 | * Attach the dquots to the inode. | ||
498 | */ | ||
499 | error = xfs_qm_dqattach(dp, 0); | 441 | error = xfs_qm_dqattach(dp, 0); |
500 | if (error) | 442 | if (error) |
501 | return error; | 443 | return error; |
@@ -524,7 +466,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
524 | XFS_ATTRRM_SPACE_RES(mp), 0); | 466 | XFS_ATTRRM_SPACE_RES(mp), 0); |
525 | if (error) { | 467 | if (error) { |
526 | xfs_trans_cancel(args.trans, 0); | 468 | xfs_trans_cancel(args.trans, 0); |
527 | return(error); | 469 | return error; |
528 | } | 470 | } |
529 | 471 | ||
530 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 472 | xfs_ilock(dp, XFS_ILOCK_EXCL); |
@@ -534,35 +476,26 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
534 | */ | 476 | */ |
535 | xfs_trans_ijoin(args.trans, dp, 0); | 477 | xfs_trans_ijoin(args.trans, dp, 0); |
536 | 478 | ||
537 | /* | ||
538 | * Decide on what work routines to call based on the inode size. | ||
539 | */ | ||
540 | if (!xfs_inode_hasattr(dp)) { | 479 | if (!xfs_inode_hasattr(dp)) { |
541 | error = XFS_ERROR(ENOATTR); | 480 | error = XFS_ERROR(ENOATTR); |
542 | goto out; | 481 | } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { |
543 | } | ||
544 | if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | ||
545 | ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); | 482 | ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); |
546 | error = xfs_attr_shortform_remove(&args); | 483 | error = xfs_attr_shortform_remove(&args); |
547 | if (error) { | ||
548 | goto out; | ||
549 | } | ||
550 | } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { | 484 | } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { |
551 | error = xfs_attr_leaf_removename(&args); | 485 | error = xfs_attr_leaf_removename(&args); |
552 | } else { | 486 | } else { |
553 | error = xfs_attr_node_removename(&args); | 487 | error = xfs_attr_node_removename(&args); |
554 | } | 488 | } |
555 | if (error) { | 489 | |
490 | if (error) | ||
556 | goto out; | 491 | goto out; |
557 | } | ||
558 | 492 | ||
559 | /* | 493 | /* |
560 | * If this is a synchronous mount, make sure that the | 494 | * If this is a synchronous mount, make sure that the |
561 | * transaction goes to disk before returning to the user. | 495 | * transaction goes to disk before returning to the user. |
562 | */ | 496 | */ |
563 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 497 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
564 | xfs_trans_set_sync(args.trans); | 498 | xfs_trans_set_sync(args.trans); |
565 | } | ||
566 | 499 | ||
567 | if ((flags & ATTR_KERNOTIME) == 0) | 500 | if ((flags & ATTR_KERNOTIME) == 0) |
568 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); | 501 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); |
@@ -574,45 +507,17 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
574 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); | 507 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); |
575 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 508 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
576 | 509 | ||
577 | return(error); | 510 | return error; |
578 | 511 | ||
579 | out: | 512 | out: |
580 | if (args.trans) | 513 | if (args.trans) { |
581 | xfs_trans_cancel(args.trans, | 514 | xfs_trans_cancel(args.trans, |
582 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); | 515 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); |
583 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | ||
584 | return(error); | ||
585 | } | ||
586 | |||
587 | int | ||
588 | xfs_attr_remove( | ||
589 | xfs_inode_t *dp, | ||
590 | const unsigned char *name, | ||
591 | int flags) | ||
592 | { | ||
593 | int error; | ||
594 | struct xfs_name xname; | ||
595 | |||
596 | XFS_STATS_INC(xs_attr_remove); | ||
597 | |||
598 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
599 | return (EIO); | ||
600 | |||
601 | error = xfs_attr_name_to_xname(&xname, name); | ||
602 | if (error) | ||
603 | return error; | ||
604 | |||
605 | xfs_ilock(dp, XFS_ILOCK_SHARED); | ||
606 | if (!xfs_inode_hasattr(dp)) { | ||
607 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
608 | return XFS_ERROR(ENOATTR); | ||
609 | } | 516 | } |
610 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 517 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
611 | 518 | return error; | |
612 | return xfs_attr_remove_int(dp, &xname, flags); | ||
613 | } | 519 | } |
614 | 520 | ||
615 | |||
616 | /*======================================================================== | 521 | /*======================================================================== |
617 | * External routines when attribute list is inside the inode | 522 | * External routines when attribute list is inside the inode |
618 | *========================================================================*/ | 523 | *========================================================================*/ |
@@ -958,7 +863,7 @@ xfs_attr_leaf_get(xfs_da_args_t *args) | |||
958 | } | 863 | } |
959 | 864 | ||
960 | /*======================================================================== | 865 | /*======================================================================== |
961 | * External routines when attribute list size > XFS_LBSIZE(mp). | 866 | * External routines when attribute list size > geo->blksize |
962 | *========================================================================*/ | 867 | *========================================================================*/ |
963 | 868 | ||
964 | /* | 869 | /* |
@@ -991,8 +896,6 @@ restart: | |||
991 | state = xfs_da_state_alloc(); | 896 | state = xfs_da_state_alloc(); |
992 | state->args = args; | 897 | state->args = args; |
993 | state->mp = mp; | 898 | state->mp = mp; |
994 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
995 | state->node_ents = state->mp->m_attr_node_ents; | ||
996 | 899 | ||
997 | /* | 900 | /* |
998 | * Search to see if name already exists, and get back a pointer | 901 | * Search to see if name already exists, and get back a pointer |
@@ -1170,8 +1073,6 @@ restart: | |||
1170 | state = xfs_da_state_alloc(); | 1073 | state = xfs_da_state_alloc(); |
1171 | state->args = args; | 1074 | state->args = args; |
1172 | state->mp = mp; | 1075 | state->mp = mp; |
1173 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
1174 | state->node_ents = state->mp->m_attr_node_ents; | ||
1175 | state->inleaf = 0; | 1076 | state->inleaf = 0; |
1176 | error = xfs_da3_node_lookup_int(state, &retval); | 1077 | error = xfs_da3_node_lookup_int(state, &retval); |
1177 | if (error) | 1078 | if (error) |
@@ -1262,8 +1163,6 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1262 | state = xfs_da_state_alloc(); | 1163 | state = xfs_da_state_alloc(); |
1263 | state->args = args; | 1164 | state->args = args; |
1264 | state->mp = dp->i_mount; | 1165 | state->mp = dp->i_mount; |
1265 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
1266 | state->node_ents = state->mp->m_attr_node_ents; | ||
1267 | 1166 | ||
1268 | /* | 1167 | /* |
1269 | * Search to see if name exists, and get back a pointer to it. | 1168 | * Search to see if name exists, and get back a pointer to it. |
@@ -1525,8 +1424,6 @@ xfs_attr_node_get(xfs_da_args_t *args) | |||
1525 | state = xfs_da_state_alloc(); | 1424 | state = xfs_da_state_alloc(); |
1526 | state->args = args; | 1425 | state->args = args; |
1527 | state->mp = args->dp->i_mount; | 1426 | state->mp = args->dp->i_mount; |
1528 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
1529 | state->node_ents = state->mp->m_attr_node_ents; | ||
1530 | 1427 | ||
1531 | /* | 1428 | /* |
1532 | * Search to see if name exists, and get back a pointer to it. | 1429 | * Search to see if name exists, and get back a pointer to it. |
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 511c283459b1..28712d29e43c 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -80,11 +80,12 @@ STATIC int xfs_attr3_leaf_figure_balance(xfs_da_state_t *state, | |||
80 | /* | 80 | /* |
81 | * Utility routines. | 81 | * Utility routines. |
82 | */ | 82 | */ |
83 | STATIC void xfs_attr3_leaf_moveents(struct xfs_attr_leafblock *src_leaf, | 83 | STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args, |
84 | struct xfs_attr_leafblock *src_leaf, | ||
84 | struct xfs_attr3_icleaf_hdr *src_ichdr, int src_start, | 85 | struct xfs_attr3_icleaf_hdr *src_ichdr, int src_start, |
85 | struct xfs_attr_leafblock *dst_leaf, | 86 | struct xfs_attr_leafblock *dst_leaf, |
86 | struct xfs_attr3_icleaf_hdr *dst_ichdr, int dst_start, | 87 | struct xfs_attr3_icleaf_hdr *dst_ichdr, int dst_start, |
87 | int move_count, struct xfs_mount *mp); | 88 | int move_count); |
88 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); | 89 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); |
89 | 90 | ||
90 | void | 91 | void |
@@ -711,6 +712,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) | |||
711 | 712 | ||
712 | memset((char *)&nargs, 0, sizeof(nargs)); | 713 | memset((char *)&nargs, 0, sizeof(nargs)); |
713 | nargs.dp = dp; | 714 | nargs.dp = dp; |
715 | nargs.geo = args->geo; | ||
714 | nargs.firstblock = args->firstblock; | 716 | nargs.firstblock = args->firstblock; |
715 | nargs.flist = args->flist; | 717 | nargs.flist = args->flist; |
716 | nargs.total = args->total; | 718 | nargs.total = args->total; |
@@ -805,18 +807,18 @@ xfs_attr3_leaf_to_shortform( | |||
805 | 807 | ||
806 | trace_xfs_attr_leaf_to_sf(args); | 808 | trace_xfs_attr_leaf_to_sf(args); |
807 | 809 | ||
808 | tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP); | 810 | tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP); |
809 | if (!tmpbuffer) | 811 | if (!tmpbuffer) |
810 | return ENOMEM; | 812 | return ENOMEM; |
811 | 813 | ||
812 | memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(dp->i_mount)); | 814 | memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); |
813 | 815 | ||
814 | leaf = (xfs_attr_leafblock_t *)tmpbuffer; | 816 | leaf = (xfs_attr_leafblock_t *)tmpbuffer; |
815 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | 817 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
816 | entry = xfs_attr3_leaf_entryp(leaf); | 818 | entry = xfs_attr3_leaf_entryp(leaf); |
817 | 819 | ||
818 | /* XXX (dgc): buffer is about to be marked stale - why zero it? */ | 820 | /* XXX (dgc): buffer is about to be marked stale - why zero it? */ |
819 | memset(bp->b_addr, 0, XFS_LBSIZE(dp->i_mount)); | 821 | memset(bp->b_addr, 0, args->geo->blksize); |
820 | 822 | ||
821 | /* | 823 | /* |
822 | * Clean out the prior contents of the attribute list. | 824 | * Clean out the prior contents of the attribute list. |
@@ -838,6 +840,7 @@ xfs_attr3_leaf_to_shortform( | |||
838 | * Copy the attributes | 840 | * Copy the attributes |
839 | */ | 841 | */ |
840 | memset((char *)&nargs, 0, sizeof(nargs)); | 842 | memset((char *)&nargs, 0, sizeof(nargs)); |
843 | nargs.geo = args->geo; | ||
841 | nargs.dp = dp; | 844 | nargs.dp = dp; |
842 | nargs.firstblock = args->firstblock; | 845 | nargs.firstblock = args->firstblock; |
843 | nargs.flist = args->flist; | 846 | nargs.flist = args->flist; |
@@ -904,12 +907,12 @@ xfs_attr3_leaf_to_node( | |||
904 | /* copy leaf to new buffer, update identifiers */ | 907 | /* copy leaf to new buffer, update identifiers */ |
905 | xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF); | 908 | xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF); |
906 | bp2->b_ops = bp1->b_ops; | 909 | bp2->b_ops = bp1->b_ops; |
907 | memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp)); | 910 | memcpy(bp2->b_addr, bp1->b_addr, args->geo->blksize); |
908 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 911 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
909 | struct xfs_da3_blkinfo *hdr3 = bp2->b_addr; | 912 | struct xfs_da3_blkinfo *hdr3 = bp2->b_addr; |
910 | hdr3->blkno = cpu_to_be64(bp2->b_bn); | 913 | hdr3->blkno = cpu_to_be64(bp2->b_bn); |
911 | } | 914 | } |
912 | xfs_trans_log_buf(args->trans, bp2, 0, XFS_LBSIZE(mp) - 1); | 915 | xfs_trans_log_buf(args->trans, bp2, 0, args->geo->blksize - 1); |
913 | 916 | ||
914 | /* | 917 | /* |
915 | * Set up the new root node. | 918 | * Set up the new root node. |
@@ -930,7 +933,7 @@ xfs_attr3_leaf_to_node( | |||
930 | btree[0].before = cpu_to_be32(blkno); | 933 | btree[0].before = cpu_to_be32(blkno); |
931 | icnodehdr.count = 1; | 934 | icnodehdr.count = 1; |
932 | dp->d_ops->node_hdr_to_disk(node, &icnodehdr); | 935 | dp->d_ops->node_hdr_to_disk(node, &icnodehdr); |
933 | xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(mp) - 1); | 936 | xfs_trans_log_buf(args->trans, bp1, 0, args->geo->blksize - 1); |
934 | error = 0; | 937 | error = 0; |
935 | out: | 938 | out: |
936 | return error; | 939 | return error; |
@@ -966,10 +969,10 @@ xfs_attr3_leaf_create( | |||
966 | bp->b_ops = &xfs_attr3_leaf_buf_ops; | 969 | bp->b_ops = &xfs_attr3_leaf_buf_ops; |
967 | xfs_trans_buf_set_type(args->trans, bp, XFS_BLFT_ATTR_LEAF_BUF); | 970 | xfs_trans_buf_set_type(args->trans, bp, XFS_BLFT_ATTR_LEAF_BUF); |
968 | leaf = bp->b_addr; | 971 | leaf = bp->b_addr; |
969 | memset(leaf, 0, XFS_LBSIZE(mp)); | 972 | memset(leaf, 0, args->geo->blksize); |
970 | 973 | ||
971 | memset(&ichdr, 0, sizeof(ichdr)); | 974 | memset(&ichdr, 0, sizeof(ichdr)); |
972 | ichdr.firstused = XFS_LBSIZE(mp); | 975 | ichdr.firstused = args->geo->blksize; |
973 | 976 | ||
974 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 977 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
975 | struct xfs_da3_blkinfo *hdr3 = bp->b_addr; | 978 | struct xfs_da3_blkinfo *hdr3 = bp->b_addr; |
@@ -988,7 +991,7 @@ xfs_attr3_leaf_create( | |||
988 | ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base; | 991 | ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base; |
989 | 992 | ||
990 | xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); | 993 | xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); |
991 | xfs_trans_log_buf(args->trans, bp, 0, XFS_LBSIZE(mp) - 1); | 994 | xfs_trans_log_buf(args->trans, bp, 0, args->geo->blksize - 1); |
992 | 995 | ||
993 | *bpp = bp; | 996 | *bpp = bp; |
994 | return 0; | 997 | return 0; |
@@ -1074,8 +1077,7 @@ xfs_attr3_leaf_add( | |||
1074 | leaf = bp->b_addr; | 1077 | leaf = bp->b_addr; |
1075 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | 1078 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
1076 | ASSERT(args->index >= 0 && args->index <= ichdr.count); | 1079 | ASSERT(args->index >= 0 && args->index <= ichdr.count); |
1077 | entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen, | 1080 | entsize = xfs_attr_leaf_newentsize(args, NULL); |
1078 | args->trans->t_mountp->m_sb.sb_blocksize, NULL); | ||
1079 | 1081 | ||
1080 | /* | 1082 | /* |
1081 | * Search through freemap for first-fit on new name length. | 1083 | * Search through freemap for first-fit on new name length. |
@@ -1174,17 +1176,14 @@ xfs_attr3_leaf_add_work( | |||
1174 | * Allocate space for the new string (at the end of the run). | 1176 | * Allocate space for the new string (at the end of the run). |
1175 | */ | 1177 | */ |
1176 | mp = args->trans->t_mountp; | 1178 | mp = args->trans->t_mountp; |
1177 | ASSERT(ichdr->freemap[mapindex].base < XFS_LBSIZE(mp)); | 1179 | ASSERT(ichdr->freemap[mapindex].base < args->geo->blksize); |
1178 | ASSERT((ichdr->freemap[mapindex].base & 0x3) == 0); | 1180 | ASSERT((ichdr->freemap[mapindex].base & 0x3) == 0); |
1179 | ASSERT(ichdr->freemap[mapindex].size >= | 1181 | ASSERT(ichdr->freemap[mapindex].size >= |
1180 | xfs_attr_leaf_newentsize(args->namelen, args->valuelen, | 1182 | xfs_attr_leaf_newentsize(args, NULL)); |
1181 | mp->m_sb.sb_blocksize, NULL)); | 1183 | ASSERT(ichdr->freemap[mapindex].size < args->geo->blksize); |
1182 | ASSERT(ichdr->freemap[mapindex].size < XFS_LBSIZE(mp)); | ||
1183 | ASSERT((ichdr->freemap[mapindex].size & 0x3) == 0); | 1184 | ASSERT((ichdr->freemap[mapindex].size & 0x3) == 0); |
1184 | 1185 | ||
1185 | ichdr->freemap[mapindex].size -= | 1186 | ichdr->freemap[mapindex].size -= xfs_attr_leaf_newentsize(args, &tmp); |
1186 | xfs_attr_leaf_newentsize(args->namelen, args->valuelen, | ||
1187 | mp->m_sb.sb_blocksize, &tmp); | ||
1188 | 1187 | ||
1189 | entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base + | 1188 | entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base + |
1190 | ichdr->freemap[mapindex].size); | 1189 | ichdr->freemap[mapindex].size); |
@@ -1269,14 +1268,13 @@ xfs_attr3_leaf_compact( | |||
1269 | struct xfs_attr_leafblock *leaf_dst; | 1268 | struct xfs_attr_leafblock *leaf_dst; |
1270 | struct xfs_attr3_icleaf_hdr ichdr_src; | 1269 | struct xfs_attr3_icleaf_hdr ichdr_src; |
1271 | struct xfs_trans *trans = args->trans; | 1270 | struct xfs_trans *trans = args->trans; |
1272 | struct xfs_mount *mp = trans->t_mountp; | ||
1273 | char *tmpbuffer; | 1271 | char *tmpbuffer; |
1274 | 1272 | ||
1275 | trace_xfs_attr_leaf_compact(args); | 1273 | trace_xfs_attr_leaf_compact(args); |
1276 | 1274 | ||
1277 | tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP); | 1275 | tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP); |
1278 | memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp)); | 1276 | memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); |
1279 | memset(bp->b_addr, 0, XFS_LBSIZE(mp)); | 1277 | memset(bp->b_addr, 0, args->geo->blksize); |
1280 | leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; | 1278 | leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; |
1281 | leaf_dst = bp->b_addr; | 1279 | leaf_dst = bp->b_addr; |
1282 | 1280 | ||
@@ -1289,7 +1287,7 @@ xfs_attr3_leaf_compact( | |||
1289 | 1287 | ||
1290 | /* Initialise the incore headers */ | 1288 | /* Initialise the incore headers */ |
1291 | ichdr_src = *ichdr_dst; /* struct copy */ | 1289 | ichdr_src = *ichdr_dst; /* struct copy */ |
1292 | ichdr_dst->firstused = XFS_LBSIZE(mp); | 1290 | ichdr_dst->firstused = args->geo->blksize; |
1293 | ichdr_dst->usedbytes = 0; | 1291 | ichdr_dst->usedbytes = 0; |
1294 | ichdr_dst->count = 0; | 1292 | ichdr_dst->count = 0; |
1295 | ichdr_dst->holes = 0; | 1293 | ichdr_dst->holes = 0; |
@@ -1304,13 +1302,13 @@ xfs_attr3_leaf_compact( | |||
1304 | * Copy all entry's in the same (sorted) order, | 1302 | * Copy all entry's in the same (sorted) order, |
1305 | * but allocate name/value pairs packed and in sequence. | 1303 | * but allocate name/value pairs packed and in sequence. |
1306 | */ | 1304 | */ |
1307 | xfs_attr3_leaf_moveents(leaf_src, &ichdr_src, 0, leaf_dst, ichdr_dst, 0, | 1305 | xfs_attr3_leaf_moveents(args, leaf_src, &ichdr_src, 0, |
1308 | ichdr_src.count, mp); | 1306 | leaf_dst, ichdr_dst, 0, ichdr_src.count); |
1309 | /* | 1307 | /* |
1310 | * this logs the entire buffer, but the caller must write the header | 1308 | * this logs the entire buffer, but the caller must write the header |
1311 | * back to the buffer when it is finished modifying it. | 1309 | * back to the buffer when it is finished modifying it. |
1312 | */ | 1310 | */ |
1313 | xfs_trans_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); | 1311 | xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1); |
1314 | 1312 | ||
1315 | kmem_free(tmpbuffer); | 1313 | kmem_free(tmpbuffer); |
1316 | } | 1314 | } |
@@ -1461,8 +1459,8 @@ xfs_attr3_leaf_rebalance( | |||
1461 | /* | 1459 | /* |
1462 | * Move high entries from leaf1 to low end of leaf2. | 1460 | * Move high entries from leaf1 to low end of leaf2. |
1463 | */ | 1461 | */ |
1464 | xfs_attr3_leaf_moveents(leaf1, &ichdr1, ichdr1.count - count, | 1462 | xfs_attr3_leaf_moveents(args, leaf1, &ichdr1, |
1465 | leaf2, &ichdr2, 0, count, state->mp); | 1463 | ichdr1.count - count, leaf2, &ichdr2, 0, count); |
1466 | 1464 | ||
1467 | } else if (count > ichdr1.count) { | 1465 | } else if (count > ichdr1.count) { |
1468 | /* | 1466 | /* |
@@ -1490,14 +1488,14 @@ xfs_attr3_leaf_rebalance( | |||
1490 | /* | 1488 | /* |
1491 | * Move low entries from leaf2 to high end of leaf1. | 1489 | * Move low entries from leaf2 to high end of leaf1. |
1492 | */ | 1490 | */ |
1493 | xfs_attr3_leaf_moveents(leaf2, &ichdr2, 0, leaf1, &ichdr1, | 1491 | xfs_attr3_leaf_moveents(args, leaf2, &ichdr2, 0, leaf1, &ichdr1, |
1494 | ichdr1.count, count, state->mp); | 1492 | ichdr1.count, count); |
1495 | } | 1493 | } |
1496 | 1494 | ||
1497 | xfs_attr3_leaf_hdr_to_disk(leaf1, &ichdr1); | 1495 | xfs_attr3_leaf_hdr_to_disk(leaf1, &ichdr1); |
1498 | xfs_attr3_leaf_hdr_to_disk(leaf2, &ichdr2); | 1496 | xfs_attr3_leaf_hdr_to_disk(leaf2, &ichdr2); |
1499 | xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); | 1497 | xfs_trans_log_buf(args->trans, blk1->bp, 0, args->geo->blksize - 1); |
1500 | xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); | 1498 | xfs_trans_log_buf(args->trans, blk2->bp, 0, args->geo->blksize - 1); |
1501 | 1499 | ||
1502 | /* | 1500 | /* |
1503 | * Copy out last hashval in each block for B-tree code. | 1501 | * Copy out last hashval in each block for B-tree code. |
@@ -1592,11 +1590,9 @@ xfs_attr3_leaf_figure_balance( | |||
1592 | max = ichdr1->count + ichdr2->count; | 1590 | max = ichdr1->count + ichdr2->count; |
1593 | half = (max + 1) * sizeof(*entry); | 1591 | half = (max + 1) * sizeof(*entry); |
1594 | half += ichdr1->usedbytes + ichdr2->usedbytes + | 1592 | half += ichdr1->usedbytes + ichdr2->usedbytes + |
1595 | xfs_attr_leaf_newentsize(state->args->namelen, | 1593 | xfs_attr_leaf_newentsize(state->args, NULL); |
1596 | state->args->valuelen, | ||
1597 | state->blocksize, NULL); | ||
1598 | half /= 2; | 1594 | half /= 2; |
1599 | lastdelta = state->blocksize; | 1595 | lastdelta = state->args->geo->blksize; |
1600 | entry = xfs_attr3_leaf_entryp(leaf1); | 1596 | entry = xfs_attr3_leaf_entryp(leaf1); |
1601 | for (count = index = 0; count < max; entry++, index++, count++) { | 1597 | for (count = index = 0; count < max; entry++, index++, count++) { |
1602 | 1598 | ||
@@ -1606,10 +1602,7 @@ xfs_attr3_leaf_figure_balance( | |||
1606 | */ | 1602 | */ |
1607 | if (count == blk1->index) { | 1603 | if (count == blk1->index) { |
1608 | tmp = totallen + sizeof(*entry) + | 1604 | tmp = totallen + sizeof(*entry) + |
1609 | xfs_attr_leaf_newentsize( | 1605 | xfs_attr_leaf_newentsize(state->args, NULL); |
1610 | state->args->namelen, | ||
1611 | state->args->valuelen, | ||
1612 | state->blocksize, NULL); | ||
1613 | if (XFS_ATTR_ABS(half - tmp) > lastdelta) | 1606 | if (XFS_ATTR_ABS(half - tmp) > lastdelta) |
1614 | break; | 1607 | break; |
1615 | lastdelta = XFS_ATTR_ABS(half - tmp); | 1608 | lastdelta = XFS_ATTR_ABS(half - tmp); |
@@ -1645,10 +1638,7 @@ xfs_attr3_leaf_figure_balance( | |||
1645 | totallen -= count * sizeof(*entry); | 1638 | totallen -= count * sizeof(*entry); |
1646 | if (foundit) { | 1639 | if (foundit) { |
1647 | totallen -= sizeof(*entry) + | 1640 | totallen -= sizeof(*entry) + |
1648 | xfs_attr_leaf_newentsize( | 1641 | xfs_attr_leaf_newentsize(state->args, NULL); |
1649 | state->args->namelen, | ||
1650 | state->args->valuelen, | ||
1651 | state->blocksize, NULL); | ||
1652 | } | 1642 | } |
1653 | 1643 | ||
1654 | *countarg = count; | 1644 | *countarg = count; |
@@ -1700,7 +1690,7 @@ xfs_attr3_leaf_toosmall( | |||
1700 | bytes = xfs_attr3_leaf_hdr_size(leaf) + | 1690 | bytes = xfs_attr3_leaf_hdr_size(leaf) + |
1701 | ichdr.count * sizeof(xfs_attr_leaf_entry_t) + | 1691 | ichdr.count * sizeof(xfs_attr_leaf_entry_t) + |
1702 | ichdr.usedbytes; | 1692 | ichdr.usedbytes; |
1703 | if (bytes > (state->blocksize >> 1)) { | 1693 | if (bytes > (state->args->geo->blksize >> 1)) { |
1704 | *action = 0; /* blk over 50%, don't try to join */ | 1694 | *action = 0; /* blk over 50%, don't try to join */ |
1705 | return(0); | 1695 | return(0); |
1706 | } | 1696 | } |
@@ -1754,7 +1744,8 @@ xfs_attr3_leaf_toosmall( | |||
1754 | 1744 | ||
1755 | xfs_attr3_leaf_hdr_from_disk(&ichdr2, bp->b_addr); | 1745 | xfs_attr3_leaf_hdr_from_disk(&ichdr2, bp->b_addr); |
1756 | 1746 | ||
1757 | bytes = state->blocksize - (state->blocksize >> 2) - | 1747 | bytes = state->args->geo->blksize - |
1748 | (state->args->geo->blksize >> 2) - | ||
1758 | ichdr.usedbytes - ichdr2.usedbytes - | 1749 | ichdr.usedbytes - ichdr2.usedbytes - |
1759 | ((ichdr.count + ichdr2.count) * | 1750 | ((ichdr.count + ichdr2.count) * |
1760 | sizeof(xfs_attr_leaf_entry_t)) - | 1751 | sizeof(xfs_attr_leaf_entry_t)) - |
@@ -1805,7 +1796,6 @@ xfs_attr3_leaf_remove( | |||
1805 | struct xfs_attr_leafblock *leaf; | 1796 | struct xfs_attr_leafblock *leaf; |
1806 | struct xfs_attr3_icleaf_hdr ichdr; | 1797 | struct xfs_attr3_icleaf_hdr ichdr; |
1807 | struct xfs_attr_leaf_entry *entry; | 1798 | struct xfs_attr_leaf_entry *entry; |
1808 | struct xfs_mount *mp = args->trans->t_mountp; | ||
1809 | int before; | 1799 | int before; |
1810 | int after; | 1800 | int after; |
1811 | int smallest; | 1801 | int smallest; |
@@ -1819,7 +1809,7 @@ xfs_attr3_leaf_remove( | |||
1819 | leaf = bp->b_addr; | 1809 | leaf = bp->b_addr; |
1820 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | 1810 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
1821 | 1811 | ||
1822 | ASSERT(ichdr.count > 0 && ichdr.count < XFS_LBSIZE(mp) / 8); | 1812 | ASSERT(ichdr.count > 0 && ichdr.count < args->geo->blksize / 8); |
1823 | ASSERT(args->index >= 0 && args->index < ichdr.count); | 1813 | ASSERT(args->index >= 0 && args->index < ichdr.count); |
1824 | ASSERT(ichdr.firstused >= ichdr.count * sizeof(*entry) + | 1814 | ASSERT(ichdr.firstused >= ichdr.count * sizeof(*entry) + |
1825 | xfs_attr3_leaf_hdr_size(leaf)); | 1815 | xfs_attr3_leaf_hdr_size(leaf)); |
@@ -1827,7 +1817,7 @@ xfs_attr3_leaf_remove( | |||
1827 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; | 1817 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; |
1828 | 1818 | ||
1829 | ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); | 1819 | ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); |
1830 | ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); | 1820 | ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize); |
1831 | 1821 | ||
1832 | /* | 1822 | /* |
1833 | * Scan through free region table: | 1823 | * Scan through free region table: |
@@ -1842,8 +1832,8 @@ xfs_attr3_leaf_remove( | |||
1842 | smallest = XFS_ATTR_LEAF_MAPSIZE - 1; | 1832 | smallest = XFS_ATTR_LEAF_MAPSIZE - 1; |
1843 | entsize = xfs_attr_leaf_entsize(leaf, args->index); | 1833 | entsize = xfs_attr_leaf_entsize(leaf, args->index); |
1844 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | 1834 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { |
1845 | ASSERT(ichdr.freemap[i].base < XFS_LBSIZE(mp)); | 1835 | ASSERT(ichdr.freemap[i].base < args->geo->blksize); |
1846 | ASSERT(ichdr.freemap[i].size < XFS_LBSIZE(mp)); | 1836 | ASSERT(ichdr.freemap[i].size < args->geo->blksize); |
1847 | if (ichdr.freemap[i].base == tablesize) { | 1837 | if (ichdr.freemap[i].base == tablesize) { |
1848 | ichdr.freemap[i].base -= sizeof(xfs_attr_leaf_entry_t); | 1838 | ichdr.freemap[i].base -= sizeof(xfs_attr_leaf_entry_t); |
1849 | ichdr.freemap[i].size += sizeof(xfs_attr_leaf_entry_t); | 1839 | ichdr.freemap[i].size += sizeof(xfs_attr_leaf_entry_t); |
@@ -1920,11 +1910,11 @@ xfs_attr3_leaf_remove( | |||
1920 | * removing the name. | 1910 | * removing the name. |
1921 | */ | 1911 | */ |
1922 | if (smallest) { | 1912 | if (smallest) { |
1923 | tmp = XFS_LBSIZE(mp); | 1913 | tmp = args->geo->blksize; |
1924 | entry = xfs_attr3_leaf_entryp(leaf); | 1914 | entry = xfs_attr3_leaf_entryp(leaf); |
1925 | for (i = ichdr.count - 1; i >= 0; entry++, i--) { | 1915 | for (i = ichdr.count - 1; i >= 0; entry++, i--) { |
1926 | ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); | 1916 | ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); |
1927 | ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); | 1917 | ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize); |
1928 | 1918 | ||
1929 | if (be16_to_cpu(entry->nameidx) < tmp) | 1919 | if (be16_to_cpu(entry->nameidx) < tmp) |
1930 | tmp = be16_to_cpu(entry->nameidx); | 1920 | tmp = be16_to_cpu(entry->nameidx); |
@@ -1947,7 +1937,7 @@ xfs_attr3_leaf_remove( | |||
1947 | tmp = ichdr.usedbytes + xfs_attr3_leaf_hdr_size(leaf) + | 1937 | tmp = ichdr.usedbytes + xfs_attr3_leaf_hdr_size(leaf) + |
1948 | ichdr.count * sizeof(xfs_attr_leaf_entry_t); | 1938 | ichdr.count * sizeof(xfs_attr_leaf_entry_t); |
1949 | 1939 | ||
1950 | return tmp < mp->m_attr_magicpct; /* leaf is < 37% full */ | 1940 | return tmp < args->geo->magicpct; /* leaf is < 37% full */ |
1951 | } | 1941 | } |
1952 | 1942 | ||
1953 | /* | 1943 | /* |
@@ -1964,7 +1954,6 @@ xfs_attr3_leaf_unbalance( | |||
1964 | struct xfs_attr3_icleaf_hdr drophdr; | 1954 | struct xfs_attr3_icleaf_hdr drophdr; |
1965 | struct xfs_attr3_icleaf_hdr savehdr; | 1955 | struct xfs_attr3_icleaf_hdr savehdr; |
1966 | struct xfs_attr_leaf_entry *entry; | 1956 | struct xfs_attr_leaf_entry *entry; |
1967 | struct xfs_mount *mp = state->mp; | ||
1968 | 1957 | ||
1969 | trace_xfs_attr_leaf_unbalance(state->args); | 1958 | trace_xfs_attr_leaf_unbalance(state->args); |
1970 | 1959 | ||
@@ -1991,13 +1980,15 @@ xfs_attr3_leaf_unbalance( | |||
1991 | */ | 1980 | */ |
1992 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, | 1981 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, |
1993 | drop_blk->bp, &drophdr)) { | 1982 | drop_blk->bp, &drophdr)) { |
1994 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, | 1983 | xfs_attr3_leaf_moveents(state->args, |
1984 | drop_leaf, &drophdr, 0, | ||
1995 | save_leaf, &savehdr, 0, | 1985 | save_leaf, &savehdr, 0, |
1996 | drophdr.count, mp); | 1986 | drophdr.count); |
1997 | } else { | 1987 | } else { |
1998 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, | 1988 | xfs_attr3_leaf_moveents(state->args, |
1989 | drop_leaf, &drophdr, 0, | ||
1999 | save_leaf, &savehdr, | 1990 | save_leaf, &savehdr, |
2000 | savehdr.count, drophdr.count, mp); | 1991 | savehdr.count, drophdr.count); |
2001 | } | 1992 | } |
2002 | } else { | 1993 | } else { |
2003 | /* | 1994 | /* |
@@ -2007,7 +1998,7 @@ xfs_attr3_leaf_unbalance( | |||
2007 | struct xfs_attr_leafblock *tmp_leaf; | 1998 | struct xfs_attr_leafblock *tmp_leaf; |
2008 | struct xfs_attr3_icleaf_hdr tmphdr; | 1999 | struct xfs_attr3_icleaf_hdr tmphdr; |
2009 | 2000 | ||
2010 | tmp_leaf = kmem_zalloc(state->blocksize, KM_SLEEP); | 2001 | tmp_leaf = kmem_zalloc(state->args->geo->blksize, KM_SLEEP); |
2011 | 2002 | ||
2012 | /* | 2003 | /* |
2013 | * Copy the header into the temp leaf so that all the stuff | 2004 | * Copy the header into the temp leaf so that all the stuff |
@@ -2020,35 +2011,39 @@ xfs_attr3_leaf_unbalance( | |||
2020 | tmphdr.magic = savehdr.magic; | 2011 | tmphdr.magic = savehdr.magic; |
2021 | tmphdr.forw = savehdr.forw; | 2012 | tmphdr.forw = savehdr.forw; |
2022 | tmphdr.back = savehdr.back; | 2013 | tmphdr.back = savehdr.back; |
2023 | tmphdr.firstused = state->blocksize; | 2014 | tmphdr.firstused = state->args->geo->blksize; |
2024 | 2015 | ||
2025 | /* write the header to the temp buffer to initialise it */ | 2016 | /* write the header to the temp buffer to initialise it */ |
2026 | xfs_attr3_leaf_hdr_to_disk(tmp_leaf, &tmphdr); | 2017 | xfs_attr3_leaf_hdr_to_disk(tmp_leaf, &tmphdr); |
2027 | 2018 | ||
2028 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, | 2019 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, |
2029 | drop_blk->bp, &drophdr)) { | 2020 | drop_blk->bp, &drophdr)) { |
2030 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, | 2021 | xfs_attr3_leaf_moveents(state->args, |
2022 | drop_leaf, &drophdr, 0, | ||
2031 | tmp_leaf, &tmphdr, 0, | 2023 | tmp_leaf, &tmphdr, 0, |
2032 | drophdr.count, mp); | 2024 | drophdr.count); |
2033 | xfs_attr3_leaf_moveents(save_leaf, &savehdr, 0, | 2025 | xfs_attr3_leaf_moveents(state->args, |
2026 | save_leaf, &savehdr, 0, | ||
2034 | tmp_leaf, &tmphdr, tmphdr.count, | 2027 | tmp_leaf, &tmphdr, tmphdr.count, |
2035 | savehdr.count, mp); | 2028 | savehdr.count); |
2036 | } else { | 2029 | } else { |
2037 | xfs_attr3_leaf_moveents(save_leaf, &savehdr, 0, | 2030 | xfs_attr3_leaf_moveents(state->args, |
2031 | save_leaf, &savehdr, 0, | ||
2038 | tmp_leaf, &tmphdr, 0, | 2032 | tmp_leaf, &tmphdr, 0, |
2039 | savehdr.count, mp); | 2033 | savehdr.count); |
2040 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, | 2034 | xfs_attr3_leaf_moveents(state->args, |
2035 | drop_leaf, &drophdr, 0, | ||
2041 | tmp_leaf, &tmphdr, tmphdr.count, | 2036 | tmp_leaf, &tmphdr, tmphdr.count, |
2042 | drophdr.count, mp); | 2037 | drophdr.count); |
2043 | } | 2038 | } |
2044 | memcpy(save_leaf, tmp_leaf, state->blocksize); | 2039 | memcpy(save_leaf, tmp_leaf, state->args->geo->blksize); |
2045 | savehdr = tmphdr; /* struct copy */ | 2040 | savehdr = tmphdr; /* struct copy */ |
2046 | kmem_free(tmp_leaf); | 2041 | kmem_free(tmp_leaf); |
2047 | } | 2042 | } |
2048 | 2043 | ||
2049 | xfs_attr3_leaf_hdr_to_disk(save_leaf, &savehdr); | 2044 | xfs_attr3_leaf_hdr_to_disk(save_leaf, &savehdr); |
2050 | xfs_trans_log_buf(state->args->trans, save_blk->bp, 0, | 2045 | xfs_trans_log_buf(state->args->trans, save_blk->bp, 0, |
2051 | state->blocksize - 1); | 2046 | state->args->geo->blksize - 1); |
2052 | 2047 | ||
2053 | /* | 2048 | /* |
2054 | * Copy out last hashval in each block for B-tree code. | 2049 | * Copy out last hashval in each block for B-tree code. |
@@ -2094,7 +2089,7 @@ xfs_attr3_leaf_lookup_int( | |||
2094 | leaf = bp->b_addr; | 2089 | leaf = bp->b_addr; |
2095 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | 2090 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
2096 | entries = xfs_attr3_leaf_entryp(leaf); | 2091 | entries = xfs_attr3_leaf_entryp(leaf); |
2097 | ASSERT(ichdr.count < XFS_LBSIZE(args->dp->i_mount) / 8); | 2092 | ASSERT(ichdr.count < args->geo->blksize / 8); |
2098 | 2093 | ||
2099 | /* | 2094 | /* |
2100 | * Binary search. (note: small blocks will skip this loop) | 2095 | * Binary search. (note: small blocks will skip this loop) |
@@ -2198,7 +2193,7 @@ xfs_attr3_leaf_getvalue( | |||
2198 | 2193 | ||
2199 | leaf = bp->b_addr; | 2194 | leaf = bp->b_addr; |
2200 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | 2195 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
2201 | ASSERT(ichdr.count < XFS_LBSIZE(args->dp->i_mount) / 8); | 2196 | ASSERT(ichdr.count < args->geo->blksize / 8); |
2202 | ASSERT(args->index < ichdr.count); | 2197 | ASSERT(args->index < ichdr.count); |
2203 | 2198 | ||
2204 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; | 2199 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; |
@@ -2249,14 +2244,14 @@ xfs_attr3_leaf_getvalue( | |||
2249 | /*ARGSUSED*/ | 2244 | /*ARGSUSED*/ |
2250 | STATIC void | 2245 | STATIC void |
2251 | xfs_attr3_leaf_moveents( | 2246 | xfs_attr3_leaf_moveents( |
2247 | struct xfs_da_args *args, | ||
2252 | struct xfs_attr_leafblock *leaf_s, | 2248 | struct xfs_attr_leafblock *leaf_s, |
2253 | struct xfs_attr3_icleaf_hdr *ichdr_s, | 2249 | struct xfs_attr3_icleaf_hdr *ichdr_s, |
2254 | int start_s, | 2250 | int start_s, |
2255 | struct xfs_attr_leafblock *leaf_d, | 2251 | struct xfs_attr_leafblock *leaf_d, |
2256 | struct xfs_attr3_icleaf_hdr *ichdr_d, | 2252 | struct xfs_attr3_icleaf_hdr *ichdr_d, |
2257 | int start_d, | 2253 | int start_d, |
2258 | int count, | 2254 | int count) |
2259 | struct xfs_mount *mp) | ||
2260 | { | 2255 | { |
2261 | struct xfs_attr_leaf_entry *entry_s; | 2256 | struct xfs_attr_leaf_entry *entry_s; |
2262 | struct xfs_attr_leaf_entry *entry_d; | 2257 | struct xfs_attr_leaf_entry *entry_d; |
@@ -2276,10 +2271,10 @@ xfs_attr3_leaf_moveents( | |||
2276 | ASSERT(ichdr_s->magic == XFS_ATTR_LEAF_MAGIC || | 2271 | ASSERT(ichdr_s->magic == XFS_ATTR_LEAF_MAGIC || |
2277 | ichdr_s->magic == XFS_ATTR3_LEAF_MAGIC); | 2272 | ichdr_s->magic == XFS_ATTR3_LEAF_MAGIC); |
2278 | ASSERT(ichdr_s->magic == ichdr_d->magic); | 2273 | ASSERT(ichdr_s->magic == ichdr_d->magic); |
2279 | ASSERT(ichdr_s->count > 0 && ichdr_s->count < XFS_LBSIZE(mp) / 8); | 2274 | ASSERT(ichdr_s->count > 0 && ichdr_s->count < args->geo->blksize / 8); |
2280 | ASSERT(ichdr_s->firstused >= (ichdr_s->count * sizeof(*entry_s)) | 2275 | ASSERT(ichdr_s->firstused >= (ichdr_s->count * sizeof(*entry_s)) |
2281 | + xfs_attr3_leaf_hdr_size(leaf_s)); | 2276 | + xfs_attr3_leaf_hdr_size(leaf_s)); |
2282 | ASSERT(ichdr_d->count < XFS_LBSIZE(mp) / 8); | 2277 | ASSERT(ichdr_d->count < args->geo->blksize / 8); |
2283 | ASSERT(ichdr_d->firstused >= (ichdr_d->count * sizeof(*entry_d)) | 2278 | ASSERT(ichdr_d->firstused >= (ichdr_d->count * sizeof(*entry_d)) |
2284 | + xfs_attr3_leaf_hdr_size(leaf_d)); | 2279 | + xfs_attr3_leaf_hdr_size(leaf_d)); |
2285 | 2280 | ||
@@ -2331,11 +2326,11 @@ xfs_attr3_leaf_moveents( | |||
2331 | entry_d->nameidx = cpu_to_be16(ichdr_d->firstused); | 2326 | entry_d->nameidx = cpu_to_be16(ichdr_d->firstused); |
2332 | entry_d->flags = entry_s->flags; | 2327 | entry_d->flags = entry_s->flags; |
2333 | ASSERT(be16_to_cpu(entry_d->nameidx) + tmp | 2328 | ASSERT(be16_to_cpu(entry_d->nameidx) + tmp |
2334 | <= XFS_LBSIZE(mp)); | 2329 | <= args->geo->blksize); |
2335 | memmove(xfs_attr3_leaf_name(leaf_d, desti), | 2330 | memmove(xfs_attr3_leaf_name(leaf_d, desti), |
2336 | xfs_attr3_leaf_name(leaf_s, start_s + i), tmp); | 2331 | xfs_attr3_leaf_name(leaf_s, start_s + i), tmp); |
2337 | ASSERT(be16_to_cpu(entry_s->nameidx) + tmp | 2332 | ASSERT(be16_to_cpu(entry_s->nameidx) + tmp |
2338 | <= XFS_LBSIZE(mp)); | 2333 | <= args->geo->blksize); |
2339 | memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp); | 2334 | memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp); |
2340 | ichdr_s->usedbytes -= tmp; | 2335 | ichdr_s->usedbytes -= tmp; |
2341 | ichdr_d->usedbytes += tmp; | 2336 | ichdr_d->usedbytes += tmp; |
@@ -2356,7 +2351,7 @@ xfs_attr3_leaf_moveents( | |||
2356 | tmp = count * sizeof(xfs_attr_leaf_entry_t); | 2351 | tmp = count * sizeof(xfs_attr_leaf_entry_t); |
2357 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; | 2352 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; |
2358 | ASSERT(((char *)entry_s + tmp) <= | 2353 | ASSERT(((char *)entry_s + tmp) <= |
2359 | ((char *)leaf_s + XFS_LBSIZE(mp))); | 2354 | ((char *)leaf_s + args->geo->blksize)); |
2360 | memset(entry_s, 0, tmp); | 2355 | memset(entry_s, 0, tmp); |
2361 | } else { | 2356 | } else { |
2362 | /* | 2357 | /* |
@@ -2371,7 +2366,7 @@ xfs_attr3_leaf_moveents( | |||
2371 | tmp = count * sizeof(xfs_attr_leaf_entry_t); | 2366 | tmp = count * sizeof(xfs_attr_leaf_entry_t); |
2372 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[ichdr_s->count]; | 2367 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[ichdr_s->count]; |
2373 | ASSERT(((char *)entry_s + tmp) <= | 2368 | ASSERT(((char *)entry_s + tmp) <= |
2374 | ((char *)leaf_s + XFS_LBSIZE(mp))); | 2369 | ((char *)leaf_s + args->geo->blksize)); |
2375 | memset(entry_s, 0, tmp); | 2370 | memset(entry_s, 0, tmp); |
2376 | } | 2371 | } |
2377 | 2372 | ||
@@ -2439,22 +2434,21 @@ xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) | |||
2439 | * a "local" or a "remote" attribute. | 2434 | * a "local" or a "remote" attribute. |
2440 | */ | 2435 | */ |
2441 | int | 2436 | int |
2442 | xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local) | 2437 | xfs_attr_leaf_newentsize( |
2438 | struct xfs_da_args *args, | ||
2439 | int *local) | ||
2443 | { | 2440 | { |
2444 | int size; | 2441 | int size; |
2445 | 2442 | ||
2446 | size = xfs_attr_leaf_entsize_local(namelen, valuelen); | 2443 | size = xfs_attr_leaf_entsize_local(args->namelen, args->valuelen); |
2447 | if (size < xfs_attr_leaf_entsize_local_max(blocksize)) { | 2444 | if (size < xfs_attr_leaf_entsize_local_max(args->geo->blksize)) { |
2448 | if (local) { | 2445 | if (local) |
2449 | *local = 1; | 2446 | *local = 1; |
2450 | } | 2447 | return size; |
2451 | } else { | ||
2452 | size = xfs_attr_leaf_entsize_remote(namelen); | ||
2453 | if (local) { | ||
2454 | *local = 0; | ||
2455 | } | ||
2456 | } | 2448 | } |
2457 | return size; | 2449 | if (local) |
2450 | *local = 0; | ||
2451 | return xfs_attr_leaf_entsize_remote(args->namelen); | ||
2458 | } | 2452 | } |
2459 | 2453 | ||
2460 | 2454 | ||
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index 3ec5ec0b8678..e2929da7c3ba 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h | |||
@@ -96,8 +96,7 @@ int xfs_attr3_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp); | |||
96 | xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count); | 96 | xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count); |
97 | int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp, | 97 | int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp, |
98 | struct xfs_buf *leaf2_bp); | 98 | struct xfs_buf *leaf2_bp); |
99 | int xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, | 99 | int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local); |
100 | int *local); | ||
101 | int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp, | 100 | int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp, |
102 | xfs_dablk_t bno, xfs_daddr_t mappedbno, | 101 | xfs_dablk_t bno, xfs_daddr_t mappedbno, |
103 | struct xfs_buf **bpp); | 102 | struct xfs_buf **bpp); |
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 833fe5d98d80..90e2eeb21207 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c | |||
@@ -444,6 +444,7 @@ xfs_attr3_leaf_list_int( | |||
444 | xfs_da_args_t args; | 444 | xfs_da_args_t args; |
445 | 445 | ||
446 | memset((char *)&args, 0, sizeof(args)); | 446 | memset((char *)&args, 0, sizeof(args)); |
447 | args.geo = context->dp->i_mount->m_attr_geo; | ||
447 | args.dp = context->dp; | 448 | args.dp = context->dp; |
448 | args.whichfork = XFS_ATTR_FORK; | 449 | args.whichfork = XFS_ATTR_FORK; |
449 | args.valuelen = valuelen; | 450 | args.valuelen = valuelen; |
diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c index d2e6e948cec7..b5adfecbb8ee 100644 --- a/fs/xfs/xfs_attr_remote.c +++ b/fs/xfs/xfs_attr_remote.c | |||
@@ -68,7 +68,6 @@ xfs_attr3_rmt_blocks( | |||
68 | */ | 68 | */ |
69 | static bool | 69 | static bool |
70 | xfs_attr3_rmt_hdr_ok( | 70 | xfs_attr3_rmt_hdr_ok( |
71 | struct xfs_mount *mp, | ||
72 | void *ptr, | 71 | void *ptr, |
73 | xfs_ino_t ino, | 72 | xfs_ino_t ino, |
74 | uint32_t offset, | 73 | uint32_t offset, |
@@ -126,6 +125,7 @@ xfs_attr3_rmt_read_verify( | |||
126 | char *ptr; | 125 | char *ptr; |
127 | int len; | 126 | int len; |
128 | xfs_daddr_t bno; | 127 | xfs_daddr_t bno; |
128 | int blksize = mp->m_attr_geo->blksize; | ||
129 | 129 | ||
130 | /* no verification of non-crc buffers */ | 130 | /* no verification of non-crc buffers */ |
131 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 131 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
@@ -134,21 +134,20 @@ xfs_attr3_rmt_read_verify( | |||
134 | ptr = bp->b_addr; | 134 | ptr = bp->b_addr; |
135 | bno = bp->b_bn; | 135 | bno = bp->b_bn; |
136 | len = BBTOB(bp->b_length); | 136 | len = BBTOB(bp->b_length); |
137 | ASSERT(len >= XFS_LBSIZE(mp)); | 137 | ASSERT(len >= blksize); |
138 | 138 | ||
139 | while (len > 0) { | 139 | while (len > 0) { |
140 | if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp), | 140 | if (!xfs_verify_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF)) { |
141 | XFS_ATTR3_RMT_CRC_OFF)) { | ||
142 | xfs_buf_ioerror(bp, EFSBADCRC); | 141 | xfs_buf_ioerror(bp, EFSBADCRC); |
143 | break; | 142 | break; |
144 | } | 143 | } |
145 | if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) { | 144 | if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { |
146 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 145 | xfs_buf_ioerror(bp, EFSCORRUPTED); |
147 | break; | 146 | break; |
148 | } | 147 | } |
149 | len -= XFS_LBSIZE(mp); | 148 | len -= blksize; |
150 | ptr += XFS_LBSIZE(mp); | 149 | ptr += blksize; |
151 | bno += mp->m_bsize; | 150 | bno += BTOBB(blksize); |
152 | } | 151 | } |
153 | 152 | ||
154 | if (bp->b_error) | 153 | if (bp->b_error) |
@@ -166,6 +165,7 @@ xfs_attr3_rmt_write_verify( | |||
166 | char *ptr; | 165 | char *ptr; |
167 | int len; | 166 | int len; |
168 | xfs_daddr_t bno; | 167 | xfs_daddr_t bno; |
168 | int blksize = mp->m_attr_geo->blksize; | ||
169 | 169 | ||
170 | /* no verification of non-crc buffers */ | 170 | /* no verification of non-crc buffers */ |
171 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 171 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
@@ -174,10 +174,10 @@ xfs_attr3_rmt_write_verify( | |||
174 | ptr = bp->b_addr; | 174 | ptr = bp->b_addr; |
175 | bno = bp->b_bn; | 175 | bno = bp->b_bn; |
176 | len = BBTOB(bp->b_length); | 176 | len = BBTOB(bp->b_length); |
177 | ASSERT(len >= XFS_LBSIZE(mp)); | 177 | ASSERT(len >= blksize); |
178 | 178 | ||
179 | while (len > 0) { | 179 | while (len > 0) { |
180 | if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) { | 180 | if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { |
181 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 181 | xfs_buf_ioerror(bp, EFSCORRUPTED); |
182 | xfs_verifier_error(bp); | 182 | xfs_verifier_error(bp); |
183 | return; | 183 | return; |
@@ -188,11 +188,11 @@ xfs_attr3_rmt_write_verify( | |||
188 | rmt = (struct xfs_attr3_rmt_hdr *)ptr; | 188 | rmt = (struct xfs_attr3_rmt_hdr *)ptr; |
189 | rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn); | 189 | rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn); |
190 | } | 190 | } |
191 | xfs_update_cksum(ptr, XFS_LBSIZE(mp), XFS_ATTR3_RMT_CRC_OFF); | 191 | xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF); |
192 | 192 | ||
193 | len -= XFS_LBSIZE(mp); | 193 | len -= blksize; |
194 | ptr += XFS_LBSIZE(mp); | 194 | ptr += blksize; |
195 | bno += mp->m_bsize; | 195 | bno += BTOBB(blksize); |
196 | } | 196 | } |
197 | ASSERT(len == 0); | 197 | ASSERT(len == 0); |
198 | } | 198 | } |
@@ -241,17 +241,18 @@ xfs_attr_rmtval_copyout( | |||
241 | char *src = bp->b_addr; | 241 | char *src = bp->b_addr; |
242 | xfs_daddr_t bno = bp->b_bn; | 242 | xfs_daddr_t bno = bp->b_bn; |
243 | int len = BBTOB(bp->b_length); | 243 | int len = BBTOB(bp->b_length); |
244 | int blksize = mp->m_attr_geo->blksize; | ||
244 | 245 | ||
245 | ASSERT(len >= XFS_LBSIZE(mp)); | 246 | ASSERT(len >= blksize); |
246 | 247 | ||
247 | while (len > 0 && *valuelen > 0) { | 248 | while (len > 0 && *valuelen > 0) { |
248 | int hdr_size = 0; | 249 | int hdr_size = 0; |
249 | int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp)); | 250 | int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); |
250 | 251 | ||
251 | byte_cnt = min(*valuelen, byte_cnt); | 252 | byte_cnt = min(*valuelen, byte_cnt); |
252 | 253 | ||
253 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 254 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
254 | if (!xfs_attr3_rmt_hdr_ok(mp, src, ino, *offset, | 255 | if (!xfs_attr3_rmt_hdr_ok(src, ino, *offset, |
255 | byte_cnt, bno)) { | 256 | byte_cnt, bno)) { |
256 | xfs_alert(mp, | 257 | xfs_alert(mp, |
257 | "remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)", | 258 | "remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)", |
@@ -264,9 +265,9 @@ xfs_attr_rmtval_copyout( | |||
264 | memcpy(*dst, src + hdr_size, byte_cnt); | 265 | memcpy(*dst, src + hdr_size, byte_cnt); |
265 | 266 | ||
266 | /* roll buffer forwards */ | 267 | /* roll buffer forwards */ |
267 | len -= XFS_LBSIZE(mp); | 268 | len -= blksize; |
268 | src += XFS_LBSIZE(mp); | 269 | src += blksize; |
269 | bno += mp->m_bsize; | 270 | bno += BTOBB(blksize); |
270 | 271 | ||
271 | /* roll attribute data forwards */ | 272 | /* roll attribute data forwards */ |
272 | *valuelen -= byte_cnt; | 273 | *valuelen -= byte_cnt; |
@@ -288,12 +289,13 @@ xfs_attr_rmtval_copyin( | |||
288 | char *dst = bp->b_addr; | 289 | char *dst = bp->b_addr; |
289 | xfs_daddr_t bno = bp->b_bn; | 290 | xfs_daddr_t bno = bp->b_bn; |
290 | int len = BBTOB(bp->b_length); | 291 | int len = BBTOB(bp->b_length); |
292 | int blksize = mp->m_attr_geo->blksize; | ||
291 | 293 | ||
292 | ASSERT(len >= XFS_LBSIZE(mp)); | 294 | ASSERT(len >= blksize); |
293 | 295 | ||
294 | while (len > 0 && *valuelen > 0) { | 296 | while (len > 0 && *valuelen > 0) { |
295 | int hdr_size; | 297 | int hdr_size; |
296 | int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp)); | 298 | int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); |
297 | 299 | ||
298 | byte_cnt = min(*valuelen, byte_cnt); | 300 | byte_cnt = min(*valuelen, byte_cnt); |
299 | hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset, | 301 | hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset, |
@@ -305,17 +307,17 @@ xfs_attr_rmtval_copyin( | |||
305 | * If this is the last block, zero the remainder of it. | 307 | * If this is the last block, zero the remainder of it. |
306 | * Check that we are actually the last block, too. | 308 | * Check that we are actually the last block, too. |
307 | */ | 309 | */ |
308 | if (byte_cnt + hdr_size < XFS_LBSIZE(mp)) { | 310 | if (byte_cnt + hdr_size < blksize) { |
309 | ASSERT(*valuelen - byte_cnt == 0); | 311 | ASSERT(*valuelen - byte_cnt == 0); |
310 | ASSERT(len == XFS_LBSIZE(mp)); | 312 | ASSERT(len == blksize); |
311 | memset(dst + hdr_size + byte_cnt, 0, | 313 | memset(dst + hdr_size + byte_cnt, 0, |
312 | XFS_LBSIZE(mp) - hdr_size - byte_cnt); | 314 | blksize - hdr_size - byte_cnt); |
313 | } | 315 | } |
314 | 316 | ||
315 | /* roll buffer forwards */ | 317 | /* roll buffer forwards */ |
316 | len -= XFS_LBSIZE(mp); | 318 | len -= blksize; |
317 | dst += XFS_LBSIZE(mp); | 319 | dst += blksize; |
318 | bno += mp->m_bsize; | 320 | bno += BTOBB(blksize); |
319 | 321 | ||
320 | /* roll attribute data forwards */ | 322 | /* roll attribute data forwards */ |
321 | *valuelen -= byte_cnt; | 323 | *valuelen -= byte_cnt; |
diff --git a/fs/xfs/xfs_bit.h b/fs/xfs/xfs_bit.h index f1e3c907044d..e1649c0d3e02 100644 --- a/fs/xfs/xfs_bit.h +++ b/fs/xfs/xfs_bit.h | |||
@@ -66,8 +66,11 @@ static inline int xfs_lowbit64(__uint64_t v) | |||
66 | n = ffs(w); | 66 | n = ffs(w); |
67 | } else { /* upper bits */ | 67 | } else { /* upper bits */ |
68 | w = (__uint32_t)(v >> 32); | 68 | w = (__uint32_t)(v >> 32); |
69 | if (w && (n = ffs(w))) | 69 | if (w) { |
70 | n += 32; | 70 | n = ffs(w); |
71 | if (n) | ||
72 | n += 32; | ||
73 | } | ||
71 | } | 74 | } |
72 | return n - 1; | 75 | return n - 1; |
73 | } | 76 | } |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index f0efc7e970ef..96175df211b1 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -94,7 +94,7 @@ xfs_bmap_compute_maxlevels( | |||
94 | maxleafents = MAXAEXTNUM; | 94 | maxleafents = MAXAEXTNUM; |
95 | sz = XFS_BMDR_SPACE_CALC(MINABTPTRS); | 95 | sz = XFS_BMDR_SPACE_CALC(MINABTPTRS); |
96 | } | 96 | } |
97 | maxrootrecs = xfs_bmdr_maxrecs(mp, sz, 0); | 97 | maxrootrecs = xfs_bmdr_maxrecs(sz, 0); |
98 | minleafrecs = mp->m_bmap_dmnr[0]; | 98 | minleafrecs = mp->m_bmap_dmnr[0]; |
99 | minnoderecs = mp->m_bmap_dmnr[1]; | 99 | minnoderecs = mp->m_bmap_dmnr[1]; |
100 | maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; | 100 | maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; |
@@ -233,7 +233,6 @@ xfs_default_attroffset( | |||
233 | */ | 233 | */ |
234 | STATIC void | 234 | STATIC void |
235 | xfs_bmap_forkoff_reset( | 235 | xfs_bmap_forkoff_reset( |
236 | xfs_mount_t *mp, | ||
237 | xfs_inode_t *ip, | 236 | xfs_inode_t *ip, |
238 | int whichfork) | 237 | int whichfork) |
239 | { | 238 | { |
@@ -905,7 +904,7 @@ xfs_bmap_local_to_extents_empty( | |||
905 | ASSERT(ifp->if_bytes == 0); | 904 | ASSERT(ifp->if_bytes == 0); |
906 | ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); | 905 | ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); |
907 | 906 | ||
908 | xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork); | 907 | xfs_bmap_forkoff_reset(ip, whichfork); |
909 | ifp->if_flags &= ~XFS_IFINLINE; | 908 | ifp->if_flags &= ~XFS_IFINLINE; |
910 | ifp->if_flags |= XFS_IFEXTENTS; | 909 | ifp->if_flags |= XFS_IFEXTENTS; |
911 | XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); | 910 | XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); |
@@ -1099,10 +1098,11 @@ xfs_bmap_add_attrfork_local( | |||
1099 | 1098 | ||
1100 | if (S_ISDIR(ip->i_d.di_mode)) { | 1099 | if (S_ISDIR(ip->i_d.di_mode)) { |
1101 | memset(&dargs, 0, sizeof(dargs)); | 1100 | memset(&dargs, 0, sizeof(dargs)); |
1101 | dargs.geo = ip->i_mount->m_dir_geo; | ||
1102 | dargs.dp = ip; | 1102 | dargs.dp = ip; |
1103 | dargs.firstblock = firstblock; | 1103 | dargs.firstblock = firstblock; |
1104 | dargs.flist = flist; | 1104 | dargs.flist = flist; |
1105 | dargs.total = ip->i_mount->m_dirblkfsbs; | 1105 | dargs.total = dargs.geo->fsbcount; |
1106 | dargs.whichfork = XFS_DATA_FORK; | 1106 | dargs.whichfork = XFS_DATA_FORK; |
1107 | dargs.trans = tp; | 1107 | dargs.trans = tp; |
1108 | return xfs_dir2_sf_to_block(&dargs); | 1108 | return xfs_dir2_sf_to_block(&dargs); |
@@ -1675,7 +1675,6 @@ xfs_bmap_isaeof( | |||
1675 | */ | 1675 | */ |
1676 | int | 1676 | int |
1677 | xfs_bmap_last_offset( | 1677 | xfs_bmap_last_offset( |
1678 | struct xfs_trans *tp, | ||
1679 | struct xfs_inode *ip, | 1678 | struct xfs_inode *ip, |
1680 | xfs_fileoff_t *last_block, | 1679 | xfs_fileoff_t *last_block, |
1681 | int whichfork) | 1680 | int whichfork) |
@@ -3517,6 +3516,67 @@ xfs_bmap_adjacent( | |||
3517 | #undef ISVALID | 3516 | #undef ISVALID |
3518 | } | 3517 | } |
3519 | 3518 | ||
3519 | static int | ||
3520 | xfs_bmap_longest_free_extent( | ||
3521 | struct xfs_trans *tp, | ||
3522 | xfs_agnumber_t ag, | ||
3523 | xfs_extlen_t *blen, | ||
3524 | int *notinit) | ||
3525 | { | ||
3526 | struct xfs_mount *mp = tp->t_mountp; | ||
3527 | struct xfs_perag *pag; | ||
3528 | xfs_extlen_t longest; | ||
3529 | int error = 0; | ||
3530 | |||
3531 | pag = xfs_perag_get(mp, ag); | ||
3532 | if (!pag->pagf_init) { | ||
3533 | error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK); | ||
3534 | if (error) | ||
3535 | goto out; | ||
3536 | |||
3537 | if (!pag->pagf_init) { | ||
3538 | *notinit = 1; | ||
3539 | goto out; | ||
3540 | } | ||
3541 | } | ||
3542 | |||
3543 | longest = xfs_alloc_longest_free_extent(mp, pag); | ||
3544 | if (*blen < longest) | ||
3545 | *blen = longest; | ||
3546 | |||
3547 | out: | ||
3548 | xfs_perag_put(pag); | ||
3549 | return error; | ||
3550 | } | ||
3551 | |||
3552 | static void | ||
3553 | xfs_bmap_select_minlen( | ||
3554 | struct xfs_bmalloca *ap, | ||
3555 | struct xfs_alloc_arg *args, | ||
3556 | xfs_extlen_t *blen, | ||
3557 | int notinit) | ||
3558 | { | ||
3559 | if (notinit || *blen < ap->minlen) { | ||
3560 | /* | ||
3561 | * Since we did a BUF_TRYLOCK above, it is possible that | ||
3562 | * there is space for this request. | ||
3563 | */ | ||
3564 | args->minlen = ap->minlen; | ||
3565 | } else if (*blen < args->maxlen) { | ||
3566 | /* | ||
3567 | * If the best seen length is less than the request length, | ||
3568 | * use the best as the minimum. | ||
3569 | */ | ||
3570 | args->minlen = *blen; | ||
3571 | } else { | ||
3572 | /* | ||
3573 | * Otherwise we've seen an extent as big as maxlen, use that | ||
3574 | * as the minimum. | ||
3575 | */ | ||
3576 | args->minlen = args->maxlen; | ||
3577 | } | ||
3578 | } | ||
3579 | |||
3520 | STATIC int | 3580 | STATIC int |
3521 | xfs_bmap_btalloc_nullfb( | 3581 | xfs_bmap_btalloc_nullfb( |
3522 | struct xfs_bmalloca *ap, | 3582 | struct xfs_bmalloca *ap, |
@@ -3524,111 +3584,74 @@ xfs_bmap_btalloc_nullfb( | |||
3524 | xfs_extlen_t *blen) | 3584 | xfs_extlen_t *blen) |
3525 | { | 3585 | { |
3526 | struct xfs_mount *mp = ap->ip->i_mount; | 3586 | struct xfs_mount *mp = ap->ip->i_mount; |
3527 | struct xfs_perag *pag; | ||
3528 | xfs_agnumber_t ag, startag; | 3587 | xfs_agnumber_t ag, startag; |
3529 | int notinit = 0; | 3588 | int notinit = 0; |
3530 | int error; | 3589 | int error; |
3531 | 3590 | ||
3532 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) | 3591 | args->type = XFS_ALLOCTYPE_START_BNO; |
3533 | args->type = XFS_ALLOCTYPE_NEAR_BNO; | ||
3534 | else | ||
3535 | args->type = XFS_ALLOCTYPE_START_BNO; | ||
3536 | args->total = ap->total; | 3592 | args->total = ap->total; |
3537 | 3593 | ||
3538 | /* | ||
3539 | * Search for an allocation group with a single extent large enough | ||
3540 | * for the request. If one isn't found, then adjust the minimum | ||
3541 | * allocation size to the largest space found. | ||
3542 | */ | ||
3543 | startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno); | 3594 | startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno); |
3544 | if (startag == NULLAGNUMBER) | 3595 | if (startag == NULLAGNUMBER) |
3545 | startag = ag = 0; | 3596 | startag = ag = 0; |
3546 | 3597 | ||
3547 | pag = xfs_perag_get(mp, ag); | ||
3548 | while (*blen < args->maxlen) { | 3598 | while (*blen < args->maxlen) { |
3549 | if (!pag->pagf_init) { | 3599 | error = xfs_bmap_longest_free_extent(args->tp, ag, blen, |
3550 | error = xfs_alloc_pagf_init(mp, args->tp, ag, | 3600 | ¬init); |
3551 | XFS_ALLOC_FLAG_TRYLOCK); | 3601 | if (error) |
3552 | if (error) { | 3602 | return error; |
3553 | xfs_perag_put(pag); | ||
3554 | return error; | ||
3555 | } | ||
3556 | } | ||
3557 | |||
3558 | /* | ||
3559 | * See xfs_alloc_fix_freelist... | ||
3560 | */ | ||
3561 | if (pag->pagf_init) { | ||
3562 | xfs_extlen_t longest; | ||
3563 | longest = xfs_alloc_longest_free_extent(mp, pag); | ||
3564 | if (*blen < longest) | ||
3565 | *blen = longest; | ||
3566 | } else | ||
3567 | notinit = 1; | ||
3568 | |||
3569 | if (xfs_inode_is_filestream(ap->ip)) { | ||
3570 | if (*blen >= args->maxlen) | ||
3571 | break; | ||
3572 | |||
3573 | if (ap->userdata) { | ||
3574 | /* | ||
3575 | * If startag is an invalid AG, we've | ||
3576 | * come here once before and | ||
3577 | * xfs_filestream_new_ag picked the | ||
3578 | * best currently available. | ||
3579 | * | ||
3580 | * Don't continue looping, since we | ||
3581 | * could loop forever. | ||
3582 | */ | ||
3583 | if (startag == NULLAGNUMBER) | ||
3584 | break; | ||
3585 | |||
3586 | error = xfs_filestream_new_ag(ap, &ag); | ||
3587 | xfs_perag_put(pag); | ||
3588 | if (error) | ||
3589 | return error; | ||
3590 | 3603 | ||
3591 | /* loop again to set 'blen'*/ | ||
3592 | startag = NULLAGNUMBER; | ||
3593 | pag = xfs_perag_get(mp, ag); | ||
3594 | continue; | ||
3595 | } | ||
3596 | } | ||
3597 | if (++ag == mp->m_sb.sb_agcount) | 3604 | if (++ag == mp->m_sb.sb_agcount) |
3598 | ag = 0; | 3605 | ag = 0; |
3599 | if (ag == startag) | 3606 | if (ag == startag) |
3600 | break; | 3607 | break; |
3601 | xfs_perag_put(pag); | ||
3602 | pag = xfs_perag_get(mp, ag); | ||
3603 | } | 3608 | } |
3604 | xfs_perag_put(pag); | ||
3605 | 3609 | ||
3606 | /* | 3610 | xfs_bmap_select_minlen(ap, args, blen, notinit); |
3607 | * Since the above loop did a BUF_TRYLOCK, it is | 3611 | return 0; |
3608 | * possible that there is space for this request. | 3612 | } |
3609 | */ | 3613 | |
3610 | if (notinit || *blen < ap->minlen) | 3614 | STATIC int |
3611 | args->minlen = ap->minlen; | 3615 | xfs_bmap_btalloc_filestreams( |
3612 | /* | 3616 | struct xfs_bmalloca *ap, |
3613 | * If the best seen length is less than the request | 3617 | struct xfs_alloc_arg *args, |
3614 | * length, use the best as the minimum. | 3618 | xfs_extlen_t *blen) |
3615 | */ | 3619 | { |
3616 | else if (*blen < args->maxlen) | 3620 | struct xfs_mount *mp = ap->ip->i_mount; |
3617 | args->minlen = *blen; | 3621 | xfs_agnumber_t ag; |
3618 | /* | 3622 | int notinit = 0; |
3619 | * Otherwise we've seen an extent as big as maxlen, | 3623 | int error; |
3620 | * use that as the minimum. | 3624 | |
3621 | */ | 3625 | args->type = XFS_ALLOCTYPE_NEAR_BNO; |
3622 | else | 3626 | args->total = ap->total; |
3623 | args->minlen = args->maxlen; | 3627 | |
3628 | ag = XFS_FSB_TO_AGNO(mp, args->fsbno); | ||
3629 | if (ag == NULLAGNUMBER) | ||
3630 | ag = 0; | ||
3631 | |||
3632 | error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); | ||
3633 | if (error) | ||
3634 | return error; | ||
3635 | |||
3636 | if (*blen < args->maxlen) { | ||
3637 | error = xfs_filestream_new_ag(ap, &ag); | ||
3638 | if (error) | ||
3639 | return error; | ||
3640 | |||
3641 | error = xfs_bmap_longest_free_extent(args->tp, ag, blen, | ||
3642 | ¬init); | ||
3643 | if (error) | ||
3644 | return error; | ||
3645 | |||
3646 | } | ||
3647 | |||
3648 | xfs_bmap_select_minlen(ap, args, blen, notinit); | ||
3624 | 3649 | ||
3625 | /* | 3650 | /* |
3626 | * set the failure fallback case to look in the selected | 3651 | * Set the failure fallback case to look in the selected AG as stream |
3627 | * AG as the stream may have moved. | 3652 | * may have moved. |
3628 | */ | 3653 | */ |
3629 | if (xfs_inode_is_filestream(ap->ip)) | 3654 | ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); |
3630 | ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); | ||
3631 | |||
3632 | return 0; | 3655 | return 0; |
3633 | } | 3656 | } |
3634 | 3657 | ||
@@ -3708,7 +3731,15 @@ xfs_bmap_btalloc( | |||
3708 | args.firstblock = *ap->firstblock; | 3731 | args.firstblock = *ap->firstblock; |
3709 | blen = 0; | 3732 | blen = 0; |
3710 | if (nullfb) { | 3733 | if (nullfb) { |
3711 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); | 3734 | /* |
3735 | * Search for an allocation group with a single extent large | ||
3736 | * enough for the request. If one isn't found, then adjust | ||
3737 | * the minimum allocation size to the largest space found. | ||
3738 | */ | ||
3739 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) | ||
3740 | error = xfs_bmap_btalloc_filestreams(ap, &args, &blen); | ||
3741 | else | ||
3742 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); | ||
3712 | if (error) | 3743 | if (error) |
3713 | return error; | 3744 | return error; |
3714 | } else if (ap->flist->xbf_low) { | 3745 | } else if (ap->flist->xbf_low) { |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index f84bd7af43be..38ba36e9b2f0 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -156,8 +156,8 @@ int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, | |||
156 | xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); | 156 | xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); |
157 | int xfs_bmap_last_before(struct xfs_trans *tp, struct xfs_inode *ip, | 157 | int xfs_bmap_last_before(struct xfs_trans *tp, struct xfs_inode *ip, |
158 | xfs_fileoff_t *last_block, int whichfork); | 158 | xfs_fileoff_t *last_block, int whichfork); |
159 | int xfs_bmap_last_offset(struct xfs_trans *tp, struct xfs_inode *ip, | 159 | int xfs_bmap_last_offset(struct xfs_inode *ip, xfs_fileoff_t *unused, |
160 | xfs_fileoff_t *unused, int whichfork); | 160 | int whichfork); |
161 | int xfs_bmap_one_block(struct xfs_inode *ip, int whichfork); | 161 | int xfs_bmap_one_block(struct xfs_inode *ip, int whichfork); |
162 | int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip, | 162 | int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip, |
163 | int whichfork); | 163 | int whichfork); |
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 818d546664e7..948836c4fd90 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -84,7 +84,7 @@ xfs_bmdr_to_bmbt( | |||
84 | rblock->bb_level = dblock->bb_level; | 84 | rblock->bb_level = dblock->bb_level; |
85 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); | 85 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); |
86 | rblock->bb_numrecs = dblock->bb_numrecs; | 86 | rblock->bb_numrecs = dblock->bb_numrecs; |
87 | dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0); | 87 | dmxr = xfs_bmdr_maxrecs(dblocklen, 0); |
88 | fkp = XFS_BMDR_KEY_ADDR(dblock, 1); | 88 | fkp = XFS_BMDR_KEY_ADDR(dblock, 1); |
89 | tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); | 89 | tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); |
90 | fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); | 90 | fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); |
@@ -443,7 +443,7 @@ xfs_bmbt_to_bmdr( | |||
443 | ASSERT(rblock->bb_level != 0); | 443 | ASSERT(rblock->bb_level != 0); |
444 | dblock->bb_level = rblock->bb_level; | 444 | dblock->bb_level = rblock->bb_level; |
445 | dblock->bb_numrecs = rblock->bb_numrecs; | 445 | dblock->bb_numrecs = rblock->bb_numrecs; |
446 | dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0); | 446 | dmxr = xfs_bmdr_maxrecs(dblocklen, 0); |
447 | fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); | 447 | fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); |
448 | tkp = XFS_BMDR_KEY_ADDR(dblock, 1); | 448 | tkp = XFS_BMDR_KEY_ADDR(dblock, 1); |
449 | fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); | 449 | fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); |
@@ -519,7 +519,6 @@ xfs_bmbt_alloc_block( | |||
519 | struct xfs_btree_cur *cur, | 519 | struct xfs_btree_cur *cur, |
520 | union xfs_btree_ptr *start, | 520 | union xfs_btree_ptr *start, |
521 | union xfs_btree_ptr *new, | 521 | union xfs_btree_ptr *new, |
522 | int length, | ||
523 | int *stat) | 522 | int *stat) |
524 | { | 523 | { |
525 | xfs_alloc_arg_t args; /* block allocation args */ | 524 | xfs_alloc_arg_t args; /* block allocation args */ |
@@ -672,8 +671,7 @@ xfs_bmbt_get_dmaxrecs( | |||
672 | { | 671 | { |
673 | if (level != cur->bc_nlevels - 1) | 672 | if (level != cur->bc_nlevels - 1) |
674 | return cur->bc_mp->m_bmap_dmxr[level != 0]; | 673 | return cur->bc_mp->m_bmap_dmxr[level != 0]; |
675 | return xfs_bmdr_maxrecs(cur->bc_mp, cur->bc_private.b.forksize, | 674 | return xfs_bmdr_maxrecs(cur->bc_private.b.forksize, level == 0); |
676 | level == 0); | ||
677 | } | 675 | } |
678 | 676 | ||
679 | STATIC void | 677 | STATIC void |
@@ -914,7 +912,6 @@ xfs_bmbt_maxrecs( | |||
914 | */ | 912 | */ |
915 | int | 913 | int |
916 | xfs_bmdr_maxrecs( | 914 | xfs_bmdr_maxrecs( |
917 | struct xfs_mount *mp, | ||
918 | int blocklen, | 915 | int blocklen, |
919 | int leaf) | 916 | int leaf) |
920 | { | 917 | { |
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h index 6e42e1e50b89..819a8a4dee95 100644 --- a/fs/xfs/xfs_bmap_btree.h +++ b/fs/xfs/xfs_bmap_btree.h | |||
@@ -130,7 +130,7 @@ extern void xfs_bmbt_to_bmdr(struct xfs_mount *, struct xfs_btree_block *, int, | |||
130 | xfs_bmdr_block_t *, int); | 130 | xfs_bmdr_block_t *, int); |
131 | 131 | ||
132 | extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level); | 132 | extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level); |
133 | extern int xfs_bmdr_maxrecs(struct xfs_mount *, int blocklen, int leaf); | 133 | extern int xfs_bmdr_maxrecs(int blocklen, int leaf); |
134 | extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf); | 134 | extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf); |
135 | 135 | ||
136 | extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip, | 136 | extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip, |
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 296160b8e78c..703b3ec1796c 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -258,14 +258,23 @@ xfs_bmapi_allocate_worker( | |||
258 | struct xfs_bmalloca *args = container_of(work, | 258 | struct xfs_bmalloca *args = container_of(work, |
259 | struct xfs_bmalloca, work); | 259 | struct xfs_bmalloca, work); |
260 | unsigned long pflags; | 260 | unsigned long pflags; |
261 | unsigned long new_pflags = PF_FSTRANS; | ||
261 | 262 | ||
262 | /* we are in a transaction context here */ | 263 | /* |
263 | current_set_flags_nested(&pflags, PF_FSTRANS); | 264 | * we are in a transaction context here, but may also be doing work |
265 | * in kswapd context, and hence we may need to inherit that state | ||
266 | * temporarily to ensure that we don't block waiting for memory reclaim | ||
267 | * in any way. | ||
268 | */ | ||
269 | if (args->kswapd) | ||
270 | new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD; | ||
271 | |||
272 | current_set_flags_nested(&pflags, new_pflags); | ||
264 | 273 | ||
265 | args->result = __xfs_bmapi_allocate(args); | 274 | args->result = __xfs_bmapi_allocate(args); |
266 | complete(args->done); | 275 | complete(args->done); |
267 | 276 | ||
268 | current_restore_flags_nested(&pflags, PF_FSTRANS); | 277 | current_restore_flags_nested(&pflags, new_pflags); |
269 | } | 278 | } |
270 | 279 | ||
271 | /* | 280 | /* |
@@ -284,6 +293,7 @@ xfs_bmapi_allocate( | |||
284 | 293 | ||
285 | 294 | ||
286 | args->done = &done; | 295 | args->done = &done; |
296 | args->kswapd = current_is_kswapd(); | ||
287 | INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker); | 297 | INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker); |
288 | queue_work(xfs_alloc_wq, &args->work); | 298 | queue_work(xfs_alloc_wq, &args->work); |
289 | wait_for_completion(&done); | 299 | wait_for_completion(&done); |
@@ -1519,7 +1529,6 @@ xfs_collapse_file_space( | |||
1519 | 1529 | ||
1520 | while (!error && !done) { | 1530 | while (!error && !done) { |
1521 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); | 1531 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); |
1522 | tp->t_flags |= XFS_TRANS_RESERVE; | ||
1523 | /* | 1532 | /* |
1524 | * We would need to reserve permanent block for transaction. | 1533 | * We would need to reserve permanent block for transaction. |
1525 | * This will come into picture when after shifting extent into | 1534 | * This will come into picture when after shifting extent into |
@@ -1529,7 +1538,6 @@ xfs_collapse_file_space( | |||
1529 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, | 1538 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, |
1530 | XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); | 1539 | XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); |
1531 | if (error) { | 1540 | if (error) { |
1532 | ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp)); | ||
1533 | xfs_trans_cancel(tp, 0); | 1541 | xfs_trans_cancel(tp, 0); |
1534 | break; | 1542 | break; |
1535 | } | 1543 | } |
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 935ed2b24edf..075f72232a64 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h | |||
@@ -50,12 +50,13 @@ struct xfs_bmalloca { | |||
50 | xfs_extlen_t total; /* total blocks needed for xaction */ | 50 | xfs_extlen_t total; /* total blocks needed for xaction */ |
51 | xfs_extlen_t minlen; /* minimum allocation size (blocks) */ | 51 | xfs_extlen_t minlen; /* minimum allocation size (blocks) */ |
52 | xfs_extlen_t minleft; /* amount must be left after alloc */ | 52 | xfs_extlen_t minleft; /* amount must be left after alloc */ |
53 | char eof; /* set if allocating past last extent */ | 53 | bool eof; /* set if allocating past last extent */ |
54 | char wasdel; /* replacing a delayed allocation */ | 54 | bool wasdel; /* replacing a delayed allocation */ |
55 | char userdata;/* set if is user data */ | 55 | bool userdata;/* set if is user data */ |
56 | char aeof; /* allocated space at eof */ | 56 | bool aeof; /* allocated space at eof */ |
57 | char conv; /* overwriting unwritten extents */ | 57 | bool conv; /* overwriting unwritten extents */ |
58 | char stack_switch; | 58 | bool stack_switch; |
59 | bool kswapd; /* allocation in kswapd context */ | ||
59 | int flags; | 60 | int flags; |
60 | struct completion *done; | 61 | struct completion *done; |
61 | struct work_struct work; | 62 | struct work_struct work; |
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index e80d59fdf89a..bf810c6baf2b 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -43,9 +43,10 @@ kmem_zone_t *xfs_btree_cur_zone; | |||
43 | * Btree magic numbers. | 43 | * Btree magic numbers. |
44 | */ | 44 | */ |
45 | static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { | 45 | static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { |
46 | { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC }, | 46 | { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, |
47 | XFS_FIBT_MAGIC }, | ||
47 | { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, | 48 | { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, |
48 | XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC } | 49 | XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC } |
49 | }; | 50 | }; |
50 | #define xfs_btree_magic(cur) \ | 51 | #define xfs_btree_magic(cur) \ |
51 | xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] | 52 | xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] |
@@ -552,14 +553,11 @@ xfs_btree_get_bufl( | |||
552 | xfs_fsblock_t fsbno, /* file system block number */ | 553 | xfs_fsblock_t fsbno, /* file system block number */ |
553 | uint lock) /* lock flags for get_buf */ | 554 | uint lock) /* lock flags for get_buf */ |
554 | { | 555 | { |
555 | xfs_buf_t *bp; /* buffer pointer (return value) */ | ||
556 | xfs_daddr_t d; /* real disk block address */ | 556 | xfs_daddr_t d; /* real disk block address */ |
557 | 557 | ||
558 | ASSERT(fsbno != NULLFSBLOCK); | 558 | ASSERT(fsbno != NULLFSBLOCK); |
559 | d = XFS_FSB_TO_DADDR(mp, fsbno); | 559 | d = XFS_FSB_TO_DADDR(mp, fsbno); |
560 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); | 560 | return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); |
561 | ASSERT(!xfs_buf_geterror(bp)); | ||
562 | return bp; | ||
563 | } | 561 | } |
564 | 562 | ||
565 | /* | 563 | /* |
@@ -574,15 +572,12 @@ xfs_btree_get_bufs( | |||
574 | xfs_agblock_t agbno, /* allocation group block number */ | 572 | xfs_agblock_t agbno, /* allocation group block number */ |
575 | uint lock) /* lock flags for get_buf */ | 573 | uint lock) /* lock flags for get_buf */ |
576 | { | 574 | { |
577 | xfs_buf_t *bp; /* buffer pointer (return value) */ | ||
578 | xfs_daddr_t d; /* real disk block address */ | 575 | xfs_daddr_t d; /* real disk block address */ |
579 | 576 | ||
580 | ASSERT(agno != NULLAGNUMBER); | 577 | ASSERT(agno != NULLAGNUMBER); |
581 | ASSERT(agbno != NULLAGBLOCK); | 578 | ASSERT(agbno != NULLAGBLOCK); |
582 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); | 579 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); |
583 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); | 580 | return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); |
584 | ASSERT(!xfs_buf_geterror(bp)); | ||
585 | return bp; | ||
586 | } | 581 | } |
587 | 582 | ||
588 | /* | 583 | /* |
@@ -722,7 +717,6 @@ xfs_btree_read_bufl( | |||
722 | mp->m_bsize, lock, &bp, ops); | 717 | mp->m_bsize, lock, &bp, ops); |
723 | if (error) | 718 | if (error) |
724 | return error; | 719 | return error; |
725 | ASSERT(!xfs_buf_geterror(bp)); | ||
726 | if (bp) | 720 | if (bp) |
727 | xfs_buf_set_ref(bp, refval); | 721 | xfs_buf_set_ref(bp, refval); |
728 | *bpp = bp; | 722 | *bpp = bp; |
@@ -1115,6 +1109,7 @@ xfs_btree_set_refs( | |||
1115 | xfs_buf_set_ref(bp, XFS_ALLOC_BTREE_REF); | 1109 | xfs_buf_set_ref(bp, XFS_ALLOC_BTREE_REF); |
1116 | break; | 1110 | break; |
1117 | case XFS_BTNUM_INO: | 1111 | case XFS_BTNUM_INO: |
1112 | case XFS_BTNUM_FINO: | ||
1118 | xfs_buf_set_ref(bp, XFS_INO_BTREE_REF); | 1113 | xfs_buf_set_ref(bp, XFS_INO_BTREE_REF); |
1119 | break; | 1114 | break; |
1120 | case XFS_BTNUM_BMAP: | 1115 | case XFS_BTNUM_BMAP: |
@@ -1159,7 +1154,6 @@ STATIC int | |||
1159 | xfs_btree_read_buf_block( | 1154 | xfs_btree_read_buf_block( |
1160 | struct xfs_btree_cur *cur, | 1155 | struct xfs_btree_cur *cur, |
1161 | union xfs_btree_ptr *ptr, | 1156 | union xfs_btree_ptr *ptr, |
1162 | int level, | ||
1163 | int flags, | 1157 | int flags, |
1164 | struct xfs_btree_block **block, | 1158 | struct xfs_btree_block **block, |
1165 | struct xfs_buf **bpp) | 1159 | struct xfs_buf **bpp) |
@@ -1178,7 +1172,6 @@ xfs_btree_read_buf_block( | |||
1178 | if (error) | 1172 | if (error) |
1179 | return error; | 1173 | return error; |
1180 | 1174 | ||
1181 | ASSERT(!xfs_buf_geterror(*bpp)); | ||
1182 | xfs_btree_set_refs(cur, *bpp); | 1175 | xfs_btree_set_refs(cur, *bpp); |
1183 | *block = XFS_BUF_TO_BLOCK(*bpp); | 1176 | *block = XFS_BUF_TO_BLOCK(*bpp); |
1184 | return 0; | 1177 | return 0; |
@@ -1517,8 +1510,8 @@ xfs_btree_increment( | |||
1517 | union xfs_btree_ptr *ptrp; | 1510 | union xfs_btree_ptr *ptrp; |
1518 | 1511 | ||
1519 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); | 1512 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); |
1520 | error = xfs_btree_read_buf_block(cur, ptrp, --lev, | 1513 | --lev; |
1521 | 0, &block, &bp); | 1514 | error = xfs_btree_read_buf_block(cur, ptrp, 0, &block, &bp); |
1522 | if (error) | 1515 | if (error) |
1523 | goto error0; | 1516 | goto error0; |
1524 | 1517 | ||
@@ -1616,8 +1609,8 @@ xfs_btree_decrement( | |||
1616 | union xfs_btree_ptr *ptrp; | 1609 | union xfs_btree_ptr *ptrp; |
1617 | 1610 | ||
1618 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); | 1611 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); |
1619 | error = xfs_btree_read_buf_block(cur, ptrp, --lev, | 1612 | --lev; |
1620 | 0, &block, &bp); | 1613 | error = xfs_btree_read_buf_block(cur, ptrp, 0, &block, &bp); |
1621 | if (error) | 1614 | if (error) |
1622 | goto error0; | 1615 | goto error0; |
1623 | xfs_btree_setbuf(cur, lev, bp); | 1616 | xfs_btree_setbuf(cur, lev, bp); |
@@ -1667,7 +1660,7 @@ xfs_btree_lookup_get_block( | |||
1667 | return 0; | 1660 | return 0; |
1668 | } | 1661 | } |
1669 | 1662 | ||
1670 | error = xfs_btree_read_buf_block(cur, pp, level, 0, blkp, &bp); | 1663 | error = xfs_btree_read_buf_block(cur, pp, 0, blkp, &bp); |
1671 | if (error) | 1664 | if (error) |
1672 | return error; | 1665 | return error; |
1673 | 1666 | ||
@@ -2018,7 +2011,7 @@ xfs_btree_lshift( | |||
2018 | goto out0; | 2011 | goto out0; |
2019 | 2012 | ||
2020 | /* Set up the left neighbor as "left". */ | 2013 | /* Set up the left neighbor as "left". */ |
2021 | error = xfs_btree_read_buf_block(cur, &lptr, level, 0, &left, &lbp); | 2014 | error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp); |
2022 | if (error) | 2015 | if (error) |
2023 | goto error0; | 2016 | goto error0; |
2024 | 2017 | ||
@@ -2202,7 +2195,7 @@ xfs_btree_rshift( | |||
2202 | goto out0; | 2195 | goto out0; |
2203 | 2196 | ||
2204 | /* Set up the right neighbor as "right". */ | 2197 | /* Set up the right neighbor as "right". */ |
2205 | error = xfs_btree_read_buf_block(cur, &rptr, level, 0, &right, &rbp); | 2198 | error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp); |
2206 | if (error) | 2199 | if (error) |
2207 | goto error0; | 2200 | goto error0; |
2208 | 2201 | ||
@@ -2372,7 +2365,7 @@ xfs_btree_split( | |||
2372 | xfs_btree_buf_to_ptr(cur, lbp, &lptr); | 2365 | xfs_btree_buf_to_ptr(cur, lbp, &lptr); |
2373 | 2366 | ||
2374 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ | 2367 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ |
2375 | error = cur->bc_ops->alloc_block(cur, &lptr, &rptr, 1, stat); | 2368 | error = cur->bc_ops->alloc_block(cur, &lptr, &rptr, stat); |
2376 | if (error) | 2369 | if (error) |
2377 | goto error0; | 2370 | goto error0; |
2378 | if (*stat == 0) | 2371 | if (*stat == 0) |
@@ -2470,7 +2463,7 @@ xfs_btree_split( | |||
2470 | * point back to right instead of to left. | 2463 | * point back to right instead of to left. |
2471 | */ | 2464 | */ |
2472 | if (!xfs_btree_ptr_is_null(cur, &rrptr)) { | 2465 | if (!xfs_btree_ptr_is_null(cur, &rrptr)) { |
2473 | error = xfs_btree_read_buf_block(cur, &rrptr, level, | 2466 | error = xfs_btree_read_buf_block(cur, &rrptr, |
2474 | 0, &rrblock, &rrbp); | 2467 | 0, &rrblock, &rrbp); |
2475 | if (error) | 2468 | if (error) |
2476 | goto error0; | 2469 | goto error0; |
@@ -2545,7 +2538,7 @@ xfs_btree_new_iroot( | |||
2545 | pp = xfs_btree_ptr_addr(cur, 1, block); | 2538 | pp = xfs_btree_ptr_addr(cur, 1, block); |
2546 | 2539 | ||
2547 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ | 2540 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ |
2548 | error = cur->bc_ops->alloc_block(cur, pp, &nptr, 1, stat); | 2541 | error = cur->bc_ops->alloc_block(cur, pp, &nptr, stat); |
2549 | if (error) | 2542 | if (error) |
2550 | goto error0; | 2543 | goto error0; |
2551 | if (*stat == 0) { | 2544 | if (*stat == 0) { |
@@ -2649,7 +2642,7 @@ xfs_btree_new_root( | |||
2649 | cur->bc_ops->init_ptr_from_cur(cur, &rptr); | 2642 | cur->bc_ops->init_ptr_from_cur(cur, &rptr); |
2650 | 2643 | ||
2651 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ | 2644 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ |
2652 | error = cur->bc_ops->alloc_block(cur, &rptr, &lptr, 1, stat); | 2645 | error = cur->bc_ops->alloc_block(cur, &rptr, &lptr, stat); |
2653 | if (error) | 2646 | if (error) |
2654 | goto error0; | 2647 | goto error0; |
2655 | if (*stat == 0) | 2648 | if (*stat == 0) |
@@ -2684,8 +2677,7 @@ xfs_btree_new_root( | |||
2684 | lbp = bp; | 2677 | lbp = bp; |
2685 | xfs_btree_buf_to_ptr(cur, lbp, &lptr); | 2678 | xfs_btree_buf_to_ptr(cur, lbp, &lptr); |
2686 | left = block; | 2679 | left = block; |
2687 | error = xfs_btree_read_buf_block(cur, &rptr, | 2680 | error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp); |
2688 | cur->bc_nlevels - 1, 0, &right, &rbp); | ||
2689 | if (error) | 2681 | if (error) |
2690 | goto error0; | 2682 | goto error0; |
2691 | bp = rbp; | 2683 | bp = rbp; |
@@ -2696,8 +2688,7 @@ xfs_btree_new_root( | |||
2696 | xfs_btree_buf_to_ptr(cur, rbp, &rptr); | 2688 | xfs_btree_buf_to_ptr(cur, rbp, &rptr); |
2697 | right = block; | 2689 | right = block; |
2698 | xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); | 2690 | xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); |
2699 | error = xfs_btree_read_buf_block(cur, &lptr, | 2691 | error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp); |
2700 | cur->bc_nlevels - 1, 0, &left, &lbp); | ||
2701 | if (error) | 2692 | if (error) |
2702 | goto error0; | 2693 | goto error0; |
2703 | bp = lbp; | 2694 | bp = lbp; |
@@ -3649,8 +3640,7 @@ xfs_btree_delrec( | |||
3649 | rptr = cptr; | 3640 | rptr = cptr; |
3650 | right = block; | 3641 | right = block; |
3651 | rbp = bp; | 3642 | rbp = bp; |
3652 | error = xfs_btree_read_buf_block(cur, &lptr, level, | 3643 | error = xfs_btree_read_buf_block(cur, &lptr, 0, &left, &lbp); |
3653 | 0, &left, &lbp); | ||
3654 | if (error) | 3644 | if (error) |
3655 | goto error0; | 3645 | goto error0; |
3656 | 3646 | ||
@@ -3667,8 +3657,7 @@ xfs_btree_delrec( | |||
3667 | lptr = cptr; | 3657 | lptr = cptr; |
3668 | left = block; | 3658 | left = block; |
3669 | lbp = bp; | 3659 | lbp = bp; |
3670 | error = xfs_btree_read_buf_block(cur, &rptr, level, | 3660 | error = xfs_btree_read_buf_block(cur, &rptr, 0, &right, &rbp); |
3671 | 0, &right, &rbp); | ||
3672 | if (error) | 3661 | if (error) |
3673 | goto error0; | 3662 | goto error0; |
3674 | 3663 | ||
@@ -3740,8 +3729,7 @@ xfs_btree_delrec( | |||
3740 | /* If there is a right sibling, point it to the remaining block. */ | 3729 | /* If there is a right sibling, point it to the remaining block. */ |
3741 | xfs_btree_get_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB); | 3730 | xfs_btree_get_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB); |
3742 | if (!xfs_btree_ptr_is_null(cur, &cptr)) { | 3731 | if (!xfs_btree_ptr_is_null(cur, &cptr)) { |
3743 | error = xfs_btree_read_buf_block(cur, &cptr, level, | 3732 | error = xfs_btree_read_buf_block(cur, &cptr, 0, &rrblock, &rrbp); |
3744 | 0, &rrblock, &rrbp); | ||
3745 | if (error) | 3733 | if (error) |
3746 | goto error0; | 3734 | goto error0; |
3747 | xfs_btree_set_sibling(cur, rrblock, &lptr, XFS_BB_LEFTSIB); | 3735 | xfs_btree_set_sibling(cur, rrblock, &lptr, XFS_BB_LEFTSIB); |
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 91e34f21bace..a04b69422f67 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h | |||
@@ -62,6 +62,7 @@ union xfs_btree_rec { | |||
62 | #define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) | 62 | #define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) |
63 | #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) | 63 | #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) |
64 | #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) | 64 | #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) |
65 | #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) | ||
65 | 66 | ||
66 | /* | 67 | /* |
67 | * For logging record fields. | 68 | * For logging record fields. |
@@ -92,6 +93,7 @@ do { \ | |||
92 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(abtc, stat); break; \ | 93 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(abtc, stat); break; \ |
93 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(bmbt, stat); break; \ | 94 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(bmbt, stat); break; \ |
94 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(ibt, stat); break; \ | 95 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(ibt, stat); break; \ |
96 | case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(fibt, stat); break; \ | ||
95 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ | 97 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ |
96 | } \ | 98 | } \ |
97 | } while (0) | 99 | } while (0) |
@@ -105,6 +107,7 @@ do { \ | |||
105 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_ADD(abtc, stat, val); break; \ | 107 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_ADD(abtc, stat, val); break; \ |
106 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_ADD(bmbt, stat, val); break; \ | 108 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_ADD(bmbt, stat, val); break; \ |
107 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_ADD(ibt, stat, val); break; \ | 109 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_ADD(ibt, stat, val); break; \ |
110 | case XFS_BTNUM_FINO: __XFS_BTREE_STATS_ADD(fibt, stat, val); break; \ | ||
108 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ | 111 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ |
109 | } \ | 112 | } \ |
110 | } while (0) | 113 | } while (0) |
@@ -129,7 +132,7 @@ struct xfs_btree_ops { | |||
129 | int (*alloc_block)(struct xfs_btree_cur *cur, | 132 | int (*alloc_block)(struct xfs_btree_cur *cur, |
130 | union xfs_btree_ptr *start_bno, | 133 | union xfs_btree_ptr *start_bno, |
131 | union xfs_btree_ptr *new_bno, | 134 | union xfs_btree_ptr *new_bno, |
132 | int length, int *stat); | 135 | int *stat); |
133 | int (*free_block)(struct xfs_btree_cur *cur, struct xfs_buf *bp); | 136 | int (*free_block)(struct xfs_btree_cur *cur, struct xfs_buf *bp); |
134 | 137 | ||
135 | /* update last record information */ | 138 | /* update last record information */ |
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index cb10a0aaab3a..7a34a1ae6552 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
@@ -216,8 +216,7 @@ _xfs_buf_alloc( | |||
216 | STATIC int | 216 | STATIC int |
217 | _xfs_buf_get_pages( | 217 | _xfs_buf_get_pages( |
218 | xfs_buf_t *bp, | 218 | xfs_buf_t *bp, |
219 | int page_count, | 219 | int page_count) |
220 | xfs_buf_flags_t flags) | ||
221 | { | 220 | { |
222 | /* Make sure that we have a page list */ | 221 | /* Make sure that we have a page list */ |
223 | if (bp->b_pages == NULL) { | 222 | if (bp->b_pages == NULL) { |
@@ -330,7 +329,7 @@ use_alloc_page: | |||
330 | end = (BBTOB(bp->b_maps[0].bm_bn + bp->b_length) + PAGE_SIZE - 1) | 329 | end = (BBTOB(bp->b_maps[0].bm_bn + bp->b_length) + PAGE_SIZE - 1) |
331 | >> PAGE_SHIFT; | 330 | >> PAGE_SHIFT; |
332 | page_count = end - start; | 331 | page_count = end - start; |
333 | error = _xfs_buf_get_pages(bp, page_count, flags); | 332 | error = _xfs_buf_get_pages(bp, page_count); |
334 | if (unlikely(error)) | 333 | if (unlikely(error)) |
335 | return error; | 334 | return error; |
336 | 335 | ||
@@ -778,7 +777,7 @@ xfs_buf_associate_memory( | |||
778 | bp->b_pages = NULL; | 777 | bp->b_pages = NULL; |
779 | bp->b_addr = mem; | 778 | bp->b_addr = mem; |
780 | 779 | ||
781 | rval = _xfs_buf_get_pages(bp, page_count, 0); | 780 | rval = _xfs_buf_get_pages(bp, page_count); |
782 | if (rval) | 781 | if (rval) |
783 | return rval; | 782 | return rval; |
784 | 783 | ||
@@ -811,7 +810,7 @@ xfs_buf_get_uncached( | |||
811 | goto fail; | 810 | goto fail; |
812 | 811 | ||
813 | page_count = PAGE_ALIGN(numblks << BBSHIFT) >> PAGE_SHIFT; | 812 | page_count = PAGE_ALIGN(numblks << BBSHIFT) >> PAGE_SHIFT; |
814 | error = _xfs_buf_get_pages(bp, page_count, 0); | 813 | error = _xfs_buf_get_pages(bp, page_count); |
815 | if (error) | 814 | if (error) |
816 | goto fail_free_buf; | 815 | goto fail_free_buf; |
817 | 816 | ||
@@ -1615,7 +1614,6 @@ xfs_free_buftarg( | |||
1615 | int | 1614 | int |
1616 | xfs_setsize_buftarg( | 1615 | xfs_setsize_buftarg( |
1617 | xfs_buftarg_t *btp, | 1616 | xfs_buftarg_t *btp, |
1618 | unsigned int blocksize, | ||
1619 | unsigned int sectorsize) | 1617 | unsigned int sectorsize) |
1620 | { | 1618 | { |
1621 | /* Set up metadata sector size info */ | 1619 | /* Set up metadata sector size info */ |
@@ -1650,16 +1648,13 @@ xfs_setsize_buftarg_early( | |||
1650 | xfs_buftarg_t *btp, | 1648 | xfs_buftarg_t *btp, |
1651 | struct block_device *bdev) | 1649 | struct block_device *bdev) |
1652 | { | 1650 | { |
1653 | return xfs_setsize_buftarg(btp, PAGE_SIZE, | 1651 | return xfs_setsize_buftarg(btp, bdev_logical_block_size(bdev)); |
1654 | bdev_logical_block_size(bdev)); | ||
1655 | } | 1652 | } |
1656 | 1653 | ||
1657 | xfs_buftarg_t * | 1654 | xfs_buftarg_t * |
1658 | xfs_alloc_buftarg( | 1655 | xfs_alloc_buftarg( |
1659 | struct xfs_mount *mp, | 1656 | struct xfs_mount *mp, |
1660 | struct block_device *bdev, | 1657 | struct block_device *bdev) |
1661 | int external, | ||
1662 | const char *fsname) | ||
1663 | { | 1658 | { |
1664 | xfs_buftarg_t *btp; | 1659 | xfs_buftarg_t *btp; |
1665 | 1660 | ||
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index b8a3abf6cf47..3a7a5523d3dc 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h | |||
@@ -298,11 +298,6 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, | |||
298 | 298 | ||
299 | extern int xfs_bioerror_relse(struct xfs_buf *); | 299 | extern int xfs_bioerror_relse(struct xfs_buf *); |
300 | 300 | ||
301 | static inline int xfs_buf_geterror(xfs_buf_t *bp) | ||
302 | { | ||
303 | return bp ? bp->b_error : ENOMEM; | ||
304 | } | ||
305 | |||
306 | /* Buffer Utility Routines */ | 301 | /* Buffer Utility Routines */ |
307 | extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t); | 302 | extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t); |
308 | 303 | ||
@@ -387,10 +382,10 @@ xfs_buf_update_cksum(struct xfs_buf *bp, unsigned long cksum_offset) | |||
387 | * Handling of buftargs. | 382 | * Handling of buftargs. |
388 | */ | 383 | */ |
389 | extern xfs_buftarg_t *xfs_alloc_buftarg(struct xfs_mount *, | 384 | extern xfs_buftarg_t *xfs_alloc_buftarg(struct xfs_mount *, |
390 | struct block_device *, int, const char *); | 385 | struct block_device *); |
391 | extern void xfs_free_buftarg(struct xfs_mount *, struct xfs_buftarg *); | 386 | extern void xfs_free_buftarg(struct xfs_mount *, struct xfs_buftarg *); |
392 | extern void xfs_wait_buftarg(xfs_buftarg_t *); | 387 | extern void xfs_wait_buftarg(xfs_buftarg_t *); |
393 | extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); | 388 | extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int); |
394 | 389 | ||
395 | #define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) | 390 | #define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) |
396 | #define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) | 391 | #define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 8752821443be..4654338b03fc 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -812,7 +812,6 @@ xfs_buf_item_init( | |||
812 | */ | 812 | */ |
813 | static void | 813 | static void |
814 | xfs_buf_item_log_segment( | 814 | xfs_buf_item_log_segment( |
815 | struct xfs_buf_log_item *bip, | ||
816 | uint first, | 815 | uint first, |
817 | uint last, | 816 | uint last, |
818 | uint *map) | 817 | uint *map) |
@@ -920,7 +919,7 @@ xfs_buf_item_log( | |||
920 | if (end > last) | 919 | if (end > last) |
921 | end = last; | 920 | end = last; |
922 | 921 | ||
923 | xfs_buf_item_log_segment(bip, first, end, | 922 | xfs_buf_item_log_segment(first, end, |
924 | &bip->bli_formats[i].blf_data_map[0]); | 923 | &bip->bli_formats[i].blf_data_map[0]); |
925 | 924 | ||
926 | start += bp->b_maps[i].bm_len; | 925 | start += bp->b_maps[i].bm_len; |
@@ -1053,7 +1052,7 @@ xfs_buf_iodone_callbacks( | |||
1053 | static ulong lasttime; | 1052 | static ulong lasttime; |
1054 | static xfs_buftarg_t *lasttarg; | 1053 | static xfs_buftarg_t *lasttarg; |
1055 | 1054 | ||
1056 | if (likely(!xfs_buf_geterror(bp))) | 1055 | if (likely(!bp->b_error)) |
1057 | goto do_callbacks; | 1056 | goto do_callbacks; |
1058 | 1057 | ||
1059 | /* | 1058 | /* |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 6cc5f6785a77..a514ab616650 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -167,8 +167,8 @@ xfs_da3_node_verify( | |||
167 | * we don't know if the node is for and attribute or directory tree, | 167 | * we don't know if the node is for and attribute or directory tree, |
168 | * so only fail if the count is outside both bounds | 168 | * so only fail if the count is outside both bounds |
169 | */ | 169 | */ |
170 | if (ichdr.count > mp->m_dir_node_ents && | 170 | if (ichdr.count > mp->m_dir_geo->node_ents && |
171 | ichdr.count > mp->m_attr_node_ents) | 171 | ichdr.count > mp->m_attr_geo->node_ents) |
172 | return false; | 172 | return false; |
173 | 173 | ||
174 | /* XXX: hash order check? */ | 174 | /* XXX: hash order check? */ |
@@ -598,7 +598,7 @@ xfs_da3_root_split( | |||
598 | * Set up the new root node. | 598 | * Set up the new root node. |
599 | */ | 599 | */ |
600 | error = xfs_da3_node_create(args, | 600 | error = xfs_da3_node_create(args, |
601 | (args->whichfork == XFS_DATA_FORK) ? mp->m_dirleafblk : 0, | 601 | (args->whichfork == XFS_DATA_FORK) ? args->geo->leafblk : 0, |
602 | level + 1, &bp, args->whichfork); | 602 | level + 1, &bp, args->whichfork); |
603 | if (error) | 603 | if (error) |
604 | return error; | 604 | return error; |
@@ -616,10 +616,10 @@ xfs_da3_root_split( | |||
616 | #ifdef DEBUG | 616 | #ifdef DEBUG |
617 | if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | 617 | if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
618 | oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { | 618 | oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { |
619 | ASSERT(blk1->blkno >= mp->m_dirleafblk && | 619 | ASSERT(blk1->blkno >= args->geo->leafblk && |
620 | blk1->blkno < mp->m_dirfreeblk); | 620 | blk1->blkno < args->geo->freeblk); |
621 | ASSERT(blk2->blkno >= mp->m_dirleafblk && | 621 | ASSERT(blk2->blkno >= args->geo->leafblk && |
622 | blk2->blkno < mp->m_dirfreeblk); | 622 | blk2->blkno < args->geo->freeblk); |
623 | } | 623 | } |
624 | #endif | 624 | #endif |
625 | 625 | ||
@@ -663,7 +663,7 @@ xfs_da3_node_split( | |||
663 | /* | 663 | /* |
664 | * Do we have to split the node? | 664 | * Do we have to split the node? |
665 | */ | 665 | */ |
666 | if (nodehdr.count + newcount > state->node_ents) { | 666 | if (nodehdr.count + newcount > state->args->geo->node_ents) { |
667 | /* | 667 | /* |
668 | * Allocate a new node, add to the doubly linked chain of | 668 | * Allocate a new node, add to the doubly linked chain of |
669 | * nodes, then move some of our excess entries into it. | 669 | * nodes, then move some of our excess entries into it. |
@@ -894,8 +894,8 @@ xfs_da3_node_add( | |||
894 | ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); | 894 | ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); |
895 | ASSERT(newblk->blkno != 0); | 895 | ASSERT(newblk->blkno != 0); |
896 | if (state->args->whichfork == XFS_DATA_FORK) | 896 | if (state->args->whichfork == XFS_DATA_FORK) |
897 | ASSERT(newblk->blkno >= state->mp->m_dirleafblk && | 897 | ASSERT(newblk->blkno >= state->args->geo->leafblk && |
898 | newblk->blkno < state->mp->m_dirfreeblk); | 898 | newblk->blkno < state->args->geo->freeblk); |
899 | 899 | ||
900 | /* | 900 | /* |
901 | * We may need to make some room before we insert the new node. | 901 | * We may need to make some room before we insert the new node. |
@@ -1089,14 +1089,15 @@ xfs_da3_root_join( | |||
1089 | * that could occur. For dir3 blocks we also need to update the block | 1089 | * that could occur. For dir3 blocks we also need to update the block |
1090 | * number in the buffer header. | 1090 | * number in the buffer header. |
1091 | */ | 1091 | */ |
1092 | memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize); | 1092 | memcpy(root_blk->bp->b_addr, bp->b_addr, args->geo->blksize); |
1093 | root_blk->bp->b_ops = bp->b_ops; | 1093 | root_blk->bp->b_ops = bp->b_ops; |
1094 | xfs_trans_buf_copy_type(root_blk->bp, bp); | 1094 | xfs_trans_buf_copy_type(root_blk->bp, bp); |
1095 | if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) { | 1095 | if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) { |
1096 | struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr; | 1096 | struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr; |
1097 | da3->blkno = cpu_to_be64(root_blk->bp->b_bn); | 1097 | da3->blkno = cpu_to_be64(root_blk->bp->b_bn); |
1098 | } | 1098 | } |
1099 | xfs_trans_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1); | 1099 | xfs_trans_log_buf(args->trans, root_blk->bp, 0, |
1100 | args->geo->blksize - 1); | ||
1100 | error = xfs_da_shrink_inode(args, child, bp); | 1101 | error = xfs_da_shrink_inode(args, child, bp); |
1101 | return(error); | 1102 | return(error); |
1102 | } | 1103 | } |
@@ -1139,7 +1140,7 @@ xfs_da3_node_toosmall( | |||
1139 | info = blk->bp->b_addr; | 1140 | info = blk->bp->b_addr; |
1140 | node = (xfs_da_intnode_t *)info; | 1141 | node = (xfs_da_intnode_t *)info; |
1141 | dp->d_ops->node_hdr_from_disk(&nodehdr, node); | 1142 | dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
1142 | if (nodehdr.count > (state->node_ents >> 1)) { | 1143 | if (nodehdr.count > (state->args->geo->node_ents >> 1)) { |
1143 | *action = 0; /* blk over 50%, don't try to join */ | 1144 | *action = 0; /* blk over 50%, don't try to join */ |
1144 | return(0); /* blk over 50%, don't try to join */ | 1145 | return(0); /* blk over 50%, don't try to join */ |
1145 | } | 1146 | } |
@@ -1176,8 +1177,8 @@ xfs_da3_node_toosmall( | |||
1176 | * We prefer coalescing with the lower numbered sibling so as | 1177 | * We prefer coalescing with the lower numbered sibling so as |
1177 | * to shrink a directory over time. | 1178 | * to shrink a directory over time. |
1178 | */ | 1179 | */ |
1179 | count = state->node_ents; | 1180 | count = state->args->geo->node_ents; |
1180 | count -= state->node_ents >> 2; | 1181 | count -= state->args->geo->node_ents >> 2; |
1181 | count -= nodehdr.count; | 1182 | count -= nodehdr.count; |
1182 | 1183 | ||
1183 | /* start with smaller blk num */ | 1184 | /* start with smaller blk num */ |
@@ -1472,7 +1473,7 @@ xfs_da3_node_lookup_int( | |||
1472 | * Descend thru the B-tree searching each level for the right | 1473 | * Descend thru the B-tree searching each level for the right |
1473 | * node to use, until the right hashval is found. | 1474 | * node to use, until the right hashval is found. |
1474 | */ | 1475 | */ |
1475 | blkno = (args->whichfork == XFS_DATA_FORK)? state->mp->m_dirleafblk : 0; | 1476 | blkno = (args->whichfork == XFS_DATA_FORK)? args->geo->leafblk : 0; |
1476 | for (blk = &state->path.blk[0], state->path.active = 1; | 1477 | for (blk = &state->path.blk[0], state->path.active = 1; |
1477 | state->path.active <= XFS_DA_NODE_MAXDEPTH; | 1478 | state->path.active <= XFS_DA_NODE_MAXDEPTH; |
1478 | blk++, state->path.active++) { | 1479 | blk++, state->path.active++) { |
@@ -2090,20 +2091,12 @@ xfs_da_grow_inode( | |||
2090 | xfs_dablk_t *new_blkno) | 2091 | xfs_dablk_t *new_blkno) |
2091 | { | 2092 | { |
2092 | xfs_fileoff_t bno; | 2093 | xfs_fileoff_t bno; |
2093 | int count; | ||
2094 | int error; | 2094 | int error; |
2095 | 2095 | ||
2096 | trace_xfs_da_grow_inode(args); | 2096 | trace_xfs_da_grow_inode(args); |
2097 | 2097 | ||
2098 | if (args->whichfork == XFS_DATA_FORK) { | 2098 | bno = args->geo->leafblk; |
2099 | bno = args->dp->i_mount->m_dirleafblk; | 2099 | error = xfs_da_grow_inode_int(args, &bno, args->geo->fsbcount); |
2100 | count = args->dp->i_mount->m_dirblkfsbs; | ||
2101 | } else { | ||
2102 | bno = 0; | ||
2103 | count = 1; | ||
2104 | } | ||
2105 | |||
2106 | error = xfs_da_grow_inode_int(args, &bno, count); | ||
2107 | if (!error) | 2100 | if (!error) |
2108 | *new_blkno = (xfs_dablk_t)bno; | 2101 | *new_blkno = (xfs_dablk_t)bno; |
2109 | return error; | 2102 | return error; |
@@ -2158,7 +2151,7 @@ xfs_da3_swap_lastblock( | |||
2158 | w = args->whichfork; | 2151 | w = args->whichfork; |
2159 | ASSERT(w == XFS_DATA_FORK); | 2152 | ASSERT(w == XFS_DATA_FORK); |
2160 | mp = dp->i_mount; | 2153 | mp = dp->i_mount; |
2161 | lastoff = mp->m_dirfreeblk; | 2154 | lastoff = args->geo->freeblk; |
2162 | error = xfs_bmap_last_before(tp, dp, &lastoff, w); | 2155 | error = xfs_bmap_last_before(tp, dp, &lastoff, w); |
2163 | if (error) | 2156 | if (error) |
2164 | return error; | 2157 | return error; |
@@ -2170,15 +2163,15 @@ xfs_da3_swap_lastblock( | |||
2170 | /* | 2163 | /* |
2171 | * Read the last block in the btree space. | 2164 | * Read the last block in the btree space. |
2172 | */ | 2165 | */ |
2173 | last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs; | 2166 | last_blkno = (xfs_dablk_t)lastoff - args->geo->fsbcount; |
2174 | error = xfs_da3_node_read(tp, dp, last_blkno, -1, &last_buf, w); | 2167 | error = xfs_da3_node_read(tp, dp, last_blkno, -1, &last_buf, w); |
2175 | if (error) | 2168 | if (error) |
2176 | return error; | 2169 | return error; |
2177 | /* | 2170 | /* |
2178 | * Copy the last block into the dead buffer and log it. | 2171 | * Copy the last block into the dead buffer and log it. |
2179 | */ | 2172 | */ |
2180 | memcpy(dead_buf->b_addr, last_buf->b_addr, mp->m_dirblksize); | 2173 | memcpy(dead_buf->b_addr, last_buf->b_addr, args->geo->blksize); |
2181 | xfs_trans_log_buf(tp, dead_buf, 0, mp->m_dirblksize - 1); | 2174 | xfs_trans_log_buf(tp, dead_buf, 0, args->geo->blksize - 1); |
2182 | dead_info = dead_buf->b_addr; | 2175 | dead_info = dead_buf->b_addr; |
2183 | /* | 2176 | /* |
2184 | * Get values from the moved block. | 2177 | * Get values from the moved block. |
@@ -2247,7 +2240,7 @@ xfs_da3_swap_lastblock( | |||
2247 | sizeof(sib_info->back))); | 2240 | sizeof(sib_info->back))); |
2248 | sib_buf = NULL; | 2241 | sib_buf = NULL; |
2249 | } | 2242 | } |
2250 | par_blkno = mp->m_dirleafblk; | 2243 | par_blkno = args->geo->leafblk; |
2251 | level = -1; | 2244 | level = -1; |
2252 | /* | 2245 | /* |
2253 | * Walk down the tree looking for the parent of the moved block. | 2246 | * Walk down the tree looking for the parent of the moved block. |
@@ -2357,10 +2350,7 @@ xfs_da_shrink_inode( | |||
2357 | w = args->whichfork; | 2350 | w = args->whichfork; |
2358 | tp = args->trans; | 2351 | tp = args->trans; |
2359 | mp = dp->i_mount; | 2352 | mp = dp->i_mount; |
2360 | if (w == XFS_DATA_FORK) | 2353 | count = args->geo->fsbcount; |
2361 | count = mp->m_dirblkfsbs; | ||
2362 | else | ||
2363 | count = 1; | ||
2364 | for (;;) { | 2354 | for (;;) { |
2365 | /* | 2355 | /* |
2366 | * Remove extents. If we get ENOSPC for a dir we have to move | 2356 | * Remove extents. If we get ENOSPC for a dir we have to move |
@@ -2462,7 +2452,6 @@ xfs_buf_map_from_irec( | |||
2462 | */ | 2452 | */ |
2463 | static int | 2453 | static int |
2464 | xfs_dabuf_map( | 2454 | xfs_dabuf_map( |
2465 | struct xfs_trans *trans, | ||
2466 | struct xfs_inode *dp, | 2455 | struct xfs_inode *dp, |
2467 | xfs_dablk_t bno, | 2456 | xfs_dablk_t bno, |
2468 | xfs_daddr_t mappedbno, | 2457 | xfs_daddr_t mappedbno, |
@@ -2480,7 +2469,10 @@ xfs_dabuf_map( | |||
2480 | ASSERT(map && *map); | 2469 | ASSERT(map && *map); |
2481 | ASSERT(*nmaps == 1); | 2470 | ASSERT(*nmaps == 1); |
2482 | 2471 | ||
2483 | nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1; | 2472 | if (whichfork == XFS_DATA_FORK) |
2473 | nfsb = mp->m_dir_geo->fsbcount; | ||
2474 | else | ||
2475 | nfsb = mp->m_attr_geo->fsbcount; | ||
2484 | 2476 | ||
2485 | /* | 2477 | /* |
2486 | * Caller doesn't have a mapping. -2 means don't complain | 2478 | * Caller doesn't have a mapping. -2 means don't complain |
@@ -2558,7 +2550,7 @@ xfs_da_get_buf( | |||
2558 | *bpp = NULL; | 2550 | *bpp = NULL; |
2559 | mapp = ↦ | 2551 | mapp = ↦ |
2560 | nmap = 1; | 2552 | nmap = 1; |
2561 | error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork, | 2553 | error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, |
2562 | &mapp, &nmap); | 2554 | &mapp, &nmap); |
2563 | if (error) { | 2555 | if (error) { |
2564 | /* mapping a hole is not an error, but we don't continue */ | 2556 | /* mapping a hole is not an error, but we don't continue */ |
@@ -2606,7 +2598,7 @@ xfs_da_read_buf( | |||
2606 | *bpp = NULL; | 2598 | *bpp = NULL; |
2607 | mapp = ↦ | 2599 | mapp = ↦ |
2608 | nmap = 1; | 2600 | nmap = 1; |
2609 | error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork, | 2601 | error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, |
2610 | &mapp, &nmap); | 2602 | &mapp, &nmap); |
2611 | if (error) { | 2603 | if (error) { |
2612 | /* mapping a hole is not an error, but we don't continue */ | 2604 | /* mapping a hole is not an error, but we don't continue */ |
@@ -2625,47 +2617,6 @@ xfs_da_read_buf( | |||
2625 | xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); | 2617 | xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); |
2626 | else | 2618 | else |
2627 | xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); | 2619 | xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); |
2628 | |||
2629 | /* | ||
2630 | * This verification code will be moved to a CRC verification callback | ||
2631 | * function so just leave it here unchanged until then. | ||
2632 | */ | ||
2633 | { | ||
2634 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; | ||
2635 | xfs_dir2_free_t *free = bp->b_addr; | ||
2636 | xfs_da_blkinfo_t *info = bp->b_addr; | ||
2637 | uint magic, magic1; | ||
2638 | struct xfs_mount *mp = dp->i_mount; | ||
2639 | |||
2640 | magic = be16_to_cpu(info->magic); | ||
2641 | magic1 = be32_to_cpu(hdr->magic); | ||
2642 | if (unlikely( | ||
2643 | XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && | ||
2644 | (magic != XFS_DA3_NODE_MAGIC) && | ||
2645 | (magic != XFS_ATTR_LEAF_MAGIC) && | ||
2646 | (magic != XFS_ATTR3_LEAF_MAGIC) && | ||
2647 | (magic != XFS_DIR2_LEAF1_MAGIC) && | ||
2648 | (magic != XFS_DIR3_LEAF1_MAGIC) && | ||
2649 | (magic != XFS_DIR2_LEAFN_MAGIC) && | ||
2650 | (magic != XFS_DIR3_LEAFN_MAGIC) && | ||
2651 | (magic1 != XFS_DIR2_BLOCK_MAGIC) && | ||
2652 | (magic1 != XFS_DIR3_BLOCK_MAGIC) && | ||
2653 | (magic1 != XFS_DIR2_DATA_MAGIC) && | ||
2654 | (magic1 != XFS_DIR3_DATA_MAGIC) && | ||
2655 | (free->hdr.magic != | ||
2656 | cpu_to_be32(XFS_DIR2_FREE_MAGIC)) && | ||
2657 | (free->hdr.magic != | ||
2658 | cpu_to_be32(XFS_DIR3_FREE_MAGIC)), | ||
2659 | mp, XFS_ERRTAG_DA_READ_BUF, | ||
2660 | XFS_RANDOM_DA_READ_BUF))) { | ||
2661 | trace_xfs_da_btree_corrupt(bp, _RET_IP_); | ||
2662 | XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)", | ||
2663 | XFS_ERRLEVEL_LOW, mp, info); | ||
2664 | error = XFS_ERROR(EFSCORRUPTED); | ||
2665 | xfs_trans_brelse(trans, bp); | ||
2666 | goto out_free; | ||
2667 | } | ||
2668 | } | ||
2669 | *bpp = bp; | 2620 | *bpp = bp; |
2670 | out_free: | 2621 | out_free: |
2671 | if (mapp != &map) | 2622 | if (mapp != &map) |
@@ -2679,7 +2630,6 @@ out_free: | |||
2679 | */ | 2630 | */ |
2680 | xfs_daddr_t | 2631 | xfs_daddr_t |
2681 | xfs_da_reada_buf( | 2632 | xfs_da_reada_buf( |
2682 | struct xfs_trans *trans, | ||
2683 | struct xfs_inode *dp, | 2633 | struct xfs_inode *dp, |
2684 | xfs_dablk_t bno, | 2634 | xfs_dablk_t bno, |
2685 | xfs_daddr_t mappedbno, | 2635 | xfs_daddr_t mappedbno, |
@@ -2693,7 +2643,7 @@ xfs_da_reada_buf( | |||
2693 | 2643 | ||
2694 | mapp = ↦ | 2644 | mapp = ↦ |
2695 | nmap = 1; | 2645 | nmap = 1; |
2696 | error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork, | 2646 | error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, |
2697 | &mapp, &nmap); | 2647 | &mapp, &nmap); |
2698 | if (error) { | 2648 | if (error) { |
2699 | /* mapping a hole is not an error, but we don't continue */ | 2649 | /* mapping a hole is not an error, but we don't continue */ |
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 201c6091d26a..6e153e399a77 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -25,6 +25,23 @@ struct xfs_trans; | |||
25 | struct zone; | 25 | struct zone; |
26 | struct xfs_dir_ops; | 26 | struct xfs_dir_ops; |
27 | 27 | ||
28 | /* | ||
29 | * Directory/attribute geometry information. There will be one of these for each | ||
30 | * data fork type, and it will be passed around via the xfs_da_args. Global | ||
31 | * structures will be attached to the xfs_mount. | ||
32 | */ | ||
33 | struct xfs_da_geometry { | ||
34 | int blksize; /* da block size in bytes */ | ||
35 | int fsbcount; /* da block size in filesystem blocks */ | ||
36 | uint8_t fsblog; /* log2 of _filesystem_ block size */ | ||
37 | uint8_t blklog; /* log2 of da block size */ | ||
38 | uint node_ents; /* # of entries in a danode */ | ||
39 | int magicpct; /* 37% of block size in bytes */ | ||
40 | xfs_dablk_t datablk; /* blockno of dir data v2 */ | ||
41 | xfs_dablk_t leafblk; /* blockno of leaf data v2 */ | ||
42 | xfs_dablk_t freeblk; /* blockno of free data v2 */ | ||
43 | }; | ||
44 | |||
28 | /*======================================================================== | 45 | /*======================================================================== |
29 | * Btree searching and modification structure definitions. | 46 | * Btree searching and modification structure definitions. |
30 | *========================================================================*/ | 47 | *========================================================================*/ |
@@ -42,6 +59,7 @@ enum xfs_dacmp { | |||
42 | * Structure to ease passing around component names. | 59 | * Structure to ease passing around component names. |
43 | */ | 60 | */ |
44 | typedef struct xfs_da_args { | 61 | typedef struct xfs_da_args { |
62 | struct xfs_da_geometry *geo; /* da block geometry */ | ||
45 | const __uint8_t *name; /* string (maybe not NULL terminated) */ | 63 | const __uint8_t *name; /* string (maybe not NULL terminated) */ |
46 | int namelen; /* length of string (maybe no NULL) */ | 64 | int namelen; /* length of string (maybe no NULL) */ |
47 | __uint8_t filetype; /* filetype of inode for directories */ | 65 | __uint8_t filetype; /* filetype of inode for directories */ |
@@ -110,8 +128,6 @@ typedef struct xfs_da_state_path { | |||
110 | typedef struct xfs_da_state { | 128 | typedef struct xfs_da_state { |
111 | xfs_da_args_t *args; /* filename arguments */ | 129 | xfs_da_args_t *args; /* filename arguments */ |
112 | struct xfs_mount *mp; /* filesystem mount point */ | 130 | struct xfs_mount *mp; /* filesystem mount point */ |
113 | unsigned int blocksize; /* logical block size */ | ||
114 | unsigned int node_ents; /* how many entries in danode */ | ||
115 | xfs_da_state_path_t path; /* search/split paths */ | 131 | xfs_da_state_path_t path; /* search/split paths */ |
116 | xfs_da_state_path_t altpath; /* alternate path for join */ | 132 | xfs_da_state_path_t altpath; /* alternate path for join */ |
117 | unsigned char inleaf; /* insert into 1->lf, 0->splf */ | 133 | unsigned char inleaf; /* insert into 1->lf, 0->splf */ |
@@ -185,9 +201,9 @@ int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp, | |||
185 | xfs_dablk_t bno, xfs_daddr_t mappedbno, | 201 | xfs_dablk_t bno, xfs_daddr_t mappedbno, |
186 | struct xfs_buf **bpp, int whichfork, | 202 | struct xfs_buf **bpp, int whichfork, |
187 | const struct xfs_buf_ops *ops); | 203 | const struct xfs_buf_ops *ops); |
188 | xfs_daddr_t xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp, | 204 | xfs_daddr_t xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno, |
189 | xfs_dablk_t bno, xfs_daddr_t mapped_bno, | 205 | xfs_daddr_t mapped_bno, int whichfork, |
190 | int whichfork, const struct xfs_buf_ops *ops); | 206 | const struct xfs_buf_ops *ops); |
191 | int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | 207 | int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, |
192 | struct xfs_buf *dead_buf); | 208 | struct xfs_buf *dead_buf); |
193 | 209 | ||
diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index e6c83e1fbc8a..c9aee52a37e2 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c | |||
@@ -26,8 +26,10 @@ | |||
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_format.h" |
29 | #include "xfs_da_btree.h" | ||
29 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
30 | #include "xfs_dir2.h" | 31 | #include "xfs_dir2.h" |
32 | #include "xfs_dir2_priv.h" | ||
31 | 33 | ||
32 | /* | 34 | /* |
33 | * Shortform directory ops | 35 | * Shortform directory ops |
@@ -425,9 +427,9 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) | |||
425 | * Directory Leaf block operations | 427 | * Directory Leaf block operations |
426 | */ | 428 | */ |
427 | static int | 429 | static int |
428 | xfs_dir2_max_leaf_ents(struct xfs_mount *mp) | 430 | xfs_dir2_max_leaf_ents(struct xfs_da_geometry *geo) |
429 | { | 431 | { |
430 | return (mp->m_dirblksize - sizeof(struct xfs_dir2_leaf_hdr)) / | 432 | return (geo->blksize - sizeof(struct xfs_dir2_leaf_hdr)) / |
431 | (uint)sizeof(struct xfs_dir2_leaf_entry); | 433 | (uint)sizeof(struct xfs_dir2_leaf_entry); |
432 | } | 434 | } |
433 | 435 | ||
@@ -438,9 +440,9 @@ xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp) | |||
438 | } | 440 | } |
439 | 441 | ||
440 | static int | 442 | static int |
441 | xfs_dir3_max_leaf_ents(struct xfs_mount *mp) | 443 | xfs_dir3_max_leaf_ents(struct xfs_da_geometry *geo) |
442 | { | 444 | { |
443 | return (mp->m_dirblksize - sizeof(struct xfs_dir3_leaf_hdr)) / | 445 | return (geo->blksize - sizeof(struct xfs_dir3_leaf_hdr)) / |
444 | (uint)sizeof(struct xfs_dir2_leaf_entry); | 446 | (uint)sizeof(struct xfs_dir2_leaf_entry); |
445 | } | 447 | } |
446 | 448 | ||
@@ -591,9 +593,9 @@ xfs_da3_node_hdr_to_disk( | |||
591 | * Directory free space block operations | 593 | * Directory free space block operations |
592 | */ | 594 | */ |
593 | static int | 595 | static int |
594 | xfs_dir2_free_max_bests(struct xfs_mount *mp) | 596 | xfs_dir2_free_max_bests(struct xfs_da_geometry *geo) |
595 | { | 597 | { |
596 | return (mp->m_dirblksize - sizeof(struct xfs_dir2_free_hdr)) / | 598 | return (geo->blksize - sizeof(struct xfs_dir2_free_hdr)) / |
597 | sizeof(xfs_dir2_data_off_t); | 599 | sizeof(xfs_dir2_data_off_t); |
598 | } | 600 | } |
599 | 601 | ||
@@ -607,24 +609,25 @@ xfs_dir2_free_bests_p(struct xfs_dir2_free *free) | |||
607 | * Convert data space db to the corresponding free db. | 609 | * Convert data space db to the corresponding free db. |
608 | */ | 610 | */ |
609 | static xfs_dir2_db_t | 611 | static xfs_dir2_db_t |
610 | xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) | 612 | xfs_dir2_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db) |
611 | { | 613 | { |
612 | return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir2_free_max_bests(mp); | 614 | return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) + |
615 | (db / xfs_dir2_free_max_bests(geo)); | ||
613 | } | 616 | } |
614 | 617 | ||
615 | /* | 618 | /* |
616 | * Convert data space db to the corresponding index in a free db. | 619 | * Convert data space db to the corresponding index in a free db. |
617 | */ | 620 | */ |
618 | static int | 621 | static int |
619 | xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) | 622 | xfs_dir2_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db) |
620 | { | 623 | { |
621 | return db % xfs_dir2_free_max_bests(mp); | 624 | return db % xfs_dir2_free_max_bests(geo); |
622 | } | 625 | } |
623 | 626 | ||
624 | static int | 627 | static int |
625 | xfs_dir3_free_max_bests(struct xfs_mount *mp) | 628 | xfs_dir3_free_max_bests(struct xfs_da_geometry *geo) |
626 | { | 629 | { |
627 | return (mp->m_dirblksize - sizeof(struct xfs_dir3_free_hdr)) / | 630 | return (geo->blksize - sizeof(struct xfs_dir3_free_hdr)) / |
628 | sizeof(xfs_dir2_data_off_t); | 631 | sizeof(xfs_dir2_data_off_t); |
629 | } | 632 | } |
630 | 633 | ||
@@ -638,18 +641,19 @@ xfs_dir3_free_bests_p(struct xfs_dir2_free *free) | |||
638 | * Convert data space db to the corresponding free db. | 641 | * Convert data space db to the corresponding free db. |
639 | */ | 642 | */ |
640 | static xfs_dir2_db_t | 643 | static xfs_dir2_db_t |
641 | xfs_dir3_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) | 644 | xfs_dir3_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db) |
642 | { | 645 | { |
643 | return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp); | 646 | return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) + |
647 | (db / xfs_dir3_free_max_bests(geo)); | ||
644 | } | 648 | } |
645 | 649 | ||
646 | /* | 650 | /* |
647 | * Convert data space db to the corresponding index in a free db. | 651 | * Convert data space db to the corresponding index in a free db. |
648 | */ | 652 | */ |
649 | static int | 653 | static int |
650 | xfs_dir3_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) | 654 | xfs_dir3_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db) |
651 | { | 655 | { |
652 | return db % xfs_dir3_free_max_bests(mp); | 656 | return db % xfs_dir3_free_max_bests(geo); |
653 | } | 657 | } |
654 | 658 | ||
655 | static void | 659 | static void |
diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index a19d3f8f639c..0a49b0286372 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h | |||
@@ -19,10 +19,6 @@ | |||
19 | #ifndef __XFS_DA_FORMAT_H__ | 19 | #ifndef __XFS_DA_FORMAT_H__ |
20 | #define __XFS_DA_FORMAT_H__ | 20 | #define __XFS_DA_FORMAT_H__ |
21 | 21 | ||
22 | /*======================================================================== | ||
23 | * Directory Structure when greater than XFS_LBSIZE(mp) bytes. | ||
24 | *========================================================================*/ | ||
25 | |||
26 | /* | 22 | /* |
27 | * This structure is common to both leaf nodes and non-leaf nodes in the Btree. | 23 | * This structure is common to both leaf nodes and non-leaf nodes in the Btree. |
28 | * | 24 | * |
@@ -122,8 +118,6 @@ struct xfs_da3_icnode_hdr { | |||
122 | __uint16_t level; | 118 | __uint16_t level; |
123 | }; | 119 | }; |
124 | 120 | ||
125 | #define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize | ||
126 | |||
127 | /* | 121 | /* |
128 | * Directory version 2. | 122 | * Directory version 2. |
129 | * | 123 | * |
@@ -330,8 +324,6 @@ xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) | |||
330 | #define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) | 324 | #define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) |
331 | #define XFS_DIR2_DATA_SPACE 0 | 325 | #define XFS_DIR2_DATA_SPACE 0 |
332 | #define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) | 326 | #define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) |
333 | #define XFS_DIR2_DATA_FIRSTDB(mp) \ | ||
334 | xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET) | ||
335 | 327 | ||
336 | /* | 328 | /* |
337 | * Describe a free area in the data block. | 329 | * Describe a free area in the data block. |
@@ -456,8 +448,6 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) | |||
456 | */ | 448 | */ |
457 | #define XFS_DIR2_LEAF_SPACE 1 | 449 | #define XFS_DIR2_LEAF_SPACE 1 |
458 | #define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) | 450 | #define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) |
459 | #define XFS_DIR2_LEAF_FIRSTDB(mp) \ | ||
460 | xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET) | ||
461 | 451 | ||
462 | /* | 452 | /* |
463 | * Leaf block header. | 453 | * Leaf block header. |
@@ -514,17 +504,6 @@ struct xfs_dir3_leaf { | |||
514 | #define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) | 504 | #define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) |
515 | 505 | ||
516 | /* | 506 | /* |
517 | * Get address of the bestcount field in the single-leaf block. | ||
518 | */ | ||
519 | static inline struct xfs_dir2_leaf_tail * | ||
520 | xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) | ||
521 | { | ||
522 | return (struct xfs_dir2_leaf_tail *) | ||
523 | ((char *)lp + mp->m_dirblksize - | ||
524 | sizeof(struct xfs_dir2_leaf_tail)); | ||
525 | } | ||
526 | |||
527 | /* | ||
528 | * Get address of the bests array in the single-leaf block. | 507 | * Get address of the bests array in the single-leaf block. |
529 | */ | 508 | */ |
530 | static inline __be16 * | 509 | static inline __be16 * |
@@ -534,123 +513,6 @@ xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) | |||
534 | } | 513 | } |
535 | 514 | ||
536 | /* | 515 | /* |
537 | * DB blocks here are logical directory block numbers, not filesystem blocks. | ||
538 | */ | ||
539 | |||
540 | /* | ||
541 | * Convert dataptr to byte in file space | ||
542 | */ | ||
543 | static inline xfs_dir2_off_t | ||
544 | xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) | ||
545 | { | ||
546 | return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; | ||
547 | } | ||
548 | |||
549 | /* | ||
550 | * Convert byte in file space to dataptr. It had better be aligned. | ||
551 | */ | ||
552 | static inline xfs_dir2_dataptr_t | ||
553 | xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by) | ||
554 | { | ||
555 | return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * Convert byte in space to (DB) block | ||
560 | */ | ||
561 | static inline xfs_dir2_db_t | ||
562 | xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by) | ||
563 | { | ||
564 | return (xfs_dir2_db_t) | ||
565 | (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)); | ||
566 | } | ||
567 | |||
568 | /* | ||
569 | * Convert dataptr to a block number | ||
570 | */ | ||
571 | static inline xfs_dir2_db_t | ||
572 | xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) | ||
573 | { | ||
574 | return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp)); | ||
575 | } | ||
576 | |||
577 | /* | ||
578 | * Convert byte in space to offset in a block | ||
579 | */ | ||
580 | static inline xfs_dir2_data_aoff_t | ||
581 | xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by) | ||
582 | { | ||
583 | return (xfs_dir2_data_aoff_t)(by & | ||
584 | ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1)); | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * Convert dataptr to a byte offset in a block | ||
589 | */ | ||
590 | static inline xfs_dir2_data_aoff_t | ||
591 | xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) | ||
592 | { | ||
593 | return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp)); | ||
594 | } | ||
595 | |||
596 | /* | ||
597 | * Convert block and offset to byte in space | ||
598 | */ | ||
599 | static inline xfs_dir2_off_t | ||
600 | xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db, | ||
601 | xfs_dir2_data_aoff_t o) | ||
602 | { | ||
603 | return ((xfs_dir2_off_t)db << | ||
604 | (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o; | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * Convert block (DB) to block (dablk) | ||
609 | */ | ||
610 | static inline xfs_dablk_t | ||
611 | xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db) | ||
612 | { | ||
613 | return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog); | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * Convert byte in space to (DA) block | ||
618 | */ | ||
619 | static inline xfs_dablk_t | ||
620 | xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by) | ||
621 | { | ||
622 | return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by)); | ||
623 | } | ||
624 | |||
625 | /* | ||
626 | * Convert block and offset to dataptr | ||
627 | */ | ||
628 | static inline xfs_dir2_dataptr_t | ||
629 | xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db, | ||
630 | xfs_dir2_data_aoff_t o) | ||
631 | { | ||
632 | return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o)); | ||
633 | } | ||
634 | |||
635 | /* | ||
636 | * Convert block (dablk) to block (DB) | ||
637 | */ | ||
638 | static inline xfs_dir2_db_t | ||
639 | xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da) | ||
640 | { | ||
641 | return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog); | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | * Convert block (dablk) to byte offset in space | ||
646 | */ | ||
647 | static inline xfs_dir2_off_t | ||
648 | xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da) | ||
649 | { | ||
650 | return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0); | ||
651 | } | ||
652 | |||
653 | /* | ||
654 | * Free space block defintions for the node format. | 516 | * Free space block defintions for the node format. |
655 | */ | 517 | */ |
656 | 518 | ||
@@ -659,8 +521,6 @@ xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da) | |||
659 | */ | 521 | */ |
660 | #define XFS_DIR2_FREE_SPACE 2 | 522 | #define XFS_DIR2_FREE_SPACE 2 |
661 | #define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) | 523 | #define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) |
662 | #define XFS_DIR2_FREE_FIRSTDB(mp) \ | ||
663 | xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET) | ||
664 | 524 | ||
665 | typedef struct xfs_dir2_free_hdr { | 525 | typedef struct xfs_dir2_free_hdr { |
666 | __be32 magic; /* XFS_DIR2_FREE_MAGIC */ | 526 | __be32 magic; /* XFS_DIR2_FREE_MAGIC */ |
@@ -736,16 +596,6 @@ typedef struct xfs_dir2_block_tail { | |||
736 | } xfs_dir2_block_tail_t; | 596 | } xfs_dir2_block_tail_t; |
737 | 597 | ||
738 | /* | 598 | /* |
739 | * Pointer to the leaf header embedded in a data block (1-block format) | ||
740 | */ | ||
741 | static inline struct xfs_dir2_block_tail * | ||
742 | xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr) | ||
743 | { | ||
744 | return ((struct xfs_dir2_block_tail *) | ||
745 | ((char *)hdr + mp->m_dirblksize)) - 1; | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | * Pointer to the leaf entries embedded in a data block (1-block format) | 599 | * Pointer to the leaf entries embedded in a data block (1-block format) |
750 | */ | 600 | */ |
751 | static inline struct xfs_dir2_leaf_entry * | 601 | static inline struct xfs_dir2_leaf_entry * |
@@ -764,10 +614,6 @@ xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp) | |||
764 | * of an attribute name may not be unique, we may have duplicate keys. The | 614 | * 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. | 615 | * internal links in the Btree are logical block offsets into the file. |
766 | * | 616 | * |
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 | 617 | * 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 | 618 | * 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, | 619 | * for the free bytes after the leaf_entry's, but only the N largest such, |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index fda46253966a..79670cda48ae 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -85,38 +85,74 @@ static struct xfs_nameops xfs_ascii_ci_nameops = { | |||
85 | .compname = xfs_ascii_ci_compname, | 85 | .compname = xfs_ascii_ci_compname, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | void | 88 | int |
89 | xfs_dir_mount( | 89 | xfs_da_mount( |
90 | xfs_mount_t *mp) | 90 | struct xfs_mount *mp) |
91 | { | 91 | { |
92 | int nodehdr_size; | 92 | struct xfs_da_geometry *dageo; |
93 | int nodehdr_size; | ||
93 | 94 | ||
94 | 95 | ||
95 | ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); | 96 | ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT); |
96 | ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= | 97 | ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= |
97 | XFS_MAX_BLOCKSIZE); | 98 | XFS_MAX_BLOCKSIZE); |
98 | 99 | ||
99 | mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); | 100 | mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); |
100 | mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); | 101 | mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); |
101 | 102 | ||
102 | mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); | ||
103 | mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog; | ||
104 | mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp)); | ||
105 | mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); | ||
106 | mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); | ||
107 | |||
108 | nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; | 103 | nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; |
109 | mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / | 104 | mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), |
105 | KM_SLEEP | KM_MAYFAIL); | ||
106 | mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), | ||
107 | KM_SLEEP | KM_MAYFAIL); | ||
108 | if (!mp->m_dir_geo || !mp->m_attr_geo) { | ||
109 | kmem_free(mp->m_dir_geo); | ||
110 | kmem_free(mp->m_attr_geo); | ||
111 | return ENOMEM; | ||
112 | } | ||
113 | |||
114 | /* set up directory geometry */ | ||
115 | dageo = mp->m_dir_geo; | ||
116 | dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog; | ||
117 | dageo->fsblog = mp->m_sb.sb_blocklog; | ||
118 | dageo->blksize = 1 << dageo->blklog; | ||
119 | dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog; | ||
120 | |||
121 | /* | ||
122 | * Now we've set up the block conversion variables, we can calculate the | ||
123 | * segment block constants using the geometry structure. | ||
124 | */ | ||
125 | dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET); | ||
126 | dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET); | ||
127 | dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET); | ||
128 | dageo->node_ents = (dageo->blksize - nodehdr_size) / | ||
110 | (uint)sizeof(xfs_da_node_entry_t); | 129 | (uint)sizeof(xfs_da_node_entry_t); |
111 | mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / | 130 | dageo->magicpct = (dageo->blksize * 37) / 100; |
131 | |||
132 | /* set up attribute geometry - single fsb only */ | ||
133 | dageo = mp->m_attr_geo; | ||
134 | dageo->blklog = mp->m_sb.sb_blocklog; | ||
135 | dageo->fsblog = mp->m_sb.sb_blocklog; | ||
136 | dageo->blksize = 1 << dageo->blklog; | ||
137 | dageo->fsbcount = 1; | ||
138 | dageo->node_ents = (dageo->blksize - nodehdr_size) / | ||
112 | (uint)sizeof(xfs_da_node_entry_t); | 139 | (uint)sizeof(xfs_da_node_entry_t); |
140 | dageo->magicpct = (dageo->blksize * 37) / 100; | ||
113 | 141 | ||
114 | mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; | ||
115 | if (xfs_sb_version_hasasciici(&mp->m_sb)) | 142 | if (xfs_sb_version_hasasciici(&mp->m_sb)) |
116 | mp->m_dirnameops = &xfs_ascii_ci_nameops; | 143 | mp->m_dirnameops = &xfs_ascii_ci_nameops; |
117 | else | 144 | else |
118 | mp->m_dirnameops = &xfs_default_nameops; | 145 | mp->m_dirnameops = &xfs_default_nameops; |
119 | 146 | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | void | ||
151 | xfs_da_unmount( | ||
152 | struct xfs_mount *mp) | ||
153 | { | ||
154 | kmem_free(mp->m_dir_geo); | ||
155 | kmem_free(mp->m_attr_geo); | ||
120 | } | 156 | } |
121 | 157 | ||
122 | /* | 158 | /* |
@@ -192,6 +228,7 @@ xfs_dir_init( | |||
192 | if (!args) | 228 | if (!args) |
193 | return ENOMEM; | 229 | return ENOMEM; |
194 | 230 | ||
231 | args->geo = dp->i_mount->m_dir_geo; | ||
195 | args->dp = dp; | 232 | args->dp = dp; |
196 | args->trans = tp; | 233 | args->trans = tp; |
197 | error = xfs_dir2_sf_create(args, pdp->i_ino); | 234 | error = xfs_dir2_sf_create(args, pdp->i_ino); |
@@ -226,6 +263,7 @@ xfs_dir_createname( | |||
226 | if (!args) | 263 | if (!args) |
227 | return ENOMEM; | 264 | return ENOMEM; |
228 | 265 | ||
266 | args->geo = dp->i_mount->m_dir_geo; | ||
229 | args->name = name->name; | 267 | args->name = name->name; |
230 | args->namelen = name->len; | 268 | args->namelen = name->len; |
231 | args->filetype = name->type; | 269 | args->filetype = name->type; |
@@ -244,7 +282,7 @@ xfs_dir_createname( | |||
244 | goto out_free; | 282 | goto out_free; |
245 | } | 283 | } |
246 | 284 | ||
247 | rval = xfs_dir2_isblock(tp, dp, &v); | 285 | rval = xfs_dir2_isblock(args, &v); |
248 | if (rval) | 286 | if (rval) |
249 | goto out_free; | 287 | goto out_free; |
250 | if (v) { | 288 | if (v) { |
@@ -252,7 +290,7 @@ xfs_dir_createname( | |||
252 | goto out_free; | 290 | goto out_free; |
253 | } | 291 | } |
254 | 292 | ||
255 | rval = xfs_dir2_isleaf(tp, dp, &v); | 293 | rval = xfs_dir2_isleaf(args, &v); |
256 | if (rval) | 294 | if (rval) |
257 | goto out_free; | 295 | goto out_free; |
258 | if (v) | 296 | if (v) |
@@ -320,6 +358,7 @@ xfs_dir_lookup( | |||
320 | * annotations into the reclaim path for the ilock. | 358 | * annotations into the reclaim path for the ilock. |
321 | */ | 359 | */ |
322 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); | 360 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); |
361 | args->geo = dp->i_mount->m_dir_geo; | ||
323 | args->name = name->name; | 362 | args->name = name->name; |
324 | args->namelen = name->len; | 363 | args->namelen = name->len; |
325 | args->filetype = name->type; | 364 | args->filetype = name->type; |
@@ -336,7 +375,7 @@ xfs_dir_lookup( | |||
336 | goto out_check_rval; | 375 | goto out_check_rval; |
337 | } | 376 | } |
338 | 377 | ||
339 | rval = xfs_dir2_isblock(tp, dp, &v); | 378 | rval = xfs_dir2_isblock(args, &v); |
340 | if (rval) | 379 | if (rval) |
341 | goto out_free; | 380 | goto out_free; |
342 | if (v) { | 381 | if (v) { |
@@ -344,7 +383,7 @@ xfs_dir_lookup( | |||
344 | goto out_check_rval; | 383 | goto out_check_rval; |
345 | } | 384 | } |
346 | 385 | ||
347 | rval = xfs_dir2_isleaf(tp, dp, &v); | 386 | rval = xfs_dir2_isleaf(args, &v); |
348 | if (rval) | 387 | if (rval) |
349 | goto out_free; | 388 | goto out_free; |
350 | if (v) | 389 | if (v) |
@@ -391,6 +430,7 @@ xfs_dir_removename( | |||
391 | if (!args) | 430 | if (!args) |
392 | return ENOMEM; | 431 | return ENOMEM; |
393 | 432 | ||
433 | args->geo = dp->i_mount->m_dir_geo; | ||
394 | args->name = name->name; | 434 | args->name = name->name; |
395 | args->namelen = name->len; | 435 | args->namelen = name->len; |
396 | args->filetype = name->type; | 436 | args->filetype = name->type; |
@@ -408,7 +448,7 @@ xfs_dir_removename( | |||
408 | goto out_free; | 448 | goto out_free; |
409 | } | 449 | } |
410 | 450 | ||
411 | rval = xfs_dir2_isblock(tp, dp, &v); | 451 | rval = xfs_dir2_isblock(args, &v); |
412 | if (rval) | 452 | if (rval) |
413 | goto out_free; | 453 | goto out_free; |
414 | if (v) { | 454 | if (v) { |
@@ -416,7 +456,7 @@ xfs_dir_removename( | |||
416 | goto out_free; | 456 | goto out_free; |
417 | } | 457 | } |
418 | 458 | ||
419 | rval = xfs_dir2_isleaf(tp, dp, &v); | 459 | rval = xfs_dir2_isleaf(args, &v); |
420 | if (rval) | 460 | if (rval) |
421 | goto out_free; | 461 | goto out_free; |
422 | if (v) | 462 | if (v) |
@@ -455,6 +495,7 @@ xfs_dir_replace( | |||
455 | if (!args) | 495 | if (!args) |
456 | return ENOMEM; | 496 | return ENOMEM; |
457 | 497 | ||
498 | args->geo = dp->i_mount->m_dir_geo; | ||
458 | args->name = name->name; | 499 | args->name = name->name; |
459 | args->namelen = name->len; | 500 | args->namelen = name->len; |
460 | args->filetype = name->type; | 501 | args->filetype = name->type; |
@@ -472,7 +513,7 @@ xfs_dir_replace( | |||
472 | goto out_free; | 513 | goto out_free; |
473 | } | 514 | } |
474 | 515 | ||
475 | rval = xfs_dir2_isblock(tp, dp, &v); | 516 | rval = xfs_dir2_isblock(args, &v); |
476 | if (rval) | 517 | if (rval) |
477 | goto out_free; | 518 | goto out_free; |
478 | if (v) { | 519 | if (v) { |
@@ -480,7 +521,7 @@ xfs_dir_replace( | |||
480 | goto out_free; | 521 | goto out_free; |
481 | } | 522 | } |
482 | 523 | ||
483 | rval = xfs_dir2_isleaf(tp, dp, &v); | 524 | rval = xfs_dir2_isleaf(args, &v); |
484 | if (rval) | 525 | if (rval) |
485 | goto out_free; | 526 | goto out_free; |
486 | if (v) | 527 | if (v) |
@@ -516,6 +557,7 @@ xfs_dir_canenter( | |||
516 | if (!args) | 557 | if (!args) |
517 | return ENOMEM; | 558 | return ENOMEM; |
518 | 559 | ||
560 | args->geo = dp->i_mount->m_dir_geo; | ||
519 | args->name = name->name; | 561 | args->name = name->name; |
520 | args->namelen = name->len; | 562 | args->namelen = name->len; |
521 | args->filetype = name->type; | 563 | args->filetype = name->type; |
@@ -531,7 +573,7 @@ xfs_dir_canenter( | |||
531 | goto out_free; | 573 | goto out_free; |
532 | } | 574 | } |
533 | 575 | ||
534 | rval = xfs_dir2_isblock(tp, dp, &v); | 576 | rval = xfs_dir2_isblock(args, &v); |
535 | if (rval) | 577 | if (rval) |
536 | goto out_free; | 578 | goto out_free; |
537 | if (v) { | 579 | if (v) { |
@@ -539,7 +581,7 @@ xfs_dir_canenter( | |||
539 | goto out_free; | 581 | goto out_free; |
540 | } | 582 | } |
541 | 583 | ||
542 | rval = xfs_dir2_isleaf(tp, dp, &v); | 584 | rval = xfs_dir2_isleaf(args, &v); |
543 | if (rval) | 585 | if (rval) |
544 | goto out_free; | 586 | goto out_free; |
545 | if (v) | 587 | if (v) |
@@ -579,13 +621,13 @@ xfs_dir2_grow_inode( | |||
579 | * Set lowest possible block in the space requested. | 621 | * Set lowest possible block in the space requested. |
580 | */ | 622 | */ |
581 | bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); | 623 | bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); |
582 | count = mp->m_dirblkfsbs; | 624 | count = args->geo->fsbcount; |
583 | 625 | ||
584 | error = xfs_da_grow_inode_int(args, &bno, count); | 626 | error = xfs_da_grow_inode_int(args, &bno, count); |
585 | if (error) | 627 | if (error) |
586 | return error; | 628 | return error; |
587 | 629 | ||
588 | *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); | 630 | *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno); |
589 | 631 | ||
590 | /* | 632 | /* |
591 | * Update file's size if this is the data space and it grew. | 633 | * Update file's size if this is the data space and it grew. |
@@ -607,19 +649,16 @@ xfs_dir2_grow_inode( | |||
607 | */ | 649 | */ |
608 | int | 650 | int |
609 | xfs_dir2_isblock( | 651 | xfs_dir2_isblock( |
610 | xfs_trans_t *tp, | 652 | struct xfs_da_args *args, |
611 | xfs_inode_t *dp, | 653 | int *vp) /* out: 1 is block, 0 is not block */ |
612 | int *vp) /* out: 1 is block, 0 is not block */ | ||
613 | { | 654 | { |
614 | xfs_fileoff_t last; /* last file offset */ | 655 | xfs_fileoff_t last; /* last file offset */ |
615 | xfs_mount_t *mp; | 656 | int rval; |
616 | int rval; | ||
617 | 657 | ||
618 | mp = dp->i_mount; | 658 | if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) |
619 | if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) | ||
620 | return rval; | 659 | return rval; |
621 | rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; | 660 | rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; |
622 | ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); | 661 | ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize); |
623 | *vp = rval; | 662 | *vp = rval; |
624 | return 0; | 663 | return 0; |
625 | } | 664 | } |
@@ -629,18 +668,15 @@ xfs_dir2_isblock( | |||
629 | */ | 668 | */ |
630 | int | 669 | int |
631 | xfs_dir2_isleaf( | 670 | xfs_dir2_isleaf( |
632 | xfs_trans_t *tp, | 671 | struct xfs_da_args *args, |
633 | xfs_inode_t *dp, | 672 | int *vp) /* out: 1 is block, 0 is not block */ |
634 | int *vp) /* out: 1 is leaf, 0 is not leaf */ | ||
635 | { | 673 | { |
636 | xfs_fileoff_t last; /* last file offset */ | 674 | xfs_fileoff_t last; /* last file offset */ |
637 | xfs_mount_t *mp; | 675 | int rval; |
638 | int rval; | ||
639 | 676 | ||
640 | mp = dp->i_mount; | 677 | if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) |
641 | if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) | ||
642 | return rval; | 678 | return rval; |
643 | *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); | 679 | *vp = last == args->geo->leafblk + args->geo->fsbcount; |
644 | return 0; | 680 | return 0; |
645 | } | 681 | } |
646 | 682 | ||
@@ -668,11 +704,11 @@ xfs_dir2_shrink_inode( | |||
668 | dp = args->dp; | 704 | dp = args->dp; |
669 | mp = dp->i_mount; | 705 | mp = dp->i_mount; |
670 | tp = args->trans; | 706 | tp = args->trans; |
671 | da = xfs_dir2_db_to_da(mp, db); | 707 | da = xfs_dir2_db_to_da(args->geo, db); |
672 | /* | 708 | /* |
673 | * Unmap the fsblock(s). | 709 | * Unmap the fsblock(s). |
674 | */ | 710 | */ |
675 | if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, | 711 | if ((error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, |
676 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, | 712 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, |
677 | &done))) { | 713 | &done))) { |
678 | /* | 714 | /* |
@@ -699,12 +735,12 @@ xfs_dir2_shrink_inode( | |||
699 | /* | 735 | /* |
700 | * If it's not a data block, we're done. | 736 | * If it's not a data block, we're done. |
701 | */ | 737 | */ |
702 | if (db >= XFS_DIR2_LEAF_FIRSTDB(mp)) | 738 | if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET)) |
703 | return 0; | 739 | return 0; |
704 | /* | 740 | /* |
705 | * If the block isn't the last one in the directory, we're done. | 741 | * If the block isn't the last one in the directory, we're done. |
706 | */ | 742 | */ |
707 | if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0)) | 743 | if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0)) |
708 | return 0; | 744 | return 0; |
709 | bno = da; | 745 | bno = da; |
710 | if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { | 746 | if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { |
@@ -713,7 +749,7 @@ xfs_dir2_shrink_inode( | |||
713 | */ | 749 | */ |
714 | return error; | 750 | return error; |
715 | } | 751 | } |
716 | if (db == mp->m_dirdatablk) | 752 | if (db == args->geo->datablk) |
717 | ASSERT(bno == 0); | 753 | ASSERT(bno == 0); |
718 | else | 754 | else |
719 | ASSERT(bno > 0); | 755 | ASSERT(bno > 0); |
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index cec70e0781ab..c8e86b0b5e99 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h | |||
@@ -80,7 +80,7 @@ struct xfs_dir_ops { | |||
80 | struct xfs_dir3_icleaf_hdr *from); | 80 | struct xfs_dir3_icleaf_hdr *from); |
81 | void (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to, | 81 | void (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to, |
82 | struct xfs_dir2_leaf *from); | 82 | struct xfs_dir2_leaf *from); |
83 | int (*leaf_max_ents)(struct xfs_mount *mp); | 83 | int (*leaf_max_ents)(struct xfs_da_geometry *geo); |
84 | struct xfs_dir2_leaf_entry * | 84 | struct xfs_dir2_leaf_entry * |
85 | (*leaf_ents_p)(struct xfs_dir2_leaf *lp); | 85 | (*leaf_ents_p)(struct xfs_dir2_leaf *lp); |
86 | 86 | ||
@@ -97,10 +97,12 @@ struct xfs_dir_ops { | |||
97 | struct xfs_dir3_icfree_hdr *from); | 97 | struct xfs_dir3_icfree_hdr *from); |
98 | void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to, | 98 | void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to, |
99 | struct xfs_dir2_free *from); | 99 | struct xfs_dir2_free *from); |
100 | int (*free_max_bests)(struct xfs_mount *mp); | 100 | int (*free_max_bests)(struct xfs_da_geometry *geo); |
101 | __be16 * (*free_bests_p)(struct xfs_dir2_free *free); | 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); | 102 | xfs_dir2_db_t (*db_to_fdb)(struct xfs_da_geometry *geo, |
103 | int (*db_to_fdindex)(struct xfs_mount *mp, xfs_dir2_db_t db); | 103 | xfs_dir2_db_t db); |
104 | int (*db_to_fdindex)(struct xfs_da_geometry *geo, | ||
105 | xfs_dir2_db_t db); | ||
104 | }; | 106 | }; |
105 | 107 | ||
106 | extern const struct xfs_dir_ops * | 108 | extern const struct xfs_dir_ops * |
@@ -112,7 +114,9 @@ extern const struct xfs_dir_ops * | |||
112 | * Generic directory interface routines | 114 | * Generic directory interface routines |
113 | */ | 115 | */ |
114 | extern void xfs_dir_startup(void); | 116 | extern void xfs_dir_startup(void); |
115 | extern void xfs_dir_mount(struct xfs_mount *mp); | 117 | extern int xfs_da_mount(struct xfs_mount *mp); |
118 | extern void xfs_da_unmount(struct xfs_mount *mp); | ||
119 | |||
116 | extern int xfs_dir_isempty(struct xfs_inode *dp); | 120 | extern int xfs_dir_isempty(struct xfs_inode *dp); |
117 | extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, | 121 | extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, |
118 | struct xfs_inode *pdp); | 122 | struct xfs_inode *pdp); |
@@ -142,23 +146,23 @@ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args); | |||
142 | /* | 146 | /* |
143 | * Interface routines used by userspace utilities | 147 | * Interface routines used by userspace utilities |
144 | */ | 148 | */ |
145 | extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r); | 149 | extern int xfs_dir2_isblock(struct xfs_da_args *args, int *r); |
146 | extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r); | 150 | extern int xfs_dir2_isleaf(struct xfs_da_args *args, int *r); |
147 | extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, | 151 | extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, |
148 | struct xfs_buf *bp); | 152 | struct xfs_buf *bp); |
149 | 153 | ||
150 | extern void xfs_dir2_data_freescan(struct xfs_inode *dp, | 154 | extern void xfs_dir2_data_freescan(struct xfs_inode *dp, |
151 | struct xfs_dir2_data_hdr *hdr, int *loghead); | 155 | struct xfs_dir2_data_hdr *hdr, int *loghead); |
152 | extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_inode *dp, | 156 | extern void xfs_dir2_data_log_entry(struct xfs_da_args *args, |
153 | struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); | 157 | struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); |
154 | extern void xfs_dir2_data_log_header(struct xfs_trans *tp, struct xfs_inode *dp, | 158 | extern void xfs_dir2_data_log_header(struct xfs_da_args *args, |
155 | struct xfs_buf *bp); | 159 | struct xfs_buf *bp); |
156 | extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp, | 160 | extern void xfs_dir2_data_log_unused(struct xfs_da_args *args, |
157 | struct xfs_dir2_data_unused *dup); | 161 | struct xfs_buf *bp, struct xfs_dir2_data_unused *dup); |
158 | extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_inode *dp, | 162 | extern void xfs_dir2_data_make_free(struct xfs_da_args *args, |
159 | struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, | 163 | struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, |
160 | xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); | 164 | 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, | 165 | extern void xfs_dir2_data_use_free(struct xfs_da_args *args, |
162 | struct xfs_buf *bp, struct xfs_dir2_data_unused *dup, | 166 | struct xfs_buf *bp, struct xfs_dir2_data_unused *dup, |
163 | xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, | 167 | xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, |
164 | int *needlogp, int *needscanp); | 168 | int *needlogp, int *needscanp); |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 4f6a38cb83a4..c7cd3154026a 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -136,7 +136,7 @@ xfs_dir3_block_read( | |||
136 | struct xfs_mount *mp = dp->i_mount; | 136 | struct xfs_mount *mp = dp->i_mount; |
137 | int err; | 137 | int err; |
138 | 138 | ||
139 | err = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp, | 139 | err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, -1, bpp, |
140 | XFS_DATA_FORK, &xfs_dir3_block_buf_ops); | 140 | XFS_DATA_FORK, &xfs_dir3_block_buf_ops); |
141 | if (!err && tp) | 141 | if (!err && tp) |
142 | xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF); | 142 | xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF); |
@@ -281,8 +281,7 @@ out: | |||
281 | */ | 281 | */ |
282 | static void | 282 | static void |
283 | xfs_dir2_block_compact( | 283 | xfs_dir2_block_compact( |
284 | struct xfs_trans *tp, | 284 | struct xfs_da_args *args, |
285 | struct xfs_inode *dp, | ||
286 | struct xfs_buf *bp, | 285 | struct xfs_buf *bp, |
287 | struct xfs_dir2_data_hdr *hdr, | 286 | struct xfs_dir2_data_hdr *hdr, |
288 | struct xfs_dir2_block_tail *btp, | 287 | struct xfs_dir2_block_tail *btp, |
@@ -315,18 +314,17 @@ xfs_dir2_block_compact( | |||
315 | *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1); | 314 | *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1); |
316 | *lfloghigh -= be32_to_cpu(btp->stale) - 1; | 315 | *lfloghigh -= be32_to_cpu(btp->stale) - 1; |
317 | be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1)); | 316 | be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1)); |
318 | xfs_dir2_data_make_free(tp, dp, bp, | 317 | xfs_dir2_data_make_free(args, bp, |
319 | (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), | 318 | (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), |
320 | (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)), |
321 | needlog, &needscan); | 320 | needlog, &needscan); |
322 | blp += be32_to_cpu(btp->stale) - 1; | ||
323 | btp->stale = cpu_to_be32(1); | 321 | btp->stale = cpu_to_be32(1); |
324 | /* | 322 | /* |
325 | * If we now need to rebuild the bestfree map, do so. | 323 | * If we now need to rebuild the bestfree map, do so. |
326 | * This needs to happen before the next call to use_free. | 324 | * This needs to happen before the next call to use_free. |
327 | */ | 325 | */ |
328 | if (needscan) | 326 | if (needscan) |
329 | xfs_dir2_data_freescan(dp, hdr, needlog); | 327 | xfs_dir2_data_freescan(args->dp, hdr, needlog); |
330 | } | 328 | } |
331 | 329 | ||
332 | /* | 330 | /* |
@@ -378,7 +376,7 @@ xfs_dir2_block_addname( | |||
378 | * Set up pointers to parts of the block. | 376 | * Set up pointers to parts of the block. |
379 | */ | 377 | */ |
380 | hdr = bp->b_addr; | 378 | hdr = bp->b_addr; |
381 | btp = xfs_dir2_block_tail_p(mp, hdr); | 379 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
382 | blp = xfs_dir2_block_leaf_p(btp); | 380 | blp = xfs_dir2_block_leaf_p(btp); |
383 | 381 | ||
384 | /* | 382 | /* |
@@ -421,7 +419,7 @@ xfs_dir2_block_addname( | |||
421 | * If need to compact the leaf entries, do it now. | 419 | * If need to compact the leaf entries, do it now. |
422 | */ | 420 | */ |
423 | if (compact) { | 421 | if (compact) { |
424 | xfs_dir2_block_compact(tp, dp, bp, hdr, btp, blp, &needlog, | 422 | xfs_dir2_block_compact(args, bp, hdr, btp, blp, &needlog, |
425 | &lfloghigh, &lfloglow); | 423 | &lfloghigh, &lfloglow); |
426 | /* recalculate blp post-compaction */ | 424 | /* recalculate blp post-compaction */ |
427 | blp = xfs_dir2_block_leaf_p(btp); | 425 | blp = xfs_dir2_block_leaf_p(btp); |
@@ -456,7 +454,7 @@ xfs_dir2_block_addname( | |||
456 | /* | 454 | /* |
457 | * Mark the space needed for the new leaf entry, now in use. | 455 | * Mark the space needed for the new leaf entry, now in use. |
458 | */ | 456 | */ |
459 | xfs_dir2_data_use_free(tp, dp, bp, enddup, | 457 | xfs_dir2_data_use_free(args, bp, enddup, |
460 | (xfs_dir2_data_aoff_t) | 458 | (xfs_dir2_data_aoff_t) |
461 | ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) - | 459 | ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) - |
462 | sizeof(*blp)), | 460 | sizeof(*blp)), |
@@ -537,13 +535,13 @@ xfs_dir2_block_addname( | |||
537 | * Fill in the leaf entry. | 535 | * Fill in the leaf entry. |
538 | */ | 536 | */ |
539 | blp[mid].hashval = cpu_to_be32(args->hashval); | 537 | blp[mid].hashval = cpu_to_be32(args->hashval); |
540 | blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, | 538 | blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( |
541 | (char *)dep - (char *)hdr)); | 539 | (char *)dep - (char *)hdr)); |
542 | xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh); | 540 | xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh); |
543 | /* | 541 | /* |
544 | * Mark space for the data entry used. | 542 | * Mark space for the data entry used. |
545 | */ | 543 | */ |
546 | xfs_dir2_data_use_free(tp, dp, bp, dup, | 544 | xfs_dir2_data_use_free(args, bp, dup, |
547 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), | 545 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), |
548 | (xfs_dir2_data_aoff_t)len, &needlog, &needscan); | 546 | (xfs_dir2_data_aoff_t)len, &needlog, &needscan); |
549 | /* | 547 | /* |
@@ -561,9 +559,9 @@ xfs_dir2_block_addname( | |||
561 | if (needscan) | 559 | if (needscan) |
562 | xfs_dir2_data_freescan(dp, hdr, &needlog); | 560 | xfs_dir2_data_freescan(dp, hdr, &needlog); |
563 | if (needlog) | 561 | if (needlog) |
564 | xfs_dir2_data_log_header(tp, dp, bp); | 562 | xfs_dir2_data_log_header(args, bp); |
565 | xfs_dir2_block_log_tail(tp, bp); | 563 | xfs_dir2_block_log_tail(tp, bp); |
566 | xfs_dir2_data_log_entry(tp, dp, bp, dep); | 564 | xfs_dir2_data_log_entry(args, bp, dep); |
567 | xfs_dir3_data_check(dp, bp); | 565 | xfs_dir3_data_check(dp, bp); |
568 | return 0; | 566 | return 0; |
569 | } | 567 | } |
@@ -582,7 +580,7 @@ xfs_dir2_block_log_leaf( | |||
582 | xfs_dir2_leaf_entry_t *blp; | 580 | xfs_dir2_leaf_entry_t *blp; |
583 | xfs_dir2_block_tail_t *btp; | 581 | xfs_dir2_block_tail_t *btp; |
584 | 582 | ||
585 | btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr); | 583 | btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr); |
586 | blp = xfs_dir2_block_leaf_p(btp); | 584 | blp = xfs_dir2_block_leaf_p(btp); |
587 | xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr), | 585 | xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr), |
588 | (uint)((char *)&blp[last + 1] - (char *)hdr - 1)); | 586 | (uint)((char *)&blp[last + 1] - (char *)hdr - 1)); |
@@ -599,7 +597,7 @@ xfs_dir2_block_log_tail( | |||
599 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; | 597 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; |
600 | xfs_dir2_block_tail_t *btp; | 598 | xfs_dir2_block_tail_t *btp; |
601 | 599 | ||
602 | btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr); | 600 | btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr); |
603 | xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr), | 601 | xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr), |
604 | (uint)((char *)(btp + 1) - (char *)hdr - 1)); | 602 | (uint)((char *)(btp + 1) - (char *)hdr - 1)); |
605 | } | 603 | } |
@@ -634,13 +632,14 @@ xfs_dir2_block_lookup( | |||
634 | mp = dp->i_mount; | 632 | mp = dp->i_mount; |
635 | hdr = bp->b_addr; | 633 | hdr = bp->b_addr; |
636 | xfs_dir3_data_check(dp, bp); | 634 | xfs_dir3_data_check(dp, bp); |
637 | btp = xfs_dir2_block_tail_p(mp, hdr); | 635 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
638 | blp = xfs_dir2_block_leaf_p(btp); | 636 | blp = xfs_dir2_block_leaf_p(btp); |
639 | /* | 637 | /* |
640 | * Get the offset from the leaf entry, to point to the data. | 638 | * Get the offset from the leaf entry, to point to the data. |
641 | */ | 639 | */ |
642 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + | 640 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
643 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); | 641 | xfs_dir2_dataptr_to_off(args->geo, |
642 | be32_to_cpu(blp[ent].address))); | ||
644 | /* | 643 | /* |
645 | * Fill in inode number, CI name if appropriate, release the block. | 644 | * Fill in inode number, CI name if appropriate, release the block. |
646 | */ | 645 | */ |
@@ -686,7 +685,7 @@ xfs_dir2_block_lookup_int( | |||
686 | 685 | ||
687 | hdr = bp->b_addr; | 686 | hdr = bp->b_addr; |
688 | xfs_dir3_data_check(dp, bp); | 687 | xfs_dir3_data_check(dp, bp); |
689 | btp = xfs_dir2_block_tail_p(mp, hdr); | 688 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
690 | blp = xfs_dir2_block_leaf_p(btp); | 689 | blp = xfs_dir2_block_leaf_p(btp); |
691 | /* | 690 | /* |
692 | * Loop doing a binary search for our hash value. | 691 | * Loop doing a binary search for our hash value. |
@@ -724,7 +723,7 @@ xfs_dir2_block_lookup_int( | |||
724 | * Get pointer to the entry from the leaf. | 723 | * Get pointer to the entry from the leaf. |
725 | */ | 724 | */ |
726 | dep = (xfs_dir2_data_entry_t *) | 725 | dep = (xfs_dir2_data_entry_t *) |
727 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr)); | 726 | ((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, addr)); |
728 | /* | 727 | /* |
729 | * Compare name and if it's an exact match, return the index | 728 | * Compare name and if it's an exact match, return the index |
730 | * and buffer. If it's the first case-insensitive match, store | 729 | * and buffer. If it's the first case-insensitive match, store |
@@ -791,18 +790,19 @@ xfs_dir2_block_removename( | |||
791 | tp = args->trans; | 790 | tp = args->trans; |
792 | mp = dp->i_mount; | 791 | mp = dp->i_mount; |
793 | hdr = bp->b_addr; | 792 | hdr = bp->b_addr; |
794 | btp = xfs_dir2_block_tail_p(mp, hdr); | 793 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
795 | blp = xfs_dir2_block_leaf_p(btp); | 794 | blp = xfs_dir2_block_leaf_p(btp); |
796 | /* | 795 | /* |
797 | * Point to the data entry using the leaf entry. | 796 | * Point to the data entry using the leaf entry. |
798 | */ | 797 | */ |
799 | dep = (xfs_dir2_data_entry_t *) | 798 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
800 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); | 799 | xfs_dir2_dataptr_to_off(args->geo, |
800 | be32_to_cpu(blp[ent].address))); | ||
801 | /* | 801 | /* |
802 | * Mark the data entry's space free. | 802 | * Mark the data entry's space free. |
803 | */ | 803 | */ |
804 | needlog = needscan = 0; | 804 | needlog = needscan = 0; |
805 | xfs_dir2_data_make_free(tp, dp, bp, | 805 | xfs_dir2_data_make_free(args, bp, |
806 | (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), | 806 | (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), |
807 | dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); | 807 | dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); |
808 | /* | 808 | /* |
@@ -821,7 +821,7 @@ xfs_dir2_block_removename( | |||
821 | if (needscan) | 821 | if (needscan) |
822 | xfs_dir2_data_freescan(dp, hdr, &needlog); | 822 | xfs_dir2_data_freescan(dp, hdr, &needlog); |
823 | if (needlog) | 823 | if (needlog) |
824 | xfs_dir2_data_log_header(tp, dp, bp); | 824 | xfs_dir2_data_log_header(args, bp); |
825 | xfs_dir3_data_check(dp, bp); | 825 | xfs_dir3_data_check(dp, bp); |
826 | /* | 826 | /* |
827 | * See if the size as a shortform is good enough. | 827 | * See if the size as a shortform is good enough. |
@@ -866,20 +866,21 @@ xfs_dir2_block_replace( | |||
866 | dp = args->dp; | 866 | dp = args->dp; |
867 | mp = dp->i_mount; | 867 | mp = dp->i_mount; |
868 | hdr = bp->b_addr; | 868 | hdr = bp->b_addr; |
869 | btp = xfs_dir2_block_tail_p(mp, hdr); | 869 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
870 | blp = xfs_dir2_block_leaf_p(btp); | 870 | blp = xfs_dir2_block_leaf_p(btp); |
871 | /* | 871 | /* |
872 | * Point to the data entry we need to change. | 872 | * Point to the data entry we need to change. |
873 | */ | 873 | */ |
874 | dep = (xfs_dir2_data_entry_t *) | 874 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
875 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); | 875 | xfs_dir2_dataptr_to_off(args->geo, |
876 | be32_to_cpu(blp[ent].address))); | ||
876 | ASSERT(be64_to_cpu(dep->inumber) != args->inumber); | 877 | ASSERT(be64_to_cpu(dep->inumber) != args->inumber); |
877 | /* | 878 | /* |
878 | * Change the inode number to the new value. | 879 | * Change the inode number to the new value. |
879 | */ | 880 | */ |
880 | dep->inumber = cpu_to_be64(args->inumber); | 881 | dep->inumber = cpu_to_be64(args->inumber); |
881 | dp->d_ops->data_put_ftype(dep, args->filetype); | 882 | dp->d_ops->data_put_ftype(dep, args->filetype); |
882 | xfs_dir2_data_log_entry(args->trans, dp, bp, dep); | 883 | xfs_dir2_data_log_entry(args, bp, dep); |
883 | xfs_dir3_data_check(dp, bp); | 884 | xfs_dir3_data_check(dp, bp); |
884 | return 0; | 885 | return 0; |
885 | } | 886 | } |
@@ -939,7 +940,7 @@ xfs_dir2_leaf_to_block( | |||
939 | leaf = lbp->b_addr; | 940 | leaf = lbp->b_addr; |
940 | dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); | 941 | dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
941 | ents = dp->d_ops->leaf_ents_p(leaf); | 942 | ents = dp->d_ops->leaf_ents_p(leaf); |
942 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 943 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
943 | 944 | ||
944 | ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || | 945 | ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || |
945 | leafhdr.magic == XFS_DIR3_LEAF1_MAGIC); | 946 | leafhdr.magic == XFS_DIR3_LEAF1_MAGIC); |
@@ -949,13 +950,13 @@ xfs_dir2_leaf_to_block( | |||
949 | * been left behind during no-space-reservation operations. | 950 | * been left behind during no-space-reservation operations. |
950 | * These will show up in the leaf bests table. | 951 | * These will show up in the leaf bests table. |
951 | */ | 952 | */ |
952 | while (dp->i_d.di_size > mp->m_dirblksize) { | 953 | while (dp->i_d.di_size > args->geo->blksize) { |
953 | int hdrsz; | 954 | int hdrsz; |
954 | 955 | ||
955 | hdrsz = dp->d_ops->data_entry_offset; | 956 | hdrsz = dp->d_ops->data_entry_offset; |
956 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 957 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
957 | if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == | 958 | if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == |
958 | mp->m_dirblksize - hdrsz) { | 959 | args->geo->blksize - hdrsz) { |
959 | if ((error = | 960 | if ((error = |
960 | xfs_dir2_leaf_trim_data(args, lbp, | 961 | xfs_dir2_leaf_trim_data(args, lbp, |
961 | (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1)))) | 962 | (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1)))) |
@@ -967,7 +968,7 @@ xfs_dir2_leaf_to_block( | |||
967 | * Read the data block if we don't already have it, give up if it fails. | 968 | * Read the data block if we don't already have it, give up if it fails. |
968 | */ | 969 | */ |
969 | if (!dbp) { | 970 | if (!dbp) { |
970 | error = xfs_dir3_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp); | 971 | error = xfs_dir3_data_read(tp, dp, args->geo->datablk, -1, &dbp); |
971 | if (error) | 972 | if (error) |
972 | return error; | 973 | return error; |
973 | } | 974 | } |
@@ -983,7 +984,7 @@ xfs_dir2_leaf_to_block( | |||
983 | /* | 984 | /* |
984 | * Look at the last data entry. | 985 | * Look at the last data entry. |
985 | */ | 986 | */ |
986 | tagp = (__be16 *)((char *)hdr + mp->m_dirblksize) - 1; | 987 | tagp = (__be16 *)((char *)hdr + args->geo->blksize) - 1; |
987 | dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); | 988 | dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); |
988 | /* | 989 | /* |
989 | * If it's not free or is too short we can't do it. | 990 | * If it's not free or is too short we can't do it. |
@@ -1002,12 +1003,12 @@ xfs_dir2_leaf_to_block( | |||
1002 | /* | 1003 | /* |
1003 | * Use up the space at the end of the block (blp/btp). | 1004 | * Use up the space at the end of the block (blp/btp). |
1004 | */ | 1005 | */ |
1005 | xfs_dir2_data_use_free(tp, dp, dbp, dup, mp->m_dirblksize - size, size, | 1006 | xfs_dir2_data_use_free(args, dbp, dup, args->geo->blksize - size, size, |
1006 | &needlog, &needscan); | 1007 | &needlog, &needscan); |
1007 | /* | 1008 | /* |
1008 | * Initialize the block tail. | 1009 | * Initialize the block tail. |
1009 | */ | 1010 | */ |
1010 | btp = xfs_dir2_block_tail_p(mp, hdr); | 1011 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
1011 | btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale); | 1012 | btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale); |
1012 | btp->stale = 0; | 1013 | btp->stale = 0; |
1013 | xfs_dir2_block_log_tail(tp, dbp); | 1014 | xfs_dir2_block_log_tail(tp, dbp); |
@@ -1028,11 +1029,11 @@ xfs_dir2_leaf_to_block( | |||
1028 | if (needscan) | 1029 | if (needscan) |
1029 | xfs_dir2_data_freescan(dp, hdr, &needlog); | 1030 | xfs_dir2_data_freescan(dp, hdr, &needlog); |
1030 | if (needlog) | 1031 | if (needlog) |
1031 | xfs_dir2_data_log_header(tp, dp, dbp); | 1032 | xfs_dir2_data_log_header(args, dbp); |
1032 | /* | 1033 | /* |
1033 | * Pitch the old leaf block. | 1034 | * Pitch the old leaf block. |
1034 | */ | 1035 | */ |
1035 | error = xfs_da_shrink_inode(args, mp->m_dirleafblk, lbp); | 1036 | error = xfs_da_shrink_inode(args, args->geo->leafblk, lbp); |
1036 | if (error) | 1037 | if (error) |
1037 | return error; | 1038 | return error; |
1038 | 1039 | ||
@@ -1141,13 +1142,13 @@ xfs_dir2_sf_to_block( | |||
1141 | */ | 1142 | */ |
1142 | dup = dp->d_ops->data_unused_p(hdr); | 1143 | dup = dp->d_ops->data_unused_p(hdr); |
1143 | needlog = needscan = 0; | 1144 | needlog = needscan = 0; |
1144 | xfs_dir2_data_use_free(tp, dp, bp, dup, mp->m_dirblksize - i, i, &needlog, | 1145 | xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i, |
1145 | &needscan); | 1146 | i, &needlog, &needscan); |
1146 | ASSERT(needscan == 0); | 1147 | ASSERT(needscan == 0); |
1147 | /* | 1148 | /* |
1148 | * Fill in the tail. | 1149 | * Fill in the tail. |
1149 | */ | 1150 | */ |
1150 | btp = xfs_dir2_block_tail_p(mp, hdr); | 1151 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
1151 | btp->count = cpu_to_be32(sfp->count + 2); /* ., .. */ | 1152 | btp->count = cpu_to_be32(sfp->count + 2); /* ., .. */ |
1152 | btp->stale = 0; | 1153 | btp->stale = 0; |
1153 | blp = xfs_dir2_block_leaf_p(btp); | 1154 | blp = xfs_dir2_block_leaf_p(btp); |
@@ -1155,7 +1156,7 @@ xfs_dir2_sf_to_block( | |||
1155 | /* | 1156 | /* |
1156 | * Remove the freespace, we'll manage it. | 1157 | * Remove the freespace, we'll manage it. |
1157 | */ | 1158 | */ |
1158 | xfs_dir2_data_use_free(tp, dp, bp, dup, | 1159 | xfs_dir2_data_use_free(args, bp, dup, |
1159 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), | 1160 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), |
1160 | be16_to_cpu(dup->length), &needlog, &needscan); | 1161 | be16_to_cpu(dup->length), &needlog, &needscan); |
1161 | /* | 1162 | /* |
@@ -1168,9 +1169,9 @@ xfs_dir2_sf_to_block( | |||
1168 | dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); | 1169 | dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); |
1169 | tagp = dp->d_ops->data_entry_tag_p(dep); | 1170 | tagp = dp->d_ops->data_entry_tag_p(dep); |
1170 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); | 1171 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); |
1171 | xfs_dir2_data_log_entry(tp, dp, bp, dep); | 1172 | xfs_dir2_data_log_entry(args, bp, dep); |
1172 | blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); | 1173 | blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); |
1173 | blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, | 1174 | blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( |
1174 | (char *)dep - (char *)hdr)); | 1175 | (char *)dep - (char *)hdr)); |
1175 | /* | 1176 | /* |
1176 | * Create entry for .. | 1177 | * Create entry for .. |
@@ -1182,9 +1183,9 @@ xfs_dir2_sf_to_block( | |||
1182 | dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); | 1183 | dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); |
1183 | tagp = dp->d_ops->data_entry_tag_p(dep); | 1184 | tagp = dp->d_ops->data_entry_tag_p(dep); |
1184 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); | 1185 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); |
1185 | xfs_dir2_data_log_entry(tp, dp, bp, dep); | 1186 | xfs_dir2_data_log_entry(args, bp, dep); |
1186 | blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); | 1187 | blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); |
1187 | blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, | 1188 | blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( |
1188 | (char *)dep - (char *)hdr)); | 1189 | (char *)dep - (char *)hdr)); |
1189 | offset = dp->d_ops->data_first_offset; | 1190 | offset = dp->d_ops->data_first_offset; |
1190 | /* | 1191 | /* |
@@ -1216,7 +1217,7 @@ xfs_dir2_sf_to_block( | |||
1216 | dup->length = cpu_to_be16(newoffset - offset); | 1217 | dup->length = cpu_to_be16(newoffset - offset); |
1217 | *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16( | 1218 | *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16( |
1218 | ((char *)dup - (char *)hdr)); | 1219 | ((char *)dup - (char *)hdr)); |
1219 | xfs_dir2_data_log_unused(tp, bp, dup); | 1220 | xfs_dir2_data_log_unused(args, bp, dup); |
1220 | xfs_dir2_data_freeinsert(hdr, | 1221 | xfs_dir2_data_freeinsert(hdr, |
1221 | dp->d_ops->data_bestfree_p(hdr), | 1222 | dp->d_ops->data_bestfree_p(hdr), |
1222 | dup, &dummy); | 1223 | dup, &dummy); |
@@ -1233,12 +1234,12 @@ xfs_dir2_sf_to_block( | |||
1233 | memcpy(dep->name, sfep->name, dep->namelen); | 1234 | memcpy(dep->name, sfep->name, dep->namelen); |
1234 | tagp = dp->d_ops->data_entry_tag_p(dep); | 1235 | tagp = dp->d_ops->data_entry_tag_p(dep); |
1235 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); | 1236 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); |
1236 | xfs_dir2_data_log_entry(tp, dp, bp, dep); | 1237 | xfs_dir2_data_log_entry(args, bp, dep); |
1237 | name.name = sfep->name; | 1238 | name.name = sfep->name; |
1238 | name.len = sfep->namelen; | 1239 | name.len = sfep->namelen; |
1239 | blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> | 1240 | blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> |
1240 | hashname(&name)); | 1241 | hashname(&name)); |
1241 | blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, | 1242 | blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( |
1242 | (char *)dep - (char *)hdr)); | 1243 | (char *)dep - (char *)hdr)); |
1243 | offset = (int)((char *)(tagp + 1) - (char *)hdr); | 1244 | offset = (int)((char *)(tagp + 1) - (char *)hdr); |
1244 | if (++i == sfp->count) | 1245 | if (++i == sfp->count) |
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index afa4ad523f3f..8c2f6422648e 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c | |||
@@ -63,8 +63,10 @@ __xfs_dir3_data_check( | |||
63 | int stale; /* count of stale leaves */ | 63 | int stale; /* count of stale leaves */ |
64 | struct xfs_name name; | 64 | struct xfs_name name; |
65 | const struct xfs_dir_ops *ops; | 65 | const struct xfs_dir_ops *ops; |
66 | struct xfs_da_geometry *geo; | ||
66 | 67 | ||
67 | mp = bp->b_target->bt_mount; | 68 | mp = bp->b_target->bt_mount; |
69 | geo = mp->m_dir_geo; | ||
68 | 70 | ||
69 | /* | 71 | /* |
70 | * We can be passed a null dp here from a verifier, so we need to go the | 72 | * We can be passed a null dp here from a verifier, so we need to go the |
@@ -78,7 +80,7 @@ __xfs_dir3_data_check( | |||
78 | switch (hdr->magic) { | 80 | switch (hdr->magic) { |
79 | case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): | 81 | case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): |
80 | case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): | 82 | case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): |
81 | btp = xfs_dir2_block_tail_p(mp, hdr); | 83 | btp = xfs_dir2_block_tail_p(geo, hdr); |
82 | lep = xfs_dir2_block_leaf_p(btp); | 84 | lep = xfs_dir2_block_leaf_p(btp); |
83 | endp = (char *)lep; | 85 | endp = (char *)lep; |
84 | 86 | ||
@@ -94,7 +96,7 @@ __xfs_dir3_data_check( | |||
94 | break; | 96 | break; |
95 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): | 97 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): |
96 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): | 98 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): |
97 | endp = (char *)hdr + mp->m_dirblksize; | 99 | endp = (char *)hdr + geo->blksize; |
98 | break; | 100 | break; |
99 | default: | 101 | default: |
100 | XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp); | 102 | XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp); |
@@ -172,9 +174,9 @@ __xfs_dir3_data_check( | |||
172 | lastfree = 0; | 174 | lastfree = 0; |
173 | if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 175 | if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
174 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { | 176 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { |
175 | addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 177 | addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, |
176 | (xfs_dir2_data_aoff_t) | 178 | (xfs_dir2_data_aoff_t) |
177 | ((char *)dep - (char *)hdr)); | 179 | ((char *)dep - (char *)hdr)); |
178 | name.name = dep->name; | 180 | name.name = dep->name; |
179 | name.len = dep->namelen; | 181 | name.len = dep->namelen; |
180 | hash = mp->m_dirnameops->hashname(&name); | 182 | hash = mp->m_dirnameops->hashname(&name); |
@@ -329,12 +331,11 @@ xfs_dir3_data_read( | |||
329 | 331 | ||
330 | int | 332 | int |
331 | xfs_dir3_data_readahead( | 333 | xfs_dir3_data_readahead( |
332 | struct xfs_trans *tp, | ||
333 | struct xfs_inode *dp, | 334 | struct xfs_inode *dp, |
334 | xfs_dablk_t bno, | 335 | xfs_dablk_t bno, |
335 | xfs_daddr_t mapped_bno) | 336 | xfs_daddr_t mapped_bno) |
336 | { | 337 | { |
337 | return xfs_da_reada_buf(tp, dp, bno, mapped_bno, | 338 | return xfs_da_reada_buf(dp, bno, mapped_bno, |
338 | XFS_DATA_FORK, &xfs_dir3_data_reada_buf_ops); | 339 | XFS_DATA_FORK, &xfs_dir3_data_reada_buf_ops); |
339 | } | 340 | } |
340 | 341 | ||
@@ -510,6 +511,7 @@ xfs_dir2_data_freescan( | |||
510 | struct xfs_dir2_data_free *bf; | 511 | struct xfs_dir2_data_free *bf; |
511 | char *endp; /* end of block's data */ | 512 | char *endp; /* end of block's data */ |
512 | char *p; /* current entry pointer */ | 513 | char *p; /* current entry pointer */ |
514 | struct xfs_da_geometry *geo = dp->i_mount->m_dir_geo; | ||
513 | 515 | ||
514 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 516 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
515 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | 517 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || |
@@ -528,10 +530,10 @@ xfs_dir2_data_freescan( | |||
528 | p = (char *)dp->d_ops->data_entry_p(hdr); | 530 | p = (char *)dp->d_ops->data_entry_p(hdr); |
529 | if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 531 | if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
530 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { | 532 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { |
531 | btp = xfs_dir2_block_tail_p(dp->i_mount, hdr); | 533 | btp = xfs_dir2_block_tail_p(geo, hdr); |
532 | endp = (char *)xfs_dir2_block_leaf_p(btp); | 534 | endp = (char *)xfs_dir2_block_leaf_p(btp); |
533 | } else | 535 | } else |
534 | endp = (char *)hdr + dp->i_mount->m_dirblksize; | 536 | endp = (char *)hdr + geo->blksize; |
535 | /* | 537 | /* |
536 | * Loop over the block's entries. | 538 | * Loop over the block's entries. |
537 | */ | 539 | */ |
@@ -585,8 +587,8 @@ xfs_dir3_data_init( | |||
585 | /* | 587 | /* |
586 | * Get the buffer set up for the block. | 588 | * Get the buffer set up for the block. |
587 | */ | 589 | */ |
588 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp, | 590 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno), |
589 | XFS_DATA_FORK); | 591 | -1, &bp, XFS_DATA_FORK); |
590 | if (error) | 592 | if (error) |
591 | return error; | 593 | return error; |
592 | bp->b_ops = &xfs_dir3_data_buf_ops; | 594 | bp->b_ops = &xfs_dir3_data_buf_ops; |
@@ -621,15 +623,15 @@ xfs_dir3_data_init( | |||
621 | dup = dp->d_ops->data_unused_p(hdr); | 623 | dup = dp->d_ops->data_unused_p(hdr); |
622 | dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); | 624 | dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); |
623 | 625 | ||
624 | t = mp->m_dirblksize - (uint)dp->d_ops->data_entry_offset; | 626 | t = args->geo->blksize - (uint)dp->d_ops->data_entry_offset; |
625 | bf[0].length = cpu_to_be16(t); | 627 | bf[0].length = cpu_to_be16(t); |
626 | dup->length = cpu_to_be16(t); | 628 | dup->length = cpu_to_be16(t); |
627 | *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); | 629 | *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); |
628 | /* | 630 | /* |
629 | * Log it and return it. | 631 | * Log it and return it. |
630 | */ | 632 | */ |
631 | xfs_dir2_data_log_header(tp, dp, bp); | 633 | xfs_dir2_data_log_header(args, bp); |
632 | xfs_dir2_data_log_unused(tp, bp, dup); | 634 | xfs_dir2_data_log_unused(args, bp, dup); |
633 | *bpp = bp; | 635 | *bpp = bp; |
634 | return 0; | 636 | return 0; |
635 | } | 637 | } |
@@ -639,8 +641,7 @@ xfs_dir3_data_init( | |||
639 | */ | 641 | */ |
640 | void | 642 | void |
641 | xfs_dir2_data_log_entry( | 643 | xfs_dir2_data_log_entry( |
642 | struct xfs_trans *tp, | 644 | struct xfs_da_args *args, |
643 | struct xfs_inode *dp, | ||
644 | struct xfs_buf *bp, | 645 | struct xfs_buf *bp, |
645 | xfs_dir2_data_entry_t *dep) /* data entry pointer */ | 646 | xfs_dir2_data_entry_t *dep) /* data entry pointer */ |
646 | { | 647 | { |
@@ -651,8 +652,8 @@ xfs_dir2_data_log_entry( | |||
651 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 652 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
652 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 653 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
653 | 654 | ||
654 | xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), | 655 | xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr), |
655 | (uint)((char *)(dp->d_ops->data_entry_tag_p(dep) + 1) - | 656 | (uint)((char *)(args->dp->d_ops->data_entry_tag_p(dep) + 1) - |
656 | (char *)hdr - 1)); | 657 | (char *)hdr - 1)); |
657 | } | 658 | } |
658 | 659 | ||
@@ -661,8 +662,7 @@ xfs_dir2_data_log_entry( | |||
661 | */ | 662 | */ |
662 | void | 663 | void |
663 | xfs_dir2_data_log_header( | 664 | xfs_dir2_data_log_header( |
664 | struct xfs_trans *tp, | 665 | struct xfs_da_args *args, |
665 | struct xfs_inode *dp, | ||
666 | struct xfs_buf *bp) | 666 | struct xfs_buf *bp) |
667 | { | 667 | { |
668 | #ifdef DEBUG | 668 | #ifdef DEBUG |
@@ -674,7 +674,8 @@ xfs_dir2_data_log_header( | |||
674 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 674 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
675 | #endif | 675 | #endif |
676 | 676 | ||
677 | xfs_trans_log_buf(tp, bp, 0, dp->d_ops->data_entry_offset - 1); | 677 | xfs_trans_log_buf(args->trans, bp, 0, |
678 | args->dp->d_ops->data_entry_offset - 1); | ||
678 | } | 679 | } |
679 | 680 | ||
680 | /* | 681 | /* |
@@ -682,7 +683,7 @@ xfs_dir2_data_log_header( | |||
682 | */ | 683 | */ |
683 | void | 684 | void |
684 | xfs_dir2_data_log_unused( | 685 | xfs_dir2_data_log_unused( |
685 | struct xfs_trans *tp, | 686 | struct xfs_da_args *args, |
686 | struct xfs_buf *bp, | 687 | struct xfs_buf *bp, |
687 | xfs_dir2_data_unused_t *dup) /* data unused pointer */ | 688 | xfs_dir2_data_unused_t *dup) /* data unused pointer */ |
688 | { | 689 | { |
@@ -696,13 +697,13 @@ xfs_dir2_data_log_unused( | |||
696 | /* | 697 | /* |
697 | * Log the first part of the unused entry. | 698 | * Log the first part of the unused entry. |
698 | */ | 699 | */ |
699 | xfs_trans_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr), | 700 | xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr), |
700 | (uint)((char *)&dup->length + sizeof(dup->length) - | 701 | (uint)((char *)&dup->length + sizeof(dup->length) - |
701 | 1 - (char *)hdr)); | 702 | 1 - (char *)hdr)); |
702 | /* | 703 | /* |
703 | * Log the end (tag) of the unused entry. | 704 | * Log the end (tag) of the unused entry. |
704 | */ | 705 | */ |
705 | xfs_trans_log_buf(tp, bp, | 706 | xfs_trans_log_buf(args->trans, bp, |
706 | (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr), | 707 | (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr), |
707 | (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr + | 708 | (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr + |
708 | sizeof(xfs_dir2_data_off_t) - 1)); | 709 | sizeof(xfs_dir2_data_off_t) - 1)); |
@@ -714,8 +715,7 @@ xfs_dir2_data_log_unused( | |||
714 | */ | 715 | */ |
715 | void | 716 | void |
716 | xfs_dir2_data_make_free( | 717 | xfs_dir2_data_make_free( |
717 | struct xfs_trans *tp, | 718 | struct xfs_da_args *args, |
718 | struct xfs_inode *dp, | ||
719 | struct xfs_buf *bp, | 719 | struct xfs_buf *bp, |
720 | xfs_dir2_data_aoff_t offset, /* starting byte offset */ | 720 | xfs_dir2_data_aoff_t offset, /* starting byte offset */ |
721 | xfs_dir2_data_aoff_t len, /* length in bytes */ | 721 | xfs_dir2_data_aoff_t len, /* length in bytes */ |
@@ -725,14 +725,12 @@ xfs_dir2_data_make_free( | |||
725 | xfs_dir2_data_hdr_t *hdr; /* data block pointer */ | 725 | xfs_dir2_data_hdr_t *hdr; /* data block pointer */ |
726 | xfs_dir2_data_free_t *dfp; /* bestfree pointer */ | 726 | xfs_dir2_data_free_t *dfp; /* bestfree pointer */ |
727 | char *endptr; /* end of data area */ | 727 | char *endptr; /* end of data area */ |
728 | xfs_mount_t *mp; /* filesystem mount point */ | ||
729 | int needscan; /* need to regen bestfree */ | 728 | int needscan; /* need to regen bestfree */ |
730 | xfs_dir2_data_unused_t *newdup; /* new unused entry */ | 729 | xfs_dir2_data_unused_t *newdup; /* new unused entry */ |
731 | xfs_dir2_data_unused_t *postdup; /* unused entry after us */ | 730 | xfs_dir2_data_unused_t *postdup; /* unused entry after us */ |
732 | xfs_dir2_data_unused_t *prevdup; /* unused entry before us */ | 731 | xfs_dir2_data_unused_t *prevdup; /* unused entry before us */ |
733 | struct xfs_dir2_data_free *bf; | 732 | struct xfs_dir2_data_free *bf; |
734 | 733 | ||
735 | mp = tp->t_mountp; | ||
736 | hdr = bp->b_addr; | 734 | hdr = bp->b_addr; |
737 | 735 | ||
738 | /* | 736 | /* |
@@ -740,20 +738,20 @@ xfs_dir2_data_make_free( | |||
740 | */ | 738 | */ |
741 | if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 739 | if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
742 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)) | 740 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)) |
743 | endptr = (char *)hdr + mp->m_dirblksize; | 741 | endptr = (char *)hdr + args->geo->blksize; |
744 | else { | 742 | else { |
745 | xfs_dir2_block_tail_t *btp; /* block tail */ | 743 | xfs_dir2_block_tail_t *btp; /* block tail */ |
746 | 744 | ||
747 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 745 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
748 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 746 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
749 | btp = xfs_dir2_block_tail_p(mp, hdr); | 747 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
750 | endptr = (char *)xfs_dir2_block_leaf_p(btp); | 748 | endptr = (char *)xfs_dir2_block_leaf_p(btp); |
751 | } | 749 | } |
752 | /* | 750 | /* |
753 | * If this isn't the start of the block, then back up to | 751 | * If this isn't the start of the block, then back up to |
754 | * the previous entry and see if it's free. | 752 | * the previous entry and see if it's free. |
755 | */ | 753 | */ |
756 | if (offset > dp->d_ops->data_entry_offset) { | 754 | if (offset > args->dp->d_ops->data_entry_offset) { |
757 | __be16 *tagp; /* tag just before us */ | 755 | __be16 *tagp; /* tag just before us */ |
758 | 756 | ||
759 | tagp = (__be16 *)((char *)hdr + offset) - 1; | 757 | tagp = (__be16 *)((char *)hdr + offset) - 1; |
@@ -779,7 +777,7 @@ xfs_dir2_data_make_free( | |||
779 | * Previous and following entries are both free, | 777 | * Previous and following entries are both free, |
780 | * merge everything into a single free entry. | 778 | * merge everything into a single free entry. |
781 | */ | 779 | */ |
782 | bf = dp->d_ops->data_bestfree_p(hdr); | 780 | bf = args->dp->d_ops->data_bestfree_p(hdr); |
783 | if (prevdup && postdup) { | 781 | if (prevdup && postdup) { |
784 | xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */ | 782 | xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */ |
785 | 783 | ||
@@ -801,7 +799,7 @@ xfs_dir2_data_make_free( | |||
801 | be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length)); | 799 | be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length)); |
802 | *xfs_dir2_data_unused_tag_p(prevdup) = | 800 | *xfs_dir2_data_unused_tag_p(prevdup) = |
803 | cpu_to_be16((char *)prevdup - (char *)hdr); | 801 | cpu_to_be16((char *)prevdup - (char *)hdr); |
804 | xfs_dir2_data_log_unused(tp, bp, prevdup); | 802 | xfs_dir2_data_log_unused(args, bp, prevdup); |
805 | if (!needscan) { | 803 | if (!needscan) { |
806 | /* | 804 | /* |
807 | * Has to be the case that entries 0 and 1 are | 805 | * Has to be the case that entries 0 and 1 are |
@@ -836,7 +834,7 @@ xfs_dir2_data_make_free( | |||
836 | be16_add_cpu(&prevdup->length, len); | 834 | be16_add_cpu(&prevdup->length, len); |
837 | *xfs_dir2_data_unused_tag_p(prevdup) = | 835 | *xfs_dir2_data_unused_tag_p(prevdup) = |
838 | cpu_to_be16((char *)prevdup - (char *)hdr); | 836 | cpu_to_be16((char *)prevdup - (char *)hdr); |
839 | xfs_dir2_data_log_unused(tp, bp, prevdup); | 837 | xfs_dir2_data_log_unused(args, bp, prevdup); |
840 | /* | 838 | /* |
841 | * If the previous entry was in the table, the new entry | 839 | * If the previous entry was in the table, the new entry |
842 | * is longer, so it will be in the table too. Remove | 840 | * is longer, so it will be in the table too. Remove |
@@ -864,7 +862,7 @@ xfs_dir2_data_make_free( | |||
864 | newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length)); | 862 | newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length)); |
865 | *xfs_dir2_data_unused_tag_p(newdup) = | 863 | *xfs_dir2_data_unused_tag_p(newdup) = |
866 | cpu_to_be16((char *)newdup - (char *)hdr); | 864 | cpu_to_be16((char *)newdup - (char *)hdr); |
867 | xfs_dir2_data_log_unused(tp, bp, newdup); | 865 | xfs_dir2_data_log_unused(args, bp, newdup); |
868 | /* | 866 | /* |
869 | * If the following entry was in the table, the new entry | 867 | * If the following entry was in the table, the new entry |
870 | * is longer, so it will be in the table too. Remove | 868 | * is longer, so it will be in the table too. Remove |
@@ -891,7 +889,7 @@ xfs_dir2_data_make_free( | |||
891 | newdup->length = cpu_to_be16(len); | 889 | newdup->length = cpu_to_be16(len); |
892 | *xfs_dir2_data_unused_tag_p(newdup) = | 890 | *xfs_dir2_data_unused_tag_p(newdup) = |
893 | cpu_to_be16((char *)newdup - (char *)hdr); | 891 | cpu_to_be16((char *)newdup - (char *)hdr); |
894 | xfs_dir2_data_log_unused(tp, bp, newdup); | 892 | xfs_dir2_data_log_unused(args, bp, newdup); |
895 | xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); | 893 | xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); |
896 | } | 894 | } |
897 | *needscanp = needscan; | 895 | *needscanp = needscan; |
@@ -902,8 +900,7 @@ xfs_dir2_data_make_free( | |||
902 | */ | 900 | */ |
903 | void | 901 | void |
904 | xfs_dir2_data_use_free( | 902 | xfs_dir2_data_use_free( |
905 | struct xfs_trans *tp, | 903 | struct xfs_da_args *args, |
906 | struct xfs_inode *dp, | ||
907 | struct xfs_buf *bp, | 904 | struct xfs_buf *bp, |
908 | xfs_dir2_data_unused_t *dup, /* unused entry */ | 905 | xfs_dir2_data_unused_t *dup, /* unused entry */ |
909 | xfs_dir2_data_aoff_t offset, /* starting offset to use */ | 906 | xfs_dir2_data_aoff_t offset, /* starting offset to use */ |
@@ -934,7 +931,7 @@ xfs_dir2_data_use_free( | |||
934 | * Look up the entry in the bestfree table. | 931 | * Look up the entry in the bestfree table. |
935 | */ | 932 | */ |
936 | oldlen = be16_to_cpu(dup->length); | 933 | oldlen = be16_to_cpu(dup->length); |
937 | bf = dp->d_ops->data_bestfree_p(hdr); | 934 | bf = args->dp->d_ops->data_bestfree_p(hdr); |
938 | dfp = xfs_dir2_data_freefind(hdr, bf, dup); | 935 | dfp = xfs_dir2_data_freefind(hdr, bf, dup); |
939 | ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length)); | 936 | ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length)); |
940 | /* | 937 | /* |
@@ -966,7 +963,7 @@ xfs_dir2_data_use_free( | |||
966 | newdup->length = cpu_to_be16(oldlen - len); | 963 | newdup->length = cpu_to_be16(oldlen - len); |
967 | *xfs_dir2_data_unused_tag_p(newdup) = | 964 | *xfs_dir2_data_unused_tag_p(newdup) = |
968 | cpu_to_be16((char *)newdup - (char *)hdr); | 965 | cpu_to_be16((char *)newdup - (char *)hdr); |
969 | xfs_dir2_data_log_unused(tp, bp, newdup); | 966 | xfs_dir2_data_log_unused(args, bp, newdup); |
970 | /* | 967 | /* |
971 | * If it was in the table, remove it and add the new one. | 968 | * If it was in the table, remove it and add the new one. |
972 | */ | 969 | */ |
@@ -994,7 +991,7 @@ xfs_dir2_data_use_free( | |||
994 | newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); | 991 | newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); |
995 | *xfs_dir2_data_unused_tag_p(newdup) = | 992 | *xfs_dir2_data_unused_tag_p(newdup) = |
996 | cpu_to_be16((char *)newdup - (char *)hdr); | 993 | cpu_to_be16((char *)newdup - (char *)hdr); |
997 | xfs_dir2_data_log_unused(tp, bp, newdup); | 994 | xfs_dir2_data_log_unused(args, bp, newdup); |
998 | /* | 995 | /* |
999 | * If it was in the table, remove it and add the new one. | 996 | * If it was in the table, remove it and add the new one. |
1000 | */ | 997 | */ |
@@ -1022,13 +1019,13 @@ xfs_dir2_data_use_free( | |||
1022 | newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); | 1019 | newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); |
1023 | *xfs_dir2_data_unused_tag_p(newdup) = | 1020 | *xfs_dir2_data_unused_tag_p(newdup) = |
1024 | cpu_to_be16((char *)newdup - (char *)hdr); | 1021 | cpu_to_be16((char *)newdup - (char *)hdr); |
1025 | xfs_dir2_data_log_unused(tp, bp, newdup); | 1022 | xfs_dir2_data_log_unused(args, bp, newdup); |
1026 | newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); | 1023 | newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); |
1027 | newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); | 1024 | newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); |
1028 | newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length)); | 1025 | newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length)); |
1029 | *xfs_dir2_data_unused_tag_p(newdup2) = | 1026 | *xfs_dir2_data_unused_tag_p(newdup2) = |
1030 | cpu_to_be16((char *)newdup2 - (char *)hdr); | 1027 | cpu_to_be16((char *)newdup2 - (char *)hdr); |
1031 | xfs_dir2_data_log_unused(tp, bp, newdup2); | 1028 | xfs_dir2_data_log_unused(args, bp, newdup2); |
1032 | /* | 1029 | /* |
1033 | * If the old entry was in the table, we need to scan | 1030 | * If the old entry was in the table, we need to scan |
1034 | * if the 3rd entry was valid, since these entries | 1031 | * if the 3rd entry was valid, since these entries |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index d36e97df1187..fb0aad4440c1 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -41,9 +41,10 @@ | |||
41 | */ | 41 | */ |
42 | static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, | 42 | static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, |
43 | int *indexp, struct xfs_buf **dbpp); | 43 | int *indexp, struct xfs_buf **dbpp); |
44 | static void xfs_dir3_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp, | 44 | static void xfs_dir3_leaf_log_bests(struct xfs_da_args *args, |
45 | int first, int last); | 45 | struct xfs_buf *bp, int first, int last); |
46 | static void xfs_dir3_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); | 46 | static void xfs_dir3_leaf_log_tail(struct xfs_da_args *args, |
47 | struct xfs_buf *bp); | ||
47 | 48 | ||
48 | /* | 49 | /* |
49 | * Check the internal consistency of a leaf1 block. | 50 | * Check the internal consistency of a leaf1 block. |
@@ -92,6 +93,7 @@ xfs_dir3_leaf_check_int( | |||
92 | int i; | 93 | int i; |
93 | const struct xfs_dir_ops *ops; | 94 | const struct xfs_dir_ops *ops; |
94 | struct xfs_dir3_icleaf_hdr leafhdr; | 95 | struct xfs_dir3_icleaf_hdr leafhdr; |
96 | struct xfs_da_geometry *geo = mp->m_dir_geo; | ||
95 | 97 | ||
96 | /* | 98 | /* |
97 | * we can be passed a null dp here from a verifier, so we need to go the | 99 | * we can be passed a null dp here from a verifier, so we need to go the |
@@ -105,14 +107,14 @@ xfs_dir3_leaf_check_int( | |||
105 | } | 107 | } |
106 | 108 | ||
107 | ents = ops->leaf_ents_p(leaf); | 109 | ents = ops->leaf_ents_p(leaf); |
108 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 110 | ltp = xfs_dir2_leaf_tail_p(geo, leaf); |
109 | 111 | ||
110 | /* | 112 | /* |
111 | * XXX (dgc): This value is not restrictive enough. | 113 | * XXX (dgc): This value is not restrictive enough. |
112 | * Should factor in the size of the bests table as well. | 114 | * Should factor in the size of the bests table as well. |
113 | * We can deduce a value for that from di_size. | 115 | * We can deduce a value for that from di_size. |
114 | */ | 116 | */ |
115 | if (hdr->count > ops->leaf_max_ents(mp)) | 117 | if (hdr->count > ops->leaf_max_ents(geo)) |
116 | return false; | 118 | return false; |
117 | 119 | ||
118 | /* Leaves and bests don't overlap in leaf format. */ | 120 | /* Leaves and bests don't overlap in leaf format. */ |
@@ -323,7 +325,7 @@ xfs_dir3_leaf_init( | |||
323 | if (type == XFS_DIR2_LEAF1_MAGIC) { | 325 | if (type == XFS_DIR2_LEAF1_MAGIC) { |
324 | struct xfs_dir2_leaf_tail *ltp; | 326 | struct xfs_dir2_leaf_tail *ltp; |
325 | 327 | ||
326 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 328 | ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); |
327 | ltp->bestcount = 0; | 329 | ltp->bestcount = 0; |
328 | bp->b_ops = &xfs_dir3_leaf1_buf_ops; | 330 | bp->b_ops = &xfs_dir3_leaf1_buf_ops; |
329 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAF1_BUF); | 331 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAF1_BUF); |
@@ -347,18 +349,18 @@ xfs_dir3_leaf_get_buf( | |||
347 | int error; | 349 | int error; |
348 | 350 | ||
349 | ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); | 351 | ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); |
350 | ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) && | 352 | ASSERT(bno >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET) && |
351 | bno < XFS_DIR2_FREE_FIRSTDB(mp)); | 353 | bno < xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)); |
352 | 354 | ||
353 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp, | 355 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, bno), |
354 | XFS_DATA_FORK); | 356 | -1, &bp, XFS_DATA_FORK); |
355 | if (error) | 357 | if (error) |
356 | return error; | 358 | return error; |
357 | 359 | ||
358 | xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic); | 360 | xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic); |
359 | xfs_dir3_leaf_log_header(tp, dp, bp); | 361 | xfs_dir3_leaf_log_header(args, bp); |
360 | if (magic == XFS_DIR2_LEAF1_MAGIC) | 362 | if (magic == XFS_DIR2_LEAF1_MAGIC) |
361 | xfs_dir3_leaf_log_tail(tp, bp); | 363 | xfs_dir3_leaf_log_tail(args, bp); |
362 | *bpp = bp; | 364 | *bpp = bp; |
363 | return 0; | 365 | return 0; |
364 | } | 366 | } |
@@ -403,8 +405,8 @@ xfs_dir2_block_to_leaf( | |||
403 | if ((error = xfs_da_grow_inode(args, &blkno))) { | 405 | if ((error = xfs_da_grow_inode(args, &blkno))) { |
404 | return error; | 406 | return error; |
405 | } | 407 | } |
406 | ldb = xfs_dir2_da_to_db(mp, blkno); | 408 | ldb = xfs_dir2_da_to_db(args->geo, blkno); |
407 | ASSERT(ldb == XFS_DIR2_LEAF_FIRSTDB(mp)); | 409 | ASSERT(ldb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET)); |
408 | /* | 410 | /* |
409 | * Initialize the leaf block, get a buffer for it. | 411 | * Initialize the leaf block, get a buffer for it. |
410 | */ | 412 | */ |
@@ -415,7 +417,7 @@ xfs_dir2_block_to_leaf( | |||
415 | leaf = lbp->b_addr; | 417 | leaf = lbp->b_addr; |
416 | hdr = dbp->b_addr; | 418 | hdr = dbp->b_addr; |
417 | xfs_dir3_data_check(dp, dbp); | 419 | xfs_dir3_data_check(dp, dbp); |
418 | btp = xfs_dir2_block_tail_p(mp, hdr); | 420 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
419 | blp = xfs_dir2_block_leaf_p(btp); | 421 | blp = xfs_dir2_block_leaf_p(btp); |
420 | bf = dp->d_ops->data_bestfree_p(hdr); | 422 | bf = dp->d_ops->data_bestfree_p(hdr); |
421 | ents = dp->d_ops->leaf_ents_p(leaf); | 423 | ents = dp->d_ops->leaf_ents_p(leaf); |
@@ -427,23 +429,23 @@ xfs_dir2_block_to_leaf( | |||
427 | leafhdr.count = be32_to_cpu(btp->count); | 429 | leafhdr.count = be32_to_cpu(btp->count); |
428 | leafhdr.stale = be32_to_cpu(btp->stale); | 430 | leafhdr.stale = be32_to_cpu(btp->stale); |
429 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); | 431 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
430 | xfs_dir3_leaf_log_header(tp, dp, lbp); | 432 | xfs_dir3_leaf_log_header(args, lbp); |
431 | 433 | ||
432 | /* | 434 | /* |
433 | * Could compact these but I think we always do the conversion | 435 | * Could compact these but I think we always do the conversion |
434 | * after squeezing out stale entries. | 436 | * after squeezing out stale entries. |
435 | */ | 437 | */ |
436 | memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); | 438 | memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); |
437 | xfs_dir3_leaf_log_ents(tp, dp, lbp, 0, leafhdr.count - 1); | 439 | xfs_dir3_leaf_log_ents(args, lbp, 0, leafhdr.count - 1); |
438 | needscan = 0; | 440 | needscan = 0; |
439 | needlog = 1; | 441 | needlog = 1; |
440 | /* | 442 | /* |
441 | * Make the space formerly occupied by the leaf entries and block | 443 | * Make the space formerly occupied by the leaf entries and block |
442 | * tail be free. | 444 | * tail be free. |
443 | */ | 445 | */ |
444 | xfs_dir2_data_make_free(tp, dp, dbp, | 446 | xfs_dir2_data_make_free(args, dbp, |
445 | (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), | 447 | (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), |
446 | (xfs_dir2_data_aoff_t)((char *)hdr + mp->m_dirblksize - | 448 | (xfs_dir2_data_aoff_t)((char *)hdr + args->geo->blksize - |
447 | (char *)blp), | 449 | (char *)blp), |
448 | &needlog, &needscan); | 450 | &needlog, &needscan); |
449 | /* | 451 | /* |
@@ -461,7 +463,7 @@ xfs_dir2_block_to_leaf( | |||
461 | /* | 463 | /* |
462 | * Set up leaf tail and bests table. | 464 | * Set up leaf tail and bests table. |
463 | */ | 465 | */ |
464 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 466 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
465 | ltp->bestcount = cpu_to_be32(1); | 467 | ltp->bestcount = cpu_to_be32(1); |
466 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 468 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
467 | bestsp[0] = bf[0].length; | 469 | bestsp[0] = bf[0].length; |
@@ -469,10 +471,10 @@ xfs_dir2_block_to_leaf( | |||
469 | * Log the data header and leaf bests table. | 471 | * Log the data header and leaf bests table. |
470 | */ | 472 | */ |
471 | if (needlog) | 473 | if (needlog) |
472 | xfs_dir2_data_log_header(tp, dp, dbp); | 474 | xfs_dir2_data_log_header(args, dbp); |
473 | xfs_dir3_leaf_check(dp, lbp); | 475 | xfs_dir3_leaf_check(dp, lbp); |
474 | xfs_dir3_data_check(dp, dbp); | 476 | xfs_dir3_data_check(dp, dbp); |
475 | xfs_dir3_leaf_log_bests(tp, lbp, 0, 0); | 477 | xfs_dir3_leaf_log_bests(args, lbp, 0, 0); |
476 | return 0; | 478 | return 0; |
477 | } | 479 | } |
478 | 480 | ||
@@ -641,7 +643,7 @@ xfs_dir2_leaf_addname( | |||
641 | tp = args->trans; | 643 | tp = args->trans; |
642 | mp = dp->i_mount; | 644 | mp = dp->i_mount; |
643 | 645 | ||
644 | error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); | 646 | error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, -1, &lbp); |
645 | if (error) | 647 | if (error) |
646 | return error; | 648 | return error; |
647 | 649 | ||
@@ -653,7 +655,7 @@ xfs_dir2_leaf_addname( | |||
653 | */ | 655 | */ |
654 | index = xfs_dir2_leaf_search_hash(args, lbp); | 656 | index = xfs_dir2_leaf_search_hash(args, lbp); |
655 | leaf = lbp->b_addr; | 657 | leaf = lbp->b_addr; |
656 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 658 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
657 | ents = dp->d_ops->leaf_ents_p(leaf); | 659 | ents = dp->d_ops->leaf_ents_p(leaf); |
658 | dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); | 660 | dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
659 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 661 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
@@ -670,7 +672,7 @@ xfs_dir2_leaf_addname( | |||
670 | index++, lep++) { | 672 | index++, lep++) { |
671 | if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) | 673 | if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) |
672 | continue; | 674 | continue; |
673 | i = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 675 | i = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); |
674 | ASSERT(i < be32_to_cpu(ltp->bestcount)); | 676 | ASSERT(i < be32_to_cpu(ltp->bestcount)); |
675 | ASSERT(bestsp[i] != cpu_to_be16(NULLDATAOFF)); | 677 | ASSERT(bestsp[i] != cpu_to_be16(NULLDATAOFF)); |
676 | if (be16_to_cpu(bestsp[i]) >= length) { | 678 | if (be16_to_cpu(bestsp[i]) >= length) { |
@@ -810,14 +812,15 @@ xfs_dir2_leaf_addname( | |||
810 | memmove(&bestsp[0], &bestsp[1], | 812 | memmove(&bestsp[0], &bestsp[1], |
811 | be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); | 813 | be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); |
812 | be32_add_cpu(<p->bestcount, 1); | 814 | be32_add_cpu(<p->bestcount, 1); |
813 | xfs_dir3_leaf_log_tail(tp, lbp); | 815 | xfs_dir3_leaf_log_tail(args, lbp); |
814 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 816 | xfs_dir3_leaf_log_bests(args, lbp, 0, |
817 | be32_to_cpu(ltp->bestcount) - 1); | ||
815 | } | 818 | } |
816 | /* | 819 | /* |
817 | * If we're filling in a previously empty block just log it. | 820 | * If we're filling in a previously empty block just log it. |
818 | */ | 821 | */ |
819 | else | 822 | else |
820 | xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); | 823 | xfs_dir3_leaf_log_bests(args, lbp, use_block, use_block); |
821 | hdr = dbp->b_addr; | 824 | hdr = dbp->b_addr; |
822 | bf = dp->d_ops->data_bestfree_p(hdr); | 825 | bf = dp->d_ops->data_bestfree_p(hdr); |
823 | bestsp[use_block] = bf[0].length; | 826 | bestsp[use_block] = bf[0].length; |
@@ -828,8 +831,8 @@ xfs_dir2_leaf_addname( | |||
828 | * Just read that one in. | 831 | * Just read that one in. |
829 | */ | 832 | */ |
830 | error = xfs_dir3_data_read(tp, dp, | 833 | error = xfs_dir3_data_read(tp, dp, |
831 | xfs_dir2_db_to_da(mp, use_block), | 834 | xfs_dir2_db_to_da(args->geo, use_block), |
832 | -1, &dbp); | 835 | -1, &dbp); |
833 | if (error) { | 836 | if (error) { |
834 | xfs_trans_brelse(tp, lbp); | 837 | xfs_trans_brelse(tp, lbp); |
835 | return error; | 838 | return error; |
@@ -848,7 +851,7 @@ xfs_dir2_leaf_addname( | |||
848 | /* | 851 | /* |
849 | * Mark the initial part of our freespace in use for the new entry. | 852 | * Mark the initial part of our freespace in use for the new entry. |
850 | */ | 853 | */ |
851 | xfs_dir2_data_use_free(tp, dp, dbp, dup, | 854 | xfs_dir2_data_use_free(args, dbp, dup, |
852 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, | 855 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, |
853 | &needlog, &needscan); | 856 | &needlog, &needscan); |
854 | /* | 857 | /* |
@@ -870,8 +873,8 @@ xfs_dir2_leaf_addname( | |||
870 | * Need to log the data block's header. | 873 | * Need to log the data block's header. |
871 | */ | 874 | */ |
872 | if (needlog) | 875 | if (needlog) |
873 | xfs_dir2_data_log_header(tp, dp, dbp); | 876 | xfs_dir2_data_log_header(args, dbp); |
874 | xfs_dir2_data_log_entry(tp, dp, dbp, dep); | 877 | xfs_dir2_data_log_entry(args, dbp, dep); |
875 | /* | 878 | /* |
876 | * If the bests table needs to be changed, do it. | 879 | * If the bests table needs to be changed, do it. |
877 | * Log the change unless we've already done that. | 880 | * Log the change unless we've already done that. |
@@ -879,7 +882,7 @@ xfs_dir2_leaf_addname( | |||
879 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { | 882 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { |
880 | bestsp[use_block] = bf[0].length; | 883 | bestsp[use_block] = bf[0].length; |
881 | if (!grown) | 884 | if (!grown) |
882 | xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); | 885 | xfs_dir3_leaf_log_bests(args, lbp, use_block, use_block); |
883 | } | 886 | } |
884 | 887 | ||
885 | lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, | 888 | lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, |
@@ -889,14 +892,15 @@ xfs_dir2_leaf_addname( | |||
889 | * Fill in the new leaf entry. | 892 | * Fill in the new leaf entry. |
890 | */ | 893 | */ |
891 | lep->hashval = cpu_to_be32(args->hashval); | 894 | lep->hashval = cpu_to_be32(args->hashval); |
892 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, use_block, | 895 | lep->address = cpu_to_be32( |
896 | xfs_dir2_db_off_to_dataptr(args->geo, use_block, | ||
893 | be16_to_cpu(*tagp))); | 897 | be16_to_cpu(*tagp))); |
894 | /* | 898 | /* |
895 | * Log the leaf fields and give up the buffers. | 899 | * Log the leaf fields and give up the buffers. |
896 | */ | 900 | */ |
897 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); | 901 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
898 | xfs_dir3_leaf_log_header(tp, dp, lbp); | 902 | xfs_dir3_leaf_log_header(args, lbp); |
899 | xfs_dir3_leaf_log_ents(tp, dp, lbp, lfloglow, lfloghigh); | 903 | xfs_dir3_leaf_log_ents(args, lbp, lfloglow, lfloghigh); |
900 | xfs_dir3_leaf_check(dp, lbp); | 904 | xfs_dir3_leaf_check(dp, lbp); |
901 | xfs_dir3_data_check(dp, dbp); | 905 | xfs_dir3_data_check(dp, dbp); |
902 | return 0; | 906 | return 0; |
@@ -948,9 +952,9 @@ xfs_dir3_leaf_compact( | |||
948 | leafhdr->stale = 0; | 952 | leafhdr->stale = 0; |
949 | 953 | ||
950 | dp->d_ops->leaf_hdr_to_disk(leaf, leafhdr); | 954 | dp->d_ops->leaf_hdr_to_disk(leaf, leafhdr); |
951 | xfs_dir3_leaf_log_header(args->trans, dp, bp); | 955 | xfs_dir3_leaf_log_header(args, bp); |
952 | if (loglow != -1) | 956 | if (loglow != -1) |
953 | xfs_dir3_leaf_log_ents(args->trans, dp, bp, loglow, to - 1); | 957 | xfs_dir3_leaf_log_ents(args, bp, loglow, to - 1); |
954 | } | 958 | } |
955 | 959 | ||
956 | /* | 960 | /* |
@@ -1052,7 +1056,7 @@ xfs_dir3_leaf_compact_x1( | |||
1052 | */ | 1056 | */ |
1053 | static void | 1057 | static void |
1054 | xfs_dir3_leaf_log_bests( | 1058 | xfs_dir3_leaf_log_bests( |
1055 | xfs_trans_t *tp, /* transaction pointer */ | 1059 | struct xfs_da_args *args, |
1056 | struct xfs_buf *bp, /* leaf buffer */ | 1060 | struct xfs_buf *bp, /* leaf buffer */ |
1057 | int first, /* first entry to log */ | 1061 | int first, /* first entry to log */ |
1058 | int last) /* last entry to log */ | 1062 | int last) /* last entry to log */ |
@@ -1065,10 +1069,11 @@ xfs_dir3_leaf_log_bests( | |||
1065 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | 1069 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1066 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC)); | 1070 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC)); |
1067 | 1071 | ||
1068 | ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf); | 1072 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
1069 | firstb = xfs_dir2_leaf_bests_p(ltp) + first; | 1073 | firstb = xfs_dir2_leaf_bests_p(ltp) + first; |
1070 | lastb = xfs_dir2_leaf_bests_p(ltp) + last; | 1074 | lastb = xfs_dir2_leaf_bests_p(ltp) + last; |
1071 | xfs_trans_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf), | 1075 | xfs_trans_log_buf(args->trans, bp, |
1076 | (uint)((char *)firstb - (char *)leaf), | ||
1072 | (uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1)); | 1077 | (uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1)); |
1073 | } | 1078 | } |
1074 | 1079 | ||
@@ -1077,8 +1082,7 @@ xfs_dir3_leaf_log_bests( | |||
1077 | */ | 1082 | */ |
1078 | void | 1083 | void |
1079 | xfs_dir3_leaf_log_ents( | 1084 | xfs_dir3_leaf_log_ents( |
1080 | struct xfs_trans *tp, | 1085 | struct xfs_da_args *args, |
1081 | struct xfs_inode *dp, | ||
1082 | struct xfs_buf *bp, | 1086 | struct xfs_buf *bp, |
1083 | int first, | 1087 | int first, |
1084 | int last) | 1088 | int last) |
@@ -1093,10 +1097,11 @@ xfs_dir3_leaf_log_ents( | |||
1093 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | 1097 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
1094 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); | 1098 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); |
1095 | 1099 | ||
1096 | ents = dp->d_ops->leaf_ents_p(leaf); | 1100 | ents = args->dp->d_ops->leaf_ents_p(leaf); |
1097 | firstlep = &ents[first]; | 1101 | firstlep = &ents[first]; |
1098 | lastlep = &ents[last]; | 1102 | lastlep = &ents[last]; |
1099 | xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), | 1103 | xfs_trans_log_buf(args->trans, bp, |
1104 | (uint)((char *)firstlep - (char *)leaf), | ||
1100 | (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); | 1105 | (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); |
1101 | } | 1106 | } |
1102 | 1107 | ||
@@ -1105,8 +1110,7 @@ xfs_dir3_leaf_log_ents( | |||
1105 | */ | 1110 | */ |
1106 | void | 1111 | void |
1107 | xfs_dir3_leaf_log_header( | 1112 | xfs_dir3_leaf_log_header( |
1108 | struct xfs_trans *tp, | 1113 | struct xfs_da_args *args, |
1109 | struct xfs_inode *dp, | ||
1110 | struct xfs_buf *bp) | 1114 | struct xfs_buf *bp) |
1111 | { | 1115 | { |
1112 | struct xfs_dir2_leaf *leaf = bp->b_addr; | 1116 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
@@ -1116,8 +1120,9 @@ xfs_dir3_leaf_log_header( | |||
1116 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | 1120 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
1117 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); | 1121 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); |
1118 | 1122 | ||
1119 | xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), | 1123 | xfs_trans_log_buf(args->trans, bp, |
1120 | dp->d_ops->leaf_hdr_size - 1); | 1124 | (uint)((char *)&leaf->hdr - (char *)leaf), |
1125 | args->dp->d_ops->leaf_hdr_size - 1); | ||
1121 | } | 1126 | } |
1122 | 1127 | ||
1123 | /* | 1128 | /* |
@@ -1125,21 +1130,20 @@ xfs_dir3_leaf_log_header( | |||
1125 | */ | 1130 | */ |
1126 | STATIC void | 1131 | STATIC void |
1127 | xfs_dir3_leaf_log_tail( | 1132 | xfs_dir3_leaf_log_tail( |
1128 | struct xfs_trans *tp, | 1133 | struct xfs_da_args *args, |
1129 | struct xfs_buf *bp) | 1134 | struct xfs_buf *bp) |
1130 | { | 1135 | { |
1131 | struct xfs_dir2_leaf *leaf = bp->b_addr; | 1136 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1132 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ | 1137 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ |
1133 | struct xfs_mount *mp = tp->t_mountp; | ||
1134 | 1138 | ||
1135 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | 1139 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1136 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || | 1140 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || |
1137 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | 1141 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
1138 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); | 1142 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); |
1139 | 1143 | ||
1140 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1144 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
1141 | xfs_trans_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), | 1145 | xfs_trans_log_buf(args->trans, bp, (uint)((char *)ltp - (char *)leaf), |
1142 | (uint)(mp->m_dirblksize - 1)); | 1146 | (uint)(args->geo->blksize - 1)); |
1143 | } | 1147 | } |
1144 | 1148 | ||
1145 | /* | 1149 | /* |
@@ -1185,7 +1189,7 @@ xfs_dir2_leaf_lookup( | |||
1185 | */ | 1189 | */ |
1186 | dep = (xfs_dir2_data_entry_t *) | 1190 | dep = (xfs_dir2_data_entry_t *) |
1187 | ((char *)dbp->b_addr + | 1191 | ((char *)dbp->b_addr + |
1188 | xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address))); | 1192 | xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); |
1189 | /* | 1193 | /* |
1190 | * Return the found inode number & CI name if appropriate | 1194 | * Return the found inode number & CI name if appropriate |
1191 | */ | 1195 | */ |
@@ -1231,7 +1235,7 @@ xfs_dir2_leaf_lookup_int( | |||
1231 | tp = args->trans; | 1235 | tp = args->trans; |
1232 | mp = dp->i_mount; | 1236 | mp = dp->i_mount; |
1233 | 1237 | ||
1234 | error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); | 1238 | error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, -1, &lbp); |
1235 | if (error) | 1239 | if (error) |
1236 | return error; | 1240 | return error; |
1237 | 1241 | ||
@@ -1260,7 +1264,8 @@ xfs_dir2_leaf_lookup_int( | |||
1260 | /* | 1264 | /* |
1261 | * Get the new data block number. | 1265 | * Get the new data block number. |
1262 | */ | 1266 | */ |
1263 | newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 1267 | newdb = xfs_dir2_dataptr_to_db(args->geo, |
1268 | be32_to_cpu(lep->address)); | ||
1264 | /* | 1269 | /* |
1265 | * If it's not the same as the old data block number, | 1270 | * If it's not the same as the old data block number, |
1266 | * need to pitch the old one and read the new one. | 1271 | * need to pitch the old one and read the new one. |
@@ -1269,8 +1274,8 @@ xfs_dir2_leaf_lookup_int( | |||
1269 | if (dbp) | 1274 | if (dbp) |
1270 | xfs_trans_brelse(tp, dbp); | 1275 | xfs_trans_brelse(tp, dbp); |
1271 | error = xfs_dir3_data_read(tp, dp, | 1276 | error = xfs_dir3_data_read(tp, dp, |
1272 | xfs_dir2_db_to_da(mp, newdb), | 1277 | xfs_dir2_db_to_da(args->geo, newdb), |
1273 | -1, &dbp); | 1278 | -1, &dbp); |
1274 | if (error) { | 1279 | if (error) { |
1275 | xfs_trans_brelse(tp, lbp); | 1280 | xfs_trans_brelse(tp, lbp); |
1276 | return error; | 1281 | return error; |
@@ -1281,7 +1286,8 @@ xfs_dir2_leaf_lookup_int( | |||
1281 | * Point to the data entry. | 1286 | * Point to the data entry. |
1282 | */ | 1287 | */ |
1283 | dep = (xfs_dir2_data_entry_t *)((char *)dbp->b_addr + | 1288 | dep = (xfs_dir2_data_entry_t *)((char *)dbp->b_addr + |
1284 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | 1289 | xfs_dir2_dataptr_to_off(args->geo, |
1290 | be32_to_cpu(lep->address))); | ||
1285 | /* | 1291 | /* |
1286 | * Compare name and if it's an exact match, return the index | 1292 | * Compare name and if it's an exact match, return the index |
1287 | * and buffer. If it's the first case-insensitive match, store | 1293 | * and buffer. If it's the first case-insensitive match, store |
@@ -1310,8 +1316,8 @@ xfs_dir2_leaf_lookup_int( | |||
1310 | if (cidb != curdb) { | 1316 | if (cidb != curdb) { |
1311 | xfs_trans_brelse(tp, dbp); | 1317 | xfs_trans_brelse(tp, dbp); |
1312 | error = xfs_dir3_data_read(tp, dp, | 1318 | error = xfs_dir3_data_read(tp, dp, |
1313 | xfs_dir2_db_to_da(mp, cidb), | 1319 | xfs_dir2_db_to_da(args->geo, cidb), |
1314 | -1, &dbp); | 1320 | -1, &dbp); |
1315 | if (error) { | 1321 | if (error) { |
1316 | xfs_trans_brelse(tp, lbp); | 1322 | xfs_trans_brelse(tp, lbp); |
1317 | return error; | 1323 | return error; |
@@ -1380,18 +1386,18 @@ xfs_dir2_leaf_removename( | |||
1380 | * Point to the leaf entry, use that to point to the data entry. | 1386 | * Point to the leaf entry, use that to point to the data entry. |
1381 | */ | 1387 | */ |
1382 | lep = &ents[index]; | 1388 | lep = &ents[index]; |
1383 | db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 1389 | db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); |
1384 | dep = (xfs_dir2_data_entry_t *) | 1390 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
1385 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | 1391 | xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); |
1386 | needscan = needlog = 0; | 1392 | needscan = needlog = 0; |
1387 | oldbest = be16_to_cpu(bf[0].length); | 1393 | oldbest = be16_to_cpu(bf[0].length); |
1388 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1394 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
1389 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 1395 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
1390 | ASSERT(be16_to_cpu(bestsp[db]) == oldbest); | 1396 | ASSERT(be16_to_cpu(bestsp[db]) == oldbest); |
1391 | /* | 1397 | /* |
1392 | * Mark the former data entry unused. | 1398 | * Mark the former data entry unused. |
1393 | */ | 1399 | */ |
1394 | xfs_dir2_data_make_free(tp, dp, dbp, | 1400 | xfs_dir2_data_make_free(args, dbp, |
1395 | (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), | 1401 | (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), |
1396 | dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); | 1402 | dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); |
1397 | /* | 1403 | /* |
@@ -1399,10 +1405,10 @@ xfs_dir2_leaf_removename( | |||
1399 | */ | 1405 | */ |
1400 | leafhdr.stale++; | 1406 | leafhdr.stale++; |
1401 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); | 1407 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
1402 | xfs_dir3_leaf_log_header(tp, dp, lbp); | 1408 | xfs_dir3_leaf_log_header(args, lbp); |
1403 | 1409 | ||
1404 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); | 1410 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
1405 | xfs_dir3_leaf_log_ents(tp, dp, lbp, index, index); | 1411 | xfs_dir3_leaf_log_ents(args, lbp, index, index); |
1406 | 1412 | ||
1407 | /* | 1413 | /* |
1408 | * Scan the freespace in the data block again if necessary, | 1414 | * Scan the freespace in the data block again if necessary, |
@@ -1411,22 +1417,22 @@ xfs_dir2_leaf_removename( | |||
1411 | if (needscan) | 1417 | if (needscan) |
1412 | xfs_dir2_data_freescan(dp, hdr, &needlog); | 1418 | xfs_dir2_data_freescan(dp, hdr, &needlog); |
1413 | if (needlog) | 1419 | if (needlog) |
1414 | xfs_dir2_data_log_header(tp, dp, dbp); | 1420 | xfs_dir2_data_log_header(args, dbp); |
1415 | /* | 1421 | /* |
1416 | * If the longest freespace in the data block has changed, | 1422 | * If the longest freespace in the data block has changed, |
1417 | * put the new value in the bests table and log that. | 1423 | * put the new value in the bests table and log that. |
1418 | */ | 1424 | */ |
1419 | if (be16_to_cpu(bf[0].length) != oldbest) { | 1425 | if (be16_to_cpu(bf[0].length) != oldbest) { |
1420 | bestsp[db] = bf[0].length; | 1426 | bestsp[db] = bf[0].length; |
1421 | xfs_dir3_leaf_log_bests(tp, lbp, db, db); | 1427 | xfs_dir3_leaf_log_bests(args, lbp, db, db); |
1422 | } | 1428 | } |
1423 | xfs_dir3_data_check(dp, dbp); | 1429 | xfs_dir3_data_check(dp, dbp); |
1424 | /* | 1430 | /* |
1425 | * If the data block is now empty then get rid of the data block. | 1431 | * If the data block is now empty then get rid of the data block. |
1426 | */ | 1432 | */ |
1427 | if (be16_to_cpu(bf[0].length) == | 1433 | if (be16_to_cpu(bf[0].length) == |
1428 | mp->m_dirblksize - dp->d_ops->data_entry_offset) { | 1434 | args->geo->blksize - dp->d_ops->data_entry_offset) { |
1429 | ASSERT(db != mp->m_dirdatablk); | 1435 | ASSERT(db != args->geo->datablk); |
1430 | if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { | 1436 | if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { |
1431 | /* | 1437 | /* |
1432 | * Nope, can't get rid of it because it caused | 1438 | * Nope, can't get rid of it because it caused |
@@ -1459,15 +1465,16 @@ xfs_dir2_leaf_removename( | |||
1459 | memmove(&bestsp[db - i], bestsp, | 1465 | memmove(&bestsp[db - i], bestsp, |
1460 | (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); | 1466 | (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); |
1461 | be32_add_cpu(<p->bestcount, -(db - i)); | 1467 | be32_add_cpu(<p->bestcount, -(db - i)); |
1462 | xfs_dir3_leaf_log_tail(tp, lbp); | 1468 | xfs_dir3_leaf_log_tail(args, lbp); |
1463 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 1469 | xfs_dir3_leaf_log_bests(args, lbp, 0, |
1470 | be32_to_cpu(ltp->bestcount) - 1); | ||
1464 | } else | 1471 | } else |
1465 | bestsp[db] = cpu_to_be16(NULLDATAOFF); | 1472 | bestsp[db] = cpu_to_be16(NULLDATAOFF); |
1466 | } | 1473 | } |
1467 | /* | 1474 | /* |
1468 | * If the data block was not the first one, drop it. | 1475 | * If the data block was not the first one, drop it. |
1469 | */ | 1476 | */ |
1470 | else if (db != mp->m_dirdatablk) | 1477 | else if (db != args->geo->datablk) |
1471 | dbp = NULL; | 1478 | dbp = NULL; |
1472 | 1479 | ||
1473 | xfs_dir3_leaf_check(dp, lbp); | 1480 | xfs_dir3_leaf_check(dp, lbp); |
@@ -1515,7 +1522,7 @@ xfs_dir2_leaf_replace( | |||
1515 | */ | 1522 | */ |
1516 | dep = (xfs_dir2_data_entry_t *) | 1523 | dep = (xfs_dir2_data_entry_t *) |
1517 | ((char *)dbp->b_addr + | 1524 | ((char *)dbp->b_addr + |
1518 | xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address))); | 1525 | xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address))); |
1519 | ASSERT(args->inumber != be64_to_cpu(dep->inumber)); | 1526 | ASSERT(args->inumber != be64_to_cpu(dep->inumber)); |
1520 | /* | 1527 | /* |
1521 | * Put the new inode number in, log it. | 1528 | * Put the new inode number in, log it. |
@@ -1523,7 +1530,7 @@ xfs_dir2_leaf_replace( | |||
1523 | dep->inumber = cpu_to_be64(args->inumber); | 1530 | dep->inumber = cpu_to_be64(args->inumber); |
1524 | dp->d_ops->data_put_ftype(dep, args->filetype); | 1531 | dp->d_ops->data_put_ftype(dep, args->filetype); |
1525 | tp = args->trans; | 1532 | tp = args->trans; |
1526 | xfs_dir2_data_log_entry(tp, dp, dbp, dep); | 1533 | xfs_dir2_data_log_entry(args, dbp, dep); |
1527 | xfs_dir3_leaf_check(dp, lbp); | 1534 | xfs_dir3_leaf_check(dp, lbp); |
1528 | xfs_trans_brelse(tp, lbp); | 1535 | xfs_trans_brelse(tp, lbp); |
1529 | return 0; | 1536 | return 0; |
@@ -1609,12 +1616,13 @@ xfs_dir2_leaf_trim_data( | |||
1609 | /* | 1616 | /* |
1610 | * Read the offending data block. We need its buffer. | 1617 | * Read the offending data block. We need its buffer. |
1611 | */ | 1618 | */ |
1612 | error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp); | 1619 | error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, db), |
1620 | -1, &dbp); | ||
1613 | if (error) | 1621 | if (error) |
1614 | return error; | 1622 | return error; |
1615 | 1623 | ||
1616 | leaf = lbp->b_addr; | 1624 | leaf = lbp->b_addr; |
1617 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1625 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
1618 | 1626 | ||
1619 | #ifdef DEBUG | 1627 | #ifdef DEBUG |
1620 | { | 1628 | { |
@@ -1624,7 +1632,7 @@ xfs_dir2_leaf_trim_data( | |||
1624 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 1632 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
1625 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); | 1633 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); |
1626 | ASSERT(be16_to_cpu(bf[0].length) == | 1634 | ASSERT(be16_to_cpu(bf[0].length) == |
1627 | mp->m_dirblksize - dp->d_ops->data_entry_offset); | 1635 | args->geo->blksize - dp->d_ops->data_entry_offset); |
1628 | ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); | 1636 | ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); |
1629 | } | 1637 | } |
1630 | #endif | 1638 | #endif |
@@ -1643,8 +1651,8 @@ xfs_dir2_leaf_trim_data( | |||
1643 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 1651 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
1644 | be32_add_cpu(<p->bestcount, -1); | 1652 | be32_add_cpu(<p->bestcount, -1); |
1645 | memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); | 1653 | memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); |
1646 | xfs_dir3_leaf_log_tail(tp, lbp); | 1654 | xfs_dir3_leaf_log_tail(args, lbp); |
1647 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 1655 | xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
1648 | return 0; | 1656 | return 0; |
1649 | } | 1657 | } |
1650 | 1658 | ||
@@ -1708,22 +1716,22 @@ xfs_dir2_node_to_leaf( | |||
1708 | /* | 1716 | /* |
1709 | * Get the last offset in the file. | 1717 | * Get the last offset in the file. |
1710 | */ | 1718 | */ |
1711 | if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK))) { | 1719 | if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK))) { |
1712 | return error; | 1720 | return error; |
1713 | } | 1721 | } |
1714 | fo -= mp->m_dirblkfsbs; | 1722 | fo -= args->geo->fsbcount; |
1715 | /* | 1723 | /* |
1716 | * If there are freespace blocks other than the first one, | 1724 | * If there are freespace blocks other than the first one, |
1717 | * take this opportunity to remove trailing empty freespace blocks | 1725 | * take this opportunity to remove trailing empty freespace blocks |
1718 | * that may have been left behind during no-space-reservation | 1726 | * that may have been left behind during no-space-reservation |
1719 | * operations. | 1727 | * operations. |
1720 | */ | 1728 | */ |
1721 | while (fo > mp->m_dirfreeblk) { | 1729 | while (fo > args->geo->freeblk) { |
1722 | if ((error = xfs_dir2_node_trim_free(args, fo, &rval))) { | 1730 | if ((error = xfs_dir2_node_trim_free(args, fo, &rval))) { |
1723 | return error; | 1731 | return error; |
1724 | } | 1732 | } |
1725 | if (rval) | 1733 | if (rval) |
1726 | fo -= mp->m_dirblkfsbs; | 1734 | fo -= args->geo->fsbcount; |
1727 | else | 1735 | else |
1728 | return 0; | 1736 | return 0; |
1729 | } | 1737 | } |
@@ -1736,7 +1744,7 @@ xfs_dir2_node_to_leaf( | |||
1736 | /* | 1744 | /* |
1737 | * If it's not the single leaf block, give up. | 1745 | * If it's not the single leaf block, give up. |
1738 | */ | 1746 | */ |
1739 | if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + mp->m_dirblksize) | 1747 | if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + args->geo->blksize) |
1740 | return 0; | 1748 | return 0; |
1741 | lbp = state->path.blk[0].bp; | 1749 | lbp = state->path.blk[0].bp; |
1742 | leaf = lbp->b_addr; | 1750 | leaf = lbp->b_addr; |
@@ -1748,7 +1756,7 @@ xfs_dir2_node_to_leaf( | |||
1748 | /* | 1756 | /* |
1749 | * Read the freespace block. | 1757 | * Read the freespace block. |
1750 | */ | 1758 | */ |
1751 | error = xfs_dir2_free_read(tp, dp, mp->m_dirfreeblk, &fbp); | 1759 | error = xfs_dir2_free_read(tp, dp, args->geo->freeblk, &fbp); |
1752 | if (error) | 1760 | if (error) |
1753 | return error; | 1761 | return error; |
1754 | free = fbp->b_addr; | 1762 | free = fbp->b_addr; |
@@ -1760,7 +1768,7 @@ xfs_dir2_node_to_leaf( | |||
1760 | * Now see if the leafn and free data will fit in a leaf1. | 1768 | * Now see if the leafn and free data will fit in a leaf1. |
1761 | * If not, release the buffer and give up. | 1769 | * If not, release the buffer and give up. |
1762 | */ | 1770 | */ |
1763 | if (xfs_dir3_leaf_size(&leafhdr, freehdr.nvalid) > mp->m_dirblksize) { | 1771 | if (xfs_dir3_leaf_size(&leafhdr, freehdr.nvalid) > args->geo->blksize) { |
1764 | xfs_trans_brelse(tp, fbp); | 1772 | xfs_trans_brelse(tp, fbp); |
1765 | return 0; | 1773 | return 0; |
1766 | } | 1774 | } |
@@ -1780,7 +1788,7 @@ xfs_dir2_node_to_leaf( | |||
1780 | /* | 1788 | /* |
1781 | * Set up the leaf tail from the freespace block. | 1789 | * Set up the leaf tail from the freespace block. |
1782 | */ | 1790 | */ |
1783 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1791 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
1784 | ltp->bestcount = cpu_to_be32(freehdr.nvalid); | 1792 | ltp->bestcount = cpu_to_be32(freehdr.nvalid); |
1785 | 1793 | ||
1786 | /* | 1794 | /* |
@@ -1790,15 +1798,17 @@ xfs_dir2_node_to_leaf( | |||
1790 | freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); | 1798 | freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); |
1791 | 1799 | ||
1792 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); | 1800 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
1793 | xfs_dir3_leaf_log_header(tp, dp, lbp); | 1801 | xfs_dir3_leaf_log_header(args, lbp); |
1794 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 1802 | xfs_dir3_leaf_log_bests(args, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
1795 | xfs_dir3_leaf_log_tail(tp, lbp); | 1803 | xfs_dir3_leaf_log_tail(args, lbp); |
1796 | xfs_dir3_leaf_check(dp, lbp); | 1804 | xfs_dir3_leaf_check(dp, lbp); |
1797 | 1805 | ||
1798 | /* | 1806 | /* |
1799 | * Get rid of the freespace block. | 1807 | * Get rid of the freespace block. |
1800 | */ | 1808 | */ |
1801 | error = xfs_dir2_shrink_inode(args, XFS_DIR2_FREE_FIRSTDB(mp), fbp); | 1809 | error = xfs_dir2_shrink_inode(args, |
1810 | xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET), | ||
1811 | fbp); | ||
1802 | if (error) { | 1812 | if (error) { |
1803 | /* | 1813 | /* |
1804 | * This can't fail here because it can only happen when | 1814 | * This can't fail here because it can only happen when |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index cb434d732681..da43d304fca2 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -195,17 +195,18 @@ xfs_dir2_free_try_read( | |||
195 | 195 | ||
196 | static int | 196 | static int |
197 | xfs_dir3_free_get_buf( | 197 | xfs_dir3_free_get_buf( |
198 | struct xfs_trans *tp, | 198 | xfs_da_args_t *args, |
199 | struct xfs_inode *dp, | ||
200 | xfs_dir2_db_t fbno, | 199 | xfs_dir2_db_t fbno, |
201 | struct xfs_buf **bpp) | 200 | struct xfs_buf **bpp) |
202 | { | 201 | { |
202 | struct xfs_trans *tp = args->trans; | ||
203 | struct xfs_inode *dp = args->dp; | ||
203 | struct xfs_mount *mp = dp->i_mount; | 204 | struct xfs_mount *mp = dp->i_mount; |
204 | struct xfs_buf *bp; | 205 | struct xfs_buf *bp; |
205 | int error; | 206 | int error; |
206 | struct xfs_dir3_icfree_hdr hdr; | 207 | struct xfs_dir3_icfree_hdr hdr; |
207 | 208 | ||
208 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fbno), | 209 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, fbno), |
209 | -1, &bp, XFS_DATA_FORK); | 210 | -1, &bp, XFS_DATA_FORK); |
210 | if (error) | 211 | if (error) |
211 | return error; | 212 | return error; |
@@ -240,8 +241,7 @@ xfs_dir3_free_get_buf( | |||
240 | */ | 241 | */ |
241 | STATIC void | 242 | STATIC void |
242 | xfs_dir2_free_log_bests( | 243 | xfs_dir2_free_log_bests( |
243 | struct xfs_trans *tp, | 244 | struct xfs_da_args *args, |
244 | struct xfs_inode *dp, | ||
245 | struct xfs_buf *bp, | 245 | struct xfs_buf *bp, |
246 | int first, /* first entry to log */ | 246 | int first, /* first entry to log */ |
247 | int last) /* last entry to log */ | 247 | int last) /* last entry to log */ |
@@ -250,10 +250,10 @@ xfs_dir2_free_log_bests( | |||
250 | __be16 *bests; | 250 | __be16 *bests; |
251 | 251 | ||
252 | free = bp->b_addr; | 252 | free = bp->b_addr; |
253 | bests = dp->d_ops->free_bests_p(free); | 253 | bests = args->dp->d_ops->free_bests_p(free); |
254 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || | 254 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || |
255 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); | 255 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); |
256 | xfs_trans_log_buf(tp, bp, | 256 | xfs_trans_log_buf(args->trans, bp, |
257 | (uint)((char *)&bests[first] - (char *)free), | 257 | (uint)((char *)&bests[first] - (char *)free), |
258 | (uint)((char *)&bests[last] - (char *)free + | 258 | (uint)((char *)&bests[last] - (char *)free + |
259 | sizeof(bests[0]) - 1)); | 259 | sizeof(bests[0]) - 1)); |
@@ -264,8 +264,7 @@ xfs_dir2_free_log_bests( | |||
264 | */ | 264 | */ |
265 | static void | 265 | static void |
266 | xfs_dir2_free_log_header( | 266 | xfs_dir2_free_log_header( |
267 | struct xfs_trans *tp, | 267 | struct xfs_da_args *args, |
268 | struct xfs_inode *dp, | ||
269 | struct xfs_buf *bp) | 268 | struct xfs_buf *bp) |
270 | { | 269 | { |
271 | #ifdef DEBUG | 270 | #ifdef DEBUG |
@@ -275,7 +274,8 @@ xfs_dir2_free_log_header( | |||
275 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || | 274 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || |
276 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); | 275 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); |
277 | #endif | 276 | #endif |
278 | xfs_trans_log_buf(tp, bp, 0, dp->d_ops->free_hdr_size - 1); | 277 | xfs_trans_log_buf(args->trans, bp, 0, |
278 | args->dp->d_ops->free_hdr_size - 1); | ||
279 | } | 279 | } |
280 | 280 | ||
281 | /* | 281 | /* |
@@ -315,20 +315,20 @@ xfs_dir2_leaf_to_node( | |||
315 | if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) { | 315 | if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) { |
316 | return error; | 316 | return error; |
317 | } | 317 | } |
318 | ASSERT(fdb == XFS_DIR2_FREE_FIRSTDB(mp)); | 318 | ASSERT(fdb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)); |
319 | /* | 319 | /* |
320 | * Get the buffer for the new freespace block. | 320 | * Get the buffer for the new freespace block. |
321 | */ | 321 | */ |
322 | error = xfs_dir3_free_get_buf(tp, dp, fdb, &fbp); | 322 | error = xfs_dir3_free_get_buf(args, fdb, &fbp); |
323 | if (error) | 323 | if (error) |
324 | return error; | 324 | return error; |
325 | 325 | ||
326 | free = fbp->b_addr; | 326 | free = fbp->b_addr; |
327 | dp->d_ops->free_hdr_from_disk(&freehdr, free); | 327 | dp->d_ops->free_hdr_from_disk(&freehdr, free); |
328 | leaf = lbp->b_addr; | 328 | leaf = lbp->b_addr; |
329 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 329 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
330 | ASSERT(be32_to_cpu(ltp->bestcount) <= | 330 | ASSERT(be32_to_cpu(ltp->bestcount) <= |
331 | (uint)dp->i_d.di_size / mp->m_dirblksize); | 331 | (uint)dp->i_d.di_size / args->geo->blksize); |
332 | 332 | ||
333 | /* | 333 | /* |
334 | * Copy freespace entries from the leaf block to the new block. | 334 | * Copy freespace entries from the leaf block to the new block. |
@@ -349,8 +349,8 @@ xfs_dir2_leaf_to_node( | |||
349 | freehdr.nvalid = be32_to_cpu(ltp->bestcount); | 349 | freehdr.nvalid = be32_to_cpu(ltp->bestcount); |
350 | 350 | ||
351 | dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); | 351 | dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); |
352 | xfs_dir2_free_log_bests(tp, dp, fbp, 0, freehdr.nvalid - 1); | 352 | xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1); |
353 | xfs_dir2_free_log_header(tp, dp, fbp); | 353 | xfs_dir2_free_log_header(args, fbp); |
354 | 354 | ||
355 | /* | 355 | /* |
356 | * Converting the leaf to a leafnode is just a matter of changing the | 356 | * Converting the leaf to a leafnode is just a matter of changing the |
@@ -364,7 +364,7 @@ xfs_dir2_leaf_to_node( | |||
364 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); | 364 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); |
365 | lbp->b_ops = &xfs_dir3_leafn_buf_ops; | 365 | lbp->b_ops = &xfs_dir3_leafn_buf_ops; |
366 | xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF); | 366 | xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF); |
367 | xfs_dir3_leaf_log_header(tp, dp, lbp); | 367 | xfs_dir3_leaf_log_header(args, lbp); |
368 | xfs_dir3_leaf_check(dp, lbp); | 368 | xfs_dir3_leaf_check(dp, lbp); |
369 | return 0; | 369 | return 0; |
370 | } | 370 | } |
@@ -415,7 +415,7 @@ xfs_dir2_leafn_add( | |||
415 | * a compact. | 415 | * a compact. |
416 | */ | 416 | */ |
417 | 417 | ||
418 | if (leafhdr.count == dp->d_ops->leaf_max_ents(mp)) { | 418 | if (leafhdr.count == dp->d_ops->leaf_max_ents(args->geo)) { |
419 | if (!leafhdr.stale) | 419 | if (!leafhdr.stale) |
420 | return XFS_ERROR(ENOSPC); | 420 | return XFS_ERROR(ENOSPC); |
421 | compact = leafhdr.stale > 1; | 421 | compact = leafhdr.stale > 1; |
@@ -450,12 +450,12 @@ xfs_dir2_leafn_add( | |||
450 | highstale, &lfloglow, &lfloghigh); | 450 | highstale, &lfloglow, &lfloghigh); |
451 | 451 | ||
452 | lep->hashval = cpu_to_be32(args->hashval); | 452 | lep->hashval = cpu_to_be32(args->hashval); |
453 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, | 453 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(args->geo, |
454 | args->blkno, args->index)); | 454 | args->blkno, args->index)); |
455 | 455 | ||
456 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); | 456 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
457 | xfs_dir3_leaf_log_header(tp, dp, bp); | 457 | xfs_dir3_leaf_log_header(args, bp); |
458 | xfs_dir3_leaf_log_ents(tp, dp, bp, lfloglow, lfloghigh); | 458 | xfs_dir3_leaf_log_ents(args, bp, lfloglow, lfloghigh); |
459 | xfs_dir3_leaf_check(dp, bp); | 459 | xfs_dir3_leaf_check(dp, bp); |
460 | return 0; | 460 | return 0; |
461 | } | 461 | } |
@@ -471,7 +471,8 @@ xfs_dir2_free_hdr_check( | |||
471 | 471 | ||
472 | dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr); | 472 | dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr); |
473 | 473 | ||
474 | ASSERT((hdr.firstdb % dp->d_ops->free_max_bests(dp->i_mount)) == 0); | 474 | ASSERT((hdr.firstdb % |
475 | dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0); | ||
475 | ASSERT(hdr.firstdb <= db); | 476 | ASSERT(hdr.firstdb <= db); |
476 | ASSERT(db < hdr.firstdb + hdr.nvalid); | 477 | ASSERT(db < hdr.firstdb + hdr.nvalid); |
477 | } | 478 | } |
@@ -576,7 +577,8 @@ xfs_dir2_leafn_lookup_for_addname( | |||
576 | /* | 577 | /* |
577 | * Pull the data block number from the entry. | 578 | * Pull the data block number from the entry. |
578 | */ | 579 | */ |
579 | newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 580 | newdb = xfs_dir2_dataptr_to_db(args->geo, |
581 | be32_to_cpu(lep->address)); | ||
580 | /* | 582 | /* |
581 | * For addname, we're looking for a place to put the new entry. | 583 | * For addname, we're looking for a place to put the new entry. |
582 | * We want to use a data block with an entry of equal | 584 | * We want to use a data block with an entry of equal |
@@ -593,7 +595,7 @@ xfs_dir2_leafn_lookup_for_addname( | |||
593 | * Convert the data block to the free block | 595 | * Convert the data block to the free block |
594 | * holding its freespace information. | 596 | * holding its freespace information. |
595 | */ | 597 | */ |
596 | newfdb = dp->d_ops->db_to_fdb(mp, newdb); | 598 | newfdb = dp->d_ops->db_to_fdb(args->geo, newdb); |
597 | /* | 599 | /* |
598 | * If it's not the one we have in hand, read it in. | 600 | * If it's not the one we have in hand, read it in. |
599 | */ | 601 | */ |
@@ -605,7 +607,8 @@ xfs_dir2_leafn_lookup_for_addname( | |||
605 | xfs_trans_brelse(tp, curbp); | 607 | xfs_trans_brelse(tp, curbp); |
606 | 608 | ||
607 | error = xfs_dir2_free_read(tp, dp, | 609 | error = xfs_dir2_free_read(tp, dp, |
608 | xfs_dir2_db_to_da(mp, newfdb), | 610 | xfs_dir2_db_to_da(args->geo, |
611 | newfdb), | ||
609 | &curbp); | 612 | &curbp); |
610 | if (error) | 613 | if (error) |
611 | return error; | 614 | return error; |
@@ -616,7 +619,7 @@ xfs_dir2_leafn_lookup_for_addname( | |||
616 | /* | 619 | /* |
617 | * Get the index for our entry. | 620 | * Get the index for our entry. |
618 | */ | 621 | */ |
619 | fi = dp->d_ops->db_to_fdindex(mp, curdb); | 622 | fi = dp->d_ops->db_to_fdindex(args->geo, curdb); |
620 | /* | 623 | /* |
621 | * If it has room, return it. | 624 | * If it has room, return it. |
622 | */ | 625 | */ |
@@ -721,7 +724,8 @@ xfs_dir2_leafn_lookup_for_entry( | |||
721 | /* | 724 | /* |
722 | * Pull the data block number from the entry. | 725 | * Pull the data block number from the entry. |
723 | */ | 726 | */ |
724 | newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 727 | newdb = xfs_dir2_dataptr_to_db(args->geo, |
728 | be32_to_cpu(lep->address)); | ||
725 | /* | 729 | /* |
726 | * Not adding a new entry, so we really want to find | 730 | * Not adding a new entry, so we really want to find |
727 | * the name given to us. | 731 | * the name given to us. |
@@ -746,7 +750,8 @@ xfs_dir2_leafn_lookup_for_entry( | |||
746 | curbp = state->extrablk.bp; | 750 | curbp = state->extrablk.bp; |
747 | } else { | 751 | } else { |
748 | error = xfs_dir3_data_read(tp, dp, | 752 | error = xfs_dir3_data_read(tp, dp, |
749 | xfs_dir2_db_to_da(mp, newdb), | 753 | xfs_dir2_db_to_da(args->geo, |
754 | newdb), | ||
750 | -1, &curbp); | 755 | -1, &curbp); |
751 | if (error) | 756 | if (error) |
752 | return error; | 757 | return error; |
@@ -758,7 +763,8 @@ xfs_dir2_leafn_lookup_for_entry( | |||
758 | * Point to the data entry. | 763 | * Point to the data entry. |
759 | */ | 764 | */ |
760 | dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr + | 765 | dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr + |
761 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | 766 | xfs_dir2_dataptr_to_off(args->geo, |
767 | be32_to_cpu(lep->address))); | ||
762 | /* | 768 | /* |
763 | * Compare the entry and if it's an exact match, return | 769 | * Compare the entry and if it's an exact match, return |
764 | * EEXIST immediately. If it's the first case-insensitive | 770 | * EEXIST immediately. If it's the first case-insensitive |
@@ -844,7 +850,6 @@ xfs_dir3_leafn_moveents( | |||
844 | int start_d,/* destination leaf index */ | 850 | int start_d,/* destination leaf index */ |
845 | int count) /* count of leaves to copy */ | 851 | int count) /* count of leaves to copy */ |
846 | { | 852 | { |
847 | struct xfs_trans *tp = args->trans; | ||
848 | int stale; /* count stale leaves copied */ | 853 | int stale; /* count stale leaves copied */ |
849 | 854 | ||
850 | trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count); | 855 | trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count); |
@@ -863,7 +868,7 @@ xfs_dir3_leafn_moveents( | |||
863 | if (start_d < dhdr->count) { | 868 | if (start_d < dhdr->count) { |
864 | memmove(&dents[start_d + count], &dents[start_d], | 869 | memmove(&dents[start_d + count], &dents[start_d], |
865 | (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); | 870 | (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); |
866 | xfs_dir3_leaf_log_ents(tp, args->dp, bp_d, start_d + count, | 871 | xfs_dir3_leaf_log_ents(args, bp_d, start_d + count, |
867 | count + dhdr->count - 1); | 872 | count + dhdr->count - 1); |
868 | } | 873 | } |
869 | /* | 874 | /* |
@@ -885,8 +890,7 @@ xfs_dir3_leafn_moveents( | |||
885 | */ | 890 | */ |
886 | memcpy(&dents[start_d], &sents[start_s], | 891 | memcpy(&dents[start_d], &sents[start_s], |
887 | count * sizeof(xfs_dir2_leaf_entry_t)); | 892 | count * sizeof(xfs_dir2_leaf_entry_t)); |
888 | xfs_dir3_leaf_log_ents(tp, args->dp, bp_d, | 893 | xfs_dir3_leaf_log_ents(args, bp_d, start_d, start_d + count - 1); |
889 | start_d, start_d + count - 1); | ||
890 | 894 | ||
891 | /* | 895 | /* |
892 | * If there are source entries after the ones we copied, | 896 | * If there are source entries after the ones we copied, |
@@ -895,8 +899,7 @@ xfs_dir3_leafn_moveents( | |||
895 | if (start_s + count < shdr->count) { | 899 | if (start_s + count < shdr->count) { |
896 | memmove(&sents[start_s], &sents[start_s + count], | 900 | memmove(&sents[start_s], &sents[start_s + count], |
897 | count * sizeof(xfs_dir2_leaf_entry_t)); | 901 | count * sizeof(xfs_dir2_leaf_entry_t)); |
898 | xfs_dir3_leaf_log_ents(tp, args->dp, bp_s, | 902 | xfs_dir3_leaf_log_ents(args, bp_s, start_s, start_s + count - 1); |
899 | start_s, start_s + count - 1); | ||
900 | } | 903 | } |
901 | 904 | ||
902 | /* | 905 | /* |
@@ -1032,8 +1035,8 @@ xfs_dir2_leafn_rebalance( | |||
1032 | /* log the changes made when moving the entries */ | 1035 | /* log the changes made when moving the entries */ |
1033 | dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1); | 1036 | dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1); |
1034 | dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2); | 1037 | dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2); |
1035 | xfs_dir3_leaf_log_header(args->trans, dp, blk1->bp); | 1038 | xfs_dir3_leaf_log_header(args, blk1->bp); |
1036 | xfs_dir3_leaf_log_header(args->trans, dp, blk2->bp); | 1039 | xfs_dir3_leaf_log_header(args, blk2->bp); |
1037 | 1040 | ||
1038 | xfs_dir3_leaf_check(dp, blk1->bp); | 1041 | xfs_dir3_leaf_check(dp, blk1->bp); |
1039 | xfs_dir3_leaf_check(dp, blk2->bp); | 1042 | xfs_dir3_leaf_check(dp, blk2->bp); |
@@ -1076,7 +1079,6 @@ xfs_dir3_data_block_free( | |||
1076 | struct xfs_buf *fbp, | 1079 | struct xfs_buf *fbp, |
1077 | int longest) | 1080 | int longest) |
1078 | { | 1081 | { |
1079 | struct xfs_trans *tp = args->trans; | ||
1080 | int logfree = 0; | 1082 | int logfree = 0; |
1081 | __be16 *bests; | 1083 | __be16 *bests; |
1082 | struct xfs_dir3_icfree_hdr freehdr; | 1084 | struct xfs_dir3_icfree_hdr freehdr; |
@@ -1090,7 +1092,7 @@ xfs_dir3_data_block_free( | |||
1090 | * value. | 1092 | * value. |
1091 | */ | 1093 | */ |
1092 | bests[findex] = cpu_to_be16(longest); | 1094 | bests[findex] = cpu_to_be16(longest); |
1093 | xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex); | 1095 | xfs_dir2_free_log_bests(args, fbp, findex, findex); |
1094 | return 0; | 1096 | return 0; |
1095 | } | 1097 | } |
1096 | 1098 | ||
@@ -1118,7 +1120,7 @@ xfs_dir3_data_block_free( | |||
1118 | } | 1120 | } |
1119 | 1121 | ||
1120 | dp->d_ops->free_hdr_to_disk(free, &freehdr); | 1122 | dp->d_ops->free_hdr_to_disk(free, &freehdr); |
1121 | xfs_dir2_free_log_header(tp, dp, fbp); | 1123 | xfs_dir2_free_log_header(args, fbp); |
1122 | 1124 | ||
1123 | /* | 1125 | /* |
1124 | * If there are no useful entries left in the block, get rid of the | 1126 | * If there are no useful entries left in the block, get rid of the |
@@ -1142,7 +1144,7 @@ xfs_dir3_data_block_free( | |||
1142 | 1144 | ||
1143 | /* Log the free entry that changed, unless we got rid of it. */ | 1145 | /* Log the free entry that changed, unless we got rid of it. */ |
1144 | if (logfree) | 1146 | if (logfree) |
1145 | xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex); | 1147 | xfs_dir2_free_log_bests(args, fbp, findex, findex); |
1146 | return 0; | 1148 | return 0; |
1147 | } | 1149 | } |
1148 | 1150 | ||
@@ -1193,9 +1195,9 @@ xfs_dir2_leafn_remove( | |||
1193 | /* | 1195 | /* |
1194 | * Extract the data block and offset from the entry. | 1196 | * Extract the data block and offset from the entry. |
1195 | */ | 1197 | */ |
1196 | db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 1198 | db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); |
1197 | ASSERT(dblk->blkno == db); | 1199 | ASSERT(dblk->blkno == db); |
1198 | off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)); | 1200 | off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)); |
1199 | ASSERT(dblk->index == off); | 1201 | ASSERT(dblk->index == off); |
1200 | 1202 | ||
1201 | /* | 1203 | /* |
@@ -1204,10 +1206,10 @@ xfs_dir2_leafn_remove( | |||
1204 | */ | 1206 | */ |
1205 | leafhdr.stale++; | 1207 | leafhdr.stale++; |
1206 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); | 1208 | dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
1207 | xfs_dir3_leaf_log_header(tp, dp, bp); | 1209 | xfs_dir3_leaf_log_header(args, bp); |
1208 | 1210 | ||
1209 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); | 1211 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
1210 | xfs_dir3_leaf_log_ents(tp, dp, bp, index, index); | 1212 | xfs_dir3_leaf_log_ents(args, bp, index, index); |
1211 | 1213 | ||
1212 | /* | 1214 | /* |
1213 | * Make the data entry free. Keep track of the longest freespace | 1215 | * Make the data entry free. Keep track of the longest freespace |
@@ -1219,7 +1221,7 @@ xfs_dir2_leafn_remove( | |||
1219 | bf = dp->d_ops->data_bestfree_p(hdr); | 1221 | bf = dp->d_ops->data_bestfree_p(hdr); |
1220 | longest = be16_to_cpu(bf[0].length); | 1222 | longest = be16_to_cpu(bf[0].length); |
1221 | needlog = needscan = 0; | 1223 | needlog = needscan = 0; |
1222 | xfs_dir2_data_make_free(tp, dp, dbp, off, | 1224 | xfs_dir2_data_make_free(args, dbp, off, |
1223 | dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); | 1225 | dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); |
1224 | /* | 1226 | /* |
1225 | * Rescan the data block freespaces for bestfree. | 1227 | * Rescan the data block freespaces for bestfree. |
@@ -1228,7 +1230,7 @@ xfs_dir2_leafn_remove( | |||
1228 | if (needscan) | 1230 | if (needscan) |
1229 | xfs_dir2_data_freescan(dp, hdr, &needlog); | 1231 | xfs_dir2_data_freescan(dp, hdr, &needlog); |
1230 | if (needlog) | 1232 | if (needlog) |
1231 | xfs_dir2_data_log_header(tp, dp, dbp); | 1233 | xfs_dir2_data_log_header(args, dbp); |
1232 | xfs_dir3_data_check(dp, dbp); | 1234 | xfs_dir3_data_check(dp, dbp); |
1233 | /* | 1235 | /* |
1234 | * If the longest data block freespace changes, need to update | 1236 | * If the longest data block freespace changes, need to update |
@@ -1245,8 +1247,9 @@ xfs_dir2_leafn_remove( | |||
1245 | * Convert the data block number to a free block, | 1247 | * Convert the data block number to a free block, |
1246 | * read in the free block. | 1248 | * read in the free block. |
1247 | */ | 1249 | */ |
1248 | fdb = dp->d_ops->db_to_fdb(mp, db); | 1250 | fdb = dp->d_ops->db_to_fdb(args->geo, db); |
1249 | error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb), | 1251 | error = xfs_dir2_free_read(tp, dp, |
1252 | xfs_dir2_db_to_da(args->geo, fdb), | ||
1250 | &fbp); | 1253 | &fbp); |
1251 | if (error) | 1254 | if (error) |
1252 | return error; | 1255 | return error; |
@@ -1255,20 +1258,21 @@ xfs_dir2_leafn_remove( | |||
1255 | { | 1258 | { |
1256 | struct xfs_dir3_icfree_hdr freehdr; | 1259 | struct xfs_dir3_icfree_hdr freehdr; |
1257 | dp->d_ops->free_hdr_from_disk(&freehdr, free); | 1260 | dp->d_ops->free_hdr_from_disk(&freehdr, free); |
1258 | ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(mp) * | 1261 | ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) * |
1259 | (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); | 1262 | (fdb - xfs_dir2_byte_to_db(args->geo, |
1263 | XFS_DIR2_FREE_OFFSET))); | ||
1260 | } | 1264 | } |
1261 | #endif | 1265 | #endif |
1262 | /* | 1266 | /* |
1263 | * Calculate which entry we need to fix. | 1267 | * Calculate which entry we need to fix. |
1264 | */ | 1268 | */ |
1265 | findex = dp->d_ops->db_to_fdindex(mp, db); | 1269 | findex = dp->d_ops->db_to_fdindex(args->geo, db); |
1266 | longest = be16_to_cpu(bf[0].length); | 1270 | longest = be16_to_cpu(bf[0].length); |
1267 | /* | 1271 | /* |
1268 | * If the data block is now empty we can get rid of it | 1272 | * If the data block is now empty we can get rid of it |
1269 | * (usually). | 1273 | * (usually). |
1270 | */ | 1274 | */ |
1271 | if (longest == mp->m_dirblksize - | 1275 | if (longest == args->geo->blksize - |
1272 | dp->d_ops->data_entry_offset) { | 1276 | dp->d_ops->data_entry_offset) { |
1273 | /* | 1277 | /* |
1274 | * Try to punch out the data block. | 1278 | * Try to punch out the data block. |
@@ -1303,7 +1307,7 @@ xfs_dir2_leafn_remove( | |||
1303 | */ | 1307 | */ |
1304 | *rval = (dp->d_ops->leaf_hdr_size + | 1308 | *rval = (dp->d_ops->leaf_hdr_size + |
1305 | (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < | 1309 | (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < |
1306 | mp->m_dir_magicpct; | 1310 | args->geo->magicpct; |
1307 | return 0; | 1311 | return 0; |
1308 | } | 1312 | } |
1309 | 1313 | ||
@@ -1336,7 +1340,7 @@ xfs_dir2_leafn_split( | |||
1336 | /* | 1340 | /* |
1337 | * Initialize the new leaf block. | 1341 | * Initialize the new leaf block. |
1338 | */ | 1342 | */ |
1339 | error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(mp, blkno), | 1343 | error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(args->geo, blkno), |
1340 | &newblk->bp, XFS_DIR2_LEAFN_MAGIC); | 1344 | &newblk->bp, XFS_DIR2_LEAFN_MAGIC); |
1341 | if (error) | 1345 | if (error) |
1342 | return error; | 1346 | return error; |
@@ -1410,7 +1414,7 @@ xfs_dir2_leafn_toosmall( | |||
1410 | 1414 | ||
1411 | count = leafhdr.count - leafhdr.stale; | 1415 | count = leafhdr.count - leafhdr.stale; |
1412 | bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]); | 1416 | bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]); |
1413 | if (bytes > (state->blocksize >> 1)) { | 1417 | if (bytes > (state->args->geo->blksize >> 1)) { |
1414 | /* | 1418 | /* |
1415 | * Blk over 50%, don't try to join. | 1419 | * Blk over 50%, don't try to join. |
1416 | */ | 1420 | */ |
@@ -1463,7 +1467,8 @@ xfs_dir2_leafn_toosmall( | |||
1463 | * Count bytes in the two blocks combined. | 1467 | * Count bytes in the two blocks combined. |
1464 | */ | 1468 | */ |
1465 | count = leafhdr.count - leafhdr.stale; | 1469 | count = leafhdr.count - leafhdr.stale; |
1466 | bytes = state->blocksize - (state->blocksize >> 2); | 1470 | bytes = state->args->geo->blksize - |
1471 | (state->args->geo->blksize >> 2); | ||
1467 | 1472 | ||
1468 | leaf = bp->b_addr; | 1473 | leaf = bp->b_addr; |
1469 | dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf); | 1474 | dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf); |
@@ -1560,8 +1565,8 @@ xfs_dir2_leafn_unbalance( | |||
1560 | /* log the changes made when moving the entries */ | 1565 | /* log the changes made when moving the entries */ |
1561 | dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr); | 1566 | dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr); |
1562 | dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr); | 1567 | dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr); |
1563 | xfs_dir3_leaf_log_header(args->trans, dp, save_blk->bp); | 1568 | xfs_dir3_leaf_log_header(args, save_blk->bp); |
1564 | xfs_dir3_leaf_log_header(args->trans, dp, drop_blk->bp); | 1569 | xfs_dir3_leaf_log_header(args, drop_blk->bp); |
1565 | 1570 | ||
1566 | xfs_dir3_leaf_check(dp, save_blk->bp); | 1571 | xfs_dir3_leaf_check(dp, save_blk->bp); |
1567 | xfs_dir3_leaf_check(dp, drop_blk->bp); | 1572 | xfs_dir3_leaf_check(dp, drop_blk->bp); |
@@ -1587,8 +1592,6 @@ xfs_dir2_node_addname( | |||
1587 | state = xfs_da_state_alloc(); | 1592 | state = xfs_da_state_alloc(); |
1588 | state->args = args; | 1593 | state->args = args; |
1589 | state->mp = args->dp->i_mount; | 1594 | state->mp = args->dp->i_mount; |
1590 | state->blocksize = state->mp->m_dirblksize; | ||
1591 | state->node_ents = state->mp->m_dir_node_ents; | ||
1592 | /* | 1595 | /* |
1593 | * Look up the name. We're not supposed to find it, but | 1596 | * Look up the name. We're not supposed to find it, but |
1594 | * this gives us the insertion point. | 1597 | * this gives us the insertion point. |
@@ -1727,9 +1730,9 @@ xfs_dir2_node_addname_int( | |||
1727 | if (dbno == -1) { | 1730 | if (dbno == -1) { |
1728 | xfs_fileoff_t fo; /* freespace block number */ | 1731 | xfs_fileoff_t fo; /* freespace block number */ |
1729 | 1732 | ||
1730 | if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK))) | 1733 | if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK))) |
1731 | return error; | 1734 | return error; |
1732 | lastfbno = xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo); | 1735 | lastfbno = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo); |
1733 | fbno = ifbno; | 1736 | fbno = ifbno; |
1734 | } | 1737 | } |
1735 | /* | 1738 | /* |
@@ -1747,7 +1750,8 @@ xfs_dir2_node_addname_int( | |||
1747 | * us a freespace block to start with. | 1750 | * us a freespace block to start with. |
1748 | */ | 1751 | */ |
1749 | if (++fbno == 0) | 1752 | if (++fbno == 0) |
1750 | fbno = XFS_DIR2_FREE_FIRSTDB(mp); | 1753 | fbno = xfs_dir2_byte_to_db(args->geo, |
1754 | XFS_DIR2_FREE_OFFSET); | ||
1751 | /* | 1755 | /* |
1752 | * If it's ifbno we already looked at it. | 1756 | * If it's ifbno we already looked at it. |
1753 | */ | 1757 | */ |
@@ -1765,8 +1769,8 @@ xfs_dir2_node_addname_int( | |||
1765 | * to avoid it. | 1769 | * to avoid it. |
1766 | */ | 1770 | */ |
1767 | error = xfs_dir2_free_try_read(tp, dp, | 1771 | error = xfs_dir2_free_try_read(tp, dp, |
1768 | xfs_dir2_db_to_da(mp, fbno), | 1772 | xfs_dir2_db_to_da(args->geo, fbno), |
1769 | &fbp); | 1773 | &fbp); |
1770 | if (error) | 1774 | if (error) |
1771 | return error; | 1775 | return error; |
1772 | if (!fbp) | 1776 | if (!fbp) |
@@ -1834,10 +1838,10 @@ xfs_dir2_node_addname_int( | |||
1834 | * Get the freespace block corresponding to the data block | 1838 | * Get the freespace block corresponding to the data block |
1835 | * that was just allocated. | 1839 | * that was just allocated. |
1836 | */ | 1840 | */ |
1837 | fbno = dp->d_ops->db_to_fdb(mp, dbno); | 1841 | fbno = dp->d_ops->db_to_fdb(args->geo, dbno); |
1838 | error = xfs_dir2_free_try_read(tp, dp, | 1842 | error = xfs_dir2_free_try_read(tp, dp, |
1839 | xfs_dir2_db_to_da(mp, fbno), | 1843 | xfs_dir2_db_to_da(args->geo, fbno), |
1840 | &fbp); | 1844 | &fbp); |
1841 | if (error) | 1845 | if (error) |
1842 | return error; | 1846 | return error; |
1843 | 1847 | ||
@@ -1851,12 +1855,13 @@ xfs_dir2_node_addname_int( | |||
1851 | if (error) | 1855 | if (error) |
1852 | return error; | 1856 | return error; |
1853 | 1857 | ||
1854 | if (unlikely(dp->d_ops->db_to_fdb(mp, dbno) != fbno)) { | 1858 | if (dp->d_ops->db_to_fdb(args->geo, dbno) != fbno) { |
1855 | xfs_alert(mp, | 1859 | xfs_alert(mp, |
1856 | "%s: dir ino %llu needed freesp block %lld for\n" | 1860 | "%s: dir ino %llu needed freesp block %lld for\n" |
1857 | " data block %lld, got %lld ifbno %llu lastfbno %d", | 1861 | " data block %lld, got %lld ifbno %llu lastfbno %d", |
1858 | __func__, (unsigned long long)dp->i_ino, | 1862 | __func__, (unsigned long long)dp->i_ino, |
1859 | (long long)dp->d_ops->db_to_fdb(mp, dbno), | 1863 | (long long)dp->d_ops->db_to_fdb( |
1864 | args->geo, dbno), | ||
1860 | (long long)dbno, (long long)fbno, | 1865 | (long long)dbno, (long long)fbno, |
1861 | (unsigned long long)ifbno, lastfbno); | 1866 | (unsigned long long)ifbno, lastfbno); |
1862 | if (fblk) { | 1867 | if (fblk) { |
@@ -1877,7 +1882,7 @@ xfs_dir2_node_addname_int( | |||
1877 | /* | 1882 | /* |
1878 | * Get a buffer for the new block. | 1883 | * Get a buffer for the new block. |
1879 | */ | 1884 | */ |
1880 | error = xfs_dir3_free_get_buf(tp, dp, fbno, &fbp); | 1885 | error = xfs_dir3_free_get_buf(args, fbno, &fbp); |
1881 | if (error) | 1886 | if (error) |
1882 | return error; | 1887 | return error; |
1883 | free = fbp->b_addr; | 1888 | free = fbp->b_addr; |
@@ -1887,8 +1892,10 @@ xfs_dir2_node_addname_int( | |||
1887 | /* | 1892 | /* |
1888 | * Remember the first slot as our empty slot. | 1893 | * Remember the first slot as our empty slot. |
1889 | */ | 1894 | */ |
1890 | freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * | 1895 | freehdr.firstdb = |
1891 | dp->d_ops->free_max_bests(mp); | 1896 | (fbno - xfs_dir2_byte_to_db(args->geo, |
1897 | XFS_DIR2_FREE_OFFSET)) * | ||
1898 | dp->d_ops->free_max_bests(args->geo); | ||
1892 | } else { | 1899 | } else { |
1893 | free = fbp->b_addr; | 1900 | free = fbp->b_addr; |
1894 | bests = dp->d_ops->free_bests_p(free); | 1901 | bests = dp->d_ops->free_bests_p(free); |
@@ -1898,13 +1905,13 @@ xfs_dir2_node_addname_int( | |||
1898 | /* | 1905 | /* |
1899 | * Set the freespace block index from the data block number. | 1906 | * Set the freespace block index from the data block number. |
1900 | */ | 1907 | */ |
1901 | findex = dp->d_ops->db_to_fdindex(mp, dbno); | 1908 | findex = dp->d_ops->db_to_fdindex(args->geo, dbno); |
1902 | /* | 1909 | /* |
1903 | * If it's after the end of the current entries in the | 1910 | * If it's after the end of the current entries in the |
1904 | * freespace block, extend that table. | 1911 | * freespace block, extend that table. |
1905 | */ | 1912 | */ |
1906 | if (findex >= freehdr.nvalid) { | 1913 | if (findex >= freehdr.nvalid) { |
1907 | ASSERT(findex < dp->d_ops->free_max_bests(mp)); | 1914 | ASSERT(findex < dp->d_ops->free_max_bests(args->geo)); |
1908 | freehdr.nvalid = findex + 1; | 1915 | freehdr.nvalid = findex + 1; |
1909 | /* | 1916 | /* |
1910 | * Tag new entry so nused will go up. | 1917 | * Tag new entry so nused will go up. |
@@ -1918,7 +1925,7 @@ xfs_dir2_node_addname_int( | |||
1918 | if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { | 1925 | if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { |
1919 | freehdr.nused++; | 1926 | freehdr.nused++; |
1920 | dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); | 1927 | dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); |
1921 | xfs_dir2_free_log_header(tp, dp, fbp); | 1928 | xfs_dir2_free_log_header(args, fbp); |
1922 | } | 1929 | } |
1923 | /* | 1930 | /* |
1924 | * Update the real value in the table. | 1931 | * Update the real value in the table. |
@@ -1943,7 +1950,8 @@ xfs_dir2_node_addname_int( | |||
1943 | /* | 1950 | /* |
1944 | * Read the data block in. | 1951 | * Read the data block in. |
1945 | */ | 1952 | */ |
1946 | error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno), | 1953 | error = xfs_dir3_data_read(tp, dp, |
1954 | xfs_dir2_db_to_da(args->geo, dbno), | ||
1947 | -1, &dbp); | 1955 | -1, &dbp); |
1948 | if (error) | 1956 | if (error) |
1949 | return error; | 1957 | return error; |
@@ -1961,7 +1969,7 @@ xfs_dir2_node_addname_int( | |||
1961 | /* | 1969 | /* |
1962 | * Mark the first part of the unused space, inuse for us. | 1970 | * Mark the first part of the unused space, inuse for us. |
1963 | */ | 1971 | */ |
1964 | xfs_dir2_data_use_free(tp, dp, dbp, dup, | 1972 | xfs_dir2_data_use_free(args, dbp, dup, |
1965 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, | 1973 | (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, |
1966 | &needlog, &needscan); | 1974 | &needlog, &needscan); |
1967 | /* | 1975 | /* |
@@ -1974,7 +1982,7 @@ xfs_dir2_node_addname_int( | |||
1974 | dp->d_ops->data_put_ftype(dep, args->filetype); | 1982 | dp->d_ops->data_put_ftype(dep, args->filetype); |
1975 | tagp = dp->d_ops->data_entry_tag_p(dep); | 1983 | tagp = dp->d_ops->data_entry_tag_p(dep); |
1976 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); | 1984 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); |
1977 | xfs_dir2_data_log_entry(tp, dp, dbp, dep); | 1985 | xfs_dir2_data_log_entry(args, dbp, dep); |
1978 | /* | 1986 | /* |
1979 | * Rescan the block for bestfree if needed. | 1987 | * Rescan the block for bestfree if needed. |
1980 | */ | 1988 | */ |
@@ -1984,7 +1992,7 @@ xfs_dir2_node_addname_int( | |||
1984 | * Log the data block header if needed. | 1992 | * Log the data block header if needed. |
1985 | */ | 1993 | */ |
1986 | if (needlog) | 1994 | if (needlog) |
1987 | xfs_dir2_data_log_header(tp, dp, dbp); | 1995 | xfs_dir2_data_log_header(args, dbp); |
1988 | /* | 1996 | /* |
1989 | * If the freespace entry is now wrong, update it. | 1997 | * If the freespace entry is now wrong, update it. |
1990 | */ | 1998 | */ |
@@ -1997,7 +2005,7 @@ xfs_dir2_node_addname_int( | |||
1997 | * Log the freespace entry if needed. | 2005 | * Log the freespace entry if needed. |
1998 | */ | 2006 | */ |
1999 | if (logfree) | 2007 | if (logfree) |
2000 | xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex); | 2008 | xfs_dir2_free_log_bests(args, fbp, findex, findex); |
2001 | /* | 2009 | /* |
2002 | * Return the data block and offset in args, then drop the data block. | 2010 | * Return the data block and offset in args, then drop the data block. |
2003 | */ | 2011 | */ |
@@ -2028,8 +2036,6 @@ xfs_dir2_node_lookup( | |||
2028 | state = xfs_da_state_alloc(); | 2036 | state = xfs_da_state_alloc(); |
2029 | state->args = args; | 2037 | state->args = args; |
2030 | state->mp = args->dp->i_mount; | 2038 | state->mp = args->dp->i_mount; |
2031 | state->blocksize = state->mp->m_dirblksize; | ||
2032 | state->node_ents = state->mp->m_dir_node_ents; | ||
2033 | /* | 2039 | /* |
2034 | * Fill in the path to the entry in the cursor. | 2040 | * Fill in the path to the entry in the cursor. |
2035 | */ | 2041 | */ |
@@ -2083,8 +2089,6 @@ xfs_dir2_node_removename( | |||
2083 | state = xfs_da_state_alloc(); | 2089 | state = xfs_da_state_alloc(); |
2084 | state->args = args; | 2090 | state->args = args; |
2085 | state->mp = args->dp->i_mount; | 2091 | state->mp = args->dp->i_mount; |
2086 | state->blocksize = state->mp->m_dirblksize; | ||
2087 | state->node_ents = state->mp->m_dir_node_ents; | ||
2088 | 2092 | ||
2089 | /* Look up the entry we're deleting, set up the cursor. */ | 2093 | /* Look up the entry we're deleting, set up the cursor. */ |
2090 | error = xfs_da3_node_lookup_int(state, &rval); | 2094 | error = xfs_da3_node_lookup_int(state, &rval); |
@@ -2153,8 +2157,6 @@ xfs_dir2_node_replace( | |||
2153 | state = xfs_da_state_alloc(); | 2157 | state = xfs_da_state_alloc(); |
2154 | state->args = args; | 2158 | state->args = args; |
2155 | state->mp = args->dp->i_mount; | 2159 | state->mp = args->dp->i_mount; |
2156 | state->blocksize = state->mp->m_dirblksize; | ||
2157 | state->node_ents = state->mp->m_dir_node_ents; | ||
2158 | inum = args->inumber; | 2160 | inum = args->inumber; |
2159 | /* | 2161 | /* |
2160 | * Lookup the entry to change in the btree. | 2162 | * Lookup the entry to change in the btree. |
@@ -2186,15 +2188,15 @@ xfs_dir2_node_replace( | |||
2186 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); | 2188 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); |
2187 | dep = (xfs_dir2_data_entry_t *) | 2189 | dep = (xfs_dir2_data_entry_t *) |
2188 | ((char *)hdr + | 2190 | ((char *)hdr + |
2189 | xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address))); | 2191 | xfs_dir2_dataptr_to_off(args->geo, |
2192 | be32_to_cpu(lep->address))); | ||
2190 | ASSERT(inum != be64_to_cpu(dep->inumber)); | 2193 | ASSERT(inum != be64_to_cpu(dep->inumber)); |
2191 | /* | 2194 | /* |
2192 | * Fill in the new inode number and log the entry. | 2195 | * Fill in the new inode number and log the entry. |
2193 | */ | 2196 | */ |
2194 | dep->inumber = cpu_to_be64(inum); | 2197 | dep->inumber = cpu_to_be64(inum); |
2195 | args->dp->d_ops->data_put_ftype(dep, args->filetype); | 2198 | args->dp->d_ops->data_put_ftype(dep, args->filetype); |
2196 | xfs_dir2_data_log_entry(args->trans, args->dp, | 2199 | xfs_dir2_data_log_entry(args, state->extrablk.bp, dep); |
2197 | state->extrablk.bp, dep); | ||
2198 | rval = 0; | 2200 | rval = 0; |
2199 | } | 2201 | } |
2200 | /* | 2202 | /* |
@@ -2262,9 +2264,9 @@ xfs_dir2_node_trim_free( | |||
2262 | /* | 2264 | /* |
2263 | * Blow the block away. | 2265 | * Blow the block away. |
2264 | */ | 2266 | */ |
2265 | if ((error = | 2267 | error = xfs_dir2_shrink_inode(args, |
2266 | xfs_dir2_shrink_inode(args, xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo), | 2268 | xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo), bp); |
2267 | bp))) { | 2269 | if (error) { |
2268 | /* | 2270 | /* |
2269 | * Can't fail with ENOSPC since that only happens with no | 2271 | * Can't fail with ENOSPC since that only happens with no |
2270 | * space reservation, when breaking up an extent into two | 2272 | * space reservation, when breaking up an extent into two |
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index 8b9d2281f85b..27ce0794d196 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h | |||
@@ -20,6 +20,140 @@ | |||
20 | 20 | ||
21 | struct dir_context; | 21 | struct dir_context; |
22 | 22 | ||
23 | /* | ||
24 | * Directory offset/block conversion functions. | ||
25 | * | ||
26 | * DB blocks here are logical directory block numbers, not filesystem blocks. | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * Convert dataptr to byte in file space | ||
31 | */ | ||
32 | static inline xfs_dir2_off_t | ||
33 | xfs_dir2_dataptr_to_byte(xfs_dir2_dataptr_t dp) | ||
34 | { | ||
35 | return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * Convert byte in file space to dataptr. It had better be aligned. | ||
40 | */ | ||
41 | static inline xfs_dir2_dataptr_t | ||
42 | xfs_dir2_byte_to_dataptr(xfs_dir2_off_t by) | ||
43 | { | ||
44 | return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * Convert byte in space to (DB) block | ||
49 | */ | ||
50 | static inline xfs_dir2_db_t | ||
51 | xfs_dir2_byte_to_db(struct xfs_da_geometry *geo, xfs_dir2_off_t by) | ||
52 | { | ||
53 | return (xfs_dir2_db_t)(by >> geo->blklog); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Convert dataptr to a block number | ||
58 | */ | ||
59 | static inline xfs_dir2_db_t | ||
60 | xfs_dir2_dataptr_to_db(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp) | ||
61 | { | ||
62 | return xfs_dir2_byte_to_db(geo, xfs_dir2_dataptr_to_byte(dp)); | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * Convert byte in space to offset in a block | ||
67 | */ | ||
68 | static inline xfs_dir2_data_aoff_t | ||
69 | xfs_dir2_byte_to_off(struct xfs_da_geometry *geo, xfs_dir2_off_t by) | ||
70 | { | ||
71 | return (xfs_dir2_data_aoff_t)(by & (geo->blksize - 1)); | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Convert dataptr to a byte offset in a block | ||
76 | */ | ||
77 | static inline xfs_dir2_data_aoff_t | ||
78 | xfs_dir2_dataptr_to_off(struct xfs_da_geometry *geo, xfs_dir2_dataptr_t dp) | ||
79 | { | ||
80 | return xfs_dir2_byte_to_off(geo, xfs_dir2_dataptr_to_byte(dp)); | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Convert block and offset to byte in space | ||
85 | */ | ||
86 | static inline xfs_dir2_off_t | ||
87 | xfs_dir2_db_off_to_byte(struct xfs_da_geometry *geo, xfs_dir2_db_t db, | ||
88 | xfs_dir2_data_aoff_t o) | ||
89 | { | ||
90 | return ((xfs_dir2_off_t)db << geo->blklog) + o; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * Convert block (DB) to block (dablk) | ||
95 | */ | ||
96 | static inline xfs_dablk_t | ||
97 | xfs_dir2_db_to_da(struct xfs_da_geometry *geo, xfs_dir2_db_t db) | ||
98 | { | ||
99 | return (xfs_dablk_t)(db << (geo->blklog - geo->fsblog)); | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Convert byte in space to (DA) block | ||
104 | */ | ||
105 | static inline xfs_dablk_t | ||
106 | xfs_dir2_byte_to_da(struct xfs_da_geometry *geo, xfs_dir2_off_t by) | ||
107 | { | ||
108 | return xfs_dir2_db_to_da(geo, xfs_dir2_byte_to_db(geo, by)); | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * Convert block and offset to dataptr | ||
113 | */ | ||
114 | static inline xfs_dir2_dataptr_t | ||
115 | xfs_dir2_db_off_to_dataptr(struct xfs_da_geometry *geo, xfs_dir2_db_t db, | ||
116 | xfs_dir2_data_aoff_t o) | ||
117 | { | ||
118 | return xfs_dir2_byte_to_dataptr(xfs_dir2_db_off_to_byte(geo, db, o)); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Convert block (dablk) to block (DB) | ||
123 | */ | ||
124 | static inline xfs_dir2_db_t | ||
125 | xfs_dir2_da_to_db(struct xfs_da_geometry *geo, xfs_dablk_t da) | ||
126 | { | ||
127 | return (xfs_dir2_db_t)(da >> (geo->blklog - geo->fsblog)); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Convert block (dablk) to byte offset in space | ||
132 | */ | ||
133 | static inline xfs_dir2_off_t | ||
134 | xfs_dir2_da_to_byte(struct xfs_da_geometry *geo, xfs_dablk_t da) | ||
135 | { | ||
136 | return xfs_dir2_db_off_to_byte(geo, xfs_dir2_da_to_db(geo, da), 0); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Directory tail pointer accessor functions. Based on block geometry. | ||
141 | */ | ||
142 | static inline struct xfs_dir2_block_tail * | ||
143 | xfs_dir2_block_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_data_hdr *hdr) | ||
144 | { | ||
145 | return ((struct xfs_dir2_block_tail *) | ||
146 | ((char *)hdr + geo->blksize)) - 1; | ||
147 | } | ||
148 | |||
149 | static inline struct xfs_dir2_leaf_tail * | ||
150 | xfs_dir2_leaf_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_leaf *lp) | ||
151 | { | ||
152 | return (struct xfs_dir2_leaf_tail *) | ||
153 | ((char *)lp + geo->blksize - | ||
154 | sizeof(struct xfs_dir2_leaf_tail)); | ||
155 | } | ||
156 | |||
23 | /* xfs_dir2.c */ | 157 | /* xfs_dir2.c */ |
24 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); | 158 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); |
25 | extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, | 159 | extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, |
@@ -54,8 +188,8 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args, | |||
54 | extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); | 188 | extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); |
55 | extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp, | 189 | extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp, |
56 | xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp); | 190 | xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp); |
57 | extern int xfs_dir3_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp, | 191 | extern int xfs_dir3_data_readahead(struct xfs_inode *dp, xfs_dablk_t bno, |
58 | xfs_dablk_t bno, xfs_daddr_t mapped_bno); | 192 | xfs_daddr_t mapped_bno); |
59 | 193 | ||
60 | extern struct xfs_dir2_data_free * | 194 | extern struct xfs_dir2_data_free * |
61 | xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, | 195 | xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, |
@@ -77,9 +211,9 @@ extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr, | |||
77 | int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); | 211 | int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); |
78 | extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, | 212 | extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, |
79 | struct xfs_buf **bpp, __uint16_t magic); | 213 | struct xfs_buf **bpp, __uint16_t magic); |
80 | extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_inode *dp, | 214 | extern void xfs_dir3_leaf_log_ents(struct xfs_da_args *args, |
81 | struct xfs_buf *bp, int first, int last); | 215 | struct xfs_buf *bp, int first, int last); |
82 | extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, struct xfs_inode *dp, | 216 | extern void xfs_dir3_leaf_log_header(struct xfs_da_args *args, |
83 | struct xfs_buf *bp); | 217 | struct xfs_buf *bp); |
84 | extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); | 218 | extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); |
85 | extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); | 219 | extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); |
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index aead369e1c30..48e99afb9cb0 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c | |||
@@ -76,26 +76,25 @@ const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = { | |||
76 | 76 | ||
77 | STATIC int | 77 | STATIC int |
78 | xfs_dir2_sf_getdents( | 78 | xfs_dir2_sf_getdents( |
79 | xfs_inode_t *dp, /* incore directory inode */ | 79 | struct xfs_da_args *args, |
80 | struct dir_context *ctx) | 80 | struct dir_context *ctx) |
81 | { | 81 | { |
82 | int i; /* shortform entry number */ | 82 | int i; /* shortform entry number */ |
83 | xfs_mount_t *mp; /* filesystem mount point */ | 83 | struct xfs_inode *dp = args->dp; /* incore directory inode */ |
84 | xfs_dir2_dataptr_t off; /* current entry's offset */ | 84 | xfs_dir2_dataptr_t off; /* current entry's offset */ |
85 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ | 85 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ |
86 | xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ | 86 | xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ |
87 | xfs_dir2_dataptr_t dot_offset; | 87 | xfs_dir2_dataptr_t dot_offset; |
88 | xfs_dir2_dataptr_t dotdot_offset; | 88 | xfs_dir2_dataptr_t dotdot_offset; |
89 | xfs_ino_t ino; | 89 | xfs_ino_t ino; |
90 | 90 | struct xfs_da_geometry *geo = args->geo; | |
91 | mp = dp->i_mount; | ||
92 | 91 | ||
93 | ASSERT(dp->i_df.if_flags & XFS_IFINLINE); | 92 | ASSERT(dp->i_df.if_flags & XFS_IFINLINE); |
94 | /* | 93 | /* |
95 | * Give up if the directory is way too short. | 94 | * Give up if the directory is way too short. |
96 | */ | 95 | */ |
97 | if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { | 96 | if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { |
98 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | 97 | ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); |
99 | return XFS_ERROR(EIO); | 98 | return XFS_ERROR(EIO); |
100 | } | 99 | } |
101 | 100 | ||
@@ -109,18 +108,18 @@ xfs_dir2_sf_getdents( | |||
109 | /* | 108 | /* |
110 | * If the block number in the offset is out of range, we're done. | 109 | * If the block number in the offset is out of range, we're done. |
111 | */ | 110 | */ |
112 | if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk) | 111 | if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) |
113 | return 0; | 112 | return 0; |
114 | 113 | ||
115 | /* | 114 | /* |
116 | * Precalculate offsets for . and .. as we will always need them. | 115 | * Precalculate offsets for . and .. as we will always need them. |
117 | * | 116 | * |
118 | * XXX(hch): the second argument is sometimes 0 and sometimes | 117 | * XXX(hch): the second argument is sometimes 0 and sometimes |
119 | * mp->m_dirdatablk. | 118 | * geo->datablk |
120 | */ | 119 | */ |
121 | dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 120 | dot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, |
122 | dp->d_ops->data_dot_offset); | 121 | dp->d_ops->data_dot_offset); |
123 | dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 122 | dotdot_offset = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, |
124 | dp->d_ops->data_dotdot_offset); | 123 | dp->d_ops->data_dotdot_offset); |
125 | 124 | ||
126 | /* | 125 | /* |
@@ -149,7 +148,7 @@ xfs_dir2_sf_getdents( | |||
149 | for (i = 0; i < sfp->count; i++) { | 148 | for (i = 0; i < sfp->count; i++) { |
150 | __uint8_t filetype; | 149 | __uint8_t filetype; |
151 | 150 | ||
152 | off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 151 | off = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, |
153 | xfs_dir2_sf_get_offset(sfep)); | 152 | xfs_dir2_sf_get_offset(sfep)); |
154 | 153 | ||
155 | if (ctx->pos > off) { | 154 | if (ctx->pos > off) { |
@@ -161,13 +160,13 @@ xfs_dir2_sf_getdents( | |||
161 | filetype = dp->d_ops->sf_get_ftype(sfep); | 160 | filetype = dp->d_ops->sf_get_ftype(sfep); |
162 | ctx->pos = off & 0x7fffffff; | 161 | ctx->pos = off & 0x7fffffff; |
163 | if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, | 162 | if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, |
164 | xfs_dir3_get_dtype(mp, filetype))) | 163 | xfs_dir3_get_dtype(dp->i_mount, filetype))) |
165 | return 0; | 164 | return 0; |
166 | sfep = dp->d_ops->sf_nextentry(sfp, sfep); | 165 | sfep = dp->d_ops->sf_nextentry(sfp, sfep); |
167 | } | 166 | } |
168 | 167 | ||
169 | ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & | 168 | ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & |
170 | 0x7fffffff; | 169 | 0x7fffffff; |
171 | return 0; | 170 | return 0; |
172 | } | 171 | } |
173 | 172 | ||
@@ -176,9 +175,10 @@ xfs_dir2_sf_getdents( | |||
176 | */ | 175 | */ |
177 | STATIC int | 176 | STATIC int |
178 | xfs_dir2_block_getdents( | 177 | xfs_dir2_block_getdents( |
179 | xfs_inode_t *dp, /* incore inode */ | 178 | struct xfs_da_args *args, |
180 | struct dir_context *ctx) | 179 | struct dir_context *ctx) |
181 | { | 180 | { |
181 | struct xfs_inode *dp = args->dp; /* incore directory inode */ | ||
182 | xfs_dir2_data_hdr_t *hdr; /* block header */ | 182 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
183 | struct xfs_buf *bp; /* buffer for block */ | 183 | struct xfs_buf *bp; /* buffer for block */ |
184 | xfs_dir2_block_tail_t *btp; /* block tail */ | 184 | xfs_dir2_block_tail_t *btp; /* block tail */ |
@@ -186,16 +186,15 @@ xfs_dir2_block_getdents( | |||
186 | xfs_dir2_data_unused_t *dup; /* block unused entry */ | 186 | xfs_dir2_data_unused_t *dup; /* block unused entry */ |
187 | char *endptr; /* end of the data entries */ | 187 | char *endptr; /* end of the data entries */ |
188 | int error; /* error return value */ | 188 | int error; /* error return value */ |
189 | xfs_mount_t *mp; /* filesystem mount point */ | ||
190 | char *ptr; /* current data entry */ | 189 | char *ptr; /* current data entry */ |
191 | int wantoff; /* starting block offset */ | 190 | int wantoff; /* starting block offset */ |
192 | xfs_off_t cook; | 191 | xfs_off_t cook; |
192 | struct xfs_da_geometry *geo = args->geo; | ||
193 | 193 | ||
194 | mp = dp->i_mount; | ||
195 | /* | 194 | /* |
196 | * If the block number in the offset is out of range, we're done. | 195 | * If the block number in the offset is out of range, we're done. |
197 | */ | 196 | */ |
198 | if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk) | 197 | if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) |
199 | return 0; | 198 | return 0; |
200 | 199 | ||
201 | error = xfs_dir3_block_read(NULL, dp, &bp); | 200 | error = xfs_dir3_block_read(NULL, dp, &bp); |
@@ -206,13 +205,13 @@ xfs_dir2_block_getdents( | |||
206 | * Extract the byte offset we start at from the seek pointer. | 205 | * Extract the byte offset we start at from the seek pointer. |
207 | * We'll skip entries before this. | 206 | * We'll skip entries before this. |
208 | */ | 207 | */ |
209 | wantoff = xfs_dir2_dataptr_to_off(mp, ctx->pos); | 208 | wantoff = xfs_dir2_dataptr_to_off(geo, ctx->pos); |
210 | hdr = bp->b_addr; | 209 | hdr = bp->b_addr; |
211 | xfs_dir3_data_check(dp, bp); | 210 | xfs_dir3_data_check(dp, bp); |
212 | /* | 211 | /* |
213 | * Set up values for the loop. | 212 | * Set up values for the loop. |
214 | */ | 213 | */ |
215 | btp = xfs_dir2_block_tail_p(mp, hdr); | 214 | btp = xfs_dir2_block_tail_p(geo, hdr); |
216 | ptr = (char *)dp->d_ops->data_entry_p(hdr); | 215 | ptr = (char *)dp->d_ops->data_entry_p(hdr); |
217 | endptr = (char *)xfs_dir2_block_leaf_p(btp); | 216 | endptr = (char *)xfs_dir2_block_leaf_p(btp); |
218 | 217 | ||
@@ -244,7 +243,7 @@ xfs_dir2_block_getdents( | |||
244 | if ((char *)dep - (char *)hdr < wantoff) | 243 | if ((char *)dep - (char *)hdr < wantoff) |
245 | continue; | 244 | continue; |
246 | 245 | ||
247 | cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 246 | cook = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, |
248 | (char *)dep - (char *)hdr); | 247 | (char *)dep - (char *)hdr); |
249 | 248 | ||
250 | ctx->pos = cook & 0x7fffffff; | 249 | ctx->pos = cook & 0x7fffffff; |
@@ -254,7 +253,7 @@ xfs_dir2_block_getdents( | |||
254 | */ | 253 | */ |
255 | if (!dir_emit(ctx, (char *)dep->name, dep->namelen, | 254 | if (!dir_emit(ctx, (char *)dep->name, dep->namelen, |
256 | be64_to_cpu(dep->inumber), | 255 | be64_to_cpu(dep->inumber), |
257 | xfs_dir3_get_dtype(mp, filetype))) { | 256 | xfs_dir3_get_dtype(dp->i_mount, filetype))) { |
258 | xfs_trans_brelse(NULL, bp); | 257 | xfs_trans_brelse(NULL, bp); |
259 | return 0; | 258 | return 0; |
260 | } | 259 | } |
@@ -264,8 +263,8 @@ xfs_dir2_block_getdents( | |||
264 | * Reached the end of the block. | 263 | * Reached the end of the block. |
265 | * Set the offset to a non-existent block 1 and return. | 264 | * Set the offset to a non-existent block 1 and return. |
266 | */ | 265 | */ |
267 | ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & | 266 | ctx->pos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk + 1, 0) & |
268 | 0x7fffffff; | 267 | 0x7fffffff; |
269 | xfs_trans_brelse(NULL, bp); | 268 | xfs_trans_brelse(NULL, bp); |
270 | return 0; | 269 | return 0; |
271 | } | 270 | } |
@@ -286,13 +285,13 @@ struct xfs_dir2_leaf_map_info { | |||
286 | 285 | ||
287 | STATIC int | 286 | STATIC int |
288 | xfs_dir2_leaf_readbuf( | 287 | xfs_dir2_leaf_readbuf( |
289 | struct xfs_inode *dp, | 288 | struct xfs_da_args *args, |
290 | size_t bufsize, | 289 | size_t bufsize, |
291 | struct xfs_dir2_leaf_map_info *mip, | 290 | struct xfs_dir2_leaf_map_info *mip, |
292 | xfs_dir2_off_t *curoff, | 291 | xfs_dir2_off_t *curoff, |
293 | struct xfs_buf **bpp) | 292 | struct xfs_buf **bpp) |
294 | { | 293 | { |
295 | struct xfs_mount *mp = dp->i_mount; | 294 | struct xfs_inode *dp = args->dp; |
296 | struct xfs_buf *bp = *bpp; | 295 | struct xfs_buf *bp = *bpp; |
297 | struct xfs_bmbt_irec *map = mip->map; | 296 | struct xfs_bmbt_irec *map = mip->map; |
298 | struct blk_plug plug; | 297 | struct blk_plug plug; |
@@ -300,6 +299,7 @@ xfs_dir2_leaf_readbuf( | |||
300 | int length; | 299 | int length; |
301 | int i; | 300 | int i; |
302 | int j; | 301 | int j; |
302 | struct xfs_da_geometry *geo = args->geo; | ||
303 | 303 | ||
304 | /* | 304 | /* |
305 | * If we have a buffer, we need to release it and | 305 | * If we have a buffer, we need to release it and |
@@ -309,12 +309,12 @@ xfs_dir2_leaf_readbuf( | |||
309 | if (bp) { | 309 | if (bp) { |
310 | xfs_trans_brelse(NULL, bp); | 310 | xfs_trans_brelse(NULL, bp); |
311 | bp = NULL; | 311 | bp = NULL; |
312 | mip->map_blocks -= mp->m_dirblkfsbs; | 312 | mip->map_blocks -= geo->fsbcount; |
313 | /* | 313 | /* |
314 | * Loop to get rid of the extents for the | 314 | * Loop to get rid of the extents for the |
315 | * directory block. | 315 | * directory block. |
316 | */ | 316 | */ |
317 | for (i = mp->m_dirblkfsbs; i > 0; ) { | 317 | for (i = geo->fsbcount; i > 0; ) { |
318 | j = min_t(int, map->br_blockcount, i); | 318 | j = min_t(int, map->br_blockcount, i); |
319 | map->br_blockcount -= j; | 319 | map->br_blockcount -= j; |
320 | map->br_startblock += j; | 320 | map->br_startblock += j; |
@@ -333,8 +333,7 @@ xfs_dir2_leaf_readbuf( | |||
333 | /* | 333 | /* |
334 | * Recalculate the readahead blocks wanted. | 334 | * Recalculate the readahead blocks wanted. |
335 | */ | 335 | */ |
336 | mip->ra_want = howmany(bufsize + mp->m_dirblksize, | 336 | mip->ra_want = howmany(bufsize + geo->blksize, (1 << geo->fsblog)) - 1; |
337 | mp->m_sb.sb_blocksize) - 1; | ||
338 | ASSERT(mip->ra_want >= 0); | 337 | ASSERT(mip->ra_want >= 0); |
339 | 338 | ||
340 | /* | 339 | /* |
@@ -342,14 +341,14 @@ xfs_dir2_leaf_readbuf( | |||
342 | * run out of data blocks, get some more mappings. | 341 | * run out of data blocks, get some more mappings. |
343 | */ | 342 | */ |
344 | if (1 + mip->ra_want > mip->map_blocks && | 343 | if (1 + mip->ra_want > mip->map_blocks && |
345 | mip->map_off < xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) { | 344 | mip->map_off < xfs_dir2_byte_to_da(geo, XFS_DIR2_LEAF_OFFSET)) { |
346 | /* | 345 | /* |
347 | * Get more bmaps, fill in after the ones | 346 | * Get more bmaps, fill in after the ones |
348 | * we already have in the table. | 347 | * we already have in the table. |
349 | */ | 348 | */ |
350 | mip->nmap = mip->map_size - mip->map_valid; | 349 | mip->nmap = mip->map_size - mip->map_valid; |
351 | error = xfs_bmapi_read(dp, mip->map_off, | 350 | error = xfs_bmapi_read(dp, mip->map_off, |
352 | xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET) - | 351 | xfs_dir2_byte_to_da(geo, XFS_DIR2_LEAF_OFFSET) - |
353 | mip->map_off, | 352 | mip->map_off, |
354 | &map[mip->map_valid], &mip->nmap, 0); | 353 | &map[mip->map_valid], &mip->nmap, 0); |
355 | 354 | ||
@@ -370,7 +369,7 @@ xfs_dir2_leaf_readbuf( | |||
370 | i = mip->map_valid + mip->nmap - 1; | 369 | i = mip->map_valid + mip->nmap - 1; |
371 | mip->map_off = map[i].br_startoff + map[i].br_blockcount; | 370 | mip->map_off = map[i].br_startoff + map[i].br_blockcount; |
372 | } else | 371 | } else |
373 | mip->map_off = xfs_dir2_byte_to_da(mp, | 372 | mip->map_off = xfs_dir2_byte_to_da(geo, |
374 | XFS_DIR2_LEAF_OFFSET); | 373 | XFS_DIR2_LEAF_OFFSET); |
375 | 374 | ||
376 | /* | 375 | /* |
@@ -396,18 +395,18 @@ xfs_dir2_leaf_readbuf( | |||
396 | * No valid mappings, so no more data blocks. | 395 | * No valid mappings, so no more data blocks. |
397 | */ | 396 | */ |
398 | if (!mip->map_valid) { | 397 | if (!mip->map_valid) { |
399 | *curoff = xfs_dir2_da_to_byte(mp, mip->map_off); | 398 | *curoff = xfs_dir2_da_to_byte(geo, mip->map_off); |
400 | goto out; | 399 | goto out; |
401 | } | 400 | } |
402 | 401 | ||
403 | /* | 402 | /* |
404 | * Read the directory block starting at the first mapping. | 403 | * Read the directory block starting at the first mapping. |
405 | */ | 404 | */ |
406 | mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff); | 405 | mip->curdb = xfs_dir2_da_to_db(geo, map->br_startoff); |
407 | error = xfs_dir3_data_read(NULL, dp, map->br_startoff, | 406 | error = xfs_dir3_data_read(NULL, dp, map->br_startoff, |
408 | map->br_blockcount >= mp->m_dirblkfsbs ? | 407 | map->br_blockcount >= geo->fsbcount ? |
409 | XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp); | 408 | XFS_FSB_TO_DADDR(dp->i_mount, map->br_startblock) : |
410 | 409 | -1, &bp); | |
411 | /* | 410 | /* |
412 | * Should just skip over the data block instead of giving up. | 411 | * Should just skip over the data block instead of giving up. |
413 | */ | 412 | */ |
@@ -419,7 +418,7 @@ xfs_dir2_leaf_readbuf( | |||
419 | * was previously ra. | 418 | * was previously ra. |
420 | */ | 419 | */ |
421 | if (mip->ra_current) | 420 | if (mip->ra_current) |
422 | mip->ra_current -= mp->m_dirblkfsbs; | 421 | mip->ra_current -= geo->fsbcount; |
423 | 422 | ||
424 | /* | 423 | /* |
425 | * Do we need more readahead? | 424 | * Do we need more readahead? |
@@ -427,16 +426,16 @@ xfs_dir2_leaf_readbuf( | |||
427 | blk_start_plug(&plug); | 426 | blk_start_plug(&plug); |
428 | for (mip->ra_index = mip->ra_offset = i = 0; | 427 | for (mip->ra_index = mip->ra_offset = i = 0; |
429 | mip->ra_want > mip->ra_current && i < mip->map_blocks; | 428 | mip->ra_want > mip->ra_current && i < mip->map_blocks; |
430 | i += mp->m_dirblkfsbs) { | 429 | i += geo->fsbcount) { |
431 | ASSERT(mip->ra_index < mip->map_valid); | 430 | ASSERT(mip->ra_index < mip->map_valid); |
432 | /* | 431 | /* |
433 | * Read-ahead a contiguous directory block. | 432 | * Read-ahead a contiguous directory block. |
434 | */ | 433 | */ |
435 | if (i > mip->ra_current && | 434 | if (i > mip->ra_current && |
436 | map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) { | 435 | map[mip->ra_index].br_blockcount >= geo->fsbcount) { |
437 | xfs_dir3_data_readahead(NULL, dp, | 436 | xfs_dir3_data_readahead(dp, |
438 | map[mip->ra_index].br_startoff + mip->ra_offset, | 437 | map[mip->ra_index].br_startoff + mip->ra_offset, |
439 | XFS_FSB_TO_DADDR(mp, | 438 | XFS_FSB_TO_DADDR(dp->i_mount, |
440 | map[mip->ra_index].br_startblock + | 439 | map[mip->ra_index].br_startblock + |
441 | mip->ra_offset)); | 440 | mip->ra_offset)); |
442 | mip->ra_current = i; | 441 | mip->ra_current = i; |
@@ -447,7 +446,7 @@ xfs_dir2_leaf_readbuf( | |||
447 | * use our mapping, but this is a very rare case. | 446 | * use our mapping, but this is a very rare case. |
448 | */ | 447 | */ |
449 | else if (i > mip->ra_current) { | 448 | else if (i > mip->ra_current) { |
450 | xfs_dir3_data_readahead(NULL, dp, | 449 | xfs_dir3_data_readahead(dp, |
451 | map[mip->ra_index].br_startoff + | 450 | map[mip->ra_index].br_startoff + |
452 | mip->ra_offset, -1); | 451 | mip->ra_offset, -1); |
453 | mip->ra_current = i; | 452 | mip->ra_current = i; |
@@ -456,15 +455,14 @@ xfs_dir2_leaf_readbuf( | |||
456 | /* | 455 | /* |
457 | * Advance offset through the mapping table. | 456 | * Advance offset through the mapping table. |
458 | */ | 457 | */ |
459 | for (j = 0; j < mp->m_dirblkfsbs; j++) { | 458 | for (j = 0; j < geo->fsbcount; j += length ) { |
460 | /* | 459 | /* |
461 | * The rest of this extent but not more than a dir | 460 | * The rest of this extent but not more than a dir |
462 | * block. | 461 | * block. |
463 | */ | 462 | */ |
464 | length = min_t(int, mp->m_dirblkfsbs, | 463 | length = min_t(int, geo->fsbcount, |
465 | map[mip->ra_index].br_blockcount - | 464 | map[mip->ra_index].br_blockcount - |
466 | mip->ra_offset); | 465 | mip->ra_offset); |
467 | j += length; | ||
468 | mip->ra_offset += length; | 466 | mip->ra_offset += length; |
469 | 467 | ||
470 | /* | 468 | /* |
@@ -489,22 +487,23 @@ out: | |||
489 | */ | 487 | */ |
490 | STATIC int | 488 | STATIC int |
491 | xfs_dir2_leaf_getdents( | 489 | xfs_dir2_leaf_getdents( |
492 | xfs_inode_t *dp, /* incore directory inode */ | 490 | struct xfs_da_args *args, |
493 | struct dir_context *ctx, | 491 | struct dir_context *ctx, |
494 | size_t bufsize) | 492 | size_t bufsize) |
495 | { | 493 | { |
494 | struct xfs_inode *dp = args->dp; | ||
496 | struct xfs_buf *bp = NULL; /* data block buffer */ | 495 | struct xfs_buf *bp = NULL; /* data block buffer */ |
497 | xfs_dir2_data_hdr_t *hdr; /* data block header */ | 496 | xfs_dir2_data_hdr_t *hdr; /* data block header */ |
498 | xfs_dir2_data_entry_t *dep; /* data entry */ | 497 | xfs_dir2_data_entry_t *dep; /* data entry */ |
499 | xfs_dir2_data_unused_t *dup; /* unused entry */ | 498 | xfs_dir2_data_unused_t *dup; /* unused entry */ |
500 | int error = 0; /* error return value */ | 499 | int error = 0; /* error return value */ |
501 | int length; /* temporary length value */ | 500 | int length; /* temporary length value */ |
502 | xfs_mount_t *mp; /* filesystem mount point */ | ||
503 | int byteoff; /* offset in current block */ | 501 | int byteoff; /* offset in current block */ |
504 | xfs_dir2_off_t curoff; /* current overall offset */ | 502 | xfs_dir2_off_t curoff; /* current overall offset */ |
505 | xfs_dir2_off_t newoff; /* new curoff after new blk */ | 503 | xfs_dir2_off_t newoff; /* new curoff after new blk */ |
506 | char *ptr = NULL; /* pointer to current data */ | 504 | char *ptr = NULL; /* pointer to current data */ |
507 | struct xfs_dir2_leaf_map_info *map_info; | 505 | struct xfs_dir2_leaf_map_info *map_info; |
506 | struct xfs_da_geometry *geo = args->geo; | ||
508 | 507 | ||
509 | /* | 508 | /* |
510 | * If the offset is at or past the largest allowed value, | 509 | * If the offset is at or past the largest allowed value, |
@@ -513,15 +512,12 @@ xfs_dir2_leaf_getdents( | |||
513 | if (ctx->pos >= XFS_DIR2_MAX_DATAPTR) | 512 | if (ctx->pos >= XFS_DIR2_MAX_DATAPTR) |
514 | return 0; | 513 | return 0; |
515 | 514 | ||
516 | mp = dp->i_mount; | ||
517 | |||
518 | /* | 515 | /* |
519 | * Set up to bmap a number of blocks based on the caller's | 516 | * Set up to bmap a number of blocks based on the caller's |
520 | * buffer size, the directory block size, and the filesystem | 517 | * buffer size, the directory block size, and the filesystem |
521 | * block size. | 518 | * block size. |
522 | */ | 519 | */ |
523 | length = howmany(bufsize + mp->m_dirblksize, | 520 | length = howmany(bufsize + geo->blksize, (1 << geo->fsblog)); |
524 | mp->m_sb.sb_blocksize); | ||
525 | map_info = kmem_zalloc(offsetof(struct xfs_dir2_leaf_map_info, map) + | 521 | map_info = kmem_zalloc(offsetof(struct xfs_dir2_leaf_map_info, map) + |
526 | (length * sizeof(struct xfs_bmbt_irec)), | 522 | (length * sizeof(struct xfs_bmbt_irec)), |
527 | KM_SLEEP | KM_NOFS); | 523 | KM_SLEEP | KM_NOFS); |
@@ -531,14 +527,14 @@ xfs_dir2_leaf_getdents( | |||
531 | * Inside the loop we keep the main offset value as a byte offset | 527 | * Inside the loop we keep the main offset value as a byte offset |
532 | * in the directory file. | 528 | * in the directory file. |
533 | */ | 529 | */ |
534 | curoff = xfs_dir2_dataptr_to_byte(mp, ctx->pos); | 530 | curoff = xfs_dir2_dataptr_to_byte(ctx->pos); |
535 | 531 | ||
536 | /* | 532 | /* |
537 | * Force this conversion through db so we truncate the offset | 533 | * Force this conversion through db so we truncate the offset |
538 | * down to get the start of the data block. | 534 | * down to get the start of the data block. |
539 | */ | 535 | */ |
540 | map_info->map_off = xfs_dir2_db_to_da(mp, | 536 | map_info->map_off = xfs_dir2_db_to_da(geo, |
541 | xfs_dir2_byte_to_db(mp, curoff)); | 537 | xfs_dir2_byte_to_db(geo, curoff)); |
542 | 538 | ||
543 | /* | 539 | /* |
544 | * Loop over directory entries until we reach the end offset. | 540 | * Loop over directory entries until we reach the end offset. |
@@ -551,9 +547,9 @@ xfs_dir2_leaf_getdents( | |||
551 | * If we have no buffer, or we're off the end of the | 547 | * If we have no buffer, or we're off the end of the |
552 | * current buffer, need to get another one. | 548 | * current buffer, need to get another one. |
553 | */ | 549 | */ |
554 | if (!bp || ptr >= (char *)bp->b_addr + mp->m_dirblksize) { | 550 | if (!bp || ptr >= (char *)bp->b_addr + geo->blksize) { |
555 | 551 | ||
556 | error = xfs_dir2_leaf_readbuf(dp, bufsize, map_info, | 552 | error = xfs_dir2_leaf_readbuf(args, bufsize, map_info, |
557 | &curoff, &bp); | 553 | &curoff, &bp); |
558 | if (error || !map_info->map_valid) | 554 | if (error || !map_info->map_valid) |
559 | break; | 555 | break; |
@@ -561,7 +557,8 @@ xfs_dir2_leaf_getdents( | |||
561 | /* | 557 | /* |
562 | * Having done a read, we need to set a new offset. | 558 | * Having done a read, we need to set a new offset. |
563 | */ | 559 | */ |
564 | newoff = xfs_dir2_db_off_to_byte(mp, map_info->curdb, 0); | 560 | newoff = xfs_dir2_db_off_to_byte(geo, |
561 | map_info->curdb, 0); | ||
565 | /* | 562 | /* |
566 | * Start of the current block. | 563 | * Start of the current block. |
567 | */ | 564 | */ |
@@ -571,7 +568,7 @@ xfs_dir2_leaf_getdents( | |||
571 | * Make sure we're in the right block. | 568 | * Make sure we're in the right block. |
572 | */ | 569 | */ |
573 | else if (curoff > newoff) | 570 | else if (curoff > newoff) |
574 | ASSERT(xfs_dir2_byte_to_db(mp, curoff) == | 571 | ASSERT(xfs_dir2_byte_to_db(geo, curoff) == |
575 | map_info->curdb); | 572 | map_info->curdb); |
576 | hdr = bp->b_addr; | 573 | hdr = bp->b_addr; |
577 | xfs_dir3_data_check(dp, bp); | 574 | xfs_dir3_data_check(dp, bp); |
@@ -579,7 +576,7 @@ xfs_dir2_leaf_getdents( | |||
579 | * Find our position in the block. | 576 | * Find our position in the block. |
580 | */ | 577 | */ |
581 | ptr = (char *)dp->d_ops->data_entry_p(hdr); | 578 | ptr = (char *)dp->d_ops->data_entry_p(hdr); |
582 | byteoff = xfs_dir2_byte_to_off(mp, curoff); | 579 | byteoff = xfs_dir2_byte_to_off(geo, curoff); |
583 | /* | 580 | /* |
584 | * Skip past the header. | 581 | * Skip past the header. |
585 | */ | 582 | */ |
@@ -608,10 +605,10 @@ xfs_dir2_leaf_getdents( | |||
608 | * Now set our real offset. | 605 | * Now set our real offset. |
609 | */ | 606 | */ |
610 | curoff = | 607 | curoff = |
611 | xfs_dir2_db_off_to_byte(mp, | 608 | xfs_dir2_db_off_to_byte(geo, |
612 | xfs_dir2_byte_to_db(mp, curoff), | 609 | xfs_dir2_byte_to_db(geo, curoff), |
613 | (char *)ptr - (char *)hdr); | 610 | (char *)ptr - (char *)hdr); |
614 | if (ptr >= (char *)hdr + mp->m_dirblksize) { | 611 | if (ptr >= (char *)hdr + geo->blksize) { |
615 | continue; | 612 | continue; |
616 | } | 613 | } |
617 | } | 614 | } |
@@ -635,10 +632,10 @@ xfs_dir2_leaf_getdents( | |||
635 | length = dp->d_ops->data_entsize(dep->namelen); | 632 | length = dp->d_ops->data_entsize(dep->namelen); |
636 | filetype = dp->d_ops->data_get_ftype(dep); | 633 | filetype = dp->d_ops->data_get_ftype(dep); |
637 | 634 | ||
638 | ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; | 635 | ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; |
639 | if (!dir_emit(ctx, (char *)dep->name, dep->namelen, | 636 | if (!dir_emit(ctx, (char *)dep->name, dep->namelen, |
640 | be64_to_cpu(dep->inumber), | 637 | be64_to_cpu(dep->inumber), |
641 | xfs_dir3_get_dtype(mp, filetype))) | 638 | xfs_dir3_get_dtype(dp->i_mount, filetype))) |
642 | break; | 639 | break; |
643 | 640 | ||
644 | /* | 641 | /* |
@@ -653,10 +650,10 @@ xfs_dir2_leaf_getdents( | |||
653 | /* | 650 | /* |
654 | * All done. Set output offset value to current offset. | 651 | * All done. Set output offset value to current offset. |
655 | */ | 652 | */ |
656 | if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR)) | 653 | if (curoff > xfs_dir2_dataptr_to_byte(XFS_DIR2_MAX_DATAPTR)) |
657 | ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; | 654 | ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; |
658 | else | 655 | else |
659 | ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; | 656 | ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; |
660 | kmem_free(map_info); | 657 | kmem_free(map_info); |
661 | if (bp) | 658 | if (bp) |
662 | xfs_trans_brelse(NULL, bp); | 659 | xfs_trans_brelse(NULL, bp); |
@@ -668,13 +665,14 @@ xfs_dir2_leaf_getdents( | |||
668 | */ | 665 | */ |
669 | int | 666 | int |
670 | xfs_readdir( | 667 | xfs_readdir( |
671 | xfs_inode_t *dp, | 668 | struct xfs_inode *dp, |
672 | struct dir_context *ctx, | 669 | struct dir_context *ctx, |
673 | size_t bufsize) | 670 | size_t bufsize) |
674 | { | 671 | { |
675 | int rval; /* return value */ | 672 | struct xfs_da_args args = { NULL }; |
676 | int v; /* type-checking value */ | 673 | int rval; |
677 | uint lock_mode; | 674 | int v; |
675 | uint lock_mode; | ||
678 | 676 | ||
679 | trace_xfs_readdir(dp); | 677 | trace_xfs_readdir(dp); |
680 | 678 | ||
@@ -684,15 +682,18 @@ xfs_readdir( | |||
684 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 682 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
685 | XFS_STATS_INC(xs_dir_getdents); | 683 | XFS_STATS_INC(xs_dir_getdents); |
686 | 684 | ||
685 | args.dp = dp; | ||
686 | args.geo = dp->i_mount->m_dir_geo; | ||
687 | |||
687 | lock_mode = xfs_ilock_data_map_shared(dp); | 688 | lock_mode = xfs_ilock_data_map_shared(dp); |
688 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 689 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
689 | rval = xfs_dir2_sf_getdents(dp, ctx); | 690 | rval = xfs_dir2_sf_getdents(&args, ctx); |
690 | else if ((rval = xfs_dir2_isblock(NULL, dp, &v))) | 691 | else if ((rval = xfs_dir2_isblock(&args, &v))) |
691 | ; | 692 | ; |
692 | else if (v) | 693 | else if (v) |
693 | rval = xfs_dir2_block_getdents(dp, ctx); | 694 | rval = xfs_dir2_block_getdents(&args, ctx); |
694 | else | 695 | else |
695 | rval = xfs_dir2_leaf_getdents(dp, ctx, bufsize); | 696 | rval = xfs_dir2_leaf_getdents(&args, ctx, bufsize); |
696 | xfs_iunlock(dp, lock_mode); | 697 | xfs_iunlock(dp, lock_mode); |
697 | 698 | ||
698 | return rval; | 699 | return rval; |
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 3725fb1b902b..53c3be619db5 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -82,8 +82,10 @@ xfs_dir2_block_sfsize( | |||
82 | xfs_ino_t parent = 0; /* parent inode number */ | 82 | xfs_ino_t parent = 0; /* parent inode number */ |
83 | int size=0; /* total computed size */ | 83 | int size=0; /* total computed size */ |
84 | int has_ftype; | 84 | int has_ftype; |
85 | struct xfs_da_geometry *geo; | ||
85 | 86 | ||
86 | mp = dp->i_mount; | 87 | mp = dp->i_mount; |
88 | geo = mp->m_dir_geo; | ||
87 | 89 | ||
88 | /* | 90 | /* |
89 | * if there is a filetype field, add the extra byte to the namelen | 91 | * if there is a filetype field, add the extra byte to the namelen |
@@ -92,7 +94,7 @@ xfs_dir2_block_sfsize( | |||
92 | has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0; | 94 | has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0; |
93 | 95 | ||
94 | count = i8count = namelen = 0; | 96 | count = i8count = namelen = 0; |
95 | btp = xfs_dir2_block_tail_p(mp, hdr); | 97 | btp = xfs_dir2_block_tail_p(geo, hdr); |
96 | blp = xfs_dir2_block_leaf_p(btp); | 98 | blp = xfs_dir2_block_leaf_p(btp); |
97 | 99 | ||
98 | /* | 100 | /* |
@@ -104,8 +106,8 @@ xfs_dir2_block_sfsize( | |||
104 | /* | 106 | /* |
105 | * Calculate the pointer to the entry at hand. | 107 | * Calculate the pointer to the entry at hand. |
106 | */ | 108 | */ |
107 | dep = (xfs_dir2_data_entry_t *) | 109 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
108 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr)); | 110 | xfs_dir2_dataptr_to_off(geo, addr)); |
109 | /* | 111 | /* |
110 | * Detect . and .., so we can special-case them. | 112 | * Detect . and .., so we can special-case them. |
111 | * . is not included in sf directories. | 113 | * . is not included in sf directories. |
@@ -195,7 +197,7 @@ xfs_dir2_block_to_sf( | |||
195 | /* | 197 | /* |
196 | * Set up to loop over the block's entries. | 198 | * Set up to loop over the block's entries. |
197 | */ | 199 | */ |
198 | btp = xfs_dir2_block_tail_p(mp, hdr); | 200 | btp = xfs_dir2_block_tail_p(args->geo, hdr); |
199 | ptr = (char *)dp->d_ops->data_entry_p(hdr); | 201 | ptr = (char *)dp->d_ops->data_entry_p(hdr); |
200 | endptr = (char *)xfs_dir2_block_leaf_p(btp); | 202 | endptr = (char *)xfs_dir2_block_leaf_p(btp); |
201 | sfep = xfs_dir2_sf_firstentry(sfp); | 203 | sfep = xfs_dir2_sf_firstentry(sfp); |
@@ -247,7 +249,7 @@ xfs_dir2_block_to_sf( | |||
247 | 249 | ||
248 | /* now we are done with the block, we can shrink the inode */ | 250 | /* now we are done with the block, we can shrink the inode */ |
249 | logflags = XFS_ILOG_CORE; | 251 | logflags = XFS_ILOG_CORE; |
250 | error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp); | 252 | error = xfs_dir2_shrink_inode(args, args->geo->datablk, bp); |
251 | if (error) { | 253 | if (error) { |
252 | ASSERT(error != ENOSPC); | 254 | ASSERT(error != ENOSPC); |
253 | goto out; | 255 | goto out; |
@@ -285,14 +287,12 @@ int /* error */ | |||
285 | xfs_dir2_sf_addname( | 287 | xfs_dir2_sf_addname( |
286 | xfs_da_args_t *args) /* operation arguments */ | 288 | xfs_da_args_t *args) /* operation arguments */ |
287 | { | 289 | { |
288 | int add_entsize; /* size of the new entry */ | ||
289 | xfs_inode_t *dp; /* incore directory inode */ | 290 | xfs_inode_t *dp; /* incore directory inode */ |
290 | int error; /* error return value */ | 291 | int error; /* error return value */ |
291 | int incr_isize; /* total change in size */ | 292 | int incr_isize; /* total change in size */ |
292 | int new_isize; /* di_size after adding name */ | 293 | int new_isize; /* di_size after adding name */ |
293 | int objchange; /* changing to 8-byte inodes */ | 294 | int objchange; /* changing to 8-byte inodes */ |
294 | xfs_dir2_data_aoff_t offset = 0; /* offset for new entry */ | 295 | xfs_dir2_data_aoff_t offset = 0; /* offset for new entry */ |
295 | int old_isize; /* di_size before adding name */ | ||
296 | int pick; /* which algorithm to use */ | 296 | int pick; /* which algorithm to use */ |
297 | xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ | 297 | xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ |
298 | xfs_dir2_sf_entry_t *sfep = NULL; /* shortform entry */ | 298 | xfs_dir2_sf_entry_t *sfep = NULL; /* shortform entry */ |
@@ -316,8 +316,7 @@ xfs_dir2_sf_addname( | |||
316 | /* | 316 | /* |
317 | * Compute entry (and change in) size. | 317 | * Compute entry (and change in) size. |
318 | */ | 318 | */ |
319 | add_entsize = dp->d_ops->sf_entsize(sfp, args->namelen); | 319 | incr_isize = dp->d_ops->sf_entsize(sfp, args->namelen); |
320 | incr_isize = add_entsize; | ||
321 | objchange = 0; | 320 | objchange = 0; |
322 | #if XFS_BIG_INUMS | 321 | #if XFS_BIG_INUMS |
323 | /* | 322 | /* |
@@ -325,11 +324,8 @@ xfs_dir2_sf_addname( | |||
325 | */ | 324 | */ |
326 | if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) { | 325 | if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) { |
327 | /* | 326 | /* |
328 | * Yes, adjust the entry size and the total size. | 327 | * Yes, adjust the inode size. old count + (parent + new) |
329 | */ | 328 | */ |
330 | add_entsize += | ||
331 | (uint)sizeof(xfs_dir2_ino8_t) - | ||
332 | (uint)sizeof(xfs_dir2_ino4_t); | ||
333 | incr_isize += | 329 | incr_isize += |
334 | (sfp->count + 2) * | 330 | (sfp->count + 2) * |
335 | ((uint)sizeof(xfs_dir2_ino8_t) - | 331 | ((uint)sizeof(xfs_dir2_ino8_t) - |
@@ -337,8 +333,7 @@ xfs_dir2_sf_addname( | |||
337 | objchange = 1; | 333 | objchange = 1; |
338 | } | 334 | } |
339 | #endif | 335 | #endif |
340 | old_isize = (int)dp->i_d.di_size; | 336 | new_isize = (int)dp->i_d.di_size + incr_isize; |
341 | new_isize = old_isize + incr_isize; | ||
342 | /* | 337 | /* |
343 | * Won't fit as shortform any more (due to size), | 338 | * Won't fit as shortform any more (due to size), |
344 | * or the pick routine says it won't (due to offset values). | 339 | * or the pick routine says it won't (due to offset values). |
@@ -593,7 +588,7 @@ xfs_dir2_sf_addname_pick( | |||
593 | * we'll go back, convert to block, then try the insert and convert | 588 | * we'll go back, convert to block, then try the insert and convert |
594 | * to leaf. | 589 | * to leaf. |
595 | */ | 590 | */ |
596 | if (used + (holefit ? 0 : size) > mp->m_dirblksize) | 591 | if (used + (holefit ? 0 : size) > args->geo->blksize) |
597 | return 0; | 592 | return 0; |
598 | /* | 593 | /* |
599 | * If changing the inode number size, do it the hard way. | 594 | * If changing the inode number size, do it the hard way. |
@@ -608,7 +603,7 @@ xfs_dir2_sf_addname_pick( | |||
608 | /* | 603 | /* |
609 | * If it won't fit at the end then do it the hard way (use the hole). | 604 | * If it won't fit at the end then do it the hard way (use the hole). |
610 | */ | 605 | */ |
611 | if (used + size > mp->m_dirblksize) | 606 | if (used + size > args->geo->blksize) |
612 | return 2; | 607 | return 2; |
613 | /* | 608 | /* |
614 | * Do it the easy way. | 609 | * Do it the easy way. |
@@ -659,7 +654,7 @@ xfs_dir2_sf_check( | |||
659 | ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size); | 654 | ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size); |
660 | ASSERT(offset + | 655 | ASSERT(offset + |
661 | (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + | 656 | (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + |
662 | (uint)sizeof(xfs_dir2_block_tail_t) <= mp->m_dirblksize); | 657 | (uint)sizeof(xfs_dir2_block_tail_t) <= args->geo->blksize); |
663 | } | 658 | } |
664 | #endif /* DEBUG */ | 659 | #endif /* DEBUG */ |
665 | 660 | ||
@@ -1110,9 +1105,9 @@ xfs_dir2_sf_toino4( | |||
1110 | } | 1105 | } |
1111 | 1106 | ||
1112 | /* | 1107 | /* |
1113 | * Convert from 4-byte inode numbers to 8-byte inode numbers. | 1108 | * Convert existing entries from 4-byte inode numbers to 8-byte inode numbers. |
1114 | * The new 8-byte inode number is not there yet, we leave with the | 1109 | * The new entry w/ an 8-byte inode number is not there yet; we leave with |
1115 | * count 1 but no corresponding entry. | 1110 | * i8count set to 1, but no corresponding 8-byte entry. |
1116 | */ | 1111 | */ |
1117 | static void | 1112 | static void |
1118 | xfs_dir2_sf_toino8( | 1113 | xfs_dir2_sf_toino8( |
@@ -1145,7 +1140,7 @@ xfs_dir2_sf_toino8( | |||
1145 | ASSERT(oldsfp->i8count == 0); | 1140 | ASSERT(oldsfp->i8count == 0); |
1146 | memcpy(buf, oldsfp, oldsize); | 1141 | memcpy(buf, oldsfp, oldsize); |
1147 | /* | 1142 | /* |
1148 | * Compute the new inode size. | 1143 | * Compute the new inode size (nb: entry count + 1 for parent) |
1149 | */ | 1144 | */ |
1150 | newsize = | 1145 | newsize = |
1151 | oldsize + | 1146 | oldsize + |
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 868b19f096bf..3ee0cd43edc0 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
@@ -353,10 +353,10 @@ xfs_qm_dqalloc( | |||
353 | dqp->q_blkno, | 353 | dqp->q_blkno, |
354 | mp->m_quotainfo->qi_dqchunklen, | 354 | mp->m_quotainfo->qi_dqchunklen, |
355 | 0); | 355 | 0); |
356 | 356 | if (!bp) { | |
357 | error = xfs_buf_geterror(bp); | 357 | error = ENOMEM; |
358 | if (error) | ||
359 | goto error1; | 358 | goto error1; |
359 | } | ||
360 | bp->b_ops = &xfs_dquot_buf_ops; | 360 | bp->b_ops = &xfs_dquot_buf_ops; |
361 | 361 | ||
362 | /* | 362 | /* |
@@ -832,47 +832,6 @@ restart: | |||
832 | return (0); | 832 | return (0); |
833 | } | 833 | } |
834 | 834 | ||
835 | |||
836 | STATIC void | ||
837 | xfs_qm_dqput_final( | ||
838 | struct xfs_dquot *dqp) | ||
839 | { | ||
840 | struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; | ||
841 | struct xfs_dquot *gdqp; | ||
842 | struct xfs_dquot *pdqp; | ||
843 | |||
844 | trace_xfs_dqput_free(dqp); | ||
845 | |||
846 | if (list_lru_add(&qi->qi_lru, &dqp->q_lru)) | ||
847 | XFS_STATS_INC(xs_qm_dquot_unused); | ||
848 | |||
849 | /* | ||
850 | * If we just added a udquot to the freelist, then we want to release | ||
851 | * the gdquot/pdquot reference that it (probably) has. Otherwise it'll | ||
852 | * keep the gdquot/pdquot from getting reclaimed. | ||
853 | */ | ||
854 | gdqp = dqp->q_gdquot; | ||
855 | if (gdqp) { | ||
856 | xfs_dqlock(gdqp); | ||
857 | dqp->q_gdquot = NULL; | ||
858 | } | ||
859 | |||
860 | pdqp = dqp->q_pdquot; | ||
861 | if (pdqp) { | ||
862 | xfs_dqlock(pdqp); | ||
863 | dqp->q_pdquot = NULL; | ||
864 | } | ||
865 | xfs_dqunlock(dqp); | ||
866 | |||
867 | /* | ||
868 | * If we had a group/project quota hint, release it now. | ||
869 | */ | ||
870 | if (gdqp) | ||
871 | xfs_qm_dqput(gdqp); | ||
872 | if (pdqp) | ||
873 | xfs_qm_dqput(pdqp); | ||
874 | } | ||
875 | |||
876 | /* | 835 | /* |
877 | * Release a reference to the dquot (decrement ref-count) and unlock it. | 836 | * Release a reference to the dquot (decrement ref-count) and unlock it. |
878 | * | 837 | * |
@@ -888,10 +847,14 @@ xfs_qm_dqput( | |||
888 | 847 | ||
889 | trace_xfs_dqput(dqp); | 848 | trace_xfs_dqput(dqp); |
890 | 849 | ||
891 | if (--dqp->q_nrefs > 0) | 850 | if (--dqp->q_nrefs == 0) { |
892 | xfs_dqunlock(dqp); | 851 | struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; |
893 | else | 852 | trace_xfs_dqput_free(dqp); |
894 | xfs_qm_dqput_final(dqp); | 853 | |
854 | if (list_lru_add(&qi->qi_lru, &dqp->q_lru)) | ||
855 | XFS_STATS_INC(xs_qm_dquot_unused); | ||
856 | } | ||
857 | xfs_dqunlock(dqp); | ||
895 | } | 858 | } |
896 | 859 | ||
897 | /* | 860 | /* |
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h index d22ed0053c32..68a68f704837 100644 --- a/fs/xfs/xfs_dquot.h +++ b/fs/xfs/xfs_dquot.h | |||
@@ -52,8 +52,6 @@ typedef struct xfs_dquot { | |||
52 | int q_bufoffset; /* off of dq in buffer (# dquots) */ | 52 | int q_bufoffset; /* off of dq in buffer (# dquots) */ |
53 | xfs_fileoff_t q_fileoffset; /* offset in quotas file */ | 53 | xfs_fileoff_t q_fileoffset; /* offset in quotas file */ |
54 | 54 | ||
55 | struct xfs_dquot*q_gdquot; /* group dquot, hint only */ | ||
56 | struct xfs_dquot*q_pdquot; /* project dquot, hint only */ | ||
57 | xfs_disk_dquot_t q_core; /* actual usage & quotas */ | 55 | xfs_disk_dquot_t q_core; /* actual usage & quotas */ |
58 | xfs_dq_logitem_t q_logitem; /* dquot log item */ | 56 | xfs_dq_logitem_t q_logitem; /* dquot log item */ |
59 | xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ | 57 | xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ |
diff --git a/fs/xfs/xfs_dquot_buf.c b/fs/xfs/xfs_dquot_buf.c index 610da8177737..c2ac0c611ad8 100644 --- a/fs/xfs/xfs_dquot_buf.c +++ b/fs/xfs/xfs_dquot_buf.c | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | int | 36 | int |
37 | xfs_calc_dquots_per_chunk( | 37 | xfs_calc_dquots_per_chunk( |
38 | struct xfs_mount *mp, | ||
39 | unsigned int nbblks) /* basic block units */ | 38 | unsigned int nbblks) /* basic block units */ |
40 | { | 39 | { |
41 | unsigned int ndquots; | 40 | unsigned int ndquots; |
@@ -194,7 +193,7 @@ xfs_dquot_buf_verify_crc( | |||
194 | if (mp->m_quotainfo) | 193 | if (mp->m_quotainfo) |
195 | ndquots = mp->m_quotainfo->qi_dqperchunk; | 194 | ndquots = mp->m_quotainfo->qi_dqperchunk; |
196 | else | 195 | else |
197 | ndquots = xfs_calc_dquots_per_chunk(mp, | 196 | ndquots = xfs_calc_dquots_per_chunk( |
198 | XFS_BB_TO_FSB(mp, bp->b_length)); | 197 | XFS_BB_TO_FSB(mp, bp->b_length)); |
199 | 198 | ||
200 | for (i = 0; i < ndquots; i++, d++) { | 199 | for (i = 0; i < ndquots; i++, d++) { |
@@ -225,7 +224,7 @@ xfs_dquot_buf_verify( | |||
225 | if (mp->m_quotainfo) | 224 | if (mp->m_quotainfo) |
226 | ndquots = mp->m_quotainfo->qi_dqperchunk; | 225 | ndquots = mp->m_quotainfo->qi_dqperchunk; |
227 | else | 226 | else |
228 | ndquots = xfs_calc_dquots_per_chunk(mp, bp->b_length); | 227 | ndquots = xfs_calc_dquots_per_chunk(bp->b_length); |
229 | 228 | ||
230 | /* | 229 | /* |
231 | * On the first read of the buffer, verify that each dquot is valid. | 230 | * On the first read of the buffer, verify that each dquot is valid. |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 830c1c937b88..1b8160dc04d1 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -944,7 +944,7 @@ xfs_dir_open( | |||
944 | */ | 944 | */ |
945 | mode = xfs_ilock_data_map_shared(ip); | 945 | mode = xfs_ilock_data_map_shared(ip); |
946 | if (ip->i_d.di_nextents > 0) | 946 | if (ip->i_d.di_nextents > 0) |
947 | xfs_dir3_data_readahead(NULL, ip, 0, -1); | 947 | xfs_dir3_data_readahead(ip, 0, -1); |
948 | xfs_iunlock(ip, mode); | 948 | xfs_iunlock(ip, mode); |
949 | return 0; | 949 | return 0; |
950 | } | 950 | } |
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 12b6e7701985..8ec81bed7992 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006-2007 Silicon Graphics, Inc. | 2 | * Copyright (c) 2006-2007 Silicon Graphics, Inc. |
3 | * Copyright (c) 2014 Christoph Hellwig. | ||
3 | * All Rights Reserved. | 4 | * All Rights Reserved. |
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -32,100 +33,20 @@ | |||
32 | #include "xfs_filestream.h" | 33 | #include "xfs_filestream.h" |
33 | #include "xfs_trace.h" | 34 | #include "xfs_trace.h" |
34 | 35 | ||
35 | #ifdef XFS_FILESTREAMS_TRACE | 36 | struct xfs_fstrm_item { |
36 | 37 | struct xfs_mru_cache_elem mru; | |
37 | ktrace_t *xfs_filestreams_trace_buf; | 38 | struct xfs_inode *ip; |
38 | 39 | xfs_agnumber_t ag; /* AG in use for this directory */ | |
39 | STATIC void | 40 | }; |
40 | xfs_filestreams_trace( | ||
41 | xfs_mount_t *mp, /* mount point */ | ||
42 | int type, /* type of trace */ | ||
43 | const char *func, /* source function */ | ||
44 | int line, /* source line number */ | ||
45 | __psunsigned_t arg0, | ||
46 | __psunsigned_t arg1, | ||
47 | __psunsigned_t arg2, | ||
48 | __psunsigned_t arg3, | ||
49 | __psunsigned_t arg4, | ||
50 | __psunsigned_t arg5) | ||
51 | { | ||
52 | ktrace_enter(xfs_filestreams_trace_buf, | ||
53 | (void *)(__psint_t)(type | (line << 16)), | ||
54 | (void *)func, | ||
55 | (void *)(__psunsigned_t)current_pid(), | ||
56 | (void *)mp, | ||
57 | (void *)(__psunsigned_t)arg0, | ||
58 | (void *)(__psunsigned_t)arg1, | ||
59 | (void *)(__psunsigned_t)arg2, | ||
60 | (void *)(__psunsigned_t)arg3, | ||
61 | (void *)(__psunsigned_t)arg4, | ||
62 | (void *)(__psunsigned_t)arg5, | ||
63 | NULL, NULL, NULL, NULL, NULL, NULL); | ||
64 | } | ||
65 | |||
66 | #define TRACE0(mp,t) TRACE6(mp,t,0,0,0,0,0,0) | ||
67 | #define TRACE1(mp,t,a0) TRACE6(mp,t,a0,0,0,0,0,0) | ||
68 | #define TRACE2(mp,t,a0,a1) TRACE6(mp,t,a0,a1,0,0,0,0) | ||
69 | #define TRACE3(mp,t,a0,a1,a2) TRACE6(mp,t,a0,a1,a2,0,0,0) | ||
70 | #define TRACE4(mp,t,a0,a1,a2,a3) TRACE6(mp,t,a0,a1,a2,a3,0,0) | ||
71 | #define TRACE5(mp,t,a0,a1,a2,a3,a4) TRACE6(mp,t,a0,a1,a2,a3,a4,0) | ||
72 | #define TRACE6(mp,t,a0,a1,a2,a3,a4,a5) \ | ||
73 | xfs_filestreams_trace(mp, t, __func__, __LINE__, \ | ||
74 | (__psunsigned_t)a0, (__psunsigned_t)a1, \ | ||
75 | (__psunsigned_t)a2, (__psunsigned_t)a3, \ | ||
76 | (__psunsigned_t)a4, (__psunsigned_t)a5) | ||
77 | |||
78 | #define TRACE_AG_SCAN(mp, ag, ag2) \ | ||
79 | TRACE2(mp, XFS_FSTRM_KTRACE_AGSCAN, ag, ag2); | ||
80 | #define TRACE_AG_PICK1(mp, max_ag, maxfree) \ | ||
81 | TRACE2(mp, XFS_FSTRM_KTRACE_AGPICK1, max_ag, maxfree); | ||
82 | #define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag) \ | ||
83 | TRACE6(mp, XFS_FSTRM_KTRACE_AGPICK2, ag, ag2, \ | ||
84 | cnt, free, scan, flag) | ||
85 | #define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2) \ | ||
86 | TRACE5(mp, XFS_FSTRM_KTRACE_UPDATE, ip, ag, cnt, ag2, cnt2) | ||
87 | #define TRACE_FREE(mp, ip, pip, ag, cnt) \ | ||
88 | TRACE4(mp, XFS_FSTRM_KTRACE_FREE, ip, pip, ag, cnt) | ||
89 | #define TRACE_LOOKUP(mp, ip, pip, ag, cnt) \ | ||
90 | TRACE4(mp, XFS_FSTRM_KTRACE_ITEM_LOOKUP, ip, pip, ag, cnt) | ||
91 | #define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt) \ | ||
92 | TRACE4(mp, XFS_FSTRM_KTRACE_ASSOCIATE, ip, pip, ag, cnt) | ||
93 | #define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt) \ | ||
94 | TRACE6(mp, XFS_FSTRM_KTRACE_MOVEAG, ip, pip, oag, ocnt, nag, ncnt) | ||
95 | #define TRACE_ORPHAN(mp, ip, ag) \ | ||
96 | TRACE2(mp, XFS_FSTRM_KTRACE_ORPHAN, ip, ag); | ||
97 | |||
98 | |||
99 | #else | ||
100 | #define TRACE_AG_SCAN(mp, ag, ag2) | ||
101 | #define TRACE_AG_PICK1(mp, max_ag, maxfree) | ||
102 | #define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag) | ||
103 | #define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2) | ||
104 | #define TRACE_FREE(mp, ip, pip, ag, cnt) | ||
105 | #define TRACE_LOOKUP(mp, ip, pip, ag, cnt) | ||
106 | #define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt) | ||
107 | #define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt) | ||
108 | #define TRACE_ORPHAN(mp, ip, ag) | ||
109 | #endif | ||
110 | |||
111 | static kmem_zone_t *item_zone; | ||
112 | 41 | ||
113 | /* | 42 | enum xfs_fstrm_alloc { |
114 | * Structure for associating a file or a directory with an allocation group. | 43 | XFS_PICK_USERDATA = 1, |
115 | * The parent directory pointer is only needed for files, but since there will | 44 | XFS_PICK_LOWSPACE = 2, |
116 | * generally be vastly more files than directories in the cache, using the same | 45 | }; |
117 | * data structure simplifies the code with very little memory overhead. | ||
118 | */ | ||
119 | typedef struct fstrm_item | ||
120 | { | ||
121 | xfs_agnumber_t ag; /* AG currently in use for the file/directory. */ | ||
122 | xfs_inode_t *ip; /* inode self-pointer. */ | ||
123 | xfs_inode_t *pip; /* Parent directory inode pointer. */ | ||
124 | } fstrm_item_t; | ||
125 | 46 | ||
126 | /* | 47 | /* |
127 | * Allocation group filestream associations are tracked with per-ag atomic | 48 | * Allocation group filestream associations are tracked with per-ag atomic |
128 | * counters. These counters allow _xfs_filestream_pick_ag() to tell whether a | 49 | * counters. These counters allow xfs_filestream_pick_ag() to tell whether a |
129 | * particular AG already has active filestreams associated with it. The mount | 50 | * particular AG already has active filestreams associated with it. The mount |
130 | * point's m_peraglock is used to protect these counters from per-ag array | 51 | * point's m_peraglock is used to protect these counters from per-ag array |
131 | * re-allocation during a growfs operation. When xfs_growfs_data_private() is | 52 | * re-allocation during a growfs operation. When xfs_growfs_data_private() is |
@@ -160,7 +81,7 @@ typedef struct fstrm_item | |||
160 | * the cache that reference per-ag array elements that have since been | 81 | * the cache that reference per-ag array elements that have since been |
161 | * reallocated. | 82 | * reallocated. |
162 | */ | 83 | */ |
163 | static int | 84 | int |
164 | xfs_filestream_peek_ag( | 85 | xfs_filestream_peek_ag( |
165 | xfs_mount_t *mp, | 86 | xfs_mount_t *mp, |
166 | xfs_agnumber_t agno) | 87 | xfs_agnumber_t agno) |
@@ -200,23 +121,40 @@ xfs_filestream_put_ag( | |||
200 | xfs_perag_put(pag); | 121 | xfs_perag_put(pag); |
201 | } | 122 | } |
202 | 123 | ||
124 | static void | ||
125 | xfs_fstrm_free_func( | ||
126 | struct xfs_mru_cache_elem *mru) | ||
127 | { | ||
128 | struct xfs_fstrm_item *item = | ||
129 | container_of(mru, struct xfs_fstrm_item, mru); | ||
130 | |||
131 | xfs_filestream_put_ag(item->ip->i_mount, item->ag); | ||
132 | |||
133 | trace_xfs_filestream_free(item->ip, item->ag); | ||
134 | |||
135 | kmem_free(item); | ||
136 | } | ||
137 | |||
203 | /* | 138 | /* |
204 | * Scan the AGs starting at startag looking for an AG that isn't in use and has | 139 | * Scan the AGs starting at startag looking for an AG that isn't in use and has |
205 | * at least minlen blocks free. | 140 | * at least minlen blocks free. |
206 | */ | 141 | */ |
207 | static int | 142 | static int |
208 | _xfs_filestream_pick_ag( | 143 | xfs_filestream_pick_ag( |
209 | xfs_mount_t *mp, | 144 | struct xfs_inode *ip, |
210 | xfs_agnumber_t startag, | 145 | xfs_agnumber_t startag, |
211 | xfs_agnumber_t *agp, | 146 | xfs_agnumber_t *agp, |
212 | int flags, | 147 | int flags, |
213 | xfs_extlen_t minlen) | 148 | xfs_extlen_t minlen) |
214 | { | 149 | { |
215 | int streams, max_streams; | 150 | struct xfs_mount *mp = ip->i_mount; |
216 | int err, trylock, nscan; | 151 | struct xfs_fstrm_item *item; |
217 | xfs_extlen_t longest, free, minfree, maxfree = 0; | 152 | struct xfs_perag *pag; |
218 | xfs_agnumber_t ag, max_ag = NULLAGNUMBER; | 153 | xfs_extlen_t longest, free = 0, minfree, maxfree = 0; |
219 | struct xfs_perag *pag; | 154 | xfs_agnumber_t ag, max_ag = NULLAGNUMBER; |
155 | int err, trylock, nscan; | ||
156 | |||
157 | ASSERT(S_ISDIR(ip->i_d.di_mode)); | ||
220 | 158 | ||
221 | /* 2% of an AG's blocks must be free for it to be chosen. */ | 159 | /* 2% of an AG's blocks must be free for it to be chosen. */ |
222 | minfree = mp->m_sb.sb_agblocks / 50; | 160 | minfree = mp->m_sb.sb_agblocks / 50; |
@@ -228,8 +166,9 @@ _xfs_filestream_pick_ag( | |||
228 | trylock = XFS_ALLOC_FLAG_TRYLOCK; | 166 | trylock = XFS_ALLOC_FLAG_TRYLOCK; |
229 | 167 | ||
230 | for (nscan = 0; 1; nscan++) { | 168 | for (nscan = 0; 1; nscan++) { |
169 | trace_xfs_filestream_scan(ip, ag); | ||
170 | |||
231 | pag = xfs_perag_get(mp, ag); | 171 | pag = xfs_perag_get(mp, ag); |
232 | TRACE_AG_SCAN(mp, ag, atomic_read(&pag->pagf_fstrms)); | ||
233 | 172 | ||
234 | if (!pag->pagf_init) { | 173 | if (!pag->pagf_init) { |
235 | err = xfs_alloc_pagf_init(mp, NULL, ag, trylock); | 174 | err = xfs_alloc_pagf_init(mp, NULL, ag, trylock); |
@@ -246,7 +185,6 @@ _xfs_filestream_pick_ag( | |||
246 | /* Keep track of the AG with the most free blocks. */ | 185 | /* Keep track of the AG with the most free blocks. */ |
247 | if (pag->pagf_freeblks > maxfree) { | 186 | if (pag->pagf_freeblks > maxfree) { |
248 | maxfree = pag->pagf_freeblks; | 187 | maxfree = pag->pagf_freeblks; |
249 | max_streams = atomic_read(&pag->pagf_fstrms); | ||
250 | max_ag = ag; | 188 | max_ag = ag; |
251 | } | 189 | } |
252 | 190 | ||
@@ -269,7 +207,6 @@ _xfs_filestream_pick_ag( | |||
269 | 207 | ||
270 | /* Break out, retaining the reference on the AG. */ | 208 | /* Break out, retaining the reference on the AG. */ |
271 | free = pag->pagf_freeblks; | 209 | free = pag->pagf_freeblks; |
272 | streams = atomic_read(&pag->pagf_fstrms); | ||
273 | xfs_perag_put(pag); | 210 | xfs_perag_put(pag); |
274 | *agp = ag; | 211 | *agp = ag; |
275 | break; | 212 | break; |
@@ -305,317 +242,98 @@ next_ag: | |||
305 | */ | 242 | */ |
306 | if (max_ag != NULLAGNUMBER) { | 243 | if (max_ag != NULLAGNUMBER) { |
307 | xfs_filestream_get_ag(mp, max_ag); | 244 | xfs_filestream_get_ag(mp, max_ag); |
308 | TRACE_AG_PICK1(mp, max_ag, maxfree); | ||
309 | streams = max_streams; | ||
310 | free = maxfree; | 245 | free = maxfree; |
311 | *agp = max_ag; | 246 | *agp = max_ag; |
312 | break; | 247 | break; |
313 | } | 248 | } |
314 | 249 | ||
315 | /* take AG 0 if none matched */ | 250 | /* take AG 0 if none matched */ |
316 | TRACE_AG_PICK1(mp, max_ag, maxfree); | 251 | trace_xfs_filestream_pick(ip, *agp, free, nscan); |
317 | *agp = 0; | 252 | *agp = 0; |
318 | return 0; | 253 | return 0; |
319 | } | 254 | } |
320 | 255 | ||
321 | TRACE_AG_PICK2(mp, startag, *agp, streams, free, nscan, flags); | 256 | trace_xfs_filestream_pick(ip, *agp, free, nscan); |
322 | |||
323 | return 0; | ||
324 | } | ||
325 | 257 | ||
326 | /* | 258 | if (*agp == NULLAGNUMBER) |
327 | * Set the allocation group number for a file or a directory, updating inode | ||
328 | * references and per-AG references as appropriate. | ||
329 | */ | ||
330 | static int | ||
331 | _xfs_filestream_update_ag( | ||
332 | xfs_inode_t *ip, | ||
333 | xfs_inode_t *pip, | ||
334 | xfs_agnumber_t ag) | ||
335 | { | ||
336 | int err = 0; | ||
337 | xfs_mount_t *mp; | ||
338 | xfs_mru_cache_t *cache; | ||
339 | fstrm_item_t *item; | ||
340 | xfs_agnumber_t old_ag; | ||
341 | xfs_inode_t *old_pip; | ||
342 | |||
343 | /* | ||
344 | * Either ip is a regular file and pip is a directory, or ip is a | ||
345 | * directory and pip is NULL. | ||
346 | */ | ||
347 | ASSERT(ip && ((S_ISREG(ip->i_d.di_mode) && pip && | ||
348 | S_ISDIR(pip->i_d.di_mode)) || | ||
349 | (S_ISDIR(ip->i_d.di_mode) && !pip))); | ||
350 | |||
351 | mp = ip->i_mount; | ||
352 | cache = mp->m_filestream; | ||
353 | |||
354 | item = xfs_mru_cache_lookup(cache, ip->i_ino); | ||
355 | if (item) { | ||
356 | ASSERT(item->ip == ip); | ||
357 | old_ag = item->ag; | ||
358 | item->ag = ag; | ||
359 | old_pip = item->pip; | ||
360 | item->pip = pip; | ||
361 | xfs_mru_cache_done(cache); | ||
362 | |||
363 | /* | ||
364 | * If the AG has changed, drop the old ref and take a new one, | ||
365 | * effectively transferring the reference from old to new AG. | ||
366 | */ | ||
367 | if (ag != old_ag) { | ||
368 | xfs_filestream_put_ag(mp, old_ag); | ||
369 | xfs_filestream_get_ag(mp, ag); | ||
370 | } | ||
371 | |||
372 | /* | ||
373 | * If ip is a file and its pip has changed, drop the old ref and | ||
374 | * take a new one. | ||
375 | */ | ||
376 | if (pip && pip != old_pip) { | ||
377 | IRELE(old_pip); | ||
378 | IHOLD(pip); | ||
379 | } | ||
380 | |||
381 | TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag), | ||
382 | ag, xfs_filestream_peek_ag(mp, ag)); | ||
383 | return 0; | 259 | return 0; |
384 | } | ||
385 | 260 | ||
386 | item = kmem_zone_zalloc(item_zone, KM_MAYFAIL); | 261 | err = ENOMEM; |
262 | item = kmem_alloc(sizeof(*item), KM_MAYFAIL); | ||
387 | if (!item) | 263 | if (!item) |
388 | return ENOMEM; | 264 | goto out_put_ag; |
389 | 265 | ||
390 | item->ag = ag; | 266 | item->ag = *agp; |
391 | item->ip = ip; | 267 | item->ip = ip; |
392 | item->pip = pip; | ||
393 | 268 | ||
394 | err = xfs_mru_cache_insert(cache, ip->i_ino, item); | 269 | err = xfs_mru_cache_insert(mp->m_filestream, ip->i_ino, &item->mru); |
395 | if (err) { | 270 | if (err) { |
396 | kmem_zone_free(item_zone, item); | 271 | if (err == EEXIST) |
397 | return err; | 272 | err = 0; |
273 | goto out_free_item; | ||
398 | } | 274 | } |
399 | 275 | ||
400 | /* Take a reference on the AG. */ | ||
401 | xfs_filestream_get_ag(mp, ag); | ||
402 | |||
403 | /* | ||
404 | * Take a reference on the inode itself regardless of whether it's a | ||
405 | * regular file or a directory. | ||
406 | */ | ||
407 | IHOLD(ip); | ||
408 | |||
409 | /* | ||
410 | * In the case of a regular file, take a reference on the parent inode | ||
411 | * as well to ensure it remains in-core. | ||
412 | */ | ||
413 | if (pip) | ||
414 | IHOLD(pip); | ||
415 | |||
416 | TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag), | ||
417 | ag, xfs_filestream_peek_ag(mp, ag)); | ||
418 | |||
419 | return 0; | 276 | return 0; |
420 | } | ||
421 | |||
422 | /* xfs_fstrm_free_func(): callback for freeing cached stream items. */ | ||
423 | STATIC void | ||
424 | xfs_fstrm_free_func( | ||
425 | unsigned long ino, | ||
426 | void *data) | ||
427 | { | ||
428 | fstrm_item_t *item = (fstrm_item_t *)data; | ||
429 | xfs_inode_t *ip = item->ip; | ||
430 | |||
431 | ASSERT(ip->i_ino == ino); | ||
432 | |||
433 | xfs_iflags_clear(ip, XFS_IFILESTREAM); | ||
434 | |||
435 | /* Drop the reference taken on the AG when the item was added. */ | ||
436 | xfs_filestream_put_ag(ip->i_mount, item->ag); | ||
437 | |||
438 | TRACE_FREE(ip->i_mount, ip, item->pip, item->ag, | ||
439 | xfs_filestream_peek_ag(ip->i_mount, item->ag)); | ||
440 | |||
441 | /* | ||
442 | * _xfs_filestream_update_ag() always takes a reference on the inode | ||
443 | * itself, whether it's a file or a directory. Release it here. | ||
444 | * This can result in the inode being freed and so we must | ||
445 | * not hold any inode locks when freeing filesstreams objects | ||
446 | * otherwise we can deadlock here. | ||
447 | */ | ||
448 | IRELE(ip); | ||
449 | |||
450 | /* | ||
451 | * In the case of a regular file, _xfs_filestream_update_ag() also | ||
452 | * takes a ref on the parent inode to keep it in-core. Release that | ||
453 | * too. | ||
454 | */ | ||
455 | if (item->pip) | ||
456 | IRELE(item->pip); | ||
457 | |||
458 | /* Finally, free the memory allocated for the item. */ | ||
459 | kmem_zone_free(item_zone, item); | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * xfs_filestream_init() is called at xfs initialisation time to set up the | ||
464 | * memory zone that will be used for filestream data structure allocation. | ||
465 | */ | ||
466 | int | ||
467 | xfs_filestream_init(void) | ||
468 | { | ||
469 | item_zone = kmem_zone_init(sizeof(fstrm_item_t), "fstrm_item"); | ||
470 | if (!item_zone) | ||
471 | return -ENOMEM; | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | /* | ||
477 | * xfs_filestream_uninit() is called at xfs termination time to destroy the | ||
478 | * memory zone that was used for filestream data structure allocation. | ||
479 | */ | ||
480 | void | ||
481 | xfs_filestream_uninit(void) | ||
482 | { | ||
483 | kmem_zone_destroy(item_zone); | ||
484 | } | ||
485 | |||
486 | /* | ||
487 | * xfs_filestream_mount() is called when a file system is mounted with the | ||
488 | * filestream option. It is responsible for allocating the data structures | ||
489 | * needed to track the new file system's file streams. | ||
490 | */ | ||
491 | int | ||
492 | xfs_filestream_mount( | ||
493 | xfs_mount_t *mp) | ||
494 | { | ||
495 | int err; | ||
496 | unsigned int lifetime, grp_count; | ||
497 | |||
498 | /* | ||
499 | * The filestream timer tunable is currently fixed within the range of | ||
500 | * one second to four minutes, with five seconds being the default. The | ||
501 | * group count is somewhat arbitrary, but it'd be nice to adhere to the | ||
502 | * timer tunable to within about 10 percent. This requires at least 10 | ||
503 | * groups. | ||
504 | */ | ||
505 | lifetime = xfs_fstrm_centisecs * 10; | ||
506 | grp_count = 10; | ||
507 | |||
508 | err = xfs_mru_cache_create(&mp->m_filestream, lifetime, grp_count, | ||
509 | xfs_fstrm_free_func); | ||
510 | 277 | ||
278 | out_free_item: | ||
279 | kmem_free(item); | ||
280 | out_put_ag: | ||
281 | xfs_filestream_put_ag(mp, *agp); | ||
511 | return err; | 282 | return err; |
512 | } | 283 | } |
513 | 284 | ||
514 | /* | 285 | static struct xfs_inode * |
515 | * xfs_filestream_unmount() is called when a file system that was mounted with | 286 | xfs_filestream_get_parent( |
516 | * the filestream option is unmounted. It drains the data structures created | 287 | struct xfs_inode *ip) |
517 | * to track the file system's file streams and frees all the memory that was | ||
518 | * allocated. | ||
519 | */ | ||
520 | void | ||
521 | xfs_filestream_unmount( | ||
522 | xfs_mount_t *mp) | ||
523 | { | 288 | { |
524 | xfs_mru_cache_destroy(mp->m_filestream); | 289 | struct inode *inode = VFS_I(ip), *dir = NULL; |
525 | } | 290 | struct dentry *dentry, *parent; |
526 | 291 | ||
527 | /* | 292 | dentry = d_find_alias(inode); |
528 | * Return the AG of the filestream the file or directory belongs to, or | 293 | if (!dentry) |
529 | * NULLAGNUMBER otherwise. | 294 | goto out; |
530 | */ | ||
531 | xfs_agnumber_t | ||
532 | xfs_filestream_lookup_ag( | ||
533 | xfs_inode_t *ip) | ||
534 | { | ||
535 | xfs_mru_cache_t *cache; | ||
536 | fstrm_item_t *item; | ||
537 | xfs_agnumber_t ag; | ||
538 | int ref; | ||
539 | |||
540 | if (!S_ISREG(ip->i_d.di_mode) && !S_ISDIR(ip->i_d.di_mode)) { | ||
541 | ASSERT(0); | ||
542 | return NULLAGNUMBER; | ||
543 | } | ||
544 | 295 | ||
545 | cache = ip->i_mount->m_filestream; | 296 | parent = dget_parent(dentry); |
546 | item = xfs_mru_cache_lookup(cache, ip->i_ino); | 297 | if (!parent) |
547 | if (!item) { | 298 | goto out_dput; |
548 | TRACE_LOOKUP(ip->i_mount, ip, NULL, NULLAGNUMBER, 0); | ||
549 | return NULLAGNUMBER; | ||
550 | } | ||
551 | 299 | ||
552 | ASSERT(ip == item->ip); | 300 | dir = igrab(parent->d_inode); |
553 | ag = item->ag; | 301 | dput(parent); |
554 | ref = xfs_filestream_peek_ag(ip->i_mount, ag); | ||
555 | xfs_mru_cache_done(cache); | ||
556 | 302 | ||
557 | TRACE_LOOKUP(ip->i_mount, ip, item->pip, ag, ref); | 303 | out_dput: |
558 | return ag; | 304 | dput(dentry); |
305 | out: | ||
306 | return dir ? XFS_I(dir) : NULL; | ||
559 | } | 307 | } |
560 | 308 | ||
561 | /* | 309 | /* |
562 | * xfs_filestream_associate() should only be called to associate a regular file | 310 | * Find the right allocation group for a file, either by finding an |
563 | * with its parent directory. Calling it with a child directory isn't | 311 | * existing file stream or creating a new one. |
564 | * appropriate because filestreams don't apply to entire directory hierarchies. | ||
565 | * Creating a file in a child directory of an existing filestream directory | ||
566 | * starts a new filestream with its own allocation group association. | ||
567 | * | 312 | * |
568 | * Returns < 0 on error, 0 if successful association occurred, > 0 if | 313 | * Returns NULLAGNUMBER in case of an error. |
569 | * we failed to get an association because of locking issues. | ||
570 | */ | 314 | */ |
571 | int | 315 | xfs_agnumber_t |
572 | xfs_filestream_associate( | 316 | xfs_filestream_lookup_ag( |
573 | xfs_inode_t *pip, | 317 | struct xfs_inode *ip) |
574 | xfs_inode_t *ip) | ||
575 | { | 318 | { |
576 | xfs_mount_t *mp; | 319 | struct xfs_mount *mp = ip->i_mount; |
577 | xfs_mru_cache_t *cache; | 320 | struct xfs_inode *pip = NULL; |
578 | fstrm_item_t *item; | 321 | xfs_agnumber_t startag, ag = NULLAGNUMBER; |
579 | xfs_agnumber_t ag, rotorstep, startag; | 322 | struct xfs_mru_cache_elem *mru; |
580 | int err = 0; | ||
581 | 323 | ||
582 | ASSERT(S_ISDIR(pip->i_d.di_mode)); | ||
583 | ASSERT(S_ISREG(ip->i_d.di_mode)); | 324 | ASSERT(S_ISREG(ip->i_d.di_mode)); |
584 | if (!S_ISDIR(pip->i_d.di_mode) || !S_ISREG(ip->i_d.di_mode)) | ||
585 | return -EINVAL; | ||
586 | 325 | ||
587 | mp = pip->i_mount; | 326 | pip = xfs_filestream_get_parent(ip); |
588 | cache = mp->m_filestream; | 327 | if (!pip) |
328 | goto out; | ||
589 | 329 | ||
590 | /* | 330 | mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino); |
591 | * We have a problem, Houston. | 331 | if (mru) { |
592 | * | 332 | ag = container_of(mru, struct xfs_fstrm_item, mru)->ag; |
593 | * Taking the iolock here violates inode locking order - we already | 333 | xfs_mru_cache_done(mp->m_filestream); |
594 | * hold the ilock. Hence if we block getting this lock we may never | ||
595 | * wake. Unfortunately, that means if we can't get the lock, we're | ||
596 | * screwed in terms of getting a stream association - we can't spin | ||
597 | * waiting for the lock because someone else is waiting on the lock we | ||
598 | * hold and we cannot drop that as we are in a transaction here. | ||
599 | * | ||
600 | * Lucky for us, this inversion is not a problem because it's a | ||
601 | * directory inode that we are trying to lock here. | ||
602 | * | ||
603 | * So, if we can't get the iolock without sleeping then just give up | ||
604 | */ | ||
605 | if (!xfs_ilock_nowait(pip, XFS_IOLOCK_EXCL)) | ||
606 | return 1; | ||
607 | |||
608 | /* If the parent directory is already in the cache, use its AG. */ | ||
609 | item = xfs_mru_cache_lookup(cache, pip->i_ino); | ||
610 | if (item) { | ||
611 | ASSERT(item->ip == pip); | ||
612 | ag = item->ag; | ||
613 | xfs_mru_cache_done(cache); | ||
614 | |||
615 | TRACE_LOOKUP(mp, pip, pip, ag, xfs_filestream_peek_ag(mp, ag)); | ||
616 | err = _xfs_filestream_update_ag(ip, pip, ag); | ||
617 | 334 | ||
618 | goto exit; | 335 | trace_xfs_filestream_lookup(ip, ag); |
336 | goto out; | ||
619 | } | 337 | } |
620 | 338 | ||
621 | /* | 339 | /* |
@@ -623,202 +341,94 @@ xfs_filestream_associate( | |||
623 | * use the directory inode's AG. | 341 | * use the directory inode's AG. |
624 | */ | 342 | */ |
625 | if (mp->m_flags & XFS_MOUNT_32BITINODES) { | 343 | if (mp->m_flags & XFS_MOUNT_32BITINODES) { |
626 | rotorstep = xfs_rotorstep; | 344 | xfs_agnumber_t rotorstep = xfs_rotorstep; |
627 | startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount; | 345 | startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount; |
628 | mp->m_agfrotor = (mp->m_agfrotor + 1) % | 346 | mp->m_agfrotor = (mp->m_agfrotor + 1) % |
629 | (mp->m_sb.sb_agcount * rotorstep); | 347 | (mp->m_sb.sb_agcount * rotorstep); |
630 | } else | 348 | } else |
631 | startag = XFS_INO_TO_AGNO(mp, pip->i_ino); | 349 | startag = XFS_INO_TO_AGNO(mp, pip->i_ino); |
632 | 350 | ||
633 | /* Pick a new AG for the parent inode starting at startag. */ | 351 | if (xfs_filestream_pick_ag(pip, startag, &ag, 0, 0)) |
634 | err = _xfs_filestream_pick_ag(mp, startag, &ag, 0, 0); | 352 | ag = NULLAGNUMBER; |
635 | if (err || ag == NULLAGNUMBER) | 353 | out: |
636 | goto exit_did_pick; | 354 | IRELE(pip); |
637 | 355 | return ag; | |
638 | /* Associate the parent inode with the AG. */ | ||
639 | err = _xfs_filestream_update_ag(pip, NULL, ag); | ||
640 | if (err) | ||
641 | goto exit_did_pick; | ||
642 | |||
643 | /* Associate the file inode with the AG. */ | ||
644 | err = _xfs_filestream_update_ag(ip, pip, ag); | ||
645 | if (err) | ||
646 | goto exit_did_pick; | ||
647 | |||
648 | TRACE_ASSOCIATE(mp, ip, pip, ag, xfs_filestream_peek_ag(mp, ag)); | ||
649 | |||
650 | exit_did_pick: | ||
651 | /* | ||
652 | * If _xfs_filestream_pick_ag() returned a valid AG, remove the | ||
653 | * reference it took on it, since the file and directory will have taken | ||
654 | * their own now if they were successfully cached. | ||
655 | */ | ||
656 | if (ag != NULLAGNUMBER) | ||
657 | xfs_filestream_put_ag(mp, ag); | ||
658 | |||
659 | exit: | ||
660 | xfs_iunlock(pip, XFS_IOLOCK_EXCL); | ||
661 | return -err; | ||
662 | } | 356 | } |
663 | 357 | ||
664 | /* | 358 | /* |
665 | * Pick a new allocation group for the current file and its file stream. This | 359 | * Pick a new allocation group for the current file and its file stream. |
666 | * function is called by xfs_bmap_filestreams() with the mount point's per-ag | 360 | * |
667 | * lock held. | 361 | * This is called when the allocator can't find a suitable extent in the |
362 | * current AG, and we have to move the stream into a new AG with more space. | ||
668 | */ | 363 | */ |
669 | int | 364 | int |
670 | xfs_filestream_new_ag( | 365 | xfs_filestream_new_ag( |
671 | struct xfs_bmalloca *ap, | 366 | struct xfs_bmalloca *ap, |
672 | xfs_agnumber_t *agp) | 367 | xfs_agnumber_t *agp) |
673 | { | 368 | { |
674 | int flags, err; | 369 | struct xfs_inode *ip = ap->ip, *pip; |
675 | xfs_inode_t *ip, *pip = NULL; | 370 | struct xfs_mount *mp = ip->i_mount; |
676 | xfs_mount_t *mp; | 371 | xfs_extlen_t minlen = ap->length; |
677 | xfs_mru_cache_t *cache; | 372 | xfs_agnumber_t startag = 0; |
678 | xfs_extlen_t minlen; | 373 | int flags, err = 0; |
679 | fstrm_item_t *dir, *file; | 374 | struct xfs_mru_cache_elem *mru; |
680 | xfs_agnumber_t ag = NULLAGNUMBER; | ||
681 | |||
682 | ip = ap->ip; | ||
683 | mp = ip->i_mount; | ||
684 | cache = mp->m_filestream; | ||
685 | minlen = ap->length; | ||
686 | *agp = NULLAGNUMBER; | ||
687 | 375 | ||
688 | /* | 376 | *agp = NULLAGNUMBER; |
689 | * Look for the file in the cache, removing it if it's found. Doing | ||
690 | * this allows it to be held across the dir lookup that follows. | ||
691 | */ | ||
692 | file = xfs_mru_cache_remove(cache, ip->i_ino); | ||
693 | if (file) { | ||
694 | ASSERT(ip == file->ip); | ||
695 | |||
696 | /* Save the file's parent inode and old AG number for later. */ | ||
697 | pip = file->pip; | ||
698 | ag = file->ag; | ||
699 | |||
700 | /* Look for the file's directory in the cache. */ | ||
701 | dir = xfs_mru_cache_lookup(cache, pip->i_ino); | ||
702 | if (dir) { | ||
703 | ASSERT(pip == dir->ip); | ||
704 | |||
705 | /* | ||
706 | * If the directory has already moved on to a new AG, | ||
707 | * use that AG as the new AG for the file. Don't | ||
708 | * forget to twiddle the AG refcounts to match the | ||
709 | * movement. | ||
710 | */ | ||
711 | if (dir->ag != file->ag) { | ||
712 | xfs_filestream_put_ag(mp, file->ag); | ||
713 | xfs_filestream_get_ag(mp, dir->ag); | ||
714 | *agp = file->ag = dir->ag; | ||
715 | } | ||
716 | |||
717 | xfs_mru_cache_done(cache); | ||
718 | } | ||
719 | 377 | ||
720 | /* | 378 | pip = xfs_filestream_get_parent(ip); |
721 | * Put the file back in the cache. If this fails, the free | 379 | if (!pip) |
722 | * function needs to be called to tidy up in the same way as if | 380 | goto exit; |
723 | * the item had simply expired from the cache. | ||
724 | */ | ||
725 | err = xfs_mru_cache_insert(cache, ip->i_ino, file); | ||
726 | if (err) { | ||
727 | xfs_fstrm_free_func(ip->i_ino, file); | ||
728 | return err; | ||
729 | } | ||
730 | 381 | ||
731 | /* | 382 | mru = xfs_mru_cache_remove(mp->m_filestream, pip->i_ino); |
732 | * If the file's AG was moved to the directory's new AG, there's | 383 | if (mru) { |
733 | * nothing more to be done. | 384 | struct xfs_fstrm_item *item = |
734 | */ | 385 | container_of(mru, struct xfs_fstrm_item, mru); |
735 | if (*agp != NULLAGNUMBER) { | 386 | startag = (item->ag + 1) % mp->m_sb.sb_agcount; |
736 | TRACE_MOVEAG(mp, ip, pip, | ||
737 | ag, xfs_filestream_peek_ag(mp, ag), | ||
738 | *agp, xfs_filestream_peek_ag(mp, *agp)); | ||
739 | return 0; | ||
740 | } | ||
741 | } | 387 | } |
742 | 388 | ||
743 | /* | ||
744 | * If the file's parent directory is known, take its iolock in exclusive | ||
745 | * mode to prevent two sibling files from racing each other to migrate | ||
746 | * themselves and their parent to different AGs. | ||
747 | * | ||
748 | * Note that we lock the parent directory iolock inside the child | ||
749 | * iolock here. That's fine as we never hold both parent and child | ||
750 | * iolock in any other place. This is different from the ilock, | ||
751 | * which requires locking of the child after the parent for namespace | ||
752 | * operations. | ||
753 | */ | ||
754 | if (pip) | ||
755 | xfs_ilock(pip, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); | ||
756 | |||
757 | /* | ||
758 | * A new AG needs to be found for the file. If the file's parent | ||
759 | * directory is also known, it will be moved to the new AG as well to | ||
760 | * ensure that files created inside it in future use the new AG. | ||
761 | */ | ||
762 | ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount; | ||
763 | flags = (ap->userdata ? XFS_PICK_USERDATA : 0) | | 389 | flags = (ap->userdata ? XFS_PICK_USERDATA : 0) | |
764 | (ap->flist->xbf_low ? XFS_PICK_LOWSPACE : 0); | 390 | (ap->flist->xbf_low ? XFS_PICK_LOWSPACE : 0); |
765 | 391 | ||
766 | err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen); | 392 | err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen); |
767 | if (err || *agp == NULLAGNUMBER) | ||
768 | goto exit; | ||
769 | 393 | ||
770 | /* | 394 | /* |
771 | * If the file wasn't found in the file cache, then its parent directory | 395 | * Only free the item here so we skip over the old AG earlier. |
772 | * inode isn't known. For this to have happened, the file must either | ||
773 | * be pre-existing, or it was created long enough ago that its cache | ||
774 | * entry has expired. This isn't the sort of usage that the filestreams | ||
775 | * allocator is trying to optimise, so there's no point trying to track | ||
776 | * its new AG somehow in the filestream data structures. | ||
777 | */ | 396 | */ |
778 | if (!pip) { | 397 | if (mru) |
779 | TRACE_ORPHAN(mp, ip, *agp); | 398 | xfs_fstrm_free_func(mru); |
780 | goto exit; | ||
781 | } | ||
782 | |||
783 | /* Associate the parent inode with the AG. */ | ||
784 | err = _xfs_filestream_update_ag(pip, NULL, *agp); | ||
785 | if (err) | ||
786 | goto exit; | ||
787 | |||
788 | /* Associate the file inode with the AG. */ | ||
789 | err = _xfs_filestream_update_ag(ip, pip, *agp); | ||
790 | if (err) | ||
791 | goto exit; | ||
792 | |||
793 | TRACE_MOVEAG(mp, ip, pip, NULLAGNUMBER, 0, | ||
794 | *agp, xfs_filestream_peek_ag(mp, *agp)); | ||
795 | 399 | ||
400 | IRELE(pip); | ||
796 | exit: | 401 | exit: |
797 | /* | 402 | if (*agp == NULLAGNUMBER) |
798 | * If _xfs_filestream_pick_ag() returned a valid AG, remove the | ||
799 | * reference it took on it, since the file and directory will have taken | ||
800 | * their own now if they were successfully cached. | ||
801 | */ | ||
802 | if (*agp != NULLAGNUMBER) | ||
803 | xfs_filestream_put_ag(mp, *agp); | ||
804 | else | ||
805 | *agp = 0; | 403 | *agp = 0; |
806 | |||
807 | if (pip) | ||
808 | xfs_iunlock(pip, XFS_IOLOCK_EXCL); | ||
809 | |||
810 | return err; | 404 | return err; |
811 | } | 405 | } |
812 | 406 | ||
813 | /* | ||
814 | * Remove an association between an inode and a filestream object. | ||
815 | * Typically this is done on last close of an unlinked file. | ||
816 | */ | ||
817 | void | 407 | void |
818 | xfs_filestream_deassociate( | 408 | xfs_filestream_deassociate( |
819 | xfs_inode_t *ip) | 409 | struct xfs_inode *ip) |
820 | { | 410 | { |
821 | xfs_mru_cache_t *cache = ip->i_mount->m_filestream; | 411 | xfs_mru_cache_delete(ip->i_mount->m_filestream, ip->i_ino); |
412 | } | ||
413 | |||
414 | int | ||
415 | xfs_filestream_mount( | ||
416 | xfs_mount_t *mp) | ||
417 | { | ||
418 | /* | ||
419 | * The filestream timer tunable is currently fixed within the range of | ||
420 | * one second to four minutes, with five seconds being the default. The | ||
421 | * group count is somewhat arbitrary, but it'd be nice to adhere to the | ||
422 | * timer tunable to within about 10 percent. This requires at least 10 | ||
423 | * groups. | ||
424 | */ | ||
425 | return xfs_mru_cache_create(&mp->m_filestream, xfs_fstrm_centisecs * 10, | ||
426 | 10, xfs_fstrm_free_func); | ||
427 | } | ||
822 | 428 | ||
823 | xfs_mru_cache_delete(cache, ip->i_ino); | 429 | void |
430 | xfs_filestream_unmount( | ||
431 | xfs_mount_t *mp) | ||
432 | { | ||
433 | xfs_mru_cache_destroy(mp->m_filestream); | ||
824 | } | 434 | } |
diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h index 6d61dbee8564..2ef43406e53b 100644 --- a/fs/xfs/xfs_filestream.h +++ b/fs/xfs/xfs_filestream.h | |||
@@ -20,50 +20,20 @@ | |||
20 | 20 | ||
21 | struct xfs_mount; | 21 | struct xfs_mount; |
22 | struct xfs_inode; | 22 | struct xfs_inode; |
23 | struct xfs_perag; | ||
24 | struct xfs_bmalloca; | 23 | struct xfs_bmalloca; |
25 | 24 | ||
26 | #ifdef XFS_FILESTREAMS_TRACE | ||
27 | #define XFS_FSTRM_KTRACE_INFO 1 | ||
28 | #define XFS_FSTRM_KTRACE_AGSCAN 2 | ||
29 | #define XFS_FSTRM_KTRACE_AGPICK1 3 | ||
30 | #define XFS_FSTRM_KTRACE_AGPICK2 4 | ||
31 | #define XFS_FSTRM_KTRACE_UPDATE 5 | ||
32 | #define XFS_FSTRM_KTRACE_FREE 6 | ||
33 | #define XFS_FSTRM_KTRACE_ITEM_LOOKUP 7 | ||
34 | #define XFS_FSTRM_KTRACE_ASSOCIATE 8 | ||
35 | #define XFS_FSTRM_KTRACE_MOVEAG 9 | ||
36 | #define XFS_FSTRM_KTRACE_ORPHAN 10 | ||
37 | |||
38 | #define XFS_FSTRM_KTRACE_SIZE 16384 | ||
39 | extern ktrace_t *xfs_filestreams_trace_buf; | ||
40 | |||
41 | #endif | ||
42 | |||
43 | /* allocation selection flags */ | ||
44 | typedef enum xfs_fstrm_alloc { | ||
45 | XFS_PICK_USERDATA = 1, | ||
46 | XFS_PICK_LOWSPACE = 2, | ||
47 | } xfs_fstrm_alloc_t; | ||
48 | |||
49 | /* prototypes for filestream.c */ | ||
50 | int xfs_filestream_init(void); | ||
51 | void xfs_filestream_uninit(void); | ||
52 | int xfs_filestream_mount(struct xfs_mount *mp); | 25 | int xfs_filestream_mount(struct xfs_mount *mp); |
53 | void xfs_filestream_unmount(struct xfs_mount *mp); | 26 | void xfs_filestream_unmount(struct xfs_mount *mp); |
54 | xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip); | ||
55 | int xfs_filestream_associate(struct xfs_inode *dip, struct xfs_inode *ip); | ||
56 | void xfs_filestream_deassociate(struct xfs_inode *ip); | 27 | void xfs_filestream_deassociate(struct xfs_inode *ip); |
28 | xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip); | ||
57 | int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp); | 29 | int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp); |
30 | int xfs_filestream_peek_ag(struct xfs_mount *mp, xfs_agnumber_t agno); | ||
58 | 31 | ||
59 | |||
60 | /* filestreams for the inode? */ | ||
61 | static inline int | 32 | static inline int |
62 | xfs_inode_is_filestream( | 33 | xfs_inode_is_filestream( |
63 | struct xfs_inode *ip) | 34 | struct xfs_inode *ip) |
64 | { | 35 | { |
65 | return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) || | 36 | return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) || |
66 | xfs_iflags_test(ip, XFS_IFILESTREAM) || | ||
67 | (ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM); | 37 | (ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM); |
68 | } | 38 | } |
69 | 39 | ||
diff --git a/fs/xfs/xfs_format.h b/fs/xfs/xfs_format.h index 9898f31d05d8..34d85aca3058 100644 --- a/fs/xfs/xfs_format.h +++ b/fs/xfs/xfs_format.h | |||
@@ -202,6 +202,8 @@ typedef __be32 xfs_alloc_ptr_t; | |||
202 | */ | 202 | */ |
203 | #define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ | 203 | #define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ |
204 | #define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */ | 204 | #define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */ |
205 | #define XFS_FIBT_MAGIC 0x46494254 /* 'FIBT' */ | ||
206 | #define XFS_FIBT_CRC_MAGIC 0x46494233 /* 'FIB3' */ | ||
205 | 207 | ||
206 | typedef __uint64_t xfs_inofree_t; | 208 | typedef __uint64_t xfs_inofree_t; |
207 | #define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) | 209 | #define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) |
@@ -244,7 +246,17 @@ typedef __be32 xfs_inobt_ptr_t; | |||
244 | * block numbers in the AG. | 246 | * block numbers in the AG. |
245 | */ | 247 | */ |
246 | #define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) | 248 | #define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) |
247 | #define XFS_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) | 249 | #define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) |
250 | |||
251 | /* | ||
252 | * The first data block of an AG depends on whether the filesystem was formatted | ||
253 | * with the finobt feature. If so, account for the finobt reserved root btree | ||
254 | * block. | ||
255 | */ | ||
256 | #define XFS_PREALLOC_BLOCKS(mp) \ | ||
257 | (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ | ||
258 | XFS_FIBT_BLOCK(mp) + 1 : \ | ||
259 | XFS_IBT_BLOCK(mp) + 1) | ||
248 | 260 | ||
249 | 261 | ||
250 | 262 | ||
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index c5fc116dfaa3..d34703dbcb42 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h | |||
@@ -238,6 +238,7 @@ typedef struct xfs_fsop_resblks { | |||
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 | #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ | 240 | #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ |
241 | #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ | ||
241 | 242 | ||
242 | /* | 243 | /* |
243 | * Minimum and maximum sizes need for growth checks. | 244 | * Minimum and maximum sizes need for growth checks. |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 02fb943cbf22..d2295561570a 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -24,6 +24,8 @@ | |||
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" | ||
28 | #include "xfs_da_btree.h" | ||
27 | #include "xfs_inode.h" | 29 | #include "xfs_inode.h" |
28 | #include "xfs_trans.h" | 30 | #include "xfs_trans.h" |
29 | #include "xfs_inode_item.h" | 31 | #include "xfs_inode_item.h" |
@@ -74,23 +76,18 @@ xfs_fs_geometry( | |||
74 | } | 76 | } |
75 | if (new_version >= 3) { | 77 | if (new_version >= 3) { |
76 | geo->version = XFS_FSOP_GEOM_VERSION; | 78 | geo->version = XFS_FSOP_GEOM_VERSION; |
77 | geo->flags = | 79 | geo->flags = XFS_FSOP_GEOM_FLAGS_NLINK | |
80 | XFS_FSOP_GEOM_FLAGS_DIRV2 | | ||
78 | (xfs_sb_version_hasattr(&mp->m_sb) ? | 81 | (xfs_sb_version_hasattr(&mp->m_sb) ? |
79 | XFS_FSOP_GEOM_FLAGS_ATTR : 0) | | 82 | XFS_FSOP_GEOM_FLAGS_ATTR : 0) | |
80 | (xfs_sb_version_hasnlink(&mp->m_sb) ? | ||
81 | XFS_FSOP_GEOM_FLAGS_NLINK : 0) | | ||
82 | (xfs_sb_version_hasquota(&mp->m_sb) ? | 83 | (xfs_sb_version_hasquota(&mp->m_sb) ? |
83 | XFS_FSOP_GEOM_FLAGS_QUOTA : 0) | | 84 | XFS_FSOP_GEOM_FLAGS_QUOTA : 0) | |
84 | (xfs_sb_version_hasalign(&mp->m_sb) ? | 85 | (xfs_sb_version_hasalign(&mp->m_sb) ? |
85 | XFS_FSOP_GEOM_FLAGS_IALIGN : 0) | | 86 | XFS_FSOP_GEOM_FLAGS_IALIGN : 0) | |
86 | (xfs_sb_version_hasdalign(&mp->m_sb) ? | 87 | (xfs_sb_version_hasdalign(&mp->m_sb) ? |
87 | XFS_FSOP_GEOM_FLAGS_DALIGN : 0) | | 88 | XFS_FSOP_GEOM_FLAGS_DALIGN : 0) | |
88 | (xfs_sb_version_hasshared(&mp->m_sb) ? | ||
89 | XFS_FSOP_GEOM_FLAGS_SHARED : 0) | | ||
90 | (xfs_sb_version_hasextflgbit(&mp->m_sb) ? | 89 | (xfs_sb_version_hasextflgbit(&mp->m_sb) ? |
91 | XFS_FSOP_GEOM_FLAGS_EXTFLG : 0) | | 90 | XFS_FSOP_GEOM_FLAGS_EXTFLG : 0) | |
92 | (xfs_sb_version_hasdirv2(&mp->m_sb) ? | ||
93 | XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) | | ||
94 | (xfs_sb_version_hassector(&mp->m_sb) ? | 91 | (xfs_sb_version_hassector(&mp->m_sb) ? |
95 | XFS_FSOP_GEOM_FLAGS_SECTOR : 0) | | 92 | XFS_FSOP_GEOM_FLAGS_SECTOR : 0) | |
96 | (xfs_sb_version_hasasciici(&mp->m_sb) ? | 93 | (xfs_sb_version_hasasciici(&mp->m_sb) ? |
@@ -104,11 +101,13 @@ xfs_fs_geometry( | |||
104 | (xfs_sb_version_hascrc(&mp->m_sb) ? | 101 | (xfs_sb_version_hascrc(&mp->m_sb) ? |
105 | XFS_FSOP_GEOM_FLAGS_V5SB : 0) | | 102 | XFS_FSOP_GEOM_FLAGS_V5SB : 0) | |
106 | (xfs_sb_version_hasftype(&mp->m_sb) ? | 103 | (xfs_sb_version_hasftype(&mp->m_sb) ? |
107 | XFS_FSOP_GEOM_FLAGS_FTYPE : 0); | 104 | XFS_FSOP_GEOM_FLAGS_FTYPE : 0) | |
105 | (xfs_sb_version_hasfinobt(&mp->m_sb) ? | ||
106 | XFS_FSOP_GEOM_FLAGS_FINOBT : 0); | ||
108 | geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? | 107 | geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? |
109 | mp->m_sb.sb_logsectsize : BBSIZE; | 108 | mp->m_sb.sb_logsectsize : BBSIZE; |
110 | geo->rtsectsize = mp->m_sb.sb_blocksize; | 109 | geo->rtsectsize = mp->m_sb.sb_blocksize; |
111 | geo->dirblocksize = mp->m_dirblksize; | 110 | geo->dirblocksize = mp->m_dir_geo->blksize; |
112 | } | 111 | } |
113 | if (new_version >= 4) { | 112 | if (new_version >= 4) { |
114 | geo->flags |= | 113 | geo->flags |= |
@@ -316,6 +315,10 @@ xfs_growfs_data_private( | |||
316 | agi->agi_dirino = cpu_to_be32(NULLAGINO); | 315 | agi->agi_dirino = cpu_to_be32(NULLAGINO); |
317 | if (xfs_sb_version_hascrc(&mp->m_sb)) | 316 | if (xfs_sb_version_hascrc(&mp->m_sb)) |
318 | uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid); | 317 | uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid); |
318 | if (xfs_sb_version_hasfinobt(&mp->m_sb)) { | ||
319 | agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp)); | ||
320 | agi->agi_free_level = cpu_to_be32(1); | ||
321 | } | ||
319 | for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) | 322 | for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) |
320 | agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); | 323 | agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); |
321 | 324 | ||
@@ -407,6 +410,34 @@ xfs_growfs_data_private( | |||
407 | xfs_buf_relse(bp); | 410 | xfs_buf_relse(bp); |
408 | if (error) | 411 | if (error) |
409 | goto error0; | 412 | goto error0; |
413 | |||
414 | /* | ||
415 | * FINO btree root block | ||
416 | */ | ||
417 | if (xfs_sb_version_hasfinobt(&mp->m_sb)) { | ||
418 | bp = xfs_growfs_get_hdr_buf(mp, | ||
419 | XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)), | ||
420 | BTOBB(mp->m_sb.sb_blocksize), 0, | ||
421 | &xfs_inobt_buf_ops); | ||
422 | if (!bp) { | ||
423 | error = ENOMEM; | ||
424 | goto error0; | ||
425 | } | ||
426 | |||
427 | if (xfs_sb_version_hascrc(&mp->m_sb)) | ||
428 | xfs_btree_init_block(mp, bp, XFS_FIBT_CRC_MAGIC, | ||
429 | 0, 0, agno, | ||
430 | XFS_BTREE_CRC_BLOCKS); | ||
431 | else | ||
432 | xfs_btree_init_block(mp, bp, XFS_FIBT_MAGIC, 0, | ||
433 | 0, agno, 0); | ||
434 | |||
435 | error = xfs_bwrite(bp); | ||
436 | xfs_buf_relse(bp); | ||
437 | if (error) | ||
438 | goto error0; | ||
439 | } | ||
440 | |||
410 | } | 441 | } |
411 | xfs_trans_agblocks_delta(tp, nfree); | 442 | xfs_trans_agblocks_delta(tp, nfree); |
412 | /* | 443 | /* |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 8f711db61a0c..5960e5593fe0 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -112,6 +112,66 @@ xfs_inobt_get_rec( | |||
112 | } | 112 | } |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * Insert a single inobt record. Cursor must already point to desired location. | ||
116 | */ | ||
117 | STATIC int | ||
118 | xfs_inobt_insert_rec( | ||
119 | struct xfs_btree_cur *cur, | ||
120 | __int32_t freecount, | ||
121 | xfs_inofree_t free, | ||
122 | int *stat) | ||
123 | { | ||
124 | cur->bc_rec.i.ir_freecount = freecount; | ||
125 | cur->bc_rec.i.ir_free = free; | ||
126 | return xfs_btree_insert(cur, stat); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Insert records describing a newly allocated inode chunk into the inobt. | ||
131 | */ | ||
132 | STATIC int | ||
133 | xfs_inobt_insert( | ||
134 | struct xfs_mount *mp, | ||
135 | struct xfs_trans *tp, | ||
136 | struct xfs_buf *agbp, | ||
137 | xfs_agino_t newino, | ||
138 | xfs_agino_t newlen, | ||
139 | xfs_btnum_t btnum) | ||
140 | { | ||
141 | struct xfs_btree_cur *cur; | ||
142 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); | ||
143 | xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); | ||
144 | xfs_agino_t thisino; | ||
145 | int i; | ||
146 | int error; | ||
147 | |||
148 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, btnum); | ||
149 | |||
150 | for (thisino = newino; | ||
151 | thisino < newino + newlen; | ||
152 | thisino += XFS_INODES_PER_CHUNK) { | ||
153 | error = xfs_inobt_lookup(cur, thisino, XFS_LOOKUP_EQ, &i); | ||
154 | if (error) { | ||
155 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | ||
156 | return error; | ||
157 | } | ||
158 | ASSERT(i == 0); | ||
159 | |||
160 | error = xfs_inobt_insert_rec(cur, XFS_INODES_PER_CHUNK, | ||
161 | XFS_INOBT_ALL_FREE, &i); | ||
162 | if (error) { | ||
163 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | ||
164 | return error; | ||
165 | } | ||
166 | ASSERT(i == 1); | ||
167 | } | ||
168 | |||
169 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | /* | ||
115 | * Verify that the number of free inodes in the AGI is correct. | 175 | * Verify that the number of free inodes in the AGI is correct. |
116 | */ | 176 | */ |
117 | #ifdef DEBUG | 177 | #ifdef DEBUG |
@@ -220,10 +280,8 @@ xfs_ialloc_inode_init( | |||
220 | if (tp) | 280 | if (tp) |
221 | xfs_icreate_log(tp, agno, agbno, mp->m_ialloc_inos, | 281 | xfs_icreate_log(tp, agno, agbno, mp->m_ialloc_inos, |
222 | mp->m_sb.sb_inodesize, length, gen); | 282 | mp->m_sb.sb_inodesize, length, gen); |
223 | } else if (xfs_sb_version_hasnlink(&mp->m_sb)) | 283 | } else |
224 | version = 2; | 284 | version = 2; |
225 | else | ||
226 | version = 1; | ||
227 | 285 | ||
228 | for (j = 0; j < nbufs; j++) { | 286 | for (j = 0; j < nbufs; j++) { |
229 | /* | 287 | /* |
@@ -303,13 +361,10 @@ xfs_ialloc_ag_alloc( | |||
303 | { | 361 | { |
304 | xfs_agi_t *agi; /* allocation group header */ | 362 | xfs_agi_t *agi; /* allocation group header */ |
305 | xfs_alloc_arg_t args; /* allocation argument structure */ | 363 | xfs_alloc_arg_t args; /* allocation argument structure */ |
306 | xfs_btree_cur_t *cur; /* inode btree cursor */ | ||
307 | xfs_agnumber_t agno; | 364 | xfs_agnumber_t agno; |
308 | int error; | 365 | int error; |
309 | int i; | ||
310 | xfs_agino_t newino; /* new first inode's number */ | 366 | xfs_agino_t newino; /* new first inode's number */ |
311 | xfs_agino_t newlen; /* new number of inodes */ | 367 | xfs_agino_t newlen; /* new number of inodes */ |
312 | xfs_agino_t thisino; /* current inode number, for loop */ | ||
313 | int isaligned = 0; /* inode allocation at stripe unit */ | 368 | int isaligned = 0; /* inode allocation at stripe unit */ |
314 | /* boundary */ | 369 | /* boundary */ |
315 | struct xfs_perag *pag; | 370 | struct xfs_perag *pag; |
@@ -459,29 +514,19 @@ xfs_ialloc_ag_alloc( | |||
459 | agi->agi_newino = cpu_to_be32(newino); | 514 | agi->agi_newino = cpu_to_be32(newino); |
460 | 515 | ||
461 | /* | 516 | /* |
462 | * Insert records describing the new inode chunk into the btree. | 517 | * Insert records describing the new inode chunk into the btrees. |
463 | */ | 518 | */ |
464 | cur = xfs_inobt_init_cursor(args.mp, tp, agbp, agno); | 519 | error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen, |
465 | for (thisino = newino; | 520 | XFS_BTNUM_INO); |
466 | thisino < newino + newlen; | 521 | if (error) |
467 | thisino += XFS_INODES_PER_CHUNK) { | 522 | return error; |
468 | cur->bc_rec.i.ir_startino = thisino; | 523 | |
469 | cur->bc_rec.i.ir_freecount = XFS_INODES_PER_CHUNK; | 524 | if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) { |
470 | cur->bc_rec.i.ir_free = XFS_INOBT_ALL_FREE; | 525 | error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen, |
471 | error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, &i); | 526 | XFS_BTNUM_FINO); |
472 | if (error) { | 527 | if (error) |
473 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | ||
474 | return error; | ||
475 | } | ||
476 | ASSERT(i == 0); | ||
477 | error = xfs_btree_insert(cur, &i); | ||
478 | if (error) { | ||
479 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | ||
480 | return error; | 528 | return error; |
481 | } | ||
482 | ASSERT(i == 1); | ||
483 | } | 529 | } |
484 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
485 | /* | 530 | /* |
486 | * Log allocation group header fields | 531 | * Log allocation group header fields |
487 | */ | 532 | */ |
@@ -675,13 +720,10 @@ xfs_ialloc_get_rec( | |||
675 | } | 720 | } |
676 | 721 | ||
677 | /* | 722 | /* |
678 | * Allocate an inode. | 723 | * Allocate an inode using the inobt-only algorithm. |
679 | * | ||
680 | * The caller selected an AG for us, and made sure that free inodes are | ||
681 | * available. | ||
682 | */ | 724 | */ |
683 | STATIC int | 725 | STATIC int |
684 | xfs_dialloc_ag( | 726 | xfs_dialloc_ag_inobt( |
685 | struct xfs_trans *tp, | 727 | struct xfs_trans *tp, |
686 | struct xfs_buf *agbp, | 728 | struct xfs_buf *agbp, |
687 | xfs_ino_t parent, | 729 | xfs_ino_t parent, |
@@ -707,7 +749,7 @@ xfs_dialloc_ag( | |||
707 | ASSERT(pag->pagi_freecount > 0); | 749 | ASSERT(pag->pagi_freecount > 0); |
708 | 750 | ||
709 | restart_pagno: | 751 | restart_pagno: |
710 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); | 752 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); |
711 | /* | 753 | /* |
712 | * If pagino is 0 (this is the root inode allocation) use newino. | 754 | * If pagino is 0 (this is the root inode allocation) use newino. |
713 | * This must work because we've just allocated some. | 755 | * This must work because we've just allocated some. |
@@ -940,6 +982,294 @@ error0: | |||
940 | } | 982 | } |
941 | 983 | ||
942 | /* | 984 | /* |
985 | * Use the free inode btree to allocate an inode based on distance from the | ||
986 | * parent. Note that the provided cursor may be deleted and replaced. | ||
987 | */ | ||
988 | STATIC int | ||
989 | xfs_dialloc_ag_finobt_near( | ||
990 | xfs_agino_t pagino, | ||
991 | struct xfs_btree_cur **ocur, | ||
992 | struct xfs_inobt_rec_incore *rec) | ||
993 | { | ||
994 | struct xfs_btree_cur *lcur = *ocur; /* left search cursor */ | ||
995 | struct xfs_btree_cur *rcur; /* right search cursor */ | ||
996 | struct xfs_inobt_rec_incore rrec; | ||
997 | int error; | ||
998 | int i, j; | ||
999 | |||
1000 | error = xfs_inobt_lookup(lcur, pagino, XFS_LOOKUP_LE, &i); | ||
1001 | if (error) | ||
1002 | return error; | ||
1003 | |||
1004 | if (i == 1) { | ||
1005 | error = xfs_inobt_get_rec(lcur, rec, &i); | ||
1006 | if (error) | ||
1007 | return error; | ||
1008 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
1009 | |||
1010 | /* | ||
1011 | * See if we've landed in the parent inode record. The finobt | ||
1012 | * only tracks chunks with at least one free inode, so record | ||
1013 | * existence is enough. | ||
1014 | */ | ||
1015 | if (pagino >= rec->ir_startino && | ||
1016 | pagino < (rec->ir_startino + XFS_INODES_PER_CHUNK)) | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | error = xfs_btree_dup_cursor(lcur, &rcur); | ||
1021 | if (error) | ||
1022 | return error; | ||
1023 | |||
1024 | error = xfs_inobt_lookup(rcur, pagino, XFS_LOOKUP_GE, &j); | ||
1025 | if (error) | ||
1026 | goto error_rcur; | ||
1027 | if (j == 1) { | ||
1028 | error = xfs_inobt_get_rec(rcur, &rrec, &j); | ||
1029 | if (error) | ||
1030 | goto error_rcur; | ||
1031 | XFS_WANT_CORRUPTED_GOTO(j == 1, error_rcur); | ||
1032 | } | ||
1033 | |||
1034 | XFS_WANT_CORRUPTED_GOTO(i == 1 || j == 1, error_rcur); | ||
1035 | if (i == 1 && j == 1) { | ||
1036 | /* | ||
1037 | * Both the left and right records are valid. Choose the closer | ||
1038 | * inode chunk to the target. | ||
1039 | */ | ||
1040 | if ((pagino - rec->ir_startino + XFS_INODES_PER_CHUNK - 1) > | ||
1041 | (rrec.ir_startino - pagino)) { | ||
1042 | *rec = rrec; | ||
1043 | xfs_btree_del_cursor(lcur, XFS_BTREE_NOERROR); | ||
1044 | *ocur = rcur; | ||
1045 | } else { | ||
1046 | xfs_btree_del_cursor(rcur, XFS_BTREE_NOERROR); | ||
1047 | } | ||
1048 | } else if (j == 1) { | ||
1049 | /* only the right record is valid */ | ||
1050 | *rec = rrec; | ||
1051 | xfs_btree_del_cursor(lcur, XFS_BTREE_NOERROR); | ||
1052 | *ocur = rcur; | ||
1053 | } else if (i == 1) { | ||
1054 | /* only the left record is valid */ | ||
1055 | xfs_btree_del_cursor(rcur, XFS_BTREE_NOERROR); | ||
1056 | } | ||
1057 | |||
1058 | return 0; | ||
1059 | |||
1060 | error_rcur: | ||
1061 | xfs_btree_del_cursor(rcur, XFS_BTREE_ERROR); | ||
1062 | return error; | ||
1063 | } | ||
1064 | |||
1065 | /* | ||
1066 | * Use the free inode btree to find a free inode based on a newino hint. If | ||
1067 | * the hint is NULL, find the first free inode in the AG. | ||
1068 | */ | ||
1069 | STATIC int | ||
1070 | xfs_dialloc_ag_finobt_newino( | ||
1071 | struct xfs_agi *agi, | ||
1072 | struct xfs_btree_cur *cur, | ||
1073 | struct xfs_inobt_rec_incore *rec) | ||
1074 | { | ||
1075 | int error; | ||
1076 | int i; | ||
1077 | |||
1078 | if (agi->agi_newino != cpu_to_be32(NULLAGINO)) { | ||
1079 | error = xfs_inobt_lookup(cur, agi->agi_newino, XFS_LOOKUP_EQ, | ||
1080 | &i); | ||
1081 | if (error) | ||
1082 | return error; | ||
1083 | if (i == 1) { | ||
1084 | error = xfs_inobt_get_rec(cur, rec, &i); | ||
1085 | if (error) | ||
1086 | return error; | ||
1087 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
1088 | |||
1089 | return 0; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | /* | ||
1094 | * Find the first inode available in the AG. | ||
1095 | */ | ||
1096 | error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); | ||
1097 | if (error) | ||
1098 | return error; | ||
1099 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
1100 | |||
1101 | error = xfs_inobt_get_rec(cur, rec, &i); | ||
1102 | if (error) | ||
1103 | return error; | ||
1104 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
1105 | |||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | /* | ||
1110 | * Update the inobt based on a modification made to the finobt. Also ensure that | ||
1111 | * the records from both trees are equivalent post-modification. | ||
1112 | */ | ||
1113 | STATIC int | ||
1114 | xfs_dialloc_ag_update_inobt( | ||
1115 | struct xfs_btree_cur *cur, /* inobt cursor */ | ||
1116 | struct xfs_inobt_rec_incore *frec, /* finobt record */ | ||
1117 | int offset) /* inode offset */ | ||
1118 | { | ||
1119 | struct xfs_inobt_rec_incore rec; | ||
1120 | int error; | ||
1121 | int i; | ||
1122 | |||
1123 | error = xfs_inobt_lookup(cur, frec->ir_startino, XFS_LOOKUP_EQ, &i); | ||
1124 | if (error) | ||
1125 | return error; | ||
1126 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
1127 | |||
1128 | error = xfs_inobt_get_rec(cur, &rec, &i); | ||
1129 | if (error) | ||
1130 | return error; | ||
1131 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
1132 | ASSERT((XFS_AGINO_TO_OFFSET(cur->bc_mp, rec.ir_startino) % | ||
1133 | XFS_INODES_PER_CHUNK) == 0); | ||
1134 | |||
1135 | rec.ir_free &= ~XFS_INOBT_MASK(offset); | ||
1136 | rec.ir_freecount--; | ||
1137 | |||
1138 | XFS_WANT_CORRUPTED_RETURN((rec.ir_free == frec->ir_free) && | ||
1139 | (rec.ir_freecount == frec->ir_freecount)); | ||
1140 | |||
1141 | error = xfs_inobt_update(cur, &rec); | ||
1142 | if (error) | ||
1143 | return error; | ||
1144 | |||
1145 | return 0; | ||
1146 | } | ||
1147 | |||
1148 | /* | ||
1149 | * Allocate an inode using the free inode btree, if available. Otherwise, fall | ||
1150 | * back to the inobt search algorithm. | ||
1151 | * | ||
1152 | * The caller selected an AG for us, and made sure that free inodes are | ||
1153 | * available. | ||
1154 | */ | ||
1155 | STATIC int | ||
1156 | xfs_dialloc_ag( | ||
1157 | struct xfs_trans *tp, | ||
1158 | struct xfs_buf *agbp, | ||
1159 | xfs_ino_t parent, | ||
1160 | xfs_ino_t *inop) | ||
1161 | { | ||
1162 | struct xfs_mount *mp = tp->t_mountp; | ||
1163 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); | ||
1164 | xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); | ||
1165 | xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent); | ||
1166 | xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent); | ||
1167 | struct xfs_perag *pag; | ||
1168 | struct xfs_btree_cur *cur; /* finobt cursor */ | ||
1169 | struct xfs_btree_cur *icur; /* inobt cursor */ | ||
1170 | struct xfs_inobt_rec_incore rec; | ||
1171 | xfs_ino_t ino; | ||
1172 | int error; | ||
1173 | int offset; | ||
1174 | int i; | ||
1175 | |||
1176 | if (!xfs_sb_version_hasfinobt(&mp->m_sb)) | ||
1177 | return xfs_dialloc_ag_inobt(tp, agbp, parent, inop); | ||
1178 | |||
1179 | pag = xfs_perag_get(mp, agno); | ||
1180 | |||
1181 | /* | ||
1182 | * If pagino is 0 (this is the root inode allocation) use newino. | ||
1183 | * This must work because we've just allocated some. | ||
1184 | */ | ||
1185 | if (!pagino) | ||
1186 | pagino = be32_to_cpu(agi->agi_newino); | ||
1187 | |||
1188 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO); | ||
1189 | |||
1190 | error = xfs_check_agi_freecount(cur, agi); | ||
1191 | if (error) | ||
1192 | goto error_cur; | ||
1193 | |||
1194 | /* | ||
1195 | * The search algorithm depends on whether we're in the same AG as the | ||
1196 | * parent. If so, find the closest available inode to the parent. If | ||
1197 | * not, consider the agi hint or find the first free inode in the AG. | ||
1198 | */ | ||
1199 | if (agno == pagno) | ||
1200 | error = xfs_dialloc_ag_finobt_near(pagino, &cur, &rec); | ||
1201 | else | ||
1202 | error = xfs_dialloc_ag_finobt_newino(agi, cur, &rec); | ||
1203 | if (error) | ||
1204 | goto error_cur; | ||
1205 | |||
1206 | offset = xfs_lowbit64(rec.ir_free); | ||
1207 | ASSERT(offset >= 0); | ||
1208 | ASSERT(offset < XFS_INODES_PER_CHUNK); | ||
1209 | ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) % | ||
1210 | XFS_INODES_PER_CHUNK) == 0); | ||
1211 | ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); | ||
1212 | |||
1213 | /* | ||
1214 | * Modify or remove the finobt record. | ||
1215 | */ | ||
1216 | rec.ir_free &= ~XFS_INOBT_MASK(offset); | ||
1217 | rec.ir_freecount--; | ||
1218 | if (rec.ir_freecount) | ||
1219 | error = xfs_inobt_update(cur, &rec); | ||
1220 | else | ||
1221 | error = xfs_btree_delete(cur, &i); | ||
1222 | if (error) | ||
1223 | goto error_cur; | ||
1224 | |||
1225 | /* | ||
1226 | * The finobt has now been updated appropriately. We haven't updated the | ||
1227 | * agi and superblock yet, so we can create an inobt cursor and validate | ||
1228 | * the original freecount. If all is well, make the equivalent update to | ||
1229 | * the inobt using the finobt record and offset information. | ||
1230 | */ | ||
1231 | icur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); | ||
1232 | |||
1233 | error = xfs_check_agi_freecount(icur, agi); | ||
1234 | if (error) | ||
1235 | goto error_icur; | ||
1236 | |||
1237 | error = xfs_dialloc_ag_update_inobt(icur, &rec, offset); | ||
1238 | if (error) | ||
1239 | goto error_icur; | ||
1240 | |||
1241 | /* | ||
1242 | * Both trees have now been updated. We must update the perag and | ||
1243 | * superblock before we can check the freecount for each btree. | ||
1244 | */ | ||
1245 | be32_add_cpu(&agi->agi_freecount, -1); | ||
1246 | xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); | ||
1247 | pag->pagi_freecount--; | ||
1248 | |||
1249 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1); | ||
1250 | |||
1251 | error = xfs_check_agi_freecount(icur, agi); | ||
1252 | if (error) | ||
1253 | goto error_icur; | ||
1254 | error = xfs_check_agi_freecount(cur, agi); | ||
1255 | if (error) | ||
1256 | goto error_icur; | ||
1257 | |||
1258 | xfs_btree_del_cursor(icur, XFS_BTREE_NOERROR); | ||
1259 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
1260 | xfs_perag_put(pag); | ||
1261 | *inop = ino; | ||
1262 | return 0; | ||
1263 | |||
1264 | error_icur: | ||
1265 | xfs_btree_del_cursor(icur, XFS_BTREE_ERROR); | ||
1266 | error_cur: | ||
1267 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | ||
1268 | xfs_perag_put(pag); | ||
1269 | return error; | ||
1270 | } | ||
1271 | |||
1272 | /* | ||
943 | * Allocate an inode on disk. | 1273 | * Allocate an inode on disk. |
944 | * | 1274 | * |
945 | * Mode is used to tell whether the new inode will need space, and whether it | 1275 | * Mode is used to tell whether the new inode will need space, and whether it |
@@ -1098,78 +1428,34 @@ out_error: | |||
1098 | return XFS_ERROR(error); | 1428 | return XFS_ERROR(error); |
1099 | } | 1429 | } |
1100 | 1430 | ||
1101 | /* | 1431 | STATIC int |
1102 | * Free disk inode. Carefully avoids touching the incore inode, all | 1432 | xfs_difree_inobt( |
1103 | * manipulations incore are the caller's responsibility. | 1433 | struct xfs_mount *mp, |
1104 | * The on-disk inode is not changed by this operation, only the | 1434 | struct xfs_trans *tp, |
1105 | * btree (free inode mask) is changed. | 1435 | struct xfs_buf *agbp, |
1106 | */ | 1436 | xfs_agino_t agino, |
1107 | int | 1437 | struct xfs_bmap_free *flist, |
1108 | xfs_difree( | 1438 | int *deleted, |
1109 | xfs_trans_t *tp, /* transaction pointer */ | 1439 | xfs_ino_t *first_ino, |
1110 | xfs_ino_t inode, /* inode to be freed */ | 1440 | struct xfs_inobt_rec_incore *orec) |
1111 | xfs_bmap_free_t *flist, /* extents to free */ | ||
1112 | int *delete, /* set if inode cluster was deleted */ | ||
1113 | xfs_ino_t *first_ino) /* first inode in deleted cluster */ | ||
1114 | { | 1441 | { |
1115 | /* REFERENCED */ | 1442 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); |
1116 | xfs_agblock_t agbno; /* block number containing inode */ | 1443 | xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); |
1117 | xfs_buf_t *agbp; /* buffer containing allocation group header */ | 1444 | struct xfs_perag *pag; |
1118 | xfs_agino_t agino; /* inode number relative to allocation group */ | 1445 | struct xfs_btree_cur *cur; |
1119 | xfs_agnumber_t agno; /* allocation group number */ | 1446 | struct xfs_inobt_rec_incore rec; |
1120 | xfs_agi_t *agi; /* allocation group header */ | 1447 | int ilen; |
1121 | xfs_btree_cur_t *cur; /* inode btree cursor */ | 1448 | int error; |
1122 | int error; /* error return value */ | 1449 | int i; |
1123 | int i; /* result code */ | 1450 | int off; |
1124 | int ilen; /* inodes in an inode cluster */ | ||
1125 | xfs_mount_t *mp; /* mount structure for filesystem */ | ||
1126 | int off; /* offset of inode in inode chunk */ | ||
1127 | xfs_inobt_rec_incore_t rec; /* btree record */ | ||
1128 | struct xfs_perag *pag; | ||
1129 | 1451 | ||
1130 | mp = tp->t_mountp; | ||
1131 | |||
1132 | /* | ||
1133 | * Break up inode number into its components. | ||
1134 | */ | ||
1135 | agno = XFS_INO_TO_AGNO(mp, inode); | ||
1136 | if (agno >= mp->m_sb.sb_agcount) { | ||
1137 | xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).", | ||
1138 | __func__, agno, mp->m_sb.sb_agcount); | ||
1139 | ASSERT(0); | ||
1140 | return XFS_ERROR(EINVAL); | ||
1141 | } | ||
1142 | agino = XFS_INO_TO_AGINO(mp, inode); | ||
1143 | if (inode != XFS_AGINO_TO_INO(mp, agno, agino)) { | ||
1144 | xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).", | ||
1145 | __func__, (unsigned long long)inode, | ||
1146 | (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino)); | ||
1147 | ASSERT(0); | ||
1148 | return XFS_ERROR(EINVAL); | ||
1149 | } | ||
1150 | agbno = XFS_AGINO_TO_AGBNO(mp, agino); | ||
1151 | if (agbno >= mp->m_sb.sb_agblocks) { | ||
1152 | xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).", | ||
1153 | __func__, agbno, mp->m_sb.sb_agblocks); | ||
1154 | ASSERT(0); | ||
1155 | return XFS_ERROR(EINVAL); | ||
1156 | } | ||
1157 | /* | ||
1158 | * Get the allocation group header. | ||
1159 | */ | ||
1160 | error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); | ||
1161 | if (error) { | ||
1162 | xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", | ||
1163 | __func__, error); | ||
1164 | return error; | ||
1165 | } | ||
1166 | agi = XFS_BUF_TO_AGI(agbp); | ||
1167 | ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); | 1452 | ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); |
1168 | ASSERT(agbno < be32_to_cpu(agi->agi_length)); | 1453 | ASSERT(XFS_AGINO_TO_AGBNO(mp, agino) < be32_to_cpu(agi->agi_length)); |
1454 | |||
1169 | /* | 1455 | /* |
1170 | * Initialize the cursor. | 1456 | * Initialize the cursor. |
1171 | */ | 1457 | */ |
1172 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); | 1458 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); |
1173 | 1459 | ||
1174 | error = xfs_check_agi_freecount(cur, agi); | 1460 | error = xfs_check_agi_freecount(cur, agi); |
1175 | if (error) | 1461 | if (error) |
@@ -1209,7 +1495,7 @@ xfs_difree( | |||
1209 | if (!(mp->m_flags & XFS_MOUNT_IKEEP) && | 1495 | if (!(mp->m_flags & XFS_MOUNT_IKEEP) && |
1210 | (rec.ir_freecount == mp->m_ialloc_inos)) { | 1496 | (rec.ir_freecount == mp->m_ialloc_inos)) { |
1211 | 1497 | ||
1212 | *delete = 1; | 1498 | *deleted = 1; |
1213 | *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); | 1499 | *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); |
1214 | 1500 | ||
1215 | /* | 1501 | /* |
@@ -1237,7 +1523,7 @@ xfs_difree( | |||
1237 | XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)), | 1523 | XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)), |
1238 | mp->m_ialloc_blks, flist, mp); | 1524 | mp->m_ialloc_blks, flist, mp); |
1239 | } else { | 1525 | } else { |
1240 | *delete = 0; | 1526 | *deleted = 0; |
1241 | 1527 | ||
1242 | error = xfs_inobt_update(cur, &rec); | 1528 | error = xfs_inobt_update(cur, &rec); |
1243 | if (error) { | 1529 | if (error) { |
@@ -1261,6 +1547,7 @@ xfs_difree( | |||
1261 | if (error) | 1547 | if (error) |
1262 | goto error0; | 1548 | goto error0; |
1263 | 1549 | ||
1550 | *orec = rec; | ||
1264 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 1551 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
1265 | return 0; | 1552 | return 0; |
1266 | 1553 | ||
@@ -1269,6 +1556,182 @@ error0: | |||
1269 | return error; | 1556 | return error; |
1270 | } | 1557 | } |
1271 | 1558 | ||
1559 | /* | ||
1560 | * Free an inode in the free inode btree. | ||
1561 | */ | ||
1562 | STATIC int | ||
1563 | xfs_difree_finobt( | ||
1564 | struct xfs_mount *mp, | ||
1565 | struct xfs_trans *tp, | ||
1566 | struct xfs_buf *agbp, | ||
1567 | xfs_agino_t agino, | ||
1568 | struct xfs_inobt_rec_incore *ibtrec) /* inobt record */ | ||
1569 | { | ||
1570 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); | ||
1571 | xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); | ||
1572 | struct xfs_btree_cur *cur; | ||
1573 | struct xfs_inobt_rec_incore rec; | ||
1574 | int offset = agino - ibtrec->ir_startino; | ||
1575 | int error; | ||
1576 | int i; | ||
1577 | |||
1578 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO); | ||
1579 | |||
1580 | error = xfs_inobt_lookup(cur, ibtrec->ir_startino, XFS_LOOKUP_EQ, &i); | ||
1581 | if (error) | ||
1582 | goto error; | ||
1583 | if (i == 0) { | ||
1584 | /* | ||
1585 | * If the record does not exist in the finobt, we must have just | ||
1586 | * freed an inode in a previously fully allocated chunk. If not, | ||
1587 | * something is out of sync. | ||
1588 | */ | ||
1589 | XFS_WANT_CORRUPTED_GOTO(ibtrec->ir_freecount == 1, error); | ||
1590 | |||
1591 | error = xfs_inobt_insert_rec(cur, ibtrec->ir_freecount, | ||
1592 | ibtrec->ir_free, &i); | ||
1593 | if (error) | ||
1594 | goto error; | ||
1595 | ASSERT(i == 1); | ||
1596 | |||
1597 | goto out; | ||
1598 | } | ||
1599 | |||
1600 | /* | ||
1601 | * Read and update the existing record. We could just copy the ibtrec | ||
1602 | * across here, but that would defeat the purpose of having redundant | ||
1603 | * metadata. By making the modifications independently, we can catch | ||
1604 | * corruptions that we wouldn't see if we just copied from one record | ||
1605 | * to another. | ||
1606 | */ | ||
1607 | error = xfs_inobt_get_rec(cur, &rec, &i); | ||
1608 | if (error) | ||
1609 | goto error; | ||
1610 | XFS_WANT_CORRUPTED_GOTO(i == 1, error); | ||
1611 | |||
1612 | rec.ir_free |= XFS_INOBT_MASK(offset); | ||
1613 | rec.ir_freecount++; | ||
1614 | |||
1615 | XFS_WANT_CORRUPTED_GOTO((rec.ir_free == ibtrec->ir_free) && | ||
1616 | (rec.ir_freecount == ibtrec->ir_freecount), | ||
1617 | error); | ||
1618 | |||
1619 | /* | ||
1620 | * The content of inobt records should always match between the inobt | ||
1621 | * and finobt. The lifecycle of records in the finobt is different from | ||
1622 | * the inobt in that the finobt only tracks records with at least one | ||
1623 | * free inode. Hence, if all of the inodes are free and we aren't | ||
1624 | * keeping inode chunks permanently on disk, remove the record. | ||
1625 | * Otherwise, update the record with the new information. | ||
1626 | */ | ||
1627 | if (rec.ir_freecount == mp->m_ialloc_inos && | ||
1628 | !(mp->m_flags & XFS_MOUNT_IKEEP)) { | ||
1629 | error = xfs_btree_delete(cur, &i); | ||
1630 | if (error) | ||
1631 | goto error; | ||
1632 | ASSERT(i == 1); | ||
1633 | } else { | ||
1634 | error = xfs_inobt_update(cur, &rec); | ||
1635 | if (error) | ||
1636 | goto error; | ||
1637 | } | ||
1638 | |||
1639 | out: | ||
1640 | error = xfs_check_agi_freecount(cur, agi); | ||
1641 | if (error) | ||
1642 | goto error; | ||
1643 | |||
1644 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
1645 | return 0; | ||
1646 | |||
1647 | error: | ||
1648 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | ||
1649 | return error; | ||
1650 | } | ||
1651 | |||
1652 | /* | ||
1653 | * Free disk inode. Carefully avoids touching the incore inode, all | ||
1654 | * manipulations incore are the caller's responsibility. | ||
1655 | * The on-disk inode is not changed by this operation, only the | ||
1656 | * btree (free inode mask) is changed. | ||
1657 | */ | ||
1658 | int | ||
1659 | xfs_difree( | ||
1660 | struct xfs_trans *tp, /* transaction pointer */ | ||
1661 | xfs_ino_t inode, /* inode to be freed */ | ||
1662 | struct xfs_bmap_free *flist, /* extents to free */ | ||
1663 | int *deleted,/* set if inode cluster was deleted */ | ||
1664 | xfs_ino_t *first_ino)/* first inode in deleted cluster */ | ||
1665 | { | ||
1666 | /* REFERENCED */ | ||
1667 | xfs_agblock_t agbno; /* block number containing inode */ | ||
1668 | struct xfs_buf *agbp; /* buffer for allocation group header */ | ||
1669 | xfs_agino_t agino; /* allocation group inode number */ | ||
1670 | xfs_agnumber_t agno; /* allocation group number */ | ||
1671 | int error; /* error return value */ | ||
1672 | struct xfs_mount *mp; /* mount structure for filesystem */ | ||
1673 | struct xfs_inobt_rec_incore rec;/* btree record */ | ||
1674 | |||
1675 | mp = tp->t_mountp; | ||
1676 | |||
1677 | /* | ||
1678 | * Break up inode number into its components. | ||
1679 | */ | ||
1680 | agno = XFS_INO_TO_AGNO(mp, inode); | ||
1681 | if (agno >= mp->m_sb.sb_agcount) { | ||
1682 | xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).", | ||
1683 | __func__, agno, mp->m_sb.sb_agcount); | ||
1684 | ASSERT(0); | ||
1685 | return XFS_ERROR(EINVAL); | ||
1686 | } | ||
1687 | agino = XFS_INO_TO_AGINO(mp, inode); | ||
1688 | if (inode != XFS_AGINO_TO_INO(mp, agno, agino)) { | ||
1689 | xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).", | ||
1690 | __func__, (unsigned long long)inode, | ||
1691 | (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino)); | ||
1692 | ASSERT(0); | ||
1693 | return XFS_ERROR(EINVAL); | ||
1694 | } | ||
1695 | agbno = XFS_AGINO_TO_AGBNO(mp, agino); | ||
1696 | if (agbno >= mp->m_sb.sb_agblocks) { | ||
1697 | xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).", | ||
1698 | __func__, agbno, mp->m_sb.sb_agblocks); | ||
1699 | ASSERT(0); | ||
1700 | return XFS_ERROR(EINVAL); | ||
1701 | } | ||
1702 | /* | ||
1703 | * Get the allocation group header. | ||
1704 | */ | ||
1705 | error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); | ||
1706 | if (error) { | ||
1707 | xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", | ||
1708 | __func__, error); | ||
1709 | return error; | ||
1710 | } | ||
1711 | |||
1712 | /* | ||
1713 | * Fix up the inode allocation btree. | ||
1714 | */ | ||
1715 | error = xfs_difree_inobt(mp, tp, agbp, agino, flist, deleted, first_ino, | ||
1716 | &rec); | ||
1717 | if (error) | ||
1718 | goto error0; | ||
1719 | |||
1720 | /* | ||
1721 | * Fix up the free inode btree. | ||
1722 | */ | ||
1723 | if (xfs_sb_version_hasfinobt(&mp->m_sb)) { | ||
1724 | error = xfs_difree_finobt(mp, tp, agbp, agino, &rec); | ||
1725 | if (error) | ||
1726 | goto error0; | ||
1727 | } | ||
1728 | |||
1729 | return 0; | ||
1730 | |||
1731 | error0: | ||
1732 | return error; | ||
1733 | } | ||
1734 | |||
1272 | STATIC int | 1735 | STATIC int |
1273 | xfs_imap_lookup( | 1736 | xfs_imap_lookup( |
1274 | struct xfs_mount *mp, | 1737 | struct xfs_mount *mp, |
@@ -1300,7 +1763,7 @@ xfs_imap_lookup( | |||
1300 | * we have a record, we need to ensure it contains the inode number | 1763 | * we have a record, we need to ensure it contains the inode number |
1301 | * we are looking up. | 1764 | * we are looking up. |
1302 | */ | 1765 | */ |
1303 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); | 1766 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO); |
1304 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i); | 1767 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i); |
1305 | if (!error) { | 1768 | if (!error) { |
1306 | if (i) | 1769 | if (i) |
@@ -1488,7 +1951,16 @@ xfs_ialloc_compute_maxlevels( | |||
1488 | } | 1951 | } |
1489 | 1952 | ||
1490 | /* | 1953 | /* |
1491 | * Log specified fields for the ag hdr (inode section) | 1954 | * Log specified fields for the ag hdr (inode section). The growth of the agi |
1955 | * structure over time requires that we interpret the buffer as two logical | ||
1956 | * regions delineated by the end of the unlinked list. This is due to the size | ||
1957 | * of the hash table and its location in the middle of the agi. | ||
1958 | * | ||
1959 | * For example, a request to log a field before agi_unlinked and a field after | ||
1960 | * agi_unlinked could cause us to log the entire hash table and use an excessive | ||
1961 | * amount of log space. To avoid this behavior, log the region up through | ||
1962 | * agi_unlinked in one call and the region after agi_unlinked through the end of | ||
1963 | * the structure in another. | ||
1492 | */ | 1964 | */ |
1493 | void | 1965 | void |
1494 | xfs_ialloc_log_agi( | 1966 | xfs_ialloc_log_agi( |
@@ -1511,6 +1983,8 @@ xfs_ialloc_log_agi( | |||
1511 | offsetof(xfs_agi_t, agi_newino), | 1983 | offsetof(xfs_agi_t, agi_newino), |
1512 | offsetof(xfs_agi_t, agi_dirino), | 1984 | offsetof(xfs_agi_t, agi_dirino), |
1513 | offsetof(xfs_agi_t, agi_unlinked), | 1985 | offsetof(xfs_agi_t, agi_unlinked), |
1986 | offsetof(xfs_agi_t, agi_free_root), | ||
1987 | offsetof(xfs_agi_t, agi_free_level), | ||
1514 | sizeof(xfs_agi_t) | 1988 | sizeof(xfs_agi_t) |
1515 | }; | 1989 | }; |
1516 | #ifdef DEBUG | 1990 | #ifdef DEBUG |
@@ -1519,15 +1993,30 @@ xfs_ialloc_log_agi( | |||
1519 | agi = XFS_BUF_TO_AGI(bp); | 1993 | agi = XFS_BUF_TO_AGI(bp); |
1520 | ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); | 1994 | ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); |
1521 | #endif | 1995 | #endif |
1996 | |||
1997 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGI_BUF); | ||
1998 | |||
1522 | /* | 1999 | /* |
1523 | * Compute byte offsets for the first and last fields. | 2000 | * Compute byte offsets for the first and last fields in the first |
2001 | * region and log the agi buffer. This only logs up through | ||
2002 | * agi_unlinked. | ||
1524 | */ | 2003 | */ |
1525 | xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS, &first, &last); | 2004 | if (fields & XFS_AGI_ALL_BITS_R1) { |
2005 | xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS_R1, | ||
2006 | &first, &last); | ||
2007 | xfs_trans_log_buf(tp, bp, first, last); | ||
2008 | } | ||
2009 | |||
1526 | /* | 2010 | /* |
1527 | * Log the allocation group inode header buffer. | 2011 | * Mask off the bits in the first region and calculate the first and |
2012 | * last field offsets for any bits in the second region. | ||
1528 | */ | 2013 | */ |
1529 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGI_BUF); | 2014 | fields &= ~XFS_AGI_ALL_BITS_R1; |
1530 | xfs_trans_log_buf(tp, bp, first, last); | 2015 | if (fields) { |
2016 | xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS_R2, | ||
2017 | &first, &last); | ||
2018 | xfs_trans_log_buf(tp, bp, first, last); | ||
2019 | } | ||
1531 | } | 2020 | } |
1532 | 2021 | ||
1533 | #ifdef DEBUG | 2022 | #ifdef DEBUG |
@@ -1640,7 +2129,6 @@ xfs_read_agi( | |||
1640 | if (error) | 2129 | if (error) |
1641 | return error; | 2130 | return error; |
1642 | 2131 | ||
1643 | ASSERT(!xfs_buf_geterror(*bpp)); | ||
1644 | xfs_buf_set_ref(*bpp, XFS_AGI_REF); | 2132 | xfs_buf_set_ref(*bpp, XFS_AGI_REF); |
1645 | return 0; | 2133 | return 0; |
1646 | } | 2134 | } |
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h index 812365d17e67..95ad1c002d60 100644 --- a/fs/xfs/xfs_ialloc.h +++ b/fs/xfs/xfs_ialloc.h | |||
@@ -90,7 +90,7 @@ xfs_difree( | |||
90 | struct xfs_trans *tp, /* transaction pointer */ | 90 | struct xfs_trans *tp, /* transaction pointer */ |
91 | xfs_ino_t inode, /* inode to be freed */ | 91 | xfs_ino_t inode, /* inode to be freed */ |
92 | struct xfs_bmap_free *flist, /* extents to free */ | 92 | struct xfs_bmap_free *flist, /* extents to free */ |
93 | int *delete, /* set if inode cluster was deleted */ | 93 | int *deleted, /* set if inode cluster was deleted */ |
94 | xfs_ino_t *first_ino); /* first inode in deleted cluster */ | 94 | xfs_ino_t *first_ino); /* first inode in deleted cluster */ |
95 | 95 | ||
96 | /* | 96 | /* |
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index 7e309b11e87d..726f83a681a5 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c | |||
@@ -49,7 +49,8 @@ xfs_inobt_dup_cursor( | |||
49 | struct xfs_btree_cur *cur) | 49 | struct xfs_btree_cur *cur) |
50 | { | 50 | { |
51 | return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, | 51 | return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, |
52 | cur->bc_private.a.agbp, cur->bc_private.a.agno); | 52 | cur->bc_private.a.agbp, cur->bc_private.a.agno, |
53 | cur->bc_btnum); | ||
53 | } | 54 | } |
54 | 55 | ||
55 | STATIC void | 56 | STATIC void |
@@ -66,12 +67,26 @@ xfs_inobt_set_root( | |||
66 | xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); | 67 | xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); |
67 | } | 68 | } |
68 | 69 | ||
70 | STATIC void | ||
71 | xfs_finobt_set_root( | ||
72 | struct xfs_btree_cur *cur, | ||
73 | union xfs_btree_ptr *nptr, | ||
74 | int inc) /* level change */ | ||
75 | { | ||
76 | struct xfs_buf *agbp = cur->bc_private.a.agbp; | ||
77 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); | ||
78 | |||
79 | agi->agi_free_root = nptr->s; | ||
80 | be32_add_cpu(&agi->agi_free_level, inc); | ||
81 | xfs_ialloc_log_agi(cur->bc_tp, agbp, | ||
82 | XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL); | ||
83 | } | ||
84 | |||
69 | STATIC int | 85 | STATIC int |
70 | xfs_inobt_alloc_block( | 86 | xfs_inobt_alloc_block( |
71 | struct xfs_btree_cur *cur, | 87 | struct xfs_btree_cur *cur, |
72 | union xfs_btree_ptr *start, | 88 | union xfs_btree_ptr *start, |
73 | union xfs_btree_ptr *new, | 89 | union xfs_btree_ptr *new, |
74 | int length, | ||
75 | int *stat) | 90 | int *stat) |
76 | { | 91 | { |
77 | xfs_alloc_arg_t args; /* block allocation args */ | 92 | xfs_alloc_arg_t args; /* block allocation args */ |
@@ -173,6 +188,17 @@ xfs_inobt_init_ptr_from_cur( | |||
173 | ptr->s = agi->agi_root; | 188 | ptr->s = agi->agi_root; |
174 | } | 189 | } |
175 | 190 | ||
191 | STATIC void | ||
192 | xfs_finobt_init_ptr_from_cur( | ||
193 | struct xfs_btree_cur *cur, | ||
194 | union xfs_btree_ptr *ptr) | ||
195 | { | ||
196 | struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); | ||
197 | |||
198 | ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); | ||
199 | ptr->s = agi->agi_free_root; | ||
200 | } | ||
201 | |||
176 | STATIC __int64_t | 202 | STATIC __int64_t |
177 | xfs_inobt_key_diff( | 203 | xfs_inobt_key_diff( |
178 | struct xfs_btree_cur *cur, | 204 | struct xfs_btree_cur *cur, |
@@ -203,6 +229,7 @@ xfs_inobt_verify( | |||
203 | */ | 229 | */ |
204 | switch (block->bb_magic) { | 230 | switch (block->bb_magic) { |
205 | case cpu_to_be32(XFS_IBT_CRC_MAGIC): | 231 | case cpu_to_be32(XFS_IBT_CRC_MAGIC): |
232 | case cpu_to_be32(XFS_FIBT_CRC_MAGIC): | ||
206 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 233 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
207 | return false; | 234 | return false; |
208 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) | 235 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) |
@@ -214,6 +241,7 @@ xfs_inobt_verify( | |||
214 | return false; | 241 | return false; |
215 | /* fall through */ | 242 | /* fall through */ |
216 | case cpu_to_be32(XFS_IBT_MAGIC): | 243 | case cpu_to_be32(XFS_IBT_MAGIC): |
244 | case cpu_to_be32(XFS_FIBT_MAGIC): | ||
217 | break; | 245 | break; |
218 | default: | 246 | default: |
219 | return 0; | 247 | return 0; |
@@ -317,6 +345,28 @@ static const struct xfs_btree_ops xfs_inobt_ops = { | |||
317 | #endif | 345 | #endif |
318 | }; | 346 | }; |
319 | 347 | ||
348 | static const struct xfs_btree_ops xfs_finobt_ops = { | ||
349 | .rec_len = sizeof(xfs_inobt_rec_t), | ||
350 | .key_len = sizeof(xfs_inobt_key_t), | ||
351 | |||
352 | .dup_cursor = xfs_inobt_dup_cursor, | ||
353 | .set_root = xfs_finobt_set_root, | ||
354 | .alloc_block = xfs_inobt_alloc_block, | ||
355 | .free_block = xfs_inobt_free_block, | ||
356 | .get_minrecs = xfs_inobt_get_minrecs, | ||
357 | .get_maxrecs = xfs_inobt_get_maxrecs, | ||
358 | .init_key_from_rec = xfs_inobt_init_key_from_rec, | ||
359 | .init_rec_from_key = xfs_inobt_init_rec_from_key, | ||
360 | .init_rec_from_cur = xfs_inobt_init_rec_from_cur, | ||
361 | .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, | ||
362 | .key_diff = xfs_inobt_key_diff, | ||
363 | .buf_ops = &xfs_inobt_buf_ops, | ||
364 | #if defined(DEBUG) || defined(XFS_WARN) | ||
365 | .keys_inorder = xfs_inobt_keys_inorder, | ||
366 | .recs_inorder = xfs_inobt_recs_inorder, | ||
367 | #endif | ||
368 | }; | ||
369 | |||
320 | /* | 370 | /* |
321 | * Allocate a new inode btree cursor. | 371 | * Allocate a new inode btree cursor. |
322 | */ | 372 | */ |
@@ -325,7 +375,8 @@ xfs_inobt_init_cursor( | |||
325 | struct xfs_mount *mp, /* file system mount point */ | 375 | struct xfs_mount *mp, /* file system mount point */ |
326 | struct xfs_trans *tp, /* transaction pointer */ | 376 | struct xfs_trans *tp, /* transaction pointer */ |
327 | struct xfs_buf *agbp, /* buffer for agi structure */ | 377 | struct xfs_buf *agbp, /* buffer for agi structure */ |
328 | xfs_agnumber_t agno) /* allocation group number */ | 378 | xfs_agnumber_t agno, /* allocation group number */ |
379 | xfs_btnum_t btnum) /* ialloc or free ino btree */ | ||
329 | { | 380 | { |
330 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); | 381 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); |
331 | struct xfs_btree_cur *cur; | 382 | struct xfs_btree_cur *cur; |
@@ -334,11 +385,17 @@ xfs_inobt_init_cursor( | |||
334 | 385 | ||
335 | cur->bc_tp = tp; | 386 | cur->bc_tp = tp; |
336 | cur->bc_mp = mp; | 387 | cur->bc_mp = mp; |
337 | cur->bc_nlevels = be32_to_cpu(agi->agi_level); | 388 | cur->bc_btnum = btnum; |
338 | cur->bc_btnum = XFS_BTNUM_INO; | 389 | if (btnum == XFS_BTNUM_INO) { |
390 | cur->bc_nlevels = be32_to_cpu(agi->agi_level); | ||
391 | cur->bc_ops = &xfs_inobt_ops; | ||
392 | } else { | ||
393 | cur->bc_nlevels = be32_to_cpu(agi->agi_free_level); | ||
394 | cur->bc_ops = &xfs_finobt_ops; | ||
395 | } | ||
396 | |||
339 | cur->bc_blocklog = mp->m_sb.sb_blocklog; | 397 | cur->bc_blocklog = mp->m_sb.sb_blocklog; |
340 | 398 | ||
341 | cur->bc_ops = &xfs_inobt_ops; | ||
342 | if (xfs_sb_version_hascrc(&mp->m_sb)) | 399 | if (xfs_sb_version_hascrc(&mp->m_sb)) |
343 | cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; | 400 | cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; |
344 | 401 | ||
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h index f38b22011c4e..d7ebea72c2d0 100644 --- a/fs/xfs/xfs_ialloc_btree.h +++ b/fs/xfs/xfs_ialloc_btree.h | |||
@@ -58,7 +58,8 @@ struct xfs_mount; | |||
58 | ((index) - 1) * sizeof(xfs_inobt_ptr_t))) | 58 | ((index) - 1) * sizeof(xfs_inobt_ptr_t))) |
59 | 59 | ||
60 | extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, | 60 | extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, |
61 | struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t); | 61 | struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t, |
62 | xfs_btnum_t); | ||
62 | extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); | 63 | extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); |
63 | 64 | ||
64 | #endif /* __XFS_IALLOC_BTREE_H__ */ | 65 | #endif /* __XFS_IALLOC_BTREE_H__ */ |
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 98d35244eecc..c48df5f25b9f 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
@@ -507,8 +507,7 @@ STATIC int | |||
507 | xfs_inode_ag_walk( | 507 | xfs_inode_ag_walk( |
508 | struct xfs_mount *mp, | 508 | struct xfs_mount *mp, |
509 | struct xfs_perag *pag, | 509 | struct xfs_perag *pag, |
510 | int (*execute)(struct xfs_inode *ip, | 510 | int (*execute)(struct xfs_inode *ip, int flags, |
511 | struct xfs_perag *pag, int flags, | ||
512 | void *args), | 511 | void *args), |
513 | int flags, | 512 | int flags, |
514 | void *args, | 513 | void *args, |
@@ -582,7 +581,7 @@ restart: | |||
582 | for (i = 0; i < nr_found; i++) { | 581 | for (i = 0; i < nr_found; i++) { |
583 | if (!batch[i]) | 582 | if (!batch[i]) |
584 | continue; | 583 | continue; |
585 | error = execute(batch[i], pag, flags, args); | 584 | error = execute(batch[i], flags, args); |
586 | IRELE(batch[i]); | 585 | IRELE(batch[i]); |
587 | if (error == EAGAIN) { | 586 | if (error == EAGAIN) { |
588 | skipped++; | 587 | skipped++; |
@@ -636,8 +635,7 @@ xfs_eofblocks_worker( | |||
636 | int | 635 | int |
637 | xfs_inode_ag_iterator( | 636 | xfs_inode_ag_iterator( |
638 | struct xfs_mount *mp, | 637 | struct xfs_mount *mp, |
639 | int (*execute)(struct xfs_inode *ip, | 638 | int (*execute)(struct xfs_inode *ip, int flags, |
640 | struct xfs_perag *pag, int flags, | ||
641 | void *args), | 639 | void *args), |
642 | int flags, | 640 | int flags, |
643 | void *args) | 641 | void *args) |
@@ -664,8 +662,7 @@ xfs_inode_ag_iterator( | |||
664 | int | 662 | int |
665 | xfs_inode_ag_iterator_tag( | 663 | xfs_inode_ag_iterator_tag( |
666 | struct xfs_mount *mp, | 664 | struct xfs_mount *mp, |
667 | int (*execute)(struct xfs_inode *ip, | 665 | int (*execute)(struct xfs_inode *ip, int flags, |
668 | struct xfs_perag *pag, int flags, | ||
669 | void *args), | 666 | void *args), |
670 | int flags, | 667 | int flags, |
671 | void *args, | 668 | void *args, |
@@ -1209,7 +1206,6 @@ xfs_inode_match_id( | |||
1209 | STATIC int | 1206 | STATIC int |
1210 | xfs_inode_free_eofblocks( | 1207 | xfs_inode_free_eofblocks( |
1211 | struct xfs_inode *ip, | 1208 | struct xfs_inode *ip, |
1212 | struct xfs_perag *pag, | ||
1213 | int flags, | 1209 | int flags, |
1214 | void *args) | 1210 | void *args) |
1215 | { | 1211 | { |
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 9ed68bb750f5..9cf017b899be 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h | |||
@@ -60,12 +60,10 @@ int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); | |||
60 | void xfs_eofblocks_worker(struct work_struct *); | 60 | void xfs_eofblocks_worker(struct work_struct *); |
61 | 61 | ||
62 | int xfs_inode_ag_iterator(struct xfs_mount *mp, | 62 | int xfs_inode_ag_iterator(struct xfs_mount *mp, |
63 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, | 63 | int (*execute)(struct xfs_inode *ip, int flags, void *args), |
64 | int flags, void *args), | ||
65 | int flags, void *args); | 64 | int flags, void *args); |
66 | int xfs_inode_ag_iterator_tag(struct xfs_mount *mp, | 65 | int xfs_inode_ag_iterator_tag(struct xfs_mount *mp, |
67 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, | 66 | int (*execute)(struct xfs_inode *ip, int flags, void *args), |
68 | int flags, void *args), | ||
69 | int flags, void *args, int tag); | 67 | int flags, void *args, int tag); |
70 | 68 | ||
71 | static inline int | 69 | static inline int |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 768087bedbac..a6115fe1ac94 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -655,7 +655,6 @@ xfs_ialloc( | |||
655 | uint flags; | 655 | uint flags; |
656 | int error; | 656 | int error; |
657 | timespec_t tv; | 657 | timespec_t tv; |
658 | int filestreams = 0; | ||
659 | 658 | ||
660 | /* | 659 | /* |
661 | * Call the space management code to pick | 660 | * Call the space management code to pick |
@@ -682,6 +681,14 @@ xfs_ialloc( | |||
682 | return error; | 681 | return error; |
683 | ASSERT(ip != NULL); | 682 | ASSERT(ip != NULL); |
684 | 683 | ||
684 | /* | ||
685 | * We always convert v1 inodes to v2 now - we only support filesystems | ||
686 | * with >= v2 inode capability, so there is no reason for ever leaving | ||
687 | * an inode in v1 format. | ||
688 | */ | ||
689 | if (ip->i_d.di_version == 1) | ||
690 | ip->i_d.di_version = 2; | ||
691 | |||
685 | ip->i_d.di_mode = mode; | 692 | ip->i_d.di_mode = mode; |
686 | ip->i_d.di_onlink = 0; | 693 | ip->i_d.di_onlink = 0; |
687 | ip->i_d.di_nlink = nlink; | 694 | ip->i_d.di_nlink = nlink; |
@@ -691,27 +698,6 @@ xfs_ialloc( | |||
691 | xfs_set_projid(ip, prid); | 698 | xfs_set_projid(ip, prid); |
692 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | 699 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); |
693 | 700 | ||
694 | /* | ||
695 | * If the superblock version is up to where we support new format | ||
696 | * inodes and this is currently an old format inode, then change | ||
697 | * the inode version number now. This way we only do the conversion | ||
698 | * here rather than here and in the flush/logging code. | ||
699 | */ | ||
700 | if (xfs_sb_version_hasnlink(&mp->m_sb) && | ||
701 | ip->i_d.di_version == 1) { | ||
702 | ip->i_d.di_version = 2; | ||
703 | /* | ||
704 | * We've already zeroed the old link count, the projid field, | ||
705 | * and the pad field. | ||
706 | */ | ||
707 | } | ||
708 | |||
709 | /* | ||
710 | * Project ids won't be stored on disk if we are using a version 1 inode. | ||
711 | */ | ||
712 | if ((prid != 0) && (ip->i_d.di_version == 1)) | ||
713 | xfs_bump_ino_vers2(tp, ip); | ||
714 | |||
715 | if (pip && XFS_INHERIT_GID(pip)) { | 701 | if (pip && XFS_INHERIT_GID(pip)) { |
716 | ip->i_d.di_gid = pip->i_d.di_gid; | 702 | ip->i_d.di_gid = pip->i_d.di_gid; |
717 | if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) { | 703 | if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) { |
@@ -772,13 +758,6 @@ xfs_ialloc( | |||
772 | flags |= XFS_ILOG_DEV; | 758 | flags |= XFS_ILOG_DEV; |
773 | break; | 759 | break; |
774 | case S_IFREG: | 760 | case S_IFREG: |
775 | /* | ||
776 | * we can't set up filestreams until after the VFS inode | ||
777 | * is set up properly. | ||
778 | */ | ||
779 | if (pip && xfs_inode_is_filestream(pip)) | ||
780 | filestreams = 1; | ||
781 | /* fall through */ | ||
782 | case S_IFDIR: | 761 | case S_IFDIR: |
783 | if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { | 762 | if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { |
784 | uint di_flags = 0; | 763 | uint di_flags = 0; |
@@ -844,15 +823,6 @@ xfs_ialloc( | |||
844 | /* now that we have an i_mode we can setup inode ops and unlock */ | 823 | /* now that we have an i_mode we can setup inode ops and unlock */ |
845 | xfs_setup_inode(ip); | 824 | xfs_setup_inode(ip); |
846 | 825 | ||
847 | /* now we have set up the vfs inode we can associate the filestream */ | ||
848 | if (filestreams) { | ||
849 | error = xfs_filestream_associate(pip, ip); | ||
850 | if (error < 0) | ||
851 | return -error; | ||
852 | if (!error) | ||
853 | xfs_iflags_set(ip, XFS_IFILESTREAM); | ||
854 | } | ||
855 | |||
856 | *ipp = ip; | 826 | *ipp = ip; |
857 | return 0; | 827 | return 0; |
858 | } | 828 | } |
@@ -1073,40 +1043,6 @@ xfs_droplink( | |||
1073 | } | 1043 | } |
1074 | 1044 | ||
1075 | /* | 1045 | /* |
1076 | * This gets called when the inode's version needs to be changed from 1 to 2. | ||
1077 | * Currently this happens when the nlink field overflows the old 16-bit value | ||
1078 | * or when chproj is called to change the project for the first time. | ||
1079 | * As a side effect the superblock version will also get rev'd | ||
1080 | * to contain the NLINK bit. | ||
1081 | */ | ||
1082 | void | ||
1083 | xfs_bump_ino_vers2( | ||
1084 | xfs_trans_t *tp, | ||
1085 | xfs_inode_t *ip) | ||
1086 | { | ||
1087 | xfs_mount_t *mp; | ||
1088 | |||
1089 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
1090 | ASSERT(ip->i_d.di_version == 1); | ||
1091 | |||
1092 | ip->i_d.di_version = 2; | ||
1093 | ip->i_d.di_onlink = 0; | ||
1094 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
1095 | mp = tp->t_mountp; | ||
1096 | if (!xfs_sb_version_hasnlink(&mp->m_sb)) { | ||
1097 | spin_lock(&mp->m_sb_lock); | ||
1098 | if (!xfs_sb_version_hasnlink(&mp->m_sb)) { | ||
1099 | xfs_sb_version_addnlink(&mp->m_sb); | ||
1100 | spin_unlock(&mp->m_sb_lock); | ||
1101 | xfs_mod_sb(tp, XFS_SB_VERSIONNUM); | ||
1102 | } else { | ||
1103 | spin_unlock(&mp->m_sb_lock); | ||
1104 | } | ||
1105 | } | ||
1106 | /* Caller must log the inode */ | ||
1107 | } | ||
1108 | |||
1109 | /* | ||
1110 | * Increment the link count on an inode & log the change. | 1046 | * Increment the link count on an inode & log the change. |
1111 | */ | 1047 | */ |
1112 | int | 1048 | int |
@@ -1116,22 +1052,10 @@ xfs_bumplink( | |||
1116 | { | 1052 | { |
1117 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); | 1053 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); |
1118 | 1054 | ||
1055 | ASSERT(ip->i_d.di_version > 1); | ||
1119 | ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE)); | 1056 | ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE)); |
1120 | ip->i_d.di_nlink++; | 1057 | ip->i_d.di_nlink++; |
1121 | inc_nlink(VFS_I(ip)); | 1058 | inc_nlink(VFS_I(ip)); |
1122 | if ((ip->i_d.di_version == 1) && | ||
1123 | (ip->i_d.di_nlink > XFS_MAXLINK_1)) { | ||
1124 | /* | ||
1125 | * The inode has increased its number of links beyond | ||
1126 | * what can fit in an old format inode. It now needs | ||
1127 | * to be converted to a version 2 inode with a 32 bit | ||
1128 | * link count. If this is the first inode in the file | ||
1129 | * system to do this, then we need to bump the superblock | ||
1130 | * version number as well. | ||
1131 | */ | ||
1132 | xfs_bump_ino_vers2(tp, ip); | ||
1133 | } | ||
1134 | |||
1135 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 1059 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
1136 | return 0; | 1060 | return 0; |
1137 | } | 1061 | } |
@@ -1699,16 +1623,6 @@ xfs_release( | |||
1699 | int truncated; | 1623 | int truncated; |
1700 | 1624 | ||
1701 | /* | 1625 | /* |
1702 | * If we are using filestreams, and we have an unlinked | ||
1703 | * file that we are processing the last close on, then nothing | ||
1704 | * will be able to reopen and write to this file. Purge this | ||
1705 | * inode from the filestreams cache so that it doesn't delay | ||
1706 | * teardown of the inode. | ||
1707 | */ | ||
1708 | if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip)) | ||
1709 | xfs_filestream_deassociate(ip); | ||
1710 | |||
1711 | /* | ||
1712 | * If we previously truncated this file and removed old data | 1626 | * If we previously truncated this file and removed old data |
1713 | * in the process, we want to initiate "early" writeout on | 1627 | * in the process, we want to initiate "early" writeout on |
1714 | * the last close. This is an attempt to combat the notorious | 1628 | * the last close. This is an attempt to combat the notorious |
@@ -1838,9 +1752,33 @@ xfs_inactive_ifree( | |||
1838 | int error; | 1752 | int error; |
1839 | 1753 | ||
1840 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | 1754 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); |
1841 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); | 1755 | |
1756 | /* | ||
1757 | * The ifree transaction might need to allocate blocks for record | ||
1758 | * insertion to the finobt. We don't want to fail here at ENOSPC, so | ||
1759 | * allow ifree to dip into the reserved block pool if necessary. | ||
1760 | * | ||
1761 | * Freeing large sets of inodes generally means freeing inode chunks, | ||
1762 | * directory and file data blocks, so this should be relatively safe. | ||
1763 | * Only under severe circumstances should it be possible to free enough | ||
1764 | * inodes to exhaust the reserve block pool via finobt expansion while | ||
1765 | * at the same time not creating free space in the filesystem. | ||
1766 | * | ||
1767 | * Send a warning if the reservation does happen to fail, as the inode | ||
1768 | * now remains allocated and sits on the unlinked list until the fs is | ||
1769 | * repaired. | ||
1770 | */ | ||
1771 | tp->t_flags |= XFS_TRANS_RESERVE; | ||
1772 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, | ||
1773 | XFS_IFREE_SPACE_RES(mp), 0); | ||
1842 | if (error) { | 1774 | if (error) { |
1843 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | 1775 | if (error == ENOSPC) { |
1776 | xfs_warn_ratelimited(mp, | ||
1777 | "Failed to remove inode(s) from unlinked list. " | ||
1778 | "Please free space, unmount and run xfs_repair."); | ||
1779 | } else { | ||
1780 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
1781 | } | ||
1844 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); | 1782 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); |
1845 | return error; | 1783 | return error; |
1846 | } | 1784 | } |
@@ -2664,13 +2602,7 @@ xfs_remove( | |||
2664 | if (error) | 2602 | if (error) |
2665 | goto std_return; | 2603 | goto std_return; |
2666 | 2604 | ||
2667 | /* | 2605 | if (is_dir && xfs_inode_is_filestream(ip)) |
2668 | * If we are using filestreams, kill the stream association. | ||
2669 | * If the file is still open it may get a new one but that | ||
2670 | * will get killed on last close in xfs_close() so we don't | ||
2671 | * have to worry about that. | ||
2672 | */ | ||
2673 | if (!is_dir && link_zero && xfs_inode_is_filestream(ip)) | ||
2674 | xfs_filestream_deassociate(ip); | 2606 | xfs_filestream_deassociate(ip); |
2675 | 2607 | ||
2676 | return 0; | 2608 | return 0; |
@@ -3258,6 +3190,7 @@ xfs_iflush_int( | |||
3258 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || | 3190 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || |
3259 | ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK)); | 3191 | ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK)); |
3260 | ASSERT(iip != NULL && iip->ili_fields != 0); | 3192 | ASSERT(iip != NULL && iip->ili_fields != 0); |
3193 | ASSERT(ip->i_d.di_version > 1); | ||
3261 | 3194 | ||
3262 | /* set *dip = inode's place in the buffer */ | 3195 | /* set *dip = inode's place in the buffer */ |
3263 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); | 3196 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); |
@@ -3318,7 +3251,7 @@ xfs_iflush_int( | |||
3318 | } | 3251 | } |
3319 | 3252 | ||
3320 | /* | 3253 | /* |
3321 | * Inode item log recovery for v1/v2 inodes are dependent on the | 3254 | * Inode item log recovery for v2 inodes are dependent on the |
3322 | * di_flushiter count for correct sequencing. We bump the flush | 3255 | * di_flushiter count for correct sequencing. We bump the flush |
3323 | * iteration count so we can detect flushes which postdate a log record | 3256 | * iteration count so we can detect flushes which postdate a log record |
3324 | * during recovery. This is redundant as we now log every change and | 3257 | * during recovery. This is redundant as we now log every change and |
@@ -3341,40 +3274,9 @@ xfs_iflush_int( | |||
3341 | if (ip->i_d.di_flushiter == DI_MAX_FLUSH) | 3274 | if (ip->i_d.di_flushiter == DI_MAX_FLUSH) |
3342 | ip->i_d.di_flushiter = 0; | 3275 | ip->i_d.di_flushiter = 0; |
3343 | 3276 | ||
3344 | /* | 3277 | xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK); |
3345 | * If this is really an old format inode and the superblock version | ||
3346 | * has not been updated to support only new format inodes, then | ||
3347 | * convert back to the old inode format. If the superblock version | ||
3348 | * has been updated, then make the conversion permanent. | ||
3349 | */ | ||
3350 | ASSERT(ip->i_d.di_version == 1 || xfs_sb_version_hasnlink(&mp->m_sb)); | ||
3351 | if (ip->i_d.di_version == 1) { | ||
3352 | if (!xfs_sb_version_hasnlink(&mp->m_sb)) { | ||
3353 | /* | ||
3354 | * Convert it back. | ||
3355 | */ | ||
3356 | ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1); | ||
3357 | dip->di_onlink = cpu_to_be16(ip->i_d.di_nlink); | ||
3358 | } else { | ||
3359 | /* | ||
3360 | * The superblock version has already been bumped, | ||
3361 | * so just make the conversion to the new inode | ||
3362 | * format permanent. | ||
3363 | */ | ||
3364 | ip->i_d.di_version = 2; | ||
3365 | dip->di_version = 2; | ||
3366 | ip->i_d.di_onlink = 0; | ||
3367 | dip->di_onlink = 0; | ||
3368 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
3369 | memset(&(dip->di_pad[0]), 0, | ||
3370 | sizeof(dip->di_pad)); | ||
3371 | ASSERT(xfs_get_projid(ip) == 0); | ||
3372 | } | ||
3373 | } | ||
3374 | |||
3375 | xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp); | ||
3376 | if (XFS_IFORK_Q(ip)) | 3278 | if (XFS_IFORK_Q(ip)) |
3377 | xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp); | 3279 | xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK); |
3378 | xfs_inobp_check(mp, bp); | 3280 | xfs_inobp_check(mp, bp); |
3379 | 3281 | ||
3380 | /* | 3282 | /* |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index f2fcde52b66d..f72bffa67266 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -209,7 +209,6 @@ xfs_get_initial_prid(struct xfs_inode *dp) | |||
209 | #define XFS_ISTALE (1 << 1) /* inode has been staled */ | 209 | #define XFS_ISTALE (1 << 1) /* inode has been staled */ |
210 | #define XFS_IRECLAIMABLE (1 << 2) /* inode can be reclaimed */ | 210 | #define XFS_IRECLAIMABLE (1 << 2) /* inode can be reclaimed */ |
211 | #define XFS_INEW (1 << 3) /* inode has just been allocated */ | 211 | #define XFS_INEW (1 << 3) /* inode has just been allocated */ |
212 | #define XFS_IFILESTREAM (1 << 4) /* inode is in a filestream dir. */ | ||
213 | #define XFS_ITRUNCATED (1 << 5) /* truncated down so flush-on-close */ | 212 | #define XFS_ITRUNCATED (1 << 5) /* truncated down so flush-on-close */ |
214 | #define XFS_IDIRTY_RELEASE (1 << 6) /* dirty release already seen */ | 213 | #define XFS_IDIRTY_RELEASE (1 << 6) /* dirty release already seen */ |
215 | #define __XFS_IFLOCK_BIT 7 /* inode is being flushed right now */ | 214 | #define __XFS_IFLOCK_BIT 7 /* inode is being flushed right now */ |
@@ -225,8 +224,7 @@ xfs_get_initial_prid(struct xfs_inode *dp) | |||
225 | */ | 224 | */ |
226 | #define XFS_IRECLAIM_RESET_FLAGS \ | 225 | #define XFS_IRECLAIM_RESET_FLAGS \ |
227 | (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ | 226 | (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ |
228 | XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \ | 227 | XFS_IDIRTY_RELEASE | XFS_ITRUNCATED) |
229 | XFS_IFILESTREAM); | ||
230 | 228 | ||
231 | /* | 229 | /* |
232 | * Synchronize processes attempting to flush the in-core inode back to disk. | 230 | * Synchronize processes attempting to flush the in-core inode back to disk. |
@@ -379,7 +377,6 @@ int xfs_dir_ialloc(struct xfs_trans **, struct xfs_inode *, umode_t, | |||
379 | struct xfs_inode **, int *); | 377 | struct xfs_inode **, int *); |
380 | int xfs_droplink(struct xfs_trans *, struct xfs_inode *); | 378 | int xfs_droplink(struct xfs_trans *, struct xfs_inode *); |
381 | int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); | 379 | int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); |
382 | void xfs_bump_ino_vers2(struct xfs_trans *, struct xfs_inode *); | ||
383 | 380 | ||
384 | /* from xfs_file.c */ | 381 | /* from xfs_file.c */ |
385 | int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); | 382 | int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); |
diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c index 24e993996bdc..cb35ae41d4a1 100644 --- a/fs/xfs/xfs_inode_buf.c +++ b/fs/xfs/xfs_inode_buf.c | |||
@@ -437,17 +437,16 @@ xfs_iread( | |||
437 | } | 437 | } |
438 | 438 | ||
439 | /* | 439 | /* |
440 | * The inode format changed when we moved the link count and | 440 | * Automatically convert version 1 inode formats in memory to version 2 |
441 | * made it 32 bits long. If this is an old format inode, | 441 | * inode format. If the inode is modified, it will get logged and |
442 | * convert it in memory to look like a new one. If it gets | 442 | * rewritten as a version 2 inode. We can do this because we set the |
443 | * flushed to disk we will convert back before flushing or | 443 | * superblock feature bit for v2 inodes unconditionally during mount |
444 | * logging it. We zero out the new projid field and the old link | 444 | * and it means the reast of the code can assume the inode version is 2 |
445 | * count field. We'll handle clearing the pad field (the remains | 445 | * or higher. |
446 | * of the old uuid field) when we actually convert the inode to | ||
447 | * the new format. We don't change the version number so that we | ||
448 | * can distinguish this from a real new format inode. | ||
449 | */ | 446 | */ |
450 | if (ip->i_d.di_version == 1) { | 447 | if (ip->i_d.di_version == 1) { |
448 | ip->i_d.di_version = 2; | ||
449 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
451 | ip->i_d.di_nlink = ip->i_d.di_onlink; | 450 | ip->i_d.di_nlink = ip->i_d.di_onlink; |
452 | ip->i_d.di_onlink = 0; | 451 | ip->i_d.di_onlink = 0; |
453 | xfs_set_projid(ip, 0); | 452 | xfs_set_projid(ip, 0); |
diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c index 73514c0486b7..b031e8d0d928 100644 --- a/fs/xfs/xfs_inode_fork.c +++ b/fs/xfs/xfs_inode_fork.c | |||
@@ -798,8 +798,7 @@ xfs_iflush_fork( | |||
798 | xfs_inode_t *ip, | 798 | xfs_inode_t *ip, |
799 | xfs_dinode_t *dip, | 799 | xfs_dinode_t *dip, |
800 | xfs_inode_log_item_t *iip, | 800 | xfs_inode_log_item_t *iip, |
801 | int whichfork, | 801 | int whichfork) |
802 | xfs_buf_t *bp) | ||
803 | { | 802 | { |
804 | char *cp; | 803 | char *cp; |
805 | xfs_ifork_t *ifp; | 804 | xfs_ifork_t *ifp; |
diff --git a/fs/xfs/xfs_inode_fork.h b/fs/xfs/xfs_inode_fork.h index eb329a1ea888..7d3b1ed6dcbe 100644 --- a/fs/xfs/xfs_inode_fork.h +++ b/fs/xfs/xfs_inode_fork.h | |||
@@ -127,8 +127,7 @@ typedef struct xfs_ifork { | |||
127 | 127 | ||
128 | int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); | 128 | int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); |
129 | void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, | 129 | void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, |
130 | struct xfs_inode_log_item *, int, | 130 | struct xfs_inode_log_item *, int); |
131 | struct xfs_buf *); | ||
132 | void xfs_idestroy_fork(struct xfs_inode *, int); | 131 | void xfs_idestroy_fork(struct xfs_inode *, int); |
133 | void xfs_idata_realloc(struct xfs_inode *, int, int); | 132 | void xfs_idata_realloc(struct xfs_inode *, int, int); |
134 | void xfs_iroot_realloc(struct xfs_inode *, int, int); | 133 | void xfs_iroot_realloc(struct xfs_inode *, int, int); |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 686889b4a1e5..a640137b3573 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -145,34 +145,6 @@ xfs_inode_item_size( | |||
145 | xfs_inode_item_attr_fork_size(iip, nvecs, nbytes); | 145 | xfs_inode_item_attr_fork_size(iip, nvecs, nbytes); |
146 | } | 146 | } |
147 | 147 | ||
148 | /* | ||
149 | * If this is a v1 format inode, then we need to log it as such. This means | ||
150 | * that we have to copy the link count from the new field to the old. We | ||
151 | * don't have to worry about the new fields, because nothing trusts them as | ||
152 | * long as the old inode version number is there. | ||
153 | */ | ||
154 | STATIC void | ||
155 | xfs_inode_item_format_v1_inode( | ||
156 | struct xfs_inode *ip) | ||
157 | { | ||
158 | if (!xfs_sb_version_hasnlink(&ip->i_mount->m_sb)) { | ||
159 | /* | ||
160 | * Convert it back. | ||
161 | */ | ||
162 | ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1); | ||
163 | ip->i_d.di_onlink = ip->i_d.di_nlink; | ||
164 | } else { | ||
165 | /* | ||
166 | * The superblock version has already been bumped, | ||
167 | * so just make the conversion to the new inode | ||
168 | * format permanent. | ||
169 | */ | ||
170 | ip->i_d.di_version = 2; | ||
171 | ip->i_d.di_onlink = 0; | ||
172 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | STATIC void | 148 | STATIC void |
177 | xfs_inode_item_format_data_fork( | 149 | xfs_inode_item_format_data_fork( |
178 | struct xfs_inode_log_item *iip, | 150 | struct xfs_inode_log_item *iip, |
@@ -370,6 +342,8 @@ xfs_inode_item_format( | |||
370 | struct xfs_inode_log_format *ilf; | 342 | struct xfs_inode_log_format *ilf; |
371 | struct xfs_log_iovec *vecp = NULL; | 343 | struct xfs_log_iovec *vecp = NULL; |
372 | 344 | ||
345 | ASSERT(ip->i_d.di_version > 1); | ||
346 | |||
373 | ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT); | 347 | ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT); |
374 | ilf->ilf_type = XFS_LI_INODE; | 348 | ilf->ilf_type = XFS_LI_INODE; |
375 | ilf->ilf_ino = ip->i_ino; | 349 | ilf->ilf_ino = ip->i_ino; |
@@ -380,8 +354,6 @@ xfs_inode_item_format( | |||
380 | ilf->ilf_size = 2; /* format + core */ | 354 | ilf->ilf_size = 2; /* format + core */ |
381 | xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); | 355 | xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); |
382 | 356 | ||
383 | if (ip->i_d.di_version == 1) | ||
384 | xfs_inode_item_format_v1_inode(ip); | ||
385 | xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE, | 357 | xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE, |
386 | &ip->i_d, | 358 | &ip->i_d, |
387 | xfs_icdinode_size(ip->i_d.di_version)); | 359 | xfs_icdinode_size(ip->i_d.di_version)); |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 6152cbe353e8..8bc1bbce7451 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -543,10 +543,11 @@ xfs_attrmulti_by_handle( | |||
543 | 543 | ||
544 | ops = memdup_user(am_hreq.ops, size); | 544 | ops = memdup_user(am_hreq.ops, size); |
545 | if (IS_ERR(ops)) { | 545 | if (IS_ERR(ops)) { |
546 | error = PTR_ERR(ops); | 546 | error = -PTR_ERR(ops); |
547 | goto out_dput; | 547 | goto out_dput; |
548 | } | 548 | } |
549 | 549 | ||
550 | error = ENOMEM; | ||
550 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); | 551 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); |
551 | if (!attr_name) | 552 | if (!attr_name) |
552 | goto out_kfree_ops; | 553 | goto out_kfree_ops; |
@@ -556,7 +557,7 @@ xfs_attrmulti_by_handle( | |||
556 | ops[i].am_error = strncpy_from_user((char *)attr_name, | 557 | ops[i].am_error = strncpy_from_user((char *)attr_name, |
557 | ops[i].am_attrname, MAXNAMELEN); | 558 | ops[i].am_attrname, MAXNAMELEN); |
558 | if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) | 559 | if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) |
559 | error = -ERANGE; | 560 | error = ERANGE; |
560 | if (ops[i].am_error < 0) | 561 | if (ops[i].am_error < 0) |
561 | break; | 562 | break; |
562 | 563 | ||
@@ -1227,15 +1228,8 @@ xfs_ioctl_setattr( | |||
1227 | olddquot = xfs_qm_vop_chown(tp, ip, | 1228 | olddquot = xfs_qm_vop_chown(tp, ip, |
1228 | &ip->i_pdquot, pdqp); | 1229 | &ip->i_pdquot, pdqp); |
1229 | } | 1230 | } |
1231 | ASSERT(ip->i_d.di_version > 1); | ||
1230 | xfs_set_projid(ip, fa->fsx_projid); | 1232 | xfs_set_projid(ip, fa->fsx_projid); |
1231 | |||
1232 | /* | ||
1233 | * We may have to rev the inode as well as | ||
1234 | * the superblock version number since projids didn't | ||
1235 | * exist before DINODE_VERSION_2 and SB_VERSION_NLINK. | ||
1236 | */ | ||
1237 | if (ip->i_d.di_version == 1) | ||
1238 | xfs_bump_ino_vers2(tp, ip); | ||
1239 | } | 1233 | } |
1240 | 1234 | ||
1241 | } | 1235 | } |
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index a7992f8de9d3..944d5baa710a 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c | |||
@@ -424,10 +424,11 @@ xfs_compat_attrmulti_by_handle( | |||
424 | 424 | ||
425 | ops = memdup_user(compat_ptr(am_hreq.ops), size); | 425 | ops = memdup_user(compat_ptr(am_hreq.ops), size); |
426 | if (IS_ERR(ops)) { | 426 | if (IS_ERR(ops)) { |
427 | error = PTR_ERR(ops); | 427 | error = -PTR_ERR(ops); |
428 | goto out_dput; | 428 | goto out_dput; |
429 | } | 429 | } |
430 | 430 | ||
431 | error = ENOMEM; | ||
431 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); | 432 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); |
432 | if (!attr_name) | 433 | if (!attr_name) |
433 | goto out_kfree_ops; | 434 | goto out_kfree_ops; |
@@ -438,7 +439,7 @@ xfs_compat_attrmulti_by_handle( | |||
438 | compat_ptr(ops[i].am_attrname), | 439 | compat_ptr(ops[i].am_attrname), |
439 | MAXNAMELEN); | 440 | MAXNAMELEN); |
440 | if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) | 441 | if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) |
441 | error = -ERANGE; | 442 | error = ERANGE; |
442 | if (ops[i].am_error < 0) | 443 | if (ops[i].am_error < 0) |
443 | break; | 444 | break; |
444 | 445 | ||
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 3b80ebae05f5..6c5eb4c551e3 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -730,7 +730,7 @@ xfs_iomap_write_allocate( | |||
730 | */ | 730 | */ |
731 | nimaps = 1; | 731 | nimaps = 1; |
732 | end_fsb = XFS_B_TO_FSB(mp, XFS_ISIZE(ip)); | 732 | end_fsb = XFS_B_TO_FSB(mp, XFS_ISIZE(ip)); |
733 | error = xfs_bmap_last_offset(NULL, ip, &last_block, | 733 | error = xfs_bmap_last_offset(ip, &last_block, |
734 | XFS_DATA_FORK); | 734 | XFS_DATA_FORK); |
735 | if (error) | 735 | if (error) |
736 | goto trans_cancel; | 736 | goto trans_cancel; |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 36d630319a27..205613a06068 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -829,22 +829,34 @@ xfs_setattr_size( | |||
829 | */ | 829 | */ |
830 | inode_dio_wait(inode); | 830 | inode_dio_wait(inode); |
831 | 831 | ||
832 | /* | ||
833 | * Do all the page cache truncate work outside the transaction context | ||
834 | * as the "lock" order is page lock->log space reservation. i.e. | ||
835 | * locking pages inside the transaction can ABBA deadlock with | ||
836 | * writeback. We have to do the VFS inode size update before we truncate | ||
837 | * the pagecache, however, to avoid racing with page faults beyond the | ||
838 | * new EOF they are not serialised against truncate operations except by | ||
839 | * page locks and size updates. | ||
840 | * | ||
841 | * Hence we are in a situation where a truncate can fail with ENOMEM | ||
842 | * from xfs_trans_reserve(), but having already truncated the in-memory | ||
843 | * version of the file (i.e. made user visible changes). There's not | ||
844 | * much we can do about this, except to hope that the caller sees ENOMEM | ||
845 | * and retries the truncate operation. | ||
846 | */ | ||
832 | error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks); | 847 | error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks); |
833 | if (error) | 848 | if (error) |
834 | return error; | 849 | return error; |
850 | truncate_setsize(inode, newsize); | ||
835 | 851 | ||
836 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); | 852 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); |
837 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); | 853 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); |
838 | if (error) | 854 | if (error) |
839 | goto out_trans_cancel; | 855 | goto out_trans_cancel; |
840 | 856 | ||
841 | truncate_setsize(inode, newsize); | ||
842 | |||
843 | commit_flags = XFS_TRANS_RELEASE_LOG_RES; | 857 | commit_flags = XFS_TRANS_RELEASE_LOG_RES; |
844 | lock_flags |= XFS_ILOCK_EXCL; | 858 | lock_flags |= XFS_ILOCK_EXCL; |
845 | |||
846 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 859 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
847 | |||
848 | xfs_trans_ijoin(tp, ip, 0); | 860 | xfs_trans_ijoin(tp, ip, 0); |
849 | 861 | ||
850 | /* | 862 | /* |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index f46338285152..cb64f222d607 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -270,7 +270,8 @@ xfs_bulkstat( | |||
270 | /* | 270 | /* |
271 | * Allocate and initialize a btree cursor for ialloc btree. | 271 | * Allocate and initialize a btree cursor for ialloc btree. |
272 | */ | 272 | */ |
273 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno); | 273 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, |
274 | XFS_BTNUM_INO); | ||
274 | irbp = irbuf; | 275 | irbp = irbuf; |
275 | irbufend = irbuf + nirbuf; | 276 | irbufend = irbuf + nirbuf; |
276 | end_of_ag = 0; | 277 | end_of_ag = 0; |
@@ -621,7 +622,8 @@ xfs_inumbers( | |||
621 | agino = 0; | 622 | agino = 0; |
622 | continue; | 623 | continue; |
623 | } | 624 | } |
624 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno); | 625 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, |
626 | XFS_BTNUM_INO); | ||
625 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, | 627 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, |
626 | &tmp); | 628 | &tmp); |
627 | if (error) { | 629 | if (error) { |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index a5f8bd9899d3..292308dede6d 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -1165,7 +1165,7 @@ xlog_iodone(xfs_buf_t *bp) | |||
1165 | /* | 1165 | /* |
1166 | * Race to shutdown the filesystem if we see an error. | 1166 | * Race to shutdown the filesystem if we see an error. |
1167 | */ | 1167 | */ |
1168 | if (XFS_TEST_ERROR((xfs_buf_geterror(bp)), l->l_mp, | 1168 | if (XFS_TEST_ERROR(bp->b_error, l->l_mp, |
1169 | XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { | 1169 | XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { |
1170 | xfs_buf_ioerror_alert(bp, __func__); | 1170 | xfs_buf_ioerror_alert(bp, __func__); |
1171 | xfs_buf_stale(bp); | 1171 | xfs_buf_stale(bp); |
@@ -3952,11 +3952,14 @@ xfs_log_force_umount( | |||
3952 | retval = xlog_state_ioerror(log); | 3952 | retval = xlog_state_ioerror(log); |
3953 | spin_unlock(&log->l_icloglock); | 3953 | spin_unlock(&log->l_icloglock); |
3954 | } | 3954 | } |
3955 | |||
3955 | /* | 3956 | /* |
3956 | * Wake up everybody waiting on xfs_log_force. | 3957 | * Wake up everybody waiting on xfs_log_force. Wake the CIL push first |
3957 | * Callback all log item committed functions as if the | 3958 | * as if the log writes were completed. The abort handling in the log |
3958 | * log writes were completed. | 3959 | * item committed callback functions will do this again under lock to |
3960 | * avoid races. | ||
3959 | */ | 3961 | */ |
3962 | wake_up_all(&log->l_cilp->xc_commit_wait); | ||
3960 | xlog_state_do_callback(log, XFS_LI_ABORTED, NULL); | 3963 | xlog_state_do_callback(log, XFS_LI_ABORTED, NULL); |
3961 | 3964 | ||
3962 | #ifdef XFSERRORDEBUG | 3965 | #ifdef XFSERRORDEBUG |
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 2c4004475e71..84e0deb95abd 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
@@ -24,7 +24,8 @@ struct xfs_log_vec { | |||
24 | struct xfs_log_iovec *lv_iovecp; /* iovec array */ | 24 | struct xfs_log_iovec *lv_iovecp; /* iovec array */ |
25 | struct xfs_log_item *lv_item; /* owner */ | 25 | struct xfs_log_item *lv_item; /* owner */ |
26 | char *lv_buf; /* formatted buffer */ | 26 | char *lv_buf; /* formatted buffer */ |
27 | int lv_buf_len; /* size of formatted buffer */ | 27 | int lv_bytes; /* accounted space in buffer */ |
28 | int lv_buf_len; /* aligned size of buffer */ | ||
28 | int lv_size; /* size of allocated lv */ | 29 | int lv_size; /* size of allocated lv */ |
29 | }; | 30 | }; |
30 | 31 | ||
@@ -52,15 +53,21 @@ xlog_prepare_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp, | |||
52 | return vec->i_addr; | 53 | return vec->i_addr; |
53 | } | 54 | } |
54 | 55 | ||
56 | /* | ||
57 | * We need to make sure the next buffer is naturally aligned for the biggest | ||
58 | * basic data type we put into it. We already accounted for this padding when | ||
59 | * sizing the buffer. | ||
60 | * | ||
61 | * However, this padding does not get written into the log, and hence we have to | ||
62 | * track the space used by the log vectors separately to prevent log space hangs | ||
63 | * due to inaccurate accounting (i.e. a leak) of the used log space through the | ||
64 | * CIL context ticket. | ||
65 | */ | ||
55 | static inline void | 66 | static inline void |
56 | xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len) | 67 | xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len) |
57 | { | 68 | { |
58 | /* | ||
59 | * We need to make sure the next buffer is naturally aligned for the | ||
60 | * biggest basic data type we put into it. We already accounted for | ||
61 | * this when sizing the buffer. | ||
62 | */ | ||
63 | lv->lv_buf_len += round_up(len, sizeof(uint64_t)); | 69 | lv->lv_buf_len += round_up(len, sizeof(uint64_t)); |
70 | lv->lv_bytes += len; | ||
64 | vec->i_len = len; | 71 | vec->i_len = len; |
65 | } | 72 | } |
66 | 73 | ||
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 7e5455391176..b3425b34e3d5 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -97,7 +97,7 @@ xfs_cil_prepare_item( | |||
97 | { | 97 | { |
98 | /* Account for the new LV being passed in */ | 98 | /* Account for the new LV being passed in */ |
99 | if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED) { | 99 | if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED) { |
100 | *diff_len += lv->lv_buf_len; | 100 | *diff_len += lv->lv_bytes; |
101 | *diff_iovecs += lv->lv_niovecs; | 101 | *diff_iovecs += lv->lv_niovecs; |
102 | } | 102 | } |
103 | 103 | ||
@@ -111,7 +111,7 @@ xfs_cil_prepare_item( | |||
111 | else if (old_lv != lv) { | 111 | else if (old_lv != lv) { |
112 | ASSERT(lv->lv_buf_len != XFS_LOG_VEC_ORDERED); | 112 | ASSERT(lv->lv_buf_len != XFS_LOG_VEC_ORDERED); |
113 | 113 | ||
114 | *diff_len -= old_lv->lv_buf_len; | 114 | *diff_len -= old_lv->lv_bytes; |
115 | *diff_iovecs -= old_lv->lv_niovecs; | 115 | *diff_iovecs -= old_lv->lv_niovecs; |
116 | kmem_free(old_lv); | 116 | kmem_free(old_lv); |
117 | } | 117 | } |
@@ -239,7 +239,7 @@ xlog_cil_insert_format_items( | |||
239 | * that the space reservation accounting is correct. | 239 | * that the space reservation accounting is correct. |
240 | */ | 240 | */ |
241 | *diff_iovecs -= lv->lv_niovecs; | 241 | *diff_iovecs -= lv->lv_niovecs; |
242 | *diff_len -= lv->lv_buf_len; | 242 | *diff_len -= lv->lv_bytes; |
243 | } else { | 243 | } else { |
244 | /* allocate new data chunk */ | 244 | /* allocate new data chunk */ |
245 | lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS); | 245 | lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS); |
@@ -259,6 +259,7 @@ xlog_cil_insert_format_items( | |||
259 | 259 | ||
260 | /* The allocated data region lies beyond the iovec region */ | 260 | /* The allocated data region lies beyond the iovec region */ |
261 | lv->lv_buf_len = 0; | 261 | lv->lv_buf_len = 0; |
262 | lv->lv_bytes = 0; | ||
262 | lv->lv_buf = (char *)lv + buf_size - nbytes; | 263 | lv->lv_buf = (char *)lv + buf_size - nbytes; |
263 | ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t))); | 264 | ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t))); |
264 | 265 | ||
@@ -385,7 +386,15 @@ xlog_cil_committed( | |||
385 | xfs_extent_busy_clear(mp, &ctx->busy_extents, | 386 | xfs_extent_busy_clear(mp, &ctx->busy_extents, |
386 | (mp->m_flags & XFS_MOUNT_DISCARD) && !abort); | 387 | (mp->m_flags & XFS_MOUNT_DISCARD) && !abort); |
387 | 388 | ||
389 | /* | ||
390 | * If we are aborting the commit, wake up anyone waiting on the | ||
391 | * committing list. If we don't, then a shutdown we can leave processes | ||
392 | * waiting in xlog_cil_force_lsn() waiting on a sequence commit that | ||
393 | * will never happen because we aborted it. | ||
394 | */ | ||
388 | spin_lock(&ctx->cil->xc_push_lock); | 395 | spin_lock(&ctx->cil->xc_push_lock); |
396 | if (abort) | ||
397 | wake_up_all(&ctx->cil->xc_commit_wait); | ||
389 | list_del(&ctx->committing); | 398 | list_del(&ctx->committing); |
390 | spin_unlock(&ctx->cil->xc_push_lock); | 399 | spin_unlock(&ctx->cil->xc_push_lock); |
391 | 400 | ||
@@ -564,8 +573,18 @@ restart: | |||
564 | spin_lock(&cil->xc_push_lock); | 573 | spin_lock(&cil->xc_push_lock); |
565 | list_for_each_entry(new_ctx, &cil->xc_committing, committing) { | 574 | list_for_each_entry(new_ctx, &cil->xc_committing, committing) { |
566 | /* | 575 | /* |
576 | * Avoid getting stuck in this loop because we were woken by the | ||
577 | * shutdown, but then went back to sleep once already in the | ||
578 | * shutdown state. | ||
579 | */ | ||
580 | if (XLOG_FORCED_SHUTDOWN(log)) { | ||
581 | spin_unlock(&cil->xc_push_lock); | ||
582 | goto out_abort_free_ticket; | ||
583 | } | ||
584 | |||
585 | /* | ||
567 | * Higher sequences will wait for this one so skip them. | 586 | * Higher sequences will wait for this one so skip them. |
568 | * Don't wait for own own sequence, either. | 587 | * Don't wait for our own sequence, either. |
569 | */ | 588 | */ |
570 | if (new_ctx->sequence >= ctx->sequence) | 589 | if (new_ctx->sequence >= ctx->sequence) |
571 | continue; | 590 | continue; |
@@ -810,6 +829,13 @@ restart: | |||
810 | */ | 829 | */ |
811 | spin_lock(&cil->xc_push_lock); | 830 | spin_lock(&cil->xc_push_lock); |
812 | list_for_each_entry(ctx, &cil->xc_committing, committing) { | 831 | list_for_each_entry(ctx, &cil->xc_committing, committing) { |
832 | /* | ||
833 | * Avoid getting stuck in this loop because we were woken by the | ||
834 | * shutdown, but then went back to sleep once already in the | ||
835 | * shutdown state. | ||
836 | */ | ||
837 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
838 | goto out_shutdown; | ||
813 | if (ctx->sequence > sequence) | 839 | if (ctx->sequence > sequence) |
814 | continue; | 840 | continue; |
815 | if (!ctx->commit_lsn) { | 841 | if (!ctx->commit_lsn) { |
@@ -833,14 +859,12 @@ restart: | |||
833 | * push sequence after the above wait loop and the CIL still contains | 859 | * push sequence after the above wait loop and the CIL still contains |
834 | * dirty objects. | 860 | * dirty objects. |
835 | * | 861 | * |
836 | * When the push occurs, it will empty the CIL and | 862 | * When the push occurs, it will empty the CIL and atomically increment |
837 | * atomically increment the currect sequence past the push sequence and | 863 | * the currect sequence past the push sequence and move it into the |
838 | * move it into the committing list. Of course, if the CIL is clean at | 864 | * committing list. Of course, if the CIL is clean at the time of the |
839 | * the time of the push, it won't have pushed the CIL at all, so in that | 865 | * push, it won't have pushed the CIL at all, so in that case we should |
840 | * case we should try the push for this sequence again from the start | 866 | * try the push for this sequence again from the start just in case. |
841 | * just in case. | ||
842 | */ | 867 | */ |
843 | |||
844 | if (sequence == cil->xc_current_sequence && | 868 | if (sequence == cil->xc_current_sequence && |
845 | !list_empty(&cil->xc_cil)) { | 869 | !list_empty(&cil->xc_cil)) { |
846 | spin_unlock(&cil->xc_push_lock); | 870 | spin_unlock(&cil->xc_push_lock); |
@@ -849,6 +873,17 @@ restart: | |||
849 | 873 | ||
850 | spin_unlock(&cil->xc_push_lock); | 874 | spin_unlock(&cil->xc_push_lock); |
851 | return commit_lsn; | 875 | return commit_lsn; |
876 | |||
877 | /* | ||
878 | * We detected a shutdown in progress. We need to trigger the log force | ||
879 | * to pass through it's iclog state machine error handling, even though | ||
880 | * we are already in a shutdown state. Hence we can't return | ||
881 | * NULLCOMMITLSN here as that has special meaning to log forces (i.e. | ||
882 | * LSN is already stable), so we return a zero LSN instead. | ||
883 | */ | ||
884 | out_shutdown: | ||
885 | spin_unlock(&cil->xc_push_lock); | ||
886 | return 0; | ||
852 | } | 887 | } |
853 | 888 | ||
854 | /* | 889 | /* |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index bce53ac81096..981af0f6504b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -2138,7 +2138,9 @@ xlog_recover_validate_buf_type( | |||
2138 | bp->b_ops = &xfs_allocbt_buf_ops; | 2138 | bp->b_ops = &xfs_allocbt_buf_ops; |
2139 | break; | 2139 | break; |
2140 | case XFS_IBT_CRC_MAGIC: | 2140 | case XFS_IBT_CRC_MAGIC: |
2141 | case XFS_FIBT_CRC_MAGIC: | ||
2141 | case XFS_IBT_MAGIC: | 2142 | case XFS_IBT_MAGIC: |
2143 | case XFS_FIBT_MAGIC: | ||
2142 | bp->b_ops = &xfs_inobt_buf_ops; | 2144 | bp->b_ops = &xfs_inobt_buf_ops; |
2143 | break; | 2145 | break; |
2144 | case XFS_BMAP_CRC_MAGIC: | 2146 | case XFS_BMAP_CRC_MAGIC: |
@@ -3145,7 +3147,7 @@ xlog_recover_efd_pass2( | |||
3145 | } | 3147 | } |
3146 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | 3148 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3147 | } | 3149 | } |
3148 | xfs_trans_ail_cursor_done(ailp, &cur); | 3150 | xfs_trans_ail_cursor_done(&cur); |
3149 | spin_unlock(&ailp->xa_lock); | 3151 | spin_unlock(&ailp->xa_lock); |
3150 | 3152 | ||
3151 | return 0; | 3153 | return 0; |
@@ -3520,8 +3522,7 @@ out: | |||
3520 | 3522 | ||
3521 | STATIC int | 3523 | STATIC int |
3522 | xlog_recover_unmount_trans( | 3524 | xlog_recover_unmount_trans( |
3523 | struct xlog *log, | 3525 | struct xlog *log) |
3524 | struct xlog_recover *trans) | ||
3525 | { | 3526 | { |
3526 | /* Do nothing now */ | 3527 | /* Do nothing now */ |
3527 | xfs_warn(log->l_mp, "%s: Unmount LR", __func__); | 3528 | xfs_warn(log->l_mp, "%s: Unmount LR", __func__); |
@@ -3595,7 +3596,7 @@ xlog_recover_process_data( | |||
3595 | trans, pass); | 3596 | trans, pass); |
3596 | break; | 3597 | break; |
3597 | case XLOG_UNMOUNT_TRANS: | 3598 | case XLOG_UNMOUNT_TRANS: |
3598 | error = xlog_recover_unmount_trans(log, trans); | 3599 | error = xlog_recover_unmount_trans(log); |
3599 | break; | 3600 | break; |
3600 | case XLOG_WAS_CONT_TRANS: | 3601 | case XLOG_WAS_CONT_TRANS: |
3601 | error = xlog_recover_add_to_cont_trans(log, | 3602 | error = xlog_recover_add_to_cont_trans(log, |
@@ -3757,7 +3758,7 @@ xlog_recover_process_efis( | |||
3757 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | 3758 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3758 | } | 3759 | } |
3759 | out: | 3760 | out: |
3760 | xfs_trans_ail_cursor_done(ailp, &cur); | 3761 | xfs_trans_ail_cursor_done(&cur); |
3761 | spin_unlock(&ailp->xa_lock); | 3762 | spin_unlock(&ailp->xa_lock); |
3762 | return error; | 3763 | return error; |
3763 | } | 3764 | } |
diff --git a/fs/xfs/xfs_log_rlimit.c b/fs/xfs/xfs_log_rlimit.c index 2af1a0a4d0f1..ee7e0e80246b 100644 --- a/fs/xfs/xfs_log_rlimit.c +++ b/fs/xfs/xfs_log_rlimit.c | |||
@@ -42,7 +42,7 @@ xfs_log_calc_max_attrsetm_res( | |||
42 | int size; | 42 | int size; |
43 | int nblks; | 43 | int nblks; |
44 | 44 | ||
45 | size = xfs_attr_leaf_entsize_local_max(mp->m_sb.sb_blocksize) - | 45 | size = xfs_attr_leaf_entsize_local_max(mp->m_attr_geo->blksize) - |
46 | MAXNAMELEN - 1; | 46 | MAXNAMELEN - 1; |
47 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); | 47 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); |
48 | nblks += XFS_B_TO_FSB(mp, size); | 48 | nblks += XFS_B_TO_FSB(mp, size); |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 944f3d9456a8..3507cd0ec400 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -323,8 +323,19 @@ reread: | |||
323 | /* | 323 | /* |
324 | * Initialize the mount structure from the superblock. | 324 | * Initialize the mount structure from the superblock. |
325 | */ | 325 | */ |
326 | xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); | 326 | xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp)); |
327 | xfs_sb_quota_from_disk(&mp->m_sb); | 327 | xfs_sb_quota_from_disk(sbp); |
328 | |||
329 | /* | ||
330 | * If we haven't validated the superblock, do so now before we try | ||
331 | * to check the sector size and reread the superblock appropriately. | ||
332 | */ | ||
333 | if (sbp->sb_magicnum != XFS_SB_MAGIC) { | ||
334 | if (loud) | ||
335 | xfs_warn(mp, "Invalid superblock magic number"); | ||
336 | error = EINVAL; | ||
337 | goto release_buf; | ||
338 | } | ||
328 | 339 | ||
329 | /* | 340 | /* |
330 | * We must be able to do sector-sized and sector-aligned IO. | 341 | * We must be able to do sector-sized and sector-aligned IO. |
@@ -337,11 +348,11 @@ reread: | |||
337 | goto release_buf; | 348 | goto release_buf; |
338 | } | 349 | } |
339 | 350 | ||
340 | /* | ||
341 | * Re-read the superblock so the buffer is correctly sized, | ||
342 | * and properly verified. | ||
343 | */ | ||
344 | if (buf_ops == NULL) { | 351 | if (buf_ops == NULL) { |
352 | /* | ||
353 | * Re-read the superblock so the buffer is correctly sized, | ||
354 | * and properly verified. | ||
355 | */ | ||
345 | xfs_buf_relse(bp); | 356 | xfs_buf_relse(bp); |
346 | sector_size = sbp->sb_sectsize; | 357 | sector_size = sbp->sb_sectsize; |
347 | buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops; | 358 | buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops; |
@@ -697,6 +708,12 @@ xfs_mountfs( | |||
697 | mp->m_update_flags |= XFS_SB_VERSIONNUM; | 708 | mp->m_update_flags |= XFS_SB_VERSIONNUM; |
698 | } | 709 | } |
699 | 710 | ||
711 | /* always use v2 inodes by default now */ | ||
712 | if (!(mp->m_sb.sb_versionnum & XFS_SB_VERSION_NLINKBIT)) { | ||
713 | mp->m_sb.sb_versionnum |= XFS_SB_VERSION_NLINKBIT; | ||
714 | mp->m_update_flags |= XFS_SB_VERSIONNUM; | ||
715 | } | ||
716 | |||
700 | /* | 717 | /* |
701 | * Check if sb_agblocks is aligned at stripe boundary | 718 | * Check if sb_agblocks is aligned at stripe boundary |
702 | * If sb_agblocks is NOT aligned turn off m_dalign since | 719 | * If sb_agblocks is NOT aligned turn off m_dalign since |
@@ -774,12 +791,11 @@ xfs_mountfs( | |||
774 | 791 | ||
775 | mp->m_dmevmask = 0; /* not persistent; set after each mount */ | 792 | mp->m_dmevmask = 0; /* not persistent; set after each mount */ |
776 | 793 | ||
777 | xfs_dir_mount(mp); | 794 | error = xfs_da_mount(mp); |
778 | 795 | if (error) { | |
779 | /* | 796 | xfs_warn(mp, "Failed dir/attr init: %d", error); |
780 | * Initialize the attribute manager's entries. | 797 | goto out_remove_uuid; |
781 | */ | 798 | } |
782 | mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100; | ||
783 | 799 | ||
784 | /* | 800 | /* |
785 | * Initialize the precomputed transaction reservations values. | 801 | * Initialize the precomputed transaction reservations values. |
@@ -794,7 +810,7 @@ xfs_mountfs( | |||
794 | error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); | 810 | error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); |
795 | if (error) { | 811 | if (error) { |
796 | xfs_warn(mp, "Failed per-ag init: %d", error); | 812 | xfs_warn(mp, "Failed per-ag init: %d", error); |
797 | goto out_remove_uuid; | 813 | goto out_free_dir; |
798 | } | 814 | } |
799 | 815 | ||
800 | if (!sbp->sb_logblocks) { | 816 | if (!sbp->sb_logblocks) { |
@@ -969,6 +985,8 @@ xfs_mountfs( | |||
969 | xfs_wait_buftarg(mp->m_ddev_targp); | 985 | xfs_wait_buftarg(mp->m_ddev_targp); |
970 | out_free_perag: | 986 | out_free_perag: |
971 | xfs_free_perag(mp); | 987 | xfs_free_perag(mp); |
988 | out_free_dir: | ||
989 | xfs_da_unmount(mp); | ||
972 | out_remove_uuid: | 990 | out_remove_uuid: |
973 | xfs_uuid_unmount(mp); | 991 | xfs_uuid_unmount(mp); |
974 | out: | 992 | out: |
@@ -1046,6 +1064,7 @@ xfs_unmountfs( | |||
1046 | "Freespace may not be correct on next mount."); | 1064 | "Freespace may not be correct on next mount."); |
1047 | 1065 | ||
1048 | xfs_log_unmount(mp); | 1066 | xfs_log_unmount(mp); |
1067 | xfs_da_unmount(mp); | ||
1049 | xfs_uuid_unmount(mp); | 1068 | xfs_uuid_unmount(mp); |
1050 | 1069 | ||
1051 | #if defined(DEBUG) | 1070 | #if defined(DEBUG) |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a466c5e5826e..7295a0b7c343 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -27,6 +27,7 @@ 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 | struct xfs_dir_ops; |
30 | struct xfs_da_geometry; | ||
30 | 31 | ||
31 | #ifdef HAVE_PERCPU_SB | 32 | #ifdef HAVE_PERCPU_SB |
32 | 33 | ||
@@ -96,6 +97,8 @@ typedef struct xfs_mount { | |||
96 | uint m_readio_blocks; /* min read size blocks */ | 97 | uint m_readio_blocks; /* min read size blocks */ |
97 | uint m_writeio_log; /* min write size log bytes */ | 98 | uint m_writeio_log; /* min write size log bytes */ |
98 | uint m_writeio_blocks; /* min write size blocks */ | 99 | uint m_writeio_blocks; /* min write size blocks */ |
100 | struct xfs_da_geometry *m_dir_geo; /* directory block geometry */ | ||
101 | struct xfs_da_geometry *m_attr_geo; /* attribute block geometry */ | ||
99 | struct xlog *m_log; /* log specific stuff */ | 102 | struct xlog *m_log; /* log specific stuff */ |
100 | int m_logbufs; /* number of log buffers */ | 103 | int m_logbufs; /* number of log buffers */ |
101 | int m_logbsize; /* size of each log buffer */ | 104 | int m_logbsize; /* size of each log buffer */ |
@@ -131,8 +134,6 @@ typedef struct xfs_mount { | |||
131 | int m_fixedfsid[2]; /* unchanged for life of FS */ | 134 | int m_fixedfsid[2]; /* unchanged for life of FS */ |
132 | uint m_dmevmask; /* DMI events for this FS */ | 135 | uint m_dmevmask; /* DMI events for this FS */ |
133 | __uint64_t m_flags; /* global mount flags */ | 136 | __uint64_t m_flags; /* global mount flags */ |
134 | uint m_dir_node_ents; /* #entries in a dir danode */ | ||
135 | uint m_attr_node_ents; /* #entries in attr danode */ | ||
136 | int m_ialloc_inos; /* inodes in inode allocation */ | 137 | int m_ialloc_inos; /* inodes in inode allocation */ |
137 | int m_ialloc_blks; /* blocks in inode allocation */ | 138 | int m_ialloc_blks; /* blocks in inode allocation */ |
138 | int m_inoalign_mask;/* mask sb_inoalignmt if used */ | 139 | int m_inoalign_mask;/* mask sb_inoalignmt if used */ |
@@ -145,17 +146,10 @@ typedef struct xfs_mount { | |||
145 | int m_dalign; /* stripe unit */ | 146 | int m_dalign; /* stripe unit */ |
146 | int m_swidth; /* stripe width */ | 147 | int m_swidth; /* stripe width */ |
147 | int m_sinoalign; /* stripe unit inode alignment */ | 148 | int m_sinoalign; /* stripe unit inode alignment */ |
148 | int m_attr_magicpct;/* 37% of the blocksize */ | ||
149 | int m_dir_magicpct; /* 37% of the dir blocksize */ | ||
150 | __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ | 149 | __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ |
151 | const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */ | 150 | 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 */ | 151 | 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 */ | 152 | const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */ |
154 | int m_dirblksize; /* directory block sz--bytes */ | ||
155 | int m_dirblkfsbs; /* directory block sz--fsbs */ | ||
156 | xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ | ||
157 | xfs_dablk_t m_dirleafblk; /* blockno of dir non-data v2 */ | ||
158 | xfs_dablk_t m_dirfreeblk; /* blockno of dirfreeindex v2 */ | ||
159 | uint m_chsize; /* size of next field */ | 153 | uint m_chsize; /* size of next field */ |
160 | atomic_t m_active_trans; /* number trans frozen */ | 154 | atomic_t m_active_trans; /* number trans frozen */ |
161 | #ifdef HAVE_PERCPU_SB | 155 | #ifdef HAVE_PERCPU_SB |
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c index 4aff56395732..f99b4933dc22 100644 --- a/fs/xfs/xfs_mru_cache.c +++ b/fs/xfs/xfs_mru_cache.c | |||
@@ -100,14 +100,20 @@ | |||
100 | * likely result in a loop in one of the lists. That's a sure-fire recipe for | 100 | * likely result in a loop in one of the lists. That's a sure-fire recipe for |
101 | * an infinite loop in the code. | 101 | * an infinite loop in the code. |
102 | */ | 102 | */ |
103 | typedef struct xfs_mru_cache_elem | 103 | struct xfs_mru_cache { |
104 | { | 104 | struct radix_tree_root store; /* Core storage data structure. */ |
105 | struct list_head list_node; | 105 | struct list_head *lists; /* Array of lists, one per grp. */ |
106 | unsigned long key; | 106 | struct list_head reap_list; /* Elements overdue for reaping. */ |
107 | void *value; | 107 | spinlock_t lock; /* Lock to protect this struct. */ |
108 | } xfs_mru_cache_elem_t; | 108 | unsigned int grp_count; /* Number of discrete groups. */ |
109 | unsigned int grp_time; /* Time period spanned by grps. */ | ||
110 | unsigned int lru_grp; /* Group containing time zero. */ | ||
111 | unsigned long time_zero; /* Time first element was added. */ | ||
112 | xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */ | ||
113 | struct delayed_work work; /* Workqueue data for reaping. */ | ||
114 | unsigned int queued; /* work has been queued */ | ||
115 | }; | ||
109 | 116 | ||
110 | static kmem_zone_t *xfs_mru_elem_zone; | ||
111 | static struct workqueue_struct *xfs_mru_reap_wq; | 117 | static struct workqueue_struct *xfs_mru_reap_wq; |
112 | 118 | ||
113 | /* | 119 | /* |
@@ -129,12 +135,12 @@ static struct workqueue_struct *xfs_mru_reap_wq; | |||
129 | */ | 135 | */ |
130 | STATIC unsigned long | 136 | STATIC unsigned long |
131 | _xfs_mru_cache_migrate( | 137 | _xfs_mru_cache_migrate( |
132 | xfs_mru_cache_t *mru, | 138 | struct xfs_mru_cache *mru, |
133 | unsigned long now) | 139 | unsigned long now) |
134 | { | 140 | { |
135 | unsigned int grp; | 141 | unsigned int grp; |
136 | unsigned int migrated = 0; | 142 | unsigned int migrated = 0; |
137 | struct list_head *lru_list; | 143 | struct list_head *lru_list; |
138 | 144 | ||
139 | /* Nothing to do if the data store is empty. */ | 145 | /* Nothing to do if the data store is empty. */ |
140 | if (!mru->time_zero) | 146 | if (!mru->time_zero) |
@@ -193,11 +199,11 @@ _xfs_mru_cache_migrate( | |||
193 | */ | 199 | */ |
194 | STATIC void | 200 | STATIC void |
195 | _xfs_mru_cache_list_insert( | 201 | _xfs_mru_cache_list_insert( |
196 | xfs_mru_cache_t *mru, | 202 | struct xfs_mru_cache *mru, |
197 | xfs_mru_cache_elem_t *elem) | 203 | struct xfs_mru_cache_elem *elem) |
198 | { | 204 | { |
199 | unsigned int grp = 0; | 205 | unsigned int grp = 0; |
200 | unsigned long now = jiffies; | 206 | unsigned long now = jiffies; |
201 | 207 | ||
202 | /* | 208 | /* |
203 | * If the data store is empty, initialise time zero, leave grp set to | 209 | * If the data store is empty, initialise time zero, leave grp set to |
@@ -231,10 +237,10 @@ _xfs_mru_cache_list_insert( | |||
231 | */ | 237 | */ |
232 | STATIC void | 238 | STATIC void |
233 | _xfs_mru_cache_clear_reap_list( | 239 | _xfs_mru_cache_clear_reap_list( |
234 | xfs_mru_cache_t *mru) __releases(mru->lock) __acquires(mru->lock) | 240 | struct xfs_mru_cache *mru) |
235 | 241 | __releases(mru->lock) __acquires(mru->lock) | |
236 | { | 242 | { |
237 | xfs_mru_cache_elem_t *elem, *next; | 243 | struct xfs_mru_cache_elem *elem, *next; |
238 | struct list_head tmp; | 244 | struct list_head tmp; |
239 | 245 | ||
240 | INIT_LIST_HEAD(&tmp); | 246 | INIT_LIST_HEAD(&tmp); |
@@ -252,15 +258,8 @@ _xfs_mru_cache_clear_reap_list( | |||
252 | spin_unlock(&mru->lock); | 258 | spin_unlock(&mru->lock); |
253 | 259 | ||
254 | list_for_each_entry_safe(elem, next, &tmp, list_node) { | 260 | list_for_each_entry_safe(elem, next, &tmp, list_node) { |
255 | |||
256 | /* Remove the element from the reap list. */ | ||
257 | list_del_init(&elem->list_node); | 261 | list_del_init(&elem->list_node); |
258 | 262 | mru->free_func(elem); | |
259 | /* Call the client's free function with the key and value pointer. */ | ||
260 | mru->free_func(elem->key, elem->value); | ||
261 | |||
262 | /* Free the element structure. */ | ||
263 | kmem_zone_free(xfs_mru_elem_zone, elem); | ||
264 | } | 263 | } |
265 | 264 | ||
266 | spin_lock(&mru->lock); | 265 | spin_lock(&mru->lock); |
@@ -277,7 +276,8 @@ STATIC void | |||
277 | _xfs_mru_cache_reap( | 276 | _xfs_mru_cache_reap( |
278 | struct work_struct *work) | 277 | struct work_struct *work) |
279 | { | 278 | { |
280 | xfs_mru_cache_t *mru = container_of(work, xfs_mru_cache_t, work.work); | 279 | struct xfs_mru_cache *mru = |
280 | container_of(work, struct xfs_mru_cache, work.work); | ||
281 | unsigned long now, next; | 281 | unsigned long now, next; |
282 | 282 | ||
283 | ASSERT(mru && mru->lists); | 283 | ASSERT(mru && mru->lists); |
@@ -304,28 +304,16 @@ _xfs_mru_cache_reap( | |||
304 | int | 304 | int |
305 | xfs_mru_cache_init(void) | 305 | xfs_mru_cache_init(void) |
306 | { | 306 | { |
307 | xfs_mru_elem_zone = kmem_zone_init(sizeof(xfs_mru_cache_elem_t), | ||
308 | "xfs_mru_cache_elem"); | ||
309 | if (!xfs_mru_elem_zone) | ||
310 | goto out; | ||
311 | |||
312 | xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", WQ_MEM_RECLAIM, 1); | 307 | xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", WQ_MEM_RECLAIM, 1); |
313 | if (!xfs_mru_reap_wq) | 308 | if (!xfs_mru_reap_wq) |
314 | goto out_destroy_mru_elem_zone; | 309 | return -ENOMEM; |
315 | |||
316 | return 0; | 310 | return 0; |
317 | |||
318 | out_destroy_mru_elem_zone: | ||
319 | kmem_zone_destroy(xfs_mru_elem_zone); | ||
320 | out: | ||
321 | return -ENOMEM; | ||
322 | } | 311 | } |
323 | 312 | ||
324 | void | 313 | void |
325 | xfs_mru_cache_uninit(void) | 314 | xfs_mru_cache_uninit(void) |
326 | { | 315 | { |
327 | destroy_workqueue(xfs_mru_reap_wq); | 316 | destroy_workqueue(xfs_mru_reap_wq); |
328 | kmem_zone_destroy(xfs_mru_elem_zone); | ||
329 | } | 317 | } |
330 | 318 | ||
331 | /* | 319 | /* |
@@ -336,14 +324,14 @@ xfs_mru_cache_uninit(void) | |||
336 | */ | 324 | */ |
337 | int | 325 | int |
338 | xfs_mru_cache_create( | 326 | xfs_mru_cache_create( |
339 | xfs_mru_cache_t **mrup, | 327 | struct xfs_mru_cache **mrup, |
340 | unsigned int lifetime_ms, | 328 | unsigned int lifetime_ms, |
341 | unsigned int grp_count, | 329 | unsigned int grp_count, |
342 | xfs_mru_cache_free_func_t free_func) | 330 | xfs_mru_cache_free_func_t free_func) |
343 | { | 331 | { |
344 | xfs_mru_cache_t *mru = NULL; | 332 | struct xfs_mru_cache *mru = NULL; |
345 | int err = 0, grp; | 333 | int err = 0, grp; |
346 | unsigned int grp_time; | 334 | unsigned int grp_time; |
347 | 335 | ||
348 | if (mrup) | 336 | if (mrup) |
349 | *mrup = NULL; | 337 | *mrup = NULL; |
@@ -400,7 +388,7 @@ exit: | |||
400 | */ | 388 | */ |
401 | static void | 389 | static void |
402 | xfs_mru_cache_flush( | 390 | xfs_mru_cache_flush( |
403 | xfs_mru_cache_t *mru) | 391 | struct xfs_mru_cache *mru) |
404 | { | 392 | { |
405 | if (!mru || !mru->lists) | 393 | if (!mru || !mru->lists) |
406 | return; | 394 | return; |
@@ -420,7 +408,7 @@ xfs_mru_cache_flush( | |||
420 | 408 | ||
421 | void | 409 | void |
422 | xfs_mru_cache_destroy( | 410 | xfs_mru_cache_destroy( |
423 | xfs_mru_cache_t *mru) | 411 | struct xfs_mru_cache *mru) |
424 | { | 412 | { |
425 | if (!mru || !mru->lists) | 413 | if (!mru || !mru->lists) |
426 | return; | 414 | return; |
@@ -438,38 +426,30 @@ xfs_mru_cache_destroy( | |||
438 | */ | 426 | */ |
439 | int | 427 | int |
440 | xfs_mru_cache_insert( | 428 | xfs_mru_cache_insert( |
441 | xfs_mru_cache_t *mru, | 429 | struct xfs_mru_cache *mru, |
442 | unsigned long key, | 430 | unsigned long key, |
443 | void *value) | 431 | struct xfs_mru_cache_elem *elem) |
444 | { | 432 | { |
445 | xfs_mru_cache_elem_t *elem; | 433 | int error; |
446 | 434 | ||
447 | ASSERT(mru && mru->lists); | 435 | ASSERT(mru && mru->lists); |
448 | if (!mru || !mru->lists) | 436 | if (!mru || !mru->lists) |
449 | return EINVAL; | 437 | return EINVAL; |
450 | 438 | ||
451 | elem = kmem_zone_zalloc(xfs_mru_elem_zone, KM_SLEEP); | 439 | if (radix_tree_preload(GFP_KERNEL)) |
452 | if (!elem) | ||
453 | return ENOMEM; | 440 | return ENOMEM; |
454 | 441 | ||
455 | if (radix_tree_preload(GFP_KERNEL)) { | ||
456 | kmem_zone_free(xfs_mru_elem_zone, elem); | ||
457 | return ENOMEM; | ||
458 | } | ||
459 | |||
460 | INIT_LIST_HEAD(&elem->list_node); | 442 | INIT_LIST_HEAD(&elem->list_node); |
461 | elem->key = key; | 443 | elem->key = key; |
462 | elem->value = value; | ||
463 | 444 | ||
464 | spin_lock(&mru->lock); | 445 | spin_lock(&mru->lock); |
465 | 446 | error = -radix_tree_insert(&mru->store, key, elem); | |
466 | radix_tree_insert(&mru->store, key, elem); | ||
467 | radix_tree_preload_end(); | 447 | radix_tree_preload_end(); |
468 | _xfs_mru_cache_list_insert(mru, elem); | 448 | if (!error) |
469 | 449 | _xfs_mru_cache_list_insert(mru, elem); | |
470 | spin_unlock(&mru->lock); | 450 | spin_unlock(&mru->lock); |
471 | 451 | ||
472 | return 0; | 452 | return error; |
473 | } | 453 | } |
474 | 454 | ||
475 | /* | 455 | /* |
@@ -478,13 +458,12 @@ xfs_mru_cache_insert( | |||
478 | * the client data pointer for the removed element is returned, otherwise this | 458 | * the client data pointer for the removed element is returned, otherwise this |
479 | * function will return a NULL pointer. | 459 | * function will return a NULL pointer. |
480 | */ | 460 | */ |
481 | void * | 461 | struct xfs_mru_cache_elem * |
482 | xfs_mru_cache_remove( | 462 | xfs_mru_cache_remove( |
483 | xfs_mru_cache_t *mru, | 463 | struct xfs_mru_cache *mru, |
484 | unsigned long key) | 464 | unsigned long key) |
485 | { | 465 | { |
486 | xfs_mru_cache_elem_t *elem; | 466 | struct xfs_mru_cache_elem *elem; |
487 | void *value = NULL; | ||
488 | 467 | ||
489 | ASSERT(mru && mru->lists); | 468 | ASSERT(mru && mru->lists); |
490 | if (!mru || !mru->lists) | 469 | if (!mru || !mru->lists) |
@@ -492,17 +471,11 @@ xfs_mru_cache_remove( | |||
492 | 471 | ||
493 | spin_lock(&mru->lock); | 472 | spin_lock(&mru->lock); |
494 | elem = radix_tree_delete(&mru->store, key); | 473 | elem = radix_tree_delete(&mru->store, key); |
495 | if (elem) { | 474 | if (elem) |
496 | value = elem->value; | ||
497 | list_del(&elem->list_node); | 475 | list_del(&elem->list_node); |
498 | } | ||
499 | |||
500 | spin_unlock(&mru->lock); | 476 | spin_unlock(&mru->lock); |
501 | 477 | ||
502 | if (elem) | 478 | return elem; |
503 | kmem_zone_free(xfs_mru_elem_zone, elem); | ||
504 | |||
505 | return value; | ||
506 | } | 479 | } |
507 | 480 | ||
508 | /* | 481 | /* |
@@ -511,13 +484,14 @@ xfs_mru_cache_remove( | |||
511 | */ | 484 | */ |
512 | void | 485 | void |
513 | xfs_mru_cache_delete( | 486 | xfs_mru_cache_delete( |
514 | xfs_mru_cache_t *mru, | 487 | struct xfs_mru_cache *mru, |
515 | unsigned long key) | 488 | unsigned long key) |
516 | { | 489 | { |
517 | void *value = xfs_mru_cache_remove(mru, key); | 490 | struct xfs_mru_cache_elem *elem; |
518 | 491 | ||
519 | if (value) | 492 | elem = xfs_mru_cache_remove(mru, key); |
520 | mru->free_func(key, value); | 493 | if (elem) |
494 | mru->free_func(elem); | ||
521 | } | 495 | } |
522 | 496 | ||
523 | /* | 497 | /* |
@@ -540,12 +514,12 @@ xfs_mru_cache_delete( | |||
540 | * status, we need to help it get it right by annotating the path that does | 514 | * status, we need to help it get it right by annotating the path that does |
541 | * not release the lock. | 515 | * not release the lock. |
542 | */ | 516 | */ |
543 | void * | 517 | struct xfs_mru_cache_elem * |
544 | xfs_mru_cache_lookup( | 518 | xfs_mru_cache_lookup( |
545 | xfs_mru_cache_t *mru, | 519 | struct xfs_mru_cache *mru, |
546 | unsigned long key) | 520 | unsigned long key) |
547 | { | 521 | { |
548 | xfs_mru_cache_elem_t *elem; | 522 | struct xfs_mru_cache_elem *elem; |
549 | 523 | ||
550 | ASSERT(mru && mru->lists); | 524 | ASSERT(mru && mru->lists); |
551 | if (!mru || !mru->lists) | 525 | if (!mru || !mru->lists) |
@@ -560,7 +534,7 @@ xfs_mru_cache_lookup( | |||
560 | } else | 534 | } else |
561 | spin_unlock(&mru->lock); | 535 | spin_unlock(&mru->lock); |
562 | 536 | ||
563 | return elem ? elem->value : NULL; | 537 | return elem; |
564 | } | 538 | } |
565 | 539 | ||
566 | /* | 540 | /* |
@@ -570,7 +544,8 @@ xfs_mru_cache_lookup( | |||
570 | */ | 544 | */ |
571 | void | 545 | void |
572 | xfs_mru_cache_done( | 546 | xfs_mru_cache_done( |
573 | xfs_mru_cache_t *mru) __releases(mru->lock) | 547 | struct xfs_mru_cache *mru) |
548 | __releases(mru->lock) | ||
574 | { | 549 | { |
575 | spin_unlock(&mru->lock); | 550 | spin_unlock(&mru->lock); |
576 | } | 551 | } |
diff --git a/fs/xfs/xfs_mru_cache.h b/fs/xfs/xfs_mru_cache.h index 36dd3ec8b4eb..fb5245ba5ff7 100644 --- a/fs/xfs/xfs_mru_cache.h +++ b/fs/xfs/xfs_mru_cache.h | |||
@@ -18,24 +18,15 @@ | |||
18 | #ifndef __XFS_MRU_CACHE_H__ | 18 | #ifndef __XFS_MRU_CACHE_H__ |
19 | #define __XFS_MRU_CACHE_H__ | 19 | #define __XFS_MRU_CACHE_H__ |
20 | 20 | ||
21 | struct xfs_mru_cache; | ||
21 | 22 | ||
22 | /* Function pointer type for callback to free a client's data pointer. */ | 23 | struct xfs_mru_cache_elem { |
23 | typedef void (*xfs_mru_cache_free_func_t)(unsigned long, void*); | 24 | struct list_head list_node; |
25 | unsigned long key; | ||
26 | }; | ||
24 | 27 | ||
25 | typedef struct xfs_mru_cache | 28 | /* Function pointer type for callback to free a client's data pointer. */ |
26 | { | 29 | typedef void (*xfs_mru_cache_free_func_t)(struct xfs_mru_cache_elem *elem); |
27 | struct radix_tree_root store; /* Core storage data structure. */ | ||
28 | struct list_head *lists; /* Array of lists, one per grp. */ | ||
29 | struct list_head reap_list; /* Elements overdue for reaping. */ | ||
30 | spinlock_t lock; /* Lock to protect this struct. */ | ||
31 | unsigned int grp_count; /* Number of discrete groups. */ | ||
32 | unsigned int grp_time; /* Time period spanned by grps. */ | ||
33 | unsigned int lru_grp; /* Group containing time zero. */ | ||
34 | unsigned long time_zero; /* Time first element was added. */ | ||
35 | xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */ | ||
36 | struct delayed_work work; /* Workqueue data for reaping. */ | ||
37 | unsigned int queued; /* work has been queued */ | ||
38 | } xfs_mru_cache_t; | ||
39 | 30 | ||
40 | int xfs_mru_cache_init(void); | 31 | int xfs_mru_cache_init(void); |
41 | void xfs_mru_cache_uninit(void); | 32 | void xfs_mru_cache_uninit(void); |
@@ -44,10 +35,12 @@ int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms, | |||
44 | xfs_mru_cache_free_func_t free_func); | 35 | xfs_mru_cache_free_func_t free_func); |
45 | void xfs_mru_cache_destroy(struct xfs_mru_cache *mru); | 36 | void xfs_mru_cache_destroy(struct xfs_mru_cache *mru); |
46 | int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key, | 37 | int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key, |
47 | void *value); | 38 | struct xfs_mru_cache_elem *elem); |
48 | void * xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key); | 39 | struct xfs_mru_cache_elem * |
40 | xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key); | ||
49 | void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key); | 41 | void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key); |
50 | void *xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key); | 42 | struct xfs_mru_cache_elem * |
43 | xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key); | ||
51 | void xfs_mru_cache_done(struct xfs_mru_cache *mru); | 44 | void xfs_mru_cache_done(struct xfs_mru_cache *mru); |
52 | 45 | ||
53 | #endif /* __XFS_MRU_CACHE_H__ */ | 46 | #endif /* __XFS_MRU_CACHE_H__ */ |
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index dc977b6e6a36..6d26759c779a 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
@@ -193,47 +193,6 @@ xfs_qm_dqpurge( | |||
193 | } | 193 | } |
194 | 194 | ||
195 | /* | 195 | /* |
196 | * Release the group or project dquot pointers the user dquots maybe carrying | ||
197 | * around as a hint, and proceed to purge the user dquot cache if requested. | ||
198 | */ | ||
199 | STATIC int | ||
200 | xfs_qm_dqpurge_hints( | ||
201 | struct xfs_dquot *dqp, | ||
202 | void *data) | ||
203 | { | ||
204 | struct xfs_dquot *gdqp = NULL; | ||
205 | struct xfs_dquot *pdqp = NULL; | ||
206 | uint flags = *((uint *)data); | ||
207 | |||
208 | xfs_dqlock(dqp); | ||
209 | if (dqp->dq_flags & XFS_DQ_FREEING) { | ||
210 | xfs_dqunlock(dqp); | ||
211 | return EAGAIN; | ||
212 | } | ||
213 | |||
214 | /* If this quota has a hint attached, prepare for releasing it now */ | ||
215 | gdqp = dqp->q_gdquot; | ||
216 | if (gdqp) | ||
217 | dqp->q_gdquot = NULL; | ||
218 | |||
219 | pdqp = dqp->q_pdquot; | ||
220 | if (pdqp) | ||
221 | dqp->q_pdquot = NULL; | ||
222 | |||
223 | xfs_dqunlock(dqp); | ||
224 | |||
225 | if (gdqp) | ||
226 | xfs_qm_dqrele(gdqp); | ||
227 | if (pdqp) | ||
228 | xfs_qm_dqrele(pdqp); | ||
229 | |||
230 | if (flags & XFS_QMOPT_UQUOTA) | ||
231 | return xfs_qm_dqpurge(dqp, NULL); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * Purge the dquot cache. | 196 | * Purge the dquot cache. |
238 | */ | 197 | */ |
239 | void | 198 | void |
@@ -241,18 +200,8 @@ xfs_qm_dqpurge_all( | |||
241 | struct xfs_mount *mp, | 200 | struct xfs_mount *mp, |
242 | uint flags) | 201 | uint flags) |
243 | { | 202 | { |
244 | /* | 203 | if (flags & XFS_QMOPT_UQUOTA) |
245 | * We have to release group/project dquot hint(s) from the user dquot | 204 | xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL); |
246 | * at first if they are there, otherwise we would run into an infinite | ||
247 | * loop while walking through radix tree to purge other type of dquots | ||
248 | * since their refcount is not zero if the user dquot refers to them | ||
249 | * as hint. | ||
250 | * | ||
251 | * Call the special xfs_qm_dqpurge_hints() will end up go through the | ||
252 | * general xfs_qm_dqpurge() against user dquot cache if requested. | ||
253 | */ | ||
254 | xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge_hints, &flags); | ||
255 | |||
256 | if (flags & XFS_QMOPT_GQUOTA) | 205 | if (flags & XFS_QMOPT_GQUOTA) |
257 | xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL); | 206 | xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL); |
258 | if (flags & XFS_QMOPT_PQUOTA) | 207 | if (flags & XFS_QMOPT_PQUOTA) |
@@ -409,7 +358,6 @@ xfs_qm_dqattach_one( | |||
409 | xfs_dqid_t id, | 358 | xfs_dqid_t id, |
410 | uint type, | 359 | uint type, |
411 | uint doalloc, | 360 | uint doalloc, |
412 | xfs_dquot_t *udqhint, /* hint */ | ||
413 | xfs_dquot_t **IO_idqpp) | 361 | xfs_dquot_t **IO_idqpp) |
414 | { | 362 | { |
415 | xfs_dquot_t *dqp; | 363 | xfs_dquot_t *dqp; |
@@ -419,9 +367,9 @@ xfs_qm_dqattach_one( | |||
419 | error = 0; | 367 | error = 0; |
420 | 368 | ||
421 | /* | 369 | /* |
422 | * See if we already have it in the inode itself. IO_idqpp is | 370 | * See if we already have it in the inode itself. IO_idqpp is &i_udquot |
423 | * &i_udquot or &i_gdquot. This made the code look weird, but | 371 | * or &i_gdquot. This made the code look weird, but made the logic a lot |
424 | * made the logic a lot simpler. | 372 | * simpler. |
425 | */ | 373 | */ |
426 | dqp = *IO_idqpp; | 374 | dqp = *IO_idqpp; |
427 | if (dqp) { | 375 | if (dqp) { |
@@ -430,49 +378,10 @@ xfs_qm_dqattach_one( | |||
430 | } | 378 | } |
431 | 379 | ||
432 | /* | 380 | /* |
433 | * udqhint is the i_udquot field in inode, and is non-NULL only | 381 | * Find the dquot from somewhere. This bumps the reference count of |
434 | * when the type arg is group/project. Its purpose is to save a | 382 | * dquot and returns it locked. This can return ENOENT if dquot didn't |
435 | * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside | 383 | * exist on disk and we didn't ask it to allocate; ESRCH if quotas got |
436 | * the user dquot. | 384 | * turned off suddenly. |
437 | */ | ||
438 | if (udqhint) { | ||
439 | ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); | ||
440 | xfs_dqlock(udqhint); | ||
441 | |||
442 | /* | ||
443 | * No need to take dqlock to look at the id. | ||
444 | * | ||
445 | * The ID can't change until it gets reclaimed, and it won't | ||
446 | * be reclaimed as long as we have a ref from inode and we | ||
447 | * hold the ilock. | ||
448 | */ | ||
449 | if (type == XFS_DQ_GROUP) | ||
450 | dqp = udqhint->q_gdquot; | ||
451 | else | ||
452 | dqp = udqhint->q_pdquot; | ||
453 | if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { | ||
454 | ASSERT(*IO_idqpp == NULL); | ||
455 | |||
456 | *IO_idqpp = xfs_qm_dqhold(dqp); | ||
457 | xfs_dqunlock(udqhint); | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | /* | ||
462 | * We can't hold a dquot lock when we call the dqget code. | ||
463 | * We'll deadlock in no time, because of (not conforming to) | ||
464 | * lock ordering - the inodelock comes before any dquot lock, | ||
465 | * and we may drop and reacquire the ilock in xfs_qm_dqget(). | ||
466 | */ | ||
467 | xfs_dqunlock(udqhint); | ||
468 | } | ||
469 | |||
470 | /* | ||
471 | * Find the dquot from somewhere. This bumps the | ||
472 | * reference count of dquot and returns it locked. | ||
473 | * This can return ENOENT if dquot didn't exist on | ||
474 | * disk and we didn't ask it to allocate; | ||
475 | * ESRCH if quotas got turned off suddenly. | ||
476 | */ | 385 | */ |
477 | error = xfs_qm_dqget(ip->i_mount, ip, id, type, | 386 | error = xfs_qm_dqget(ip->i_mount, ip, id, type, |
478 | doalloc | XFS_QMOPT_DOWARN, &dqp); | 387 | doalloc | XFS_QMOPT_DOWARN, &dqp); |
@@ -490,48 +399,6 @@ xfs_qm_dqattach_one( | |||
490 | return 0; | 399 | return 0; |
491 | } | 400 | } |
492 | 401 | ||
493 | |||
494 | /* | ||
495 | * Given a udquot and group/project type, attach the group/project | ||
496 | * dquot pointer to the udquot as a hint for future lookups. | ||
497 | */ | ||
498 | STATIC void | ||
499 | xfs_qm_dqattach_hint( | ||
500 | struct xfs_inode *ip, | ||
501 | int type) | ||
502 | { | ||
503 | struct xfs_dquot **dqhintp; | ||
504 | struct xfs_dquot *dqp; | ||
505 | struct xfs_dquot *udq = ip->i_udquot; | ||
506 | |||
507 | ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); | ||
508 | |||
509 | xfs_dqlock(udq); | ||
510 | |||
511 | if (type == XFS_DQ_GROUP) { | ||
512 | dqp = ip->i_gdquot; | ||
513 | dqhintp = &udq->q_gdquot; | ||
514 | } else { | ||
515 | dqp = ip->i_pdquot; | ||
516 | dqhintp = &udq->q_pdquot; | ||
517 | } | ||
518 | |||
519 | if (*dqhintp) { | ||
520 | struct xfs_dquot *tmp; | ||
521 | |||
522 | if (*dqhintp == dqp) | ||
523 | goto done; | ||
524 | |||
525 | tmp = *dqhintp; | ||
526 | *dqhintp = NULL; | ||
527 | xfs_qm_dqrele(tmp); | ||
528 | } | ||
529 | |||
530 | *dqhintp = xfs_qm_dqhold(dqp); | ||
531 | done: | ||
532 | xfs_dqunlock(udq); | ||
533 | } | ||
534 | |||
535 | static bool | 402 | static bool |
536 | xfs_qm_need_dqattach( | 403 | xfs_qm_need_dqattach( |
537 | struct xfs_inode *ip) | 404 | struct xfs_inode *ip) |
@@ -562,7 +429,6 @@ xfs_qm_dqattach_locked( | |||
562 | uint flags) | 429 | uint flags) |
563 | { | 430 | { |
564 | xfs_mount_t *mp = ip->i_mount; | 431 | xfs_mount_t *mp = ip->i_mount; |
565 | uint nquotas = 0; | ||
566 | int error = 0; | 432 | int error = 0; |
567 | 433 | ||
568 | if (!xfs_qm_need_dqattach(ip)) | 434 | if (!xfs_qm_need_dqattach(ip)) |
@@ -570,77 +436,39 @@ xfs_qm_dqattach_locked( | |||
570 | 436 | ||
571 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 437 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
572 | 438 | ||
573 | if (XFS_IS_UQUOTA_ON(mp)) { | 439 | if (XFS_IS_UQUOTA_ON(mp) && !ip->i_udquot) { |
574 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, | 440 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, |
575 | flags & XFS_QMOPT_DQALLOC, | 441 | flags & XFS_QMOPT_DQALLOC, |
576 | NULL, &ip->i_udquot); | 442 | &ip->i_udquot); |
577 | if (error) | 443 | if (error) |
578 | goto done; | 444 | goto done; |
579 | nquotas++; | 445 | ASSERT(ip->i_udquot); |
580 | } | 446 | } |
581 | 447 | ||
582 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 448 | if (XFS_IS_GQUOTA_ON(mp) && !ip->i_gdquot) { |
583 | if (XFS_IS_GQUOTA_ON(mp)) { | ||
584 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, | 449 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, |
585 | flags & XFS_QMOPT_DQALLOC, | 450 | flags & XFS_QMOPT_DQALLOC, |
586 | ip->i_udquot, &ip->i_gdquot); | 451 | &ip->i_gdquot); |
587 | /* | ||
588 | * Don't worry about the udquot that we may have | ||
589 | * attached above. It'll get detached, if not already. | ||
590 | */ | ||
591 | if (error) | 452 | if (error) |
592 | goto done; | 453 | goto done; |
593 | nquotas++; | 454 | ASSERT(ip->i_gdquot); |
594 | } | 455 | } |
595 | 456 | ||
596 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 457 | if (XFS_IS_PQUOTA_ON(mp) && !ip->i_pdquot) { |
597 | if (XFS_IS_PQUOTA_ON(mp)) { | ||
598 | error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, | 458 | error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, |
599 | flags & XFS_QMOPT_DQALLOC, | 459 | flags & XFS_QMOPT_DQALLOC, |
600 | ip->i_udquot, &ip->i_pdquot); | 460 | &ip->i_pdquot); |
601 | /* | ||
602 | * Don't worry about the udquot that we may have | ||
603 | * attached above. It'll get detached, if not already. | ||
604 | */ | ||
605 | if (error) | 461 | if (error) |
606 | goto done; | 462 | goto done; |
607 | nquotas++; | 463 | ASSERT(ip->i_pdquot); |
608 | } | 464 | } |
609 | 465 | ||
466 | done: | ||
610 | /* | 467 | /* |
611 | * Attach this group/project quota to the user quota as a hint. | 468 | * Don't worry about the dquots that we may have attached before any |
612 | * This WON'T, in general, result in a thrash. | 469 | * error - they'll get detached later if it has not already been done. |
613 | */ | 470 | */ |
614 | if (nquotas > 1 && ip->i_udquot) { | ||
615 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
616 | ASSERT(ip->i_gdquot || !XFS_IS_GQUOTA_ON(mp)); | ||
617 | ASSERT(ip->i_pdquot || !XFS_IS_PQUOTA_ON(mp)); | ||
618 | |||
619 | /* | ||
620 | * We do not have i_udquot locked at this point, but this check | ||
621 | * is OK since we don't depend on the i_gdquot to be accurate | ||
622 | * 100% all the time. It is just a hint, and this will | ||
623 | * succeed in general. | ||
624 | */ | ||
625 | if (ip->i_udquot->q_gdquot != ip->i_gdquot) | ||
626 | xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP); | ||
627 | |||
628 | if (ip->i_udquot->q_pdquot != ip->i_pdquot) | ||
629 | xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ); | ||
630 | } | ||
631 | |||
632 | done: | ||
633 | #ifdef DEBUG | ||
634 | if (!error) { | ||
635 | if (XFS_IS_UQUOTA_ON(mp)) | ||
636 | ASSERT(ip->i_udquot); | ||
637 | if (XFS_IS_GQUOTA_ON(mp)) | ||
638 | ASSERT(ip->i_gdquot); | ||
639 | if (XFS_IS_PQUOTA_ON(mp)) | ||
640 | ASSERT(ip->i_pdquot); | ||
641 | } | ||
642 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 471 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
643 | #endif | ||
644 | return error; | 472 | return error; |
645 | } | 473 | } |
646 | 474 | ||
@@ -865,8 +693,7 @@ xfs_qm_init_quotainfo( | |||
865 | 693 | ||
866 | /* Precalc some constants */ | 694 | /* Precalc some constants */ |
867 | qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); | 695 | qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); |
868 | qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(mp, | 696 | qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(qinf->qi_dqchunklen); |
869 | qinf->qi_dqchunklen); | ||
870 | 697 | ||
871 | mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD); | 698 | mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD); |
872 | 699 | ||
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index 3daf5ea1eb8d..bbc813caba4c 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c | |||
@@ -278,9 +278,10 @@ xfs_qm_scall_trunc_qfiles( | |||
278 | xfs_mount_t *mp, | 278 | xfs_mount_t *mp, |
279 | uint flags) | 279 | uint flags) |
280 | { | 280 | { |
281 | int error; | 281 | int error = EINVAL; |
282 | 282 | ||
283 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { | 283 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0 || |
284 | (flags & ~XFS_DQ_ALLTYPES)) { | ||
284 | xfs_debug(mp, "%s: flags=%x m_qflags=%x", | 285 | xfs_debug(mp, "%s: flags=%x m_qflags=%x", |
285 | __func__, flags, mp->m_qflags); | 286 | __func__, flags, mp->m_qflags); |
286 | return XFS_ERROR(EINVAL); | 287 | return XFS_ERROR(EINVAL); |
@@ -959,7 +960,6 @@ xfs_qm_export_flags( | |||
959 | STATIC int | 960 | STATIC int |
960 | xfs_dqrele_inode( | 961 | xfs_dqrele_inode( |
961 | struct xfs_inode *ip, | 962 | struct xfs_inode *ip, |
962 | struct xfs_perag *pag, | ||
963 | int flags, | 963 | int flags, |
964 | void *args) | 964 | void *args) |
965 | { | 965 | { |
diff --git a/fs/xfs/xfs_quota_defs.h b/fs/xfs/xfs_quota_defs.h index b3b2b1065c0f..137e20937077 100644 --- a/fs/xfs/xfs_quota_defs.h +++ b/fs/xfs/xfs_quota_defs.h | |||
@@ -156,6 +156,6 @@ typedef __uint16_t xfs_qwarncnt_t; | |||
156 | 156 | ||
157 | extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq, | 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); | 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); | 159 | extern int xfs_calc_dquots_per_chunk(unsigned int nbblks); |
160 | 160 | ||
161 | #endif /* __XFS_QUOTA_H__ */ | 161 | #endif /* __XFS_QUOTA_H__ */ |
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c index af33cafe69b6..2ad1b9822e92 100644 --- a/fs/xfs/xfs_quotaops.c +++ b/fs/xfs/xfs_quotaops.c | |||
@@ -100,16 +100,36 @@ xfs_fs_set_xstate( | |||
100 | if (!XFS_IS_QUOTA_ON(mp)) | 100 | if (!XFS_IS_QUOTA_ON(mp)) |
101 | return -EINVAL; | 101 | return -EINVAL; |
102 | return -xfs_qm_scall_quotaoff(mp, flags); | 102 | return -xfs_qm_scall_quotaoff(mp, flags); |
103 | case Q_XQUOTARM: | ||
104 | if (XFS_IS_QUOTA_ON(mp)) | ||
105 | return -EINVAL; | ||
106 | return -xfs_qm_scall_trunc_qfiles(mp, flags); | ||
107 | } | 103 | } |
108 | 104 | ||
109 | return -EINVAL; | 105 | return -EINVAL; |
110 | } | 106 | } |
111 | 107 | ||
112 | STATIC int | 108 | STATIC int |
109 | xfs_fs_rm_xquota( | ||
110 | struct super_block *sb, | ||
111 | unsigned int uflags) | ||
112 | { | ||
113 | struct xfs_mount *mp = XFS_M(sb); | ||
114 | unsigned int flags = 0; | ||
115 | |||
116 | if (sb->s_flags & MS_RDONLY) | ||
117 | return -EROFS; | ||
118 | |||
119 | if (XFS_IS_QUOTA_ON(mp)) | ||
120 | return -EINVAL; | ||
121 | |||
122 | if (uflags & FS_USER_QUOTA) | ||
123 | flags |= XFS_DQ_USER; | ||
124 | if (uflags & FS_GROUP_QUOTA) | ||
125 | flags |= XFS_DQ_GROUP; | ||
126 | if (uflags & FS_USER_QUOTA) | ||
127 | flags |= XFS_DQ_PROJ; | ||
128 | |||
129 | return -xfs_qm_scall_trunc_qfiles(mp, flags); | ||
130 | } | ||
131 | |||
132 | STATIC int | ||
113 | xfs_fs_get_dqblk( | 133 | xfs_fs_get_dqblk( |
114 | struct super_block *sb, | 134 | struct super_block *sb, |
115 | struct kqid qid, | 135 | struct kqid qid, |
@@ -149,6 +169,7 @@ const struct quotactl_ops xfs_quotactl_operations = { | |||
149 | .get_xstatev = xfs_fs_get_xstatev, | 169 | .get_xstatev = xfs_fs_get_xstatev, |
150 | .get_xstate = xfs_fs_get_xstate, | 170 | .get_xstate = xfs_fs_get_xstate, |
151 | .set_xstate = xfs_fs_set_xstate, | 171 | .set_xstate = xfs_fs_set_xstate, |
172 | .rm_xquota = xfs_fs_rm_xquota, | ||
152 | .get_dqblk = xfs_fs_get_dqblk, | 173 | .get_dqblk = xfs_fs_get_dqblk, |
153 | .set_dqblk = xfs_fs_set_dqblk, | 174 | .set_dqblk = xfs_fs_set_dqblk, |
154 | }; | 175 | }; |
diff --git a/fs/xfs/xfs_rtbitmap.c b/fs/xfs/xfs_rtbitmap.c index b1f2fe8af4a8..f4dd697cac08 100644 --- a/fs/xfs/xfs_rtbitmap.c +++ b/fs/xfs/xfs_rtbitmap.c | |||
@@ -74,7 +74,6 @@ xfs_rtbuf_get( | |||
74 | mp->m_bsize, 0, &bp, NULL); | 74 | mp->m_bsize, 0, &bp, NULL); |
75 | if (error) | 75 | if (error) |
76 | return error; | 76 | return error; |
77 | ASSERT(!xfs_buf_geterror(bp)); | ||
78 | *bpp = bp; | 77 | *bpp = bp; |
79 | return 0; | 78 | return 0; |
80 | } | 79 | } |
diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 8baf61afae1d..c3453b11f563 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c | |||
@@ -291,7 +291,8 @@ xfs_mount_validate_sb( | |||
291 | (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */) || | 291 | (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */) || |
292 | sbp->sb_dblocks == 0 || | 292 | sbp->sb_dblocks == 0 || |
293 | sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || | 293 | sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || |
294 | sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) { | 294 | sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp) || |
295 | sbp->sb_shared_vn != 0)) { | ||
295 | xfs_notice(mp, "SB sanity check failed"); | 296 | xfs_notice(mp, "SB sanity check failed"); |
296 | return XFS_ERROR(EFSCORRUPTED); | 297 | return XFS_ERROR(EFSCORRUPTED); |
297 | } | 298 | } |
@@ -333,15 +334,6 @@ xfs_mount_validate_sb( | |||
333 | xfs_warn(mp, "Offline file system operation in progress!"); | 334 | xfs_warn(mp, "Offline file system operation in progress!"); |
334 | return XFS_ERROR(EFSCORRUPTED); | 335 | return XFS_ERROR(EFSCORRUPTED); |
335 | } | 336 | } |
336 | |||
337 | /* | ||
338 | * Version 1 directory format has never worked on Linux. | ||
339 | */ | ||
340 | if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { | ||
341 | xfs_warn(mp, "file system using version 1 directory format"); | ||
342 | return XFS_ERROR(ENOSYS); | ||
343 | } | ||
344 | |||
345 | return 0; | 337 | return 0; |
346 | } | 338 | } |
347 | 339 | ||
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h index f7b2fe77c5a5..c43c2d609a24 100644 --- a/fs/xfs/xfs_sb.h +++ b/fs/xfs/xfs_sb.h | |||
@@ -36,8 +36,6 @@ struct xfs_trans; | |||
36 | #define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ | 36 | #define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ |
37 | #define XFS_SB_VERSION_NUMBITS 0x000f | 37 | #define XFS_SB_VERSION_NUMBITS 0x000f |
38 | #define XFS_SB_VERSION_ALLFBITS 0xfff0 | 38 | #define XFS_SB_VERSION_ALLFBITS 0xfff0 |
39 | #define XFS_SB_VERSION_SASHFBITS 0xf000 | ||
40 | #define XFS_SB_VERSION_REALFBITS 0x0ff0 | ||
41 | #define XFS_SB_VERSION_ATTRBIT 0x0010 | 39 | #define XFS_SB_VERSION_ATTRBIT 0x0010 |
42 | #define XFS_SB_VERSION_NLINKBIT 0x0020 | 40 | #define XFS_SB_VERSION_NLINKBIT 0x0020 |
43 | #define XFS_SB_VERSION_QUOTABIT 0x0040 | 41 | #define XFS_SB_VERSION_QUOTABIT 0x0040 |
@@ -50,24 +48,15 @@ struct xfs_trans; | |||
50 | #define XFS_SB_VERSION_DIRV2BIT 0x2000 | 48 | #define XFS_SB_VERSION_DIRV2BIT 0x2000 |
51 | #define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */ | 49 | #define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */ |
52 | #define XFS_SB_VERSION_MOREBITSBIT 0x8000 | 50 | #define XFS_SB_VERSION_MOREBITSBIT 0x8000 |
53 | #define XFS_SB_VERSION_OKSASHFBITS \ | 51 | |
54 | (XFS_SB_VERSION_EXTFLGBIT | \ | 52 | /* |
55 | XFS_SB_VERSION_DIRV2BIT | \ | 53 | * Supported feature bit list is just all bits in the versionnum field because |
56 | XFS_SB_VERSION_BORGBIT) | 54 | * we've used them all up and understand them all. Except, of course, for the |
57 | #define XFS_SB_VERSION_OKREALFBITS \ | 55 | * shared superblock bit, which nobody knows what it does and so is unsupported. |
58 | (XFS_SB_VERSION_ATTRBIT | \ | 56 | */ |
59 | XFS_SB_VERSION_NLINKBIT | \ | 57 | #define XFS_SB_VERSION_OKBITS \ |
60 | XFS_SB_VERSION_QUOTABIT | \ | 58 | ((XFS_SB_VERSION_NUMBITS | XFS_SB_VERSION_ALLFBITS) & \ |
61 | XFS_SB_VERSION_ALIGNBIT | \ | 59 | ~XFS_SB_VERSION_SHAREDBIT) |
62 | XFS_SB_VERSION_DALIGNBIT | \ | ||
63 | XFS_SB_VERSION_SHAREDBIT | \ | ||
64 | XFS_SB_VERSION_LOGV2BIT | \ | ||
65 | XFS_SB_VERSION_SECTORBIT | \ | ||
66 | XFS_SB_VERSION_MOREBITSBIT) | ||
67 | #define XFS_SB_VERSION_OKREALBITS \ | ||
68 | (XFS_SB_VERSION_NUMBITS | \ | ||
69 | XFS_SB_VERSION_OKREALFBITS | \ | ||
70 | XFS_SB_VERSION_OKSASHFBITS) | ||
71 | 60 | ||
72 | /* | 61 | /* |
73 | * There are two words to hold XFS "feature" bits: the original | 62 | * There are two words to hold XFS "feature" bits: the original |
@@ -76,7 +65,6 @@ struct xfs_trans; | |||
76 | * | 65 | * |
77 | * These defines represent bits in sb_features2. | 66 | * These defines represent bits in sb_features2. |
78 | */ | 67 | */ |
79 | #define XFS_SB_VERSION2_REALFBITS 0x00ffffff /* Mask: features */ | ||
80 | #define XFS_SB_VERSION2_RESERVED1BIT 0x00000001 | 68 | #define XFS_SB_VERSION2_RESERVED1BIT 0x00000001 |
81 | #define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */ | 69 | #define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */ |
82 | #define XFS_SB_VERSION2_RESERVED4BIT 0x00000004 | 70 | #define XFS_SB_VERSION2_RESERVED4BIT 0x00000004 |
@@ -86,16 +74,11 @@ struct xfs_trans; | |||
86 | #define XFS_SB_VERSION2_CRCBIT 0x00000100 /* metadata CRCs */ | 74 | #define XFS_SB_VERSION2_CRCBIT 0x00000100 /* metadata CRCs */ |
87 | #define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ | 75 | #define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ |
88 | 76 | ||
89 | #define XFS_SB_VERSION2_OKREALFBITS \ | 77 | #define XFS_SB_VERSION2_OKBITS \ |
90 | (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ | 78 | (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ |
91 | XFS_SB_VERSION2_ATTR2BIT | \ | 79 | XFS_SB_VERSION2_ATTR2BIT | \ |
92 | XFS_SB_VERSION2_PROJID32BIT | \ | 80 | XFS_SB_VERSION2_PROJID32BIT | \ |
93 | XFS_SB_VERSION2_FTYPE) | 81 | XFS_SB_VERSION2_FTYPE) |
94 | #define XFS_SB_VERSION2_OKSASHFBITS \ | ||
95 | (0) | ||
96 | #define XFS_SB_VERSION2_OKREALBITS \ | ||
97 | (XFS_SB_VERSION2_OKREALFBITS | \ | ||
98 | XFS_SB_VERSION2_OKSASHFBITS ) | ||
99 | 82 | ||
100 | /* | 83 | /* |
101 | * Superblock - in core version. Must match the ondisk version below. | 84 | * Superblock - in core version. Must match the ondisk version below. |
@@ -345,214 +328,140 @@ typedef enum { | |||
345 | 328 | ||
346 | #define XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS) | 329 | #define XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS) |
347 | 330 | ||
348 | static inline int xfs_sb_good_version(xfs_sb_t *sbp) | ||
349 | { | ||
350 | /* We always support version 1-3 */ | ||
351 | if (sbp->sb_versionnum >= XFS_SB_VERSION_1 && | ||
352 | sbp->sb_versionnum <= XFS_SB_VERSION_3) | ||
353 | return 1; | ||
354 | |||
355 | /* We support version 4 if all feature bits are supported */ | ||
356 | if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) { | ||
357 | if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || | ||
358 | ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && | ||
359 | (sbp->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))) | ||
360 | return 0; | ||
361 | |||
362 | if (sbp->sb_shared_vn > XFS_SB_MAX_SHARED_VN) | ||
363 | return 0; | ||
364 | return 1; | ||
365 | } | ||
366 | if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) | ||
367 | return 1; | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | /* | 331 | /* |
373 | * Detect a mismatched features2 field. Older kernels read/wrote | 332 | * The first XFS version we support is a v4 superblock with V2 directories. |
374 | * this into the wrong slot, so to be safe we keep them in sync. | ||
375 | */ | 333 | */ |
376 | static inline int xfs_sb_has_mismatched_features2(xfs_sb_t *sbp) | 334 | static inline bool xfs_sb_good_v4_features(struct xfs_sb *sbp) |
377 | { | 335 | { |
378 | return (sbp->sb_bad_features2 != sbp->sb_features2); | 336 | if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) |
379 | } | 337 | return false; |
380 | |||
381 | static inline unsigned xfs_sb_version_tonew(unsigned v) | ||
382 | { | ||
383 | if (v == XFS_SB_VERSION_1) | ||
384 | return XFS_SB_VERSION_4; | ||
385 | 338 | ||
386 | if (v == XFS_SB_VERSION_2) | 339 | /* check for unknown features in the fs */ |
387 | return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT; | 340 | if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKBITS) || |
341 | ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && | ||
342 | (sbp->sb_features2 & ~XFS_SB_VERSION2_OKBITS))) | ||
343 | return false; | ||
388 | 344 | ||
389 | return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT | | 345 | return true; |
390 | XFS_SB_VERSION_NLINKBIT; | ||
391 | } | 346 | } |
392 | 347 | ||
393 | static inline unsigned xfs_sb_version_toold(unsigned v) | 348 | static inline bool xfs_sb_good_version(struct xfs_sb *sbp) |
394 | { | 349 | { |
395 | if (v & (XFS_SB_VERSION_QUOTABIT | XFS_SB_VERSION_ALIGNBIT)) | 350 | if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) |
396 | return 0; | 351 | return true; |
397 | if (v & XFS_SB_VERSION_NLINKBIT) | 352 | if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) |
398 | return XFS_SB_VERSION_3; | 353 | return xfs_sb_good_v4_features(sbp); |
399 | if (v & XFS_SB_VERSION_ATTRBIT) | 354 | return false; |
400 | return XFS_SB_VERSION_2; | ||
401 | return XFS_SB_VERSION_1; | ||
402 | } | ||
403 | |||
404 | static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) | ||
405 | { | ||
406 | return sbp->sb_versionnum == XFS_SB_VERSION_2 || | ||
407 | sbp->sb_versionnum == XFS_SB_VERSION_3 || | ||
408 | (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | ||
409 | (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT)); | ||
410 | } | 355 | } |
411 | 356 | ||
412 | static inline void xfs_sb_version_addattr(xfs_sb_t *sbp) | 357 | /* |
358 | * Detect a mismatched features2 field. Older kernels read/wrote | ||
359 | * this into the wrong slot, so to be safe we keep them in sync. | ||
360 | */ | ||
361 | static inline bool xfs_sb_has_mismatched_features2(struct xfs_sb *sbp) | ||
413 | { | 362 | { |
414 | if (sbp->sb_versionnum == XFS_SB_VERSION_1) | 363 | return sbp->sb_bad_features2 != sbp->sb_features2; |
415 | sbp->sb_versionnum = XFS_SB_VERSION_2; | ||
416 | else if (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4) | ||
417 | sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; | ||
418 | else | ||
419 | sbp->sb_versionnum = XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT; | ||
420 | } | 364 | } |
421 | 365 | ||
422 | static inline int xfs_sb_version_hasnlink(xfs_sb_t *sbp) | 366 | static inline bool xfs_sb_version_hasattr(struct xfs_sb *sbp) |
423 | { | 367 | { |
424 | return sbp->sb_versionnum == XFS_SB_VERSION_3 || | 368 | return (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT); |
425 | (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | ||
426 | (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)); | ||
427 | } | 369 | } |
428 | 370 | ||
429 | static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp) | 371 | static inline void xfs_sb_version_addattr(struct xfs_sb *sbp) |
430 | { | 372 | { |
431 | if (sbp->sb_versionnum <= XFS_SB_VERSION_2) | 373 | sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; |
432 | sbp->sb_versionnum = XFS_SB_VERSION_3; | ||
433 | else | ||
434 | sbp->sb_versionnum |= XFS_SB_VERSION_NLINKBIT; | ||
435 | } | 374 | } |
436 | 375 | ||
437 | static inline int xfs_sb_version_hasquota(xfs_sb_t *sbp) | 376 | static inline bool xfs_sb_version_hasquota(struct xfs_sb *sbp) |
438 | { | 377 | { |
439 | return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | 378 | return (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT); |
440 | (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT); | ||
441 | } | 379 | } |
442 | 380 | ||
443 | static inline void xfs_sb_version_addquota(xfs_sb_t *sbp) | 381 | static inline void xfs_sb_version_addquota(struct xfs_sb *sbp) |
444 | { | 382 | { |
445 | if (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4) | 383 | sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT; |
446 | sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT; | ||
447 | else | ||
448 | sbp->sb_versionnum = xfs_sb_version_tonew(sbp->sb_versionnum) | | ||
449 | XFS_SB_VERSION_QUOTABIT; | ||
450 | } | 384 | } |
451 | 385 | ||
452 | static inline int xfs_sb_version_hasalign(xfs_sb_t *sbp) | 386 | static inline bool xfs_sb_version_hasalign(struct xfs_sb *sbp) |
453 | { | 387 | { |
454 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | 388 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || |
455 | (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | ||
456 | (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT)); | 389 | (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT)); |
457 | } | 390 | } |
458 | 391 | ||
459 | static inline int xfs_sb_version_hasdalign(xfs_sb_t *sbp) | 392 | static inline bool xfs_sb_version_hasdalign(struct xfs_sb *sbp) |
460 | { | ||
461 | return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | ||
462 | (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT); | ||
463 | } | ||
464 | |||
465 | static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) | ||
466 | { | 393 | { |
467 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 && | 394 | return (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT); |
468 | (sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT); | ||
469 | } | 395 | } |
470 | 396 | ||
471 | static inline int xfs_sb_version_hasdirv2(xfs_sb_t *sbp) | 397 | static inline bool xfs_sb_version_haslogv2(struct xfs_sb *sbp) |
472 | { | 398 | { |
473 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | 399 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || |
474 | (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 && | 400 | (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT); |
475 | (sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)); | ||
476 | } | 401 | } |
477 | 402 | ||
478 | static inline int xfs_sb_version_haslogv2(xfs_sb_t *sbp) | 403 | static inline bool xfs_sb_version_hasextflgbit(struct xfs_sb *sbp) |
479 | { | 404 | { |
480 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | 405 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || |
481 | (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | 406 | (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT); |
482 | (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT)); | ||
483 | } | 407 | } |
484 | 408 | ||
485 | static inline int xfs_sb_version_hasextflgbit(xfs_sb_t *sbp) | 409 | static inline bool xfs_sb_version_hassector(struct xfs_sb *sbp) |
486 | { | 410 | { |
487 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | 411 | return (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT); |
488 | (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 && | ||
489 | (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT)); | ||
490 | } | 412 | } |
491 | 413 | ||
492 | static inline int xfs_sb_version_hassector(xfs_sb_t *sbp) | 414 | static inline bool xfs_sb_version_hasasciici(struct xfs_sb *sbp) |
493 | { | 415 | { |
494 | return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | 416 | return (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT); |
495 | (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT); | ||
496 | } | 417 | } |
497 | 418 | ||
498 | static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp) | 419 | static inline bool xfs_sb_version_hasmorebits(struct xfs_sb *sbp) |
499 | { | 420 | { |
500 | return XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_4 && | 421 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 || |
501 | (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT); | 422 | (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT); |
502 | } | ||
503 | |||
504 | static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) | ||
505 | { | ||
506 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | ||
507 | (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 && | ||
508 | (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT)); | ||
509 | } | 423 | } |
510 | 424 | ||
511 | /* | 425 | /* |
512 | * sb_features2 bit version macros. | 426 | * sb_features2 bit version macros. |
513 | * | ||
514 | * For example, for a bit defined as XFS_SB_VERSION2_FUNBIT, has a macro: | ||
515 | * | ||
516 | * SB_VERSION_HASFUNBIT(xfs_sb_t *sbp) | ||
517 | * ((xfs_sb_version_hasmorebits(sbp) && | ||
518 | * ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT) | ||
519 | */ | 427 | */ |
520 | 428 | static inline bool xfs_sb_version_haslazysbcount(struct xfs_sb *sbp) | |
521 | static inline int xfs_sb_version_haslazysbcount(xfs_sb_t *sbp) | ||
522 | { | 429 | { |
523 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | 430 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || |
524 | (xfs_sb_version_hasmorebits(sbp) && | 431 | (xfs_sb_version_hasmorebits(sbp) && |
525 | (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT)); | 432 | (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT)); |
526 | } | 433 | } |
527 | 434 | ||
528 | static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp) | 435 | static inline bool xfs_sb_version_hasattr2(struct xfs_sb *sbp) |
529 | { | 436 | { |
530 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | 437 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || |
531 | (xfs_sb_version_hasmorebits(sbp) && | 438 | (xfs_sb_version_hasmorebits(sbp) && |
532 | (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT)); | 439 | (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT)); |
533 | } | 440 | } |
534 | 441 | ||
535 | static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp) | 442 | static inline void xfs_sb_version_addattr2(struct xfs_sb *sbp) |
536 | { | 443 | { |
537 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; | 444 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; |
538 | sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT; | 445 | sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT; |
446 | sbp->sb_bad_features2 |= XFS_SB_VERSION2_ATTR2BIT; | ||
539 | } | 447 | } |
540 | 448 | ||
541 | static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) | 449 | static inline void xfs_sb_version_removeattr2(struct xfs_sb *sbp) |
542 | { | 450 | { |
543 | sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT; | 451 | sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT; |
452 | sbp->sb_bad_features2 &= ~XFS_SB_VERSION2_ATTR2BIT; | ||
544 | if (!sbp->sb_features2) | 453 | if (!sbp->sb_features2) |
545 | sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT; | 454 | sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT; |
546 | } | 455 | } |
547 | 456 | ||
548 | static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp) | 457 | static inline bool xfs_sb_version_hasprojid32bit(struct xfs_sb *sbp) |
549 | { | 458 | { |
550 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || | 459 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) || |
551 | (xfs_sb_version_hasmorebits(sbp) && | 460 | (xfs_sb_version_hasmorebits(sbp) && |
552 | (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT)); | 461 | (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT)); |
553 | } | 462 | } |
554 | 463 | ||
555 | static inline void xfs_sb_version_addprojid32bit(xfs_sb_t *sbp) | 464 | static inline void xfs_sb_version_addprojid32bit(struct xfs_sb *sbp) |
556 | { | 465 | { |
557 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; | 466 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; |
558 | sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; | 467 | sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; |
@@ -587,7 +496,9 @@ xfs_sb_has_compat_feature( | |||
587 | return (sbp->sb_features_compat & feature) != 0; | 496 | return (sbp->sb_features_compat & feature) != 0; |
588 | } | 497 | } |
589 | 498 | ||
590 | #define XFS_SB_FEAT_RO_COMPAT_ALL 0 | 499 | #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ |
500 | #define XFS_SB_FEAT_RO_COMPAT_ALL \ | ||
501 | (XFS_SB_FEAT_RO_COMPAT_FINOBT) | ||
591 | #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL | 502 | #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL |
592 | static inline bool | 503 | static inline bool |
593 | xfs_sb_has_ro_compat_feature( | 504 | xfs_sb_has_ro_compat_feature( |
@@ -623,12 +534,12 @@ xfs_sb_has_incompat_log_feature( | |||
623 | /* | 534 | /* |
624 | * V5 superblock specific feature checks | 535 | * V5 superblock specific feature checks |
625 | */ | 536 | */ |
626 | static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp) | 537 | static inline int xfs_sb_version_hascrc(struct xfs_sb *sbp) |
627 | { | 538 | { |
628 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; | 539 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; |
629 | } | 540 | } |
630 | 541 | ||
631 | static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp) | 542 | static inline int xfs_sb_version_has_pquotino(struct xfs_sb *sbp) |
632 | { | 543 | { |
633 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; | 544 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; |
634 | } | 545 | } |
@@ -641,6 +552,12 @@ static inline int xfs_sb_version_hasftype(struct xfs_sb *sbp) | |||
641 | (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE)); | 552 | (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE)); |
642 | } | 553 | } |
643 | 554 | ||
555 | static inline int xfs_sb_version_hasfinobt(xfs_sb_t *sbp) | ||
556 | { | ||
557 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && | ||
558 | (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); | ||
559 | } | ||
560 | |||
644 | /* | 561 | /* |
645 | * end of superblock version macros | 562 | * end of superblock version macros |
646 | */ | 563 | */ |
diff --git a/fs/xfs/xfs_shared.h b/fs/xfs/xfs_shared.h index 4484e5151395..82404da2ca67 100644 --- a/fs/xfs/xfs_shared.h +++ b/fs/xfs/xfs_shared.h | |||
@@ -238,7 +238,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *); | |||
238 | int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); | 238 | int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); |
239 | int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, | 239 | int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, |
240 | uint32_t size, struct xfs_buf *bp); | 240 | uint32_t size, struct xfs_buf *bp); |
241 | bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, | 241 | bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset, |
242 | uint32_t size, struct xfs_buf *bp); | 242 | uint32_t size, struct xfs_buf *bp); |
243 | void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp, | 243 | void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp, |
244 | struct xfs_inode *ip, struct xfs_ifork *ifp); | 244 | struct xfs_inode *ip, struct xfs_ifork *ifp); |
diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c index ce372b7d5644..f2240383d4bb 100644 --- a/fs/xfs/xfs_stats.c +++ b/fs/xfs/xfs_stats.c | |||
@@ -59,6 +59,7 @@ static int xfs_stat_proc_show(struct seq_file *m, void *v) | |||
59 | { "abtc2", XFSSTAT_END_ABTC_V2 }, | 59 | { "abtc2", XFSSTAT_END_ABTC_V2 }, |
60 | { "bmbt2", XFSSTAT_END_BMBT_V2 }, | 60 | { "bmbt2", XFSSTAT_END_BMBT_V2 }, |
61 | { "ibt2", XFSSTAT_END_IBT_V2 }, | 61 | { "ibt2", XFSSTAT_END_IBT_V2 }, |
62 | { "fibt2", XFSSTAT_END_FIBT_V2 }, | ||
62 | /* we print both series of quota information together */ | 63 | /* we print both series of quota information together */ |
63 | { "qm", XFSSTAT_END_QM }, | 64 | { "qm", XFSSTAT_END_QM }, |
64 | }; | 65 | }; |
diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h index c03ad38ceaeb..c8f238b8299a 100644 --- a/fs/xfs/xfs_stats.h +++ b/fs/xfs/xfs_stats.h | |||
@@ -183,7 +183,23 @@ struct xfsstats { | |||
183 | __uint32_t xs_ibt_2_alloc; | 183 | __uint32_t xs_ibt_2_alloc; |
184 | __uint32_t xs_ibt_2_free; | 184 | __uint32_t xs_ibt_2_free; |
185 | __uint32_t xs_ibt_2_moves; | 185 | __uint32_t xs_ibt_2_moves; |
186 | #define XFSSTAT_END_XQMSTAT (XFSSTAT_END_IBT_V2+6) | 186 | #define XFSSTAT_END_FIBT_V2 (XFSSTAT_END_IBT_V2+15) |
187 | __uint32_t xs_fibt_2_lookup; | ||
188 | __uint32_t xs_fibt_2_compare; | ||
189 | __uint32_t xs_fibt_2_insrec; | ||
190 | __uint32_t xs_fibt_2_delrec; | ||
191 | __uint32_t xs_fibt_2_newroot; | ||
192 | __uint32_t xs_fibt_2_killroot; | ||
193 | __uint32_t xs_fibt_2_increment; | ||
194 | __uint32_t xs_fibt_2_decrement; | ||
195 | __uint32_t xs_fibt_2_lshift; | ||
196 | __uint32_t xs_fibt_2_rshift; | ||
197 | __uint32_t xs_fibt_2_split; | ||
198 | __uint32_t xs_fibt_2_join; | ||
199 | __uint32_t xs_fibt_2_alloc; | ||
200 | __uint32_t xs_fibt_2_free; | ||
201 | __uint32_t xs_fibt_2_moves; | ||
202 | #define XFSSTAT_END_XQMSTAT (XFSSTAT_END_FIBT_V2+6) | ||
187 | __uint32_t xs_qm_dqreclaims; | 203 | __uint32_t xs_qm_dqreclaims; |
188 | __uint32_t xs_qm_dqreclaim_misses; | 204 | __uint32_t xs_qm_dqreclaim_misses; |
189 | __uint32_t xs_qm_dquot_dups; | 205 | __uint32_t xs_qm_dquot_dups; |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 3494eff8e4eb..8f0333b3f7a0 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -765,20 +765,18 @@ xfs_open_devices( | |||
765 | * Setup xfs_mount buffer target pointers | 765 | * Setup xfs_mount buffer target pointers |
766 | */ | 766 | */ |
767 | error = ENOMEM; | 767 | error = ENOMEM; |
768 | mp->m_ddev_targp = xfs_alloc_buftarg(mp, ddev, 0, mp->m_fsname); | 768 | mp->m_ddev_targp = xfs_alloc_buftarg(mp, ddev); |
769 | if (!mp->m_ddev_targp) | 769 | if (!mp->m_ddev_targp) |
770 | goto out_close_rtdev; | 770 | goto out_close_rtdev; |
771 | 771 | ||
772 | if (rtdev) { | 772 | if (rtdev) { |
773 | mp->m_rtdev_targp = xfs_alloc_buftarg(mp, rtdev, 1, | 773 | mp->m_rtdev_targp = xfs_alloc_buftarg(mp, rtdev); |
774 | mp->m_fsname); | ||
775 | if (!mp->m_rtdev_targp) | 774 | if (!mp->m_rtdev_targp) |
776 | goto out_free_ddev_targ; | 775 | goto out_free_ddev_targ; |
777 | } | 776 | } |
778 | 777 | ||
779 | if (logdev && logdev != ddev) { | 778 | if (logdev && logdev != ddev) { |
780 | mp->m_logdev_targp = xfs_alloc_buftarg(mp, logdev, 1, | 779 | mp->m_logdev_targp = xfs_alloc_buftarg(mp, logdev); |
781 | mp->m_fsname); | ||
782 | if (!mp->m_logdev_targp) | 780 | if (!mp->m_logdev_targp) |
783 | goto out_free_rtdev_targ; | 781 | goto out_free_rtdev_targ; |
784 | } else { | 782 | } else { |
@@ -811,8 +809,7 @@ xfs_setup_devices( | |||
811 | { | 809 | { |
812 | int error; | 810 | int error; |
813 | 811 | ||
814 | error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize, | 812 | error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_sectsize); |
815 | mp->m_sb.sb_sectsize); | ||
816 | if (error) | 813 | if (error) |
817 | return error; | 814 | return error; |
818 | 815 | ||
@@ -822,14 +819,12 @@ xfs_setup_devices( | |||
822 | if (xfs_sb_version_hassector(&mp->m_sb)) | 819 | if (xfs_sb_version_hassector(&mp->m_sb)) |
823 | log_sector_size = mp->m_sb.sb_logsectsize; | 820 | log_sector_size = mp->m_sb.sb_logsectsize; |
824 | error = xfs_setsize_buftarg(mp->m_logdev_targp, | 821 | error = xfs_setsize_buftarg(mp->m_logdev_targp, |
825 | mp->m_sb.sb_blocksize, | ||
826 | log_sector_size); | 822 | log_sector_size); |
827 | if (error) | 823 | if (error) |
828 | return error; | 824 | return error; |
829 | } | 825 | } |
830 | if (mp->m_rtdev_targp) { | 826 | if (mp->m_rtdev_targp) { |
831 | error = xfs_setsize_buftarg(mp->m_rtdev_targp, | 827 | error = xfs_setsize_buftarg(mp->m_rtdev_targp, |
832 | mp->m_sb.sb_blocksize, | ||
833 | mp->m_sb.sb_sectsize); | 828 | mp->m_sb.sb_sectsize); |
834 | if (error) | 829 | if (error) |
835 | return error; | 830 | return error; |
@@ -1754,13 +1749,9 @@ init_xfs_fs(void) | |||
1754 | if (error) | 1749 | if (error) |
1755 | goto out_destroy_wq; | 1750 | goto out_destroy_wq; |
1756 | 1751 | ||
1757 | error = xfs_filestream_init(); | ||
1758 | if (error) | ||
1759 | goto out_mru_cache_uninit; | ||
1760 | |||
1761 | error = xfs_buf_init(); | 1752 | error = xfs_buf_init(); |
1762 | if (error) | 1753 | if (error) |
1763 | goto out_filestream_uninit; | 1754 | goto out_mru_cache_uninit; |
1764 | 1755 | ||
1765 | error = xfs_init_procfs(); | 1756 | error = xfs_init_procfs(); |
1766 | if (error) | 1757 | if (error) |
@@ -1787,8 +1778,6 @@ init_xfs_fs(void) | |||
1787 | xfs_cleanup_procfs(); | 1778 | xfs_cleanup_procfs(); |
1788 | out_buf_terminate: | 1779 | out_buf_terminate: |
1789 | xfs_buf_terminate(); | 1780 | xfs_buf_terminate(); |
1790 | out_filestream_uninit: | ||
1791 | xfs_filestream_uninit(); | ||
1792 | out_mru_cache_uninit: | 1781 | out_mru_cache_uninit: |
1793 | xfs_mru_cache_uninit(); | 1782 | xfs_mru_cache_uninit(); |
1794 | out_destroy_wq: | 1783 | out_destroy_wq: |
@@ -1807,7 +1796,6 @@ exit_xfs_fs(void) | |||
1807 | xfs_sysctl_unregister(); | 1796 | xfs_sysctl_unregister(); |
1808 | xfs_cleanup_procfs(); | 1797 | xfs_cleanup_procfs(); |
1809 | xfs_buf_terminate(); | 1798 | xfs_buf_terminate(); |
1810 | xfs_filestream_uninit(); | ||
1811 | xfs_mru_cache_uninit(); | 1799 | xfs_mru_cache_uninit(); |
1812 | xfs_destroy_workqueues(); | 1800 | xfs_destroy_workqueues(); |
1813 | xfs_destroy_zones(); | 1801 | xfs_destroy_zones(); |
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 52979aa90986..d69363c833e1 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c | |||
@@ -27,6 +27,7 @@ | |||
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_format.h" |
30 | #include "xfs_da_btree.h" | ||
30 | #include "xfs_dir2.h" | 31 | #include "xfs_dir2.h" |
31 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
32 | #include "xfs_ialloc.h" | 33 | #include "xfs_ialloc.h" |
@@ -92,7 +93,7 @@ xfs_readlink_bmap( | |||
92 | 93 | ||
93 | cur_chunk = bp->b_addr; | 94 | cur_chunk = bp->b_addr; |
94 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 95 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
95 | if (!xfs_symlink_hdr_ok(mp, ip->i_ino, offset, | 96 | if (!xfs_symlink_hdr_ok(ip->i_ino, offset, |
96 | byte_cnt, bp)) { | 97 | byte_cnt, bp)) { |
97 | error = EFSCORRUPTED; | 98 | error = EFSCORRUPTED; |
98 | xfs_alert(mp, | 99 | xfs_alert(mp, |
diff --git a/fs/xfs/xfs_symlink_remote.c b/fs/xfs/xfs_symlink_remote.c index 9b32052ff65e..23c2f2577c8d 100644 --- a/fs/xfs/xfs_symlink_remote.c +++ b/fs/xfs/xfs_symlink_remote.c | |||
@@ -80,7 +80,6 @@ xfs_symlink_hdr_set( | |||
80 | */ | 80 | */ |
81 | bool | 81 | bool |
82 | xfs_symlink_hdr_ok( | 82 | xfs_symlink_hdr_ok( |
83 | struct xfs_mount *mp, | ||
84 | xfs_ino_t ino, | 83 | xfs_ino_t ino, |
85 | uint32_t offset, | 84 | uint32_t offset, |
86 | uint32_t size, | 85 | uint32_t size, |
diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index dee3279c095e..1e85bcd0e418 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "xfs_log_recover.h" | 46 | #include "xfs_log_recover.h" |
47 | #include "xfs_inode_item.h" | 47 | #include "xfs_inode_item.h" |
48 | #include "xfs_bmap_btree.h" | 48 | #include "xfs_bmap_btree.h" |
49 | #include "xfs_filestream.h" | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * We include this last to have the helpers above available for the trace | 52 | * 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 65d8c793a25c..6910458915cf 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -538,6 +538,64 @@ DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold_release); | |||
538 | DEFINE_BUF_ITEM_EVENT(xfs_trans_binval); | 538 | DEFINE_BUF_ITEM_EVENT(xfs_trans_binval); |
539 | DEFINE_BUF_ITEM_EVENT(xfs_trans_buf_ordered); | 539 | DEFINE_BUF_ITEM_EVENT(xfs_trans_buf_ordered); |
540 | 540 | ||
541 | DECLARE_EVENT_CLASS(xfs_filestream_class, | ||
542 | TP_PROTO(struct xfs_inode *ip, xfs_agnumber_t agno), | ||
543 | TP_ARGS(ip, agno), | ||
544 | TP_STRUCT__entry( | ||
545 | __field(dev_t, dev) | ||
546 | __field(xfs_ino_t, ino) | ||
547 | __field(xfs_agnumber_t, agno) | ||
548 | __field(int, streams) | ||
549 | ), | ||
550 | TP_fast_assign( | ||
551 | __entry->dev = VFS_I(ip)->i_sb->s_dev; | ||
552 | __entry->ino = ip->i_ino; | ||
553 | __entry->agno = agno; | ||
554 | __entry->streams = xfs_filestream_peek_ag(ip->i_mount, agno); | ||
555 | ), | ||
556 | TP_printk("dev %d:%d ino 0x%llx agno %u streams %d", | ||
557 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
558 | __entry->ino, | ||
559 | __entry->agno, | ||
560 | __entry->streams) | ||
561 | ) | ||
562 | #define DEFINE_FILESTREAM_EVENT(name) \ | ||
563 | DEFINE_EVENT(xfs_filestream_class, name, \ | ||
564 | TP_PROTO(struct xfs_inode *ip, xfs_agnumber_t agno), \ | ||
565 | TP_ARGS(ip, agno)) | ||
566 | DEFINE_FILESTREAM_EVENT(xfs_filestream_free); | ||
567 | DEFINE_FILESTREAM_EVENT(xfs_filestream_lookup); | ||
568 | DEFINE_FILESTREAM_EVENT(xfs_filestream_scan); | ||
569 | |||
570 | TRACE_EVENT(xfs_filestream_pick, | ||
571 | TP_PROTO(struct xfs_inode *ip, xfs_agnumber_t agno, | ||
572 | xfs_extlen_t free, int nscan), | ||
573 | TP_ARGS(ip, agno, free, nscan), | ||
574 | TP_STRUCT__entry( | ||
575 | __field(dev_t, dev) | ||
576 | __field(xfs_ino_t, ino) | ||
577 | __field(xfs_agnumber_t, agno) | ||
578 | __field(int, streams) | ||
579 | __field(xfs_extlen_t, free) | ||
580 | __field(int, nscan) | ||
581 | ), | ||
582 | TP_fast_assign( | ||
583 | __entry->dev = VFS_I(ip)->i_sb->s_dev; | ||
584 | __entry->ino = ip->i_ino; | ||
585 | __entry->agno = agno; | ||
586 | __entry->streams = xfs_filestream_peek_ag(ip->i_mount, agno); | ||
587 | __entry->free = free; | ||
588 | __entry->nscan = nscan; | ||
589 | ), | ||
590 | TP_printk("dev %d:%d ino 0x%llx agno %u streams %d free %d nscan %d", | ||
591 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
592 | __entry->ino, | ||
593 | __entry->agno, | ||
594 | __entry->streams, | ||
595 | __entry->free, | ||
596 | __entry->nscan) | ||
597 | ); | ||
598 | |||
541 | DECLARE_EVENT_CLASS(xfs_lock_class, | 599 | DECLARE_EVENT_CLASS(xfs_lock_class, |
542 | TP_PROTO(struct xfs_inode *ip, unsigned lock_flags, | 600 | TP_PROTO(struct xfs_inode *ip, unsigned lock_flags, |
543 | unsigned long caller_ip), | 601 | unsigned long caller_ip), |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 54a57326d85b..d03932564ccb 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -827,7 +827,7 @@ xfs_trans_committed_bulk( | |||
827 | xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn); | 827 | xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn); |
828 | 828 | ||
829 | spin_lock(&ailp->xa_lock); | 829 | spin_lock(&ailp->xa_lock); |
830 | xfs_trans_ail_cursor_done(ailp, &cur); | 830 | xfs_trans_ail_cursor_done(&cur); |
831 | spin_unlock(&ailp->xa_lock); | 831 | spin_unlock(&ailp->xa_lock); |
832 | } | 832 | } |
833 | 833 | ||
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index a7287354e535..cb0f3a84cc68 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
@@ -173,7 +173,6 @@ xfs_trans_ail_cursor_next( | |||
173 | */ | 173 | */ |
174 | void | 174 | void |
175 | xfs_trans_ail_cursor_done( | 175 | xfs_trans_ail_cursor_done( |
176 | struct xfs_ail *ailp, | ||
177 | struct xfs_ail_cursor *cur) | 176 | struct xfs_ail_cursor *cur) |
178 | { | 177 | { |
179 | cur->item = NULL; | 178 | cur->item = NULL; |
@@ -368,7 +367,7 @@ xfsaild_push( | |||
368 | * If the AIL is empty or our push has reached the end we are | 367 | * If the AIL is empty or our push has reached the end we are |
369 | * done now. | 368 | * done now. |
370 | */ | 369 | */ |
371 | xfs_trans_ail_cursor_done(ailp, &cur); | 370 | xfs_trans_ail_cursor_done(&cur); |
372 | spin_unlock(&ailp->xa_lock); | 371 | spin_unlock(&ailp->xa_lock); |
373 | goto out_done; | 372 | goto out_done; |
374 | } | 373 | } |
@@ -453,7 +452,7 @@ xfsaild_push( | |||
453 | break; | 452 | break; |
454 | lsn = lip->li_lsn; | 453 | lsn = lip->li_lsn; |
455 | } | 454 | } |
456 | xfs_trans_ail_cursor_done(ailp, &cur); | 455 | xfs_trans_ail_cursor_done(&cur); |
457 | spin_unlock(&ailp->xa_lock); | 456 | spin_unlock(&ailp->xa_lock); |
458 | 457 | ||
459 | if (xfs_buf_delwri_submit_nowait(&ailp->xa_buf_list)) | 458 | if (xfs_buf_delwri_submit_nowait(&ailp->xa_buf_list)) |
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index 12e86af9d9b9..bd1281862ad7 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h | |||
@@ -133,8 +133,7 @@ struct xfs_log_item * xfs_trans_ail_cursor_last(struct xfs_ail *ailp, | |||
133 | xfs_lsn_t lsn); | 133 | xfs_lsn_t lsn); |
134 | struct xfs_log_item * xfs_trans_ail_cursor_next(struct xfs_ail *ailp, | 134 | struct xfs_log_item * xfs_trans_ail_cursor_next(struct xfs_ail *ailp, |
135 | struct xfs_ail_cursor *cur); | 135 | struct xfs_ail_cursor *cur); |
136 | void xfs_trans_ail_cursor_done(struct xfs_ail *ailp, | 136 | void xfs_trans_ail_cursor_done(struct xfs_ail_cursor *cur); |
137 | struct xfs_ail_cursor *cur); | ||
138 | 137 | ||
139 | #if BITS_PER_LONG != 64 | 138 | #if BITS_PER_LONG != 64 |
140 | static inline void | 139 | static inline void |
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c index ae368165244d..f2bda7c76b8a 100644 --- a/fs/xfs/xfs_trans_resv.c +++ b/fs/xfs/xfs_trans_resv.c | |||
@@ -26,6 +26,7 @@ | |||
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_format.h" |
29 | #include "xfs_da_btree.h" | ||
29 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
30 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_ialloc.h" | 32 | #include "xfs_ialloc.h" |
@@ -106,6 +107,47 @@ xfs_calc_inode_res( | |||
106 | } | 107 | } |
107 | 108 | ||
108 | /* | 109 | /* |
110 | * The free inode btree is a conditional feature and the log reservation | ||
111 | * requirements differ slightly from that of the traditional inode allocation | ||
112 | * btree. The finobt tracks records for inode chunks with at least one free | ||
113 | * inode. A record can be removed from the tree for an inode allocation | ||
114 | * or free and thus the finobt reservation is unconditional across: | ||
115 | * | ||
116 | * - inode allocation | ||
117 | * - inode free | ||
118 | * - inode chunk allocation | ||
119 | * | ||
120 | * The 'modify' param indicates to include the record modification scenario. The | ||
121 | * 'alloc' param indicates to include the reservation for free space btree | ||
122 | * modifications on behalf of finobt modifications. This is required only for | ||
123 | * transactions that do not already account for free space btree modifications. | ||
124 | * | ||
125 | * the free inode btree: max depth * block size | ||
126 | * the allocation btrees: 2 trees * (max depth - 1) * block size | ||
127 | * the free inode btree entry: block size | ||
128 | */ | ||
129 | STATIC uint | ||
130 | xfs_calc_finobt_res( | ||
131 | struct xfs_mount *mp, | ||
132 | int alloc, | ||
133 | int modify) | ||
134 | { | ||
135 | uint res; | ||
136 | |||
137 | if (!xfs_sb_version_hasfinobt(&mp->m_sb)) | ||
138 | return 0; | ||
139 | |||
140 | res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)); | ||
141 | if (alloc) | ||
142 | res += xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), | ||
143 | XFS_FSB_TO_B(mp, 1)); | ||
144 | if (modify) | ||
145 | res += (uint)XFS_FSB_TO_B(mp, 1); | ||
146 | |||
147 | return res; | ||
148 | } | ||
149 | |||
150 | /* | ||
109 | * Various log reservation values. | 151 | * Various log reservation values. |
110 | * | 152 | * |
111 | * These are based on the size of the file system block because that is what | 153 | * These are based on the size of the file system block because that is what |
@@ -302,6 +344,7 @@ xfs_calc_remove_reservation( | |||
302 | * the superblock for the nlink flag: sector size | 344 | * the superblock for the nlink flag: sector size |
303 | * the directory btree: (max depth + v2) * dir block size | 345 | * the directory btree: (max depth + v2) * dir block size |
304 | * the directory inode's bmap btree: (max depth + v2) * block size | 346 | * the directory inode's bmap btree: (max depth + v2) * block size |
347 | * the finobt (record modification and allocation btrees) | ||
305 | */ | 348 | */ |
306 | STATIC uint | 349 | STATIC uint |
307 | xfs_calc_create_resv_modify( | 350 | xfs_calc_create_resv_modify( |
@@ -310,7 +353,8 @@ xfs_calc_create_resv_modify( | |||
310 | return xfs_calc_inode_res(mp, 2) + | 353 | return xfs_calc_inode_res(mp, 2) + |
311 | xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + | 354 | xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + |
312 | (uint)XFS_FSB_TO_B(mp, 1) + | 355 | (uint)XFS_FSB_TO_B(mp, 1) + |
313 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)); | 356 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) + |
357 | xfs_calc_finobt_res(mp, 1, 1); | ||
314 | } | 358 | } |
315 | 359 | ||
316 | /* | 360 | /* |
@@ -348,6 +392,7 @@ __xfs_calc_create_reservation( | |||
348 | * the superblock for the nlink flag: sector size | 392 | * the superblock for the nlink flag: sector size |
349 | * the inode btree: max depth * blocksize | 393 | * the inode btree: max depth * blocksize |
350 | * the allocation btrees: 2 trees * (max depth - 1) * block size | 394 | * the allocation btrees: 2 trees * (max depth - 1) * block size |
395 | * the finobt (record insertion) | ||
351 | */ | 396 | */ |
352 | STATIC uint | 397 | STATIC uint |
353 | xfs_calc_icreate_resv_alloc( | 398 | xfs_calc_icreate_resv_alloc( |
@@ -357,7 +402,8 @@ xfs_calc_icreate_resv_alloc( | |||
357 | mp->m_sb.sb_sectsize + | 402 | mp->m_sb.sb_sectsize + |
358 | xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + | 403 | xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + |
359 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), | 404 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), |
360 | XFS_FSB_TO_B(mp, 1)); | 405 | XFS_FSB_TO_B(mp, 1)) + |
406 | xfs_calc_finobt_res(mp, 0, 0); | ||
361 | } | 407 | } |
362 | 408 | ||
363 | STATIC uint | 409 | STATIC uint |
@@ -425,6 +471,7 @@ xfs_calc_symlink_reservation( | |||
425 | * the on disk inode before ours in the agi hash list: inode cluster size | 471 | * the on disk inode before ours in the agi hash list: inode cluster size |
426 | * the inode btree: max depth * blocksize | 472 | * the inode btree: max depth * blocksize |
427 | * the allocation btrees: 2 trees * (max depth - 1) * block size | 473 | * the allocation btrees: 2 trees * (max depth - 1) * block size |
474 | * the finobt (record insertion, removal or modification) | ||
428 | */ | 475 | */ |
429 | STATIC uint | 476 | STATIC uint |
430 | xfs_calc_ifree_reservation( | 477 | xfs_calc_ifree_reservation( |
@@ -439,7 +486,8 @@ xfs_calc_ifree_reservation( | |||
439 | xfs_calc_buf_res(2 + mp->m_ialloc_blks + | 486 | xfs_calc_buf_res(2 + mp->m_ialloc_blks + |
440 | mp->m_in_maxlevels, 0) + | 487 | mp->m_in_maxlevels, 0) + |
441 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), | 488 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), |
442 | XFS_FSB_TO_B(mp, 1)); | 489 | XFS_FSB_TO_B(mp, 1)) + |
490 | xfs_calc_finobt_res(mp, 0, 1); | ||
443 | } | 491 | } |
444 | 492 | ||
445 | /* | 493 | /* |
@@ -562,7 +610,7 @@ xfs_calc_addafork_reservation( | |||
562 | return XFS_DQUOT_LOGRES(mp) + | 610 | return XFS_DQUOT_LOGRES(mp) + |
563 | xfs_calc_inode_res(mp, 1) + | 611 | xfs_calc_inode_res(mp, 1) + |
564 | xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + | 612 | xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + |
565 | xfs_calc_buf_res(1, mp->m_dirblksize) + | 613 | xfs_calc_buf_res(1, mp->m_dir_geo->blksize) + |
566 | xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1, | 614 | xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1, |
567 | XFS_FSB_TO_B(mp, 1)) + | 615 | XFS_FSB_TO_B(mp, 1)) + |
568 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), | 616 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), |
diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h index af5dbe06cb65..bf9c4579334d 100644 --- a/fs/xfs/xfs_trans_space.h +++ b/fs/xfs/xfs_trans_space.h | |||
@@ -28,7 +28,8 @@ | |||
28 | (((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \ | 28 | (((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \ |
29 | XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \ | 29 | XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \ |
30 | XFS_EXTENTADD_SPACE_RES(mp,w)) | 30 | XFS_EXTENTADD_SPACE_RES(mp,w)) |
31 | #define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1) | 31 | #define XFS_DAENTER_1B(mp,w) \ |
32 | ((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1) | ||
32 | #define XFS_DAENTER_DBS(mp,w) \ | 33 | #define XFS_DAENTER_DBS(mp,w) \ |
33 | (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0)) | 34 | (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0)) |
34 | #define XFS_DAENTER_BLOCKS(mp,w) \ | 35 | #define XFS_DAENTER_BLOCKS(mp,w) \ |
@@ -47,13 +48,15 @@ | |||
47 | #define XFS_DIRREMOVE_SPACE_RES(mp) \ | 48 | #define XFS_DIRREMOVE_SPACE_RES(mp) \ |
48 | XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) | 49 | XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) |
49 | #define XFS_IALLOC_SPACE_RES(mp) \ | 50 | #define XFS_IALLOC_SPACE_RES(mp) \ |
50 | ((mp)->m_ialloc_blks + (mp)->m_in_maxlevels - 1) | 51 | ((mp)->m_ialloc_blks + \ |
52 | (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \ | ||
53 | ((mp)->m_in_maxlevels - 1))) | ||
51 | 54 | ||
52 | /* | 55 | /* |
53 | * Space reservation values for various transactions. | 56 | * Space reservation values for various transactions. |
54 | */ | 57 | */ |
55 | #define XFS_ADDAFORK_SPACE_RES(mp) \ | 58 | #define XFS_ADDAFORK_SPACE_RES(mp) \ |
56 | ((mp)->m_dirblkfsbs + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)) | 59 | ((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)) |
57 | #define XFS_ATTRRM_SPACE_RES(mp) \ | 60 | #define XFS_ATTRRM_SPACE_RES(mp) \ |
58 | XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) | 61 | XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) |
59 | /* This macro is not used - see inline code in xfs_attr_set */ | 62 | /* This macro is not used - see inline code in xfs_attr_set */ |
@@ -82,5 +85,8 @@ | |||
82 | (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) | 85 | (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) |
83 | #define XFS_SYMLINK_SPACE_RES(mp,nl,b) \ | 86 | #define XFS_SYMLINK_SPACE_RES(mp,nl,b) \ |
84 | (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b)) | 87 | (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b)) |
88 | #define XFS_IFREE_SPACE_RES(mp) \ | ||
89 | (xfs_sb_version_hasfinobt(&mp->m_sb) ? (mp)->m_in_maxlevels : 0) | ||
90 | |||
85 | 91 | ||
86 | #endif /* __XFS_TRANS_SPACE_H__ */ | 92 | #endif /* __XFS_TRANS_SPACE_H__ */ |
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index 82bbc34d54a3..65c6e6650b1a 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h | |||
@@ -134,7 +134,7 @@ typedef enum { | |||
134 | 134 | ||
135 | typedef enum { | 135 | typedef enum { |
136 | XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, | 136 | XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, |
137 | XFS_BTNUM_MAX | 137 | XFS_BTNUM_FINOi, XFS_BTNUM_MAX |
138 | } xfs_btnum_t; | 138 | } xfs_btnum_t; |
139 | 139 | ||
140 | struct xfs_name { | 140 | struct xfs_name { |