diff options
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 273 |
1 files changed, 192 insertions, 81 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 1cdd574c63a9..35e557b00db2 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -1,46 +1,26 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | ||
3 | * | 4 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or |
5 | * under the terms of version 2 of the GNU General Public License as | 6 | * modify it under the terms of the GNU General Public License as |
6 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
7 | * | 8 | * |
8 | * This program is distributed in the hope that it would be useful, but | 9 | * This program is distributed in the hope that it would be useful, |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | ||
11 | * | 13 | * |
12 | * Further, this software is distributed without any warranty that it is | 14 | * You should have received a copy of the GNU General Public License |
13 | * free of the rightful claim of any third person regarding infringement | 15 | * along with this program; if not, write the Free Software Foundation, |
14 | * or the like. Any license provided herein, whether implied or | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
15 | * otherwise, applies only to this software file. Patent licenses, if | ||
16 | * any, provided herein do not apply to combinations of this program with | ||
17 | * other software, or any other product whatsoever. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | ||
21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
22 | * | ||
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | ||
24 | * Mountain View, CA 94043, or: | ||
25 | * | ||
26 | * http://www.sgi.com | ||
27 | * | ||
28 | * For further information regarding this notice, see: | ||
29 | * | ||
30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | ||
31 | */ | 17 | */ |
32 | /* | ||
33 | * xfs_attr_leaf.c | ||
34 | * | ||
35 | * GROT: figure out how to recover gracefully when bmap returns ENOSPC. | ||
36 | */ | ||
37 | |||
38 | #include "xfs.h" | 18 | #include "xfs.h" |
39 | 19 | #include "xfs_fs.h" | |
40 | #include "xfs_macros.h" | ||
41 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
42 | #include "xfs_inum.h" | 21 | #include "xfs_bit.h" |
43 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
23 | #include "xfs_inum.h" | ||
44 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
45 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
46 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
@@ -48,23 +28,22 @@ | |||
48 | #include "xfs_dir2.h" | 28 | #include "xfs_dir2.h" |
49 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
50 | #include "xfs_mount.h" | 30 | #include "xfs_mount.h" |
51 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_da_btree.h" |
52 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | ||
53 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
54 | #include "xfs_alloc.h" | 35 | #include "xfs_alloc.h" |
55 | #include "xfs_btree.h" | 36 | #include "xfs_btree.h" |
56 | #include "xfs_attr_sf.h" | ||
57 | #include "xfs_dir_sf.h" | 37 | #include "xfs_dir_sf.h" |
58 | #include "xfs_dir2_sf.h" | 38 | #include "xfs_dir2_sf.h" |
39 | #include "xfs_attr_sf.h" | ||
59 | #include "xfs_dinode.h" | 40 | #include "xfs_dinode.h" |
60 | #include "xfs_inode_item.h" | ||
61 | #include "xfs_inode.h" | 41 | #include "xfs_inode.h" |
42 | #include "xfs_inode_item.h" | ||
62 | #include "xfs_bmap.h" | 43 | #include "xfs_bmap.h" |
63 | #include "xfs_da_btree.h" | ||
64 | #include "xfs_attr.h" | 44 | #include "xfs_attr.h" |
65 | #include "xfs_attr_leaf.h" | 45 | #include "xfs_attr_leaf.h" |
66 | #include "xfs_error.h" | 46 | #include "xfs_error.h" |
67 | #include "xfs_bit.h" | ||
68 | 47 | ||
69 | /* | 48 | /* |
70 | * xfs_attr_leaf.c | 49 | * xfs_attr_leaf.c |
@@ -118,13 +97,82 @@ STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context, | |||
118 | 97 | ||
119 | 98 | ||
120 | /*======================================================================== | 99 | /*======================================================================== |
121 | * External routines when dirsize < XFS_LITINO(mp). | 100 | * External routines when attribute fork size < XFS_LITINO(mp). |
122 | *========================================================================*/ | 101 | *========================================================================*/ |
123 | 102 | ||
124 | /* | 103 | /* |
125 | * Create the initial contents of a shortform attribute list. | 104 | * Query whether the requested number of additional bytes of extended |
105 | * attribute space will be able to fit inline. | ||
106 | * Returns zero if not, else the di_forkoff fork offset to be used in the | ||
107 | * literal area for attribute data once the new bytes have been added. | ||
108 | * | ||
109 | * di_forkoff must be 8 byte aligned, hence is stored as a >>3 value; | ||
110 | * special case for dev/uuid inodes, they have fixed size data forks. | ||
126 | */ | 111 | */ |
127 | int | 112 | int |
113 | xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | ||
114 | { | ||
115 | int offset; | ||
116 | int minforkoff; /* lower limit on valid forkoff locations */ | ||
117 | int maxforkoff; /* upper limit on valid forkoff locations */ | ||
118 | xfs_mount_t *mp = dp->i_mount; | ||
119 | |||
120 | offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ | ||
121 | |||
122 | switch (dp->i_d.di_format) { | ||
123 | case XFS_DINODE_FMT_DEV: | ||
124 | minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; | ||
125 | return (offset >= minforkoff) ? minforkoff : 0; | ||
126 | case XFS_DINODE_FMT_UUID: | ||
127 | minforkoff = roundup(sizeof(uuid_t), 8) >> 3; | ||
128 | return (offset >= minforkoff) ? minforkoff : 0; | ||
129 | } | ||
130 | |||
131 | if (unlikely(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) { | ||
132 | if (bytes <= XFS_IFORK_ASIZE(dp)) | ||
133 | return mp->m_attroffset >> 3; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* data fork btree root can have at least this many key/ptr pairs */ | ||
138 | minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); | ||
139 | minforkoff = roundup(minforkoff, 8) >> 3; | ||
140 | |||
141 | /* attr fork btree root can have at least this many key/ptr pairs */ | ||
142 | maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); | ||
143 | maxforkoff = maxforkoff >> 3; /* rounded down */ | ||
144 | |||
145 | if (offset >= minforkoff && offset < maxforkoff) | ||
146 | return offset; | ||
147 | if (offset >= maxforkoff) | ||
148 | return maxforkoff; | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Switch on the ATTR2 superblock bit (implies also FEATURES2) | ||
154 | */ | ||
155 | STATIC void | ||
156 | xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp) | ||
157 | { | ||
158 | unsigned long s; | ||
159 | |||
160 | if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR) && | ||
161 | !(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) { | ||
162 | s = XFS_SB_LOCK(mp); | ||
163 | if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) { | ||
164 | XFS_SB_VERSION_ADDATTR2(&mp->m_sb); | ||
165 | XFS_SB_UNLOCK(mp, s); | ||
166 | xfs_mod_sb(tp, XFS_SB_VERSIONNUM | XFS_SB_FEATURES2); | ||
167 | } else | ||
168 | XFS_SB_UNLOCK(mp, s); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Create the initial contents of a shortform attribute list. | ||
174 | */ | ||
175 | void | ||
128 | xfs_attr_shortform_create(xfs_da_args_t *args) | 176 | xfs_attr_shortform_create(xfs_da_args_t *args) |
129 | { | 177 | { |
130 | xfs_attr_sf_hdr_t *hdr; | 178 | xfs_attr_sf_hdr_t *hdr; |
@@ -148,29 +196,37 @@ xfs_attr_shortform_create(xfs_da_args_t *args) | |||
148 | hdr->count = 0; | 196 | hdr->count = 0; |
149 | INT_SET(hdr->totsize, ARCH_CONVERT, sizeof(*hdr)); | 197 | INT_SET(hdr->totsize, ARCH_CONVERT, sizeof(*hdr)); |
150 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); | 198 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); |
151 | return(0); | ||
152 | } | 199 | } |
153 | 200 | ||
154 | /* | 201 | /* |
155 | * Add a name/value pair to the shortform attribute list. | 202 | * Add a name/value pair to the shortform attribute list. |
156 | * Overflow from the inode has already been checked for. | 203 | * Overflow from the inode has already been checked for. |
157 | */ | 204 | */ |
158 | int | 205 | void |
159 | xfs_attr_shortform_add(xfs_da_args_t *args) | 206 | xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) |
160 | { | 207 | { |
161 | xfs_attr_shortform_t *sf; | 208 | xfs_attr_shortform_t *sf; |
162 | xfs_attr_sf_entry_t *sfe; | 209 | xfs_attr_sf_entry_t *sfe; |
163 | int i, offset, size; | 210 | int i, offset, size; |
211 | xfs_mount_t *mp; | ||
164 | xfs_inode_t *dp; | 212 | xfs_inode_t *dp; |
165 | xfs_ifork_t *ifp; | 213 | xfs_ifork_t *ifp; |
166 | 214 | ||
167 | dp = args->dp; | 215 | dp = args->dp; |
216 | mp = dp->i_mount; | ||
217 | dp->i_d.di_forkoff = forkoff; | ||
218 | dp->i_df.if_ext_max = | ||
219 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
220 | dp->i_afp->if_ext_max = | ||
221 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
222 | |||
168 | ifp = dp->i_afp; | 223 | ifp = dp->i_afp; |
169 | ASSERT(ifp->if_flags & XFS_IFINLINE); | 224 | ASSERT(ifp->if_flags & XFS_IFINLINE); |
170 | sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; | 225 | sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; |
171 | sfe = &sf->list[0]; | 226 | sfe = &sf->list[0]; |
172 | for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); | 227 | for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); |
173 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { | 228 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { |
229 | #ifdef DEBUG | ||
174 | if (sfe->namelen != args->namelen) | 230 | if (sfe->namelen != args->namelen) |
175 | continue; | 231 | continue; |
176 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) | 232 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
@@ -181,7 +237,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args) | |||
181 | if (((args->flags & ATTR_ROOT) != 0) != | 237 | if (((args->flags & ATTR_ROOT) != 0) != |
182 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) | 238 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) |
183 | continue; | 239 | continue; |
184 | return(XFS_ERROR(EEXIST)); | 240 | ASSERT(0); |
241 | #endif | ||
185 | } | 242 | } |
186 | 243 | ||
187 | offset = (char *)sfe - (char *)sf; | 244 | offset = (char *)sfe - (char *)sf; |
@@ -200,11 +257,11 @@ xfs_attr_shortform_add(xfs_da_args_t *args) | |||
200 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, size); | 257 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, size); |
201 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); | 258 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); |
202 | 259 | ||
203 | return(0); | 260 | xfs_sbversion_add_attr2(mp, args->trans); |
204 | } | 261 | } |
205 | 262 | ||
206 | /* | 263 | /* |
207 | * Remove a name from the shortform attribute list structure. | 264 | * Remove an attribute from the shortform attribute list structure. |
208 | */ | 265 | */ |
209 | int | 266 | int |
210 | xfs_attr_shortform_remove(xfs_da_args_t *args) | 267 | xfs_attr_shortform_remove(xfs_da_args_t *args) |
@@ -212,17 +269,16 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
212 | xfs_attr_shortform_t *sf; | 269 | xfs_attr_shortform_t *sf; |
213 | xfs_attr_sf_entry_t *sfe; | 270 | xfs_attr_sf_entry_t *sfe; |
214 | int base, size=0, end, totsize, i; | 271 | int base, size=0, end, totsize, i; |
272 | xfs_mount_t *mp; | ||
215 | xfs_inode_t *dp; | 273 | xfs_inode_t *dp; |
216 | 274 | ||
217 | /* | ||
218 | * Remove the attribute. | ||
219 | */ | ||
220 | dp = args->dp; | 275 | dp = args->dp; |
276 | mp = dp->i_mount; | ||
221 | base = sizeof(xfs_attr_sf_hdr_t); | 277 | base = sizeof(xfs_attr_sf_hdr_t); |
222 | sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; | 278 | sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; |
223 | sfe = &sf->list[0]; | 279 | sfe = &sf->list[0]; |
224 | for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); | 280 | end = INT_GET(sf->hdr.count, ARCH_CONVERT); |
225 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe), | 281 | for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), |
226 | base += size, i++) { | 282 | base += size, i++) { |
227 | size = XFS_ATTR_SF_ENTSIZE(sfe); | 283 | size = XFS_ATTR_SF_ENTSIZE(sfe); |
228 | if (sfe->namelen != args->namelen) | 284 | if (sfe->namelen != args->namelen) |
@@ -237,19 +293,51 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
237 | continue; | 293 | continue; |
238 | break; | 294 | break; |
239 | } | 295 | } |
240 | if (i == INT_GET(sf->hdr.count, ARCH_CONVERT)) | 296 | if (i == end) |
241 | return(XFS_ERROR(ENOATTR)); | 297 | return(XFS_ERROR(ENOATTR)); |
242 | 298 | ||
299 | /* | ||
300 | * Fix up the attribute fork data, covering the hole | ||
301 | */ | ||
243 | end = base + size; | 302 | end = base + size; |
244 | totsize = INT_GET(sf->hdr.totsize, ARCH_CONVERT); | 303 | totsize = INT_GET(sf->hdr.totsize, ARCH_CONVERT); |
245 | if (end != totsize) { | 304 | if (end != totsize) |
246 | memmove(&((char *)sf)[base], &((char *)sf)[end], | 305 | memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end); |
247 | totsize - end); | ||
248 | } | ||
249 | INT_MOD(sf->hdr.count, ARCH_CONVERT, -1); | 306 | INT_MOD(sf->hdr.count, ARCH_CONVERT, -1); |
250 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, -size); | 307 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, -size); |
251 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); | 308 | |
252 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); | 309 | /* |
310 | * Fix up the start offset of the attribute fork | ||
311 | */ | ||
312 | totsize -= size; | ||
313 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname) { | ||
314 | /* | ||
315 | * Last attribute now removed, revert to original | ||
316 | * inode format making all literal area available | ||
317 | * to the data fork once more. | ||
318 | */ | ||
319 | xfs_idestroy_fork(dp, XFS_ATTR_FORK); | ||
320 | dp->i_d.di_forkoff = 0; | ||
321 | dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | ||
322 | ASSERT(dp->i_d.di_anextents == 0); | ||
323 | ASSERT(dp->i_afp == NULL); | ||
324 | dp->i_df.if_ext_max = | ||
325 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
326 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); | ||
327 | } else { | ||
328 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); | ||
329 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); | ||
330 | ASSERT(dp->i_d.di_forkoff); | ||
331 | ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname); | ||
332 | dp->i_afp->if_ext_max = | ||
333 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
334 | dp->i_df.if_ext_max = | ||
335 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
336 | xfs_trans_log_inode(args->trans, dp, | ||
337 | XFS_ILOG_CORE | XFS_ILOG_ADATA); | ||
338 | } | ||
339 | |||
340 | xfs_sbversion_add_attr2(mp, args->trans); | ||
253 | 341 | ||
254 | return(0); | 342 | return(0); |
255 | } | 343 | } |
@@ -561,7 +649,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) | |||
561 | /* | 649 | /* |
562 | * Sort the entries on hash then entno. | 650 | * Sort the entries on hash then entno. |
563 | */ | 651 | */ |
564 | qsort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare); | 652 | xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare); |
565 | 653 | ||
566 | /* | 654 | /* |
567 | * Re-find our place IN THE SORTED LIST. | 655 | * Re-find our place IN THE SORTED LIST. |
@@ -649,14 +737,16 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) | |||
649 | + name_loc->namelen | 737 | + name_loc->namelen |
650 | + INT_GET(name_loc->valuelen, ARCH_CONVERT); | 738 | + INT_GET(name_loc->valuelen, ARCH_CONVERT); |
651 | } | 739 | } |
652 | return( bytes < XFS_IFORK_ASIZE(dp) ); | 740 | if (bytes == sizeof(struct xfs_attr_sf_hdr)) |
741 | return(-1); | ||
742 | return(xfs_attr_shortform_bytesfit(dp, bytes)); | ||
653 | } | 743 | } |
654 | 744 | ||
655 | /* | 745 | /* |
656 | * Convert a leaf attribute list to shortform attribute list | 746 | * Convert a leaf attribute list to shortform attribute list |
657 | */ | 747 | */ |
658 | int | 748 | int |
659 | xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) | 749 | xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) |
660 | { | 750 | { |
661 | xfs_attr_leafblock_t *leaf; | 751 | xfs_attr_leafblock_t *leaf; |
662 | xfs_attr_leaf_entry_t *entry; | 752 | xfs_attr_leaf_entry_t *entry; |
@@ -683,9 +773,25 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
683 | error = xfs_da_shrink_inode(args, 0, bp); | 773 | error = xfs_da_shrink_inode(args, 0, bp); |
684 | if (error) | 774 | if (error) |
685 | goto out; | 775 | goto out; |
686 | error = xfs_attr_shortform_create(args); | 776 | |
687 | if (error) | 777 | if (forkoff == -1) { |
778 | /* | ||
779 | * Last attribute was removed, revert to original | ||
780 | * inode format making all literal area available | ||
781 | * to the data fork once more. | ||
782 | */ | ||
783 | xfs_idestroy_fork(dp, XFS_ATTR_FORK); | ||
784 | dp->i_d.di_forkoff = 0; | ||
785 | dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | ||
786 | ASSERT(dp->i_d.di_anextents == 0); | ||
787 | ASSERT(dp->i_afp == NULL); | ||
788 | dp->i_df.if_ext_max = | ||
789 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
790 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); | ||
688 | goto out; | 791 | goto out; |
792 | } | ||
793 | |||
794 | xfs_attr_shortform_create(args); | ||
689 | 795 | ||
690 | /* | 796 | /* |
691 | * Copy the attributes | 797 | * Copy the attributes |
@@ -713,7 +819,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
713 | nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); | 819 | nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); |
714 | nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : | 820 | nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : |
715 | ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); | 821 | ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); |
716 | xfs_attr_shortform_add(&nargs); | 822 | xfs_attr_shortform_add(&nargs, forkoff); |
717 | } | 823 | } |
718 | error = 0; | 824 | error = 0; |
719 | 825 | ||
@@ -898,7 +1004,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
898 | ASSERT((args->index >= 0) | 1004 | ASSERT((args->index >= 0) |
899 | && (args->index <= INT_GET(leaf->hdr.count, ARCH_CONVERT))); | 1005 | && (args->index <= INT_GET(leaf->hdr.count, ARCH_CONVERT))); |
900 | hdr = &leaf->hdr; | 1006 | hdr = &leaf->hdr; |
901 | entsize = xfs_attr_leaf_newentsize(args, | 1007 | entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen, |
902 | args->trans->t_mountp->m_sb.sb_blocksize, NULL); | 1008 | args->trans->t_mountp->m_sb.sb_blocksize, NULL); |
903 | 1009 | ||
904 | /* | 1010 | /* |
@@ -995,13 +1101,14 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) | |||
995 | mp = args->trans->t_mountp; | 1101 | mp = args->trans->t_mountp; |
996 | ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); | 1102 | ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); |
997 | ASSERT((INT_GET(map->base, ARCH_CONVERT) & 0x3) == 0); | 1103 | ASSERT((INT_GET(map->base, ARCH_CONVERT) & 0x3) == 0); |
998 | ASSERT(INT_GET(map->size, ARCH_CONVERT) | 1104 | ASSERT(INT_GET(map->size, ARCH_CONVERT) >= |
999 | >= xfs_attr_leaf_newentsize(args, | 1105 | xfs_attr_leaf_newentsize(args->namelen, args->valuelen, |
1000 | mp->m_sb.sb_blocksize, NULL)); | 1106 | mp->m_sb.sb_blocksize, NULL)); |
1001 | ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); | 1107 | ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); |
1002 | ASSERT((INT_GET(map->size, ARCH_CONVERT) & 0x3) == 0); | 1108 | ASSERT((INT_GET(map->size, ARCH_CONVERT) & 0x3) == 0); |
1003 | INT_MOD(map->size, ARCH_CONVERT, | 1109 | INT_MOD(map->size, ARCH_CONVERT, |
1004 | -xfs_attr_leaf_newentsize(args, mp->m_sb.sb_blocksize, &tmp)); | 1110 | -xfs_attr_leaf_newentsize(args->namelen, args->valuelen, |
1111 | mp->m_sb.sb_blocksize, &tmp)); | ||
1005 | INT_SET(entry->nameidx, ARCH_CONVERT, | 1112 | INT_SET(entry->nameidx, ARCH_CONVERT, |
1006 | INT_GET(map->base, ARCH_CONVERT) | 1113 | INT_GET(map->base, ARCH_CONVERT) |
1007 | + INT_GET(map->size, ARCH_CONVERT)); | 1114 | + INT_GET(map->size, ARCH_CONVERT)); |
@@ -1357,8 +1464,10 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | |||
1357 | half = (max+1) * sizeof(*entry); | 1464 | half = (max+1) * sizeof(*entry); |
1358 | half += INT_GET(hdr1->usedbytes, ARCH_CONVERT) | 1465 | half += INT_GET(hdr1->usedbytes, ARCH_CONVERT) |
1359 | + INT_GET(hdr2->usedbytes, ARCH_CONVERT) | 1466 | + INT_GET(hdr2->usedbytes, ARCH_CONVERT) |
1360 | + xfs_attr_leaf_newentsize(state->args, | 1467 | + xfs_attr_leaf_newentsize( |
1361 | state->blocksize, NULL); | 1468 | state->args->namelen, |
1469 | state->args->valuelen, | ||
1470 | state->blocksize, NULL); | ||
1362 | half /= 2; | 1471 | half /= 2; |
1363 | lastdelta = state->blocksize; | 1472 | lastdelta = state->blocksize; |
1364 | entry = &leaf1->entries[0]; | 1473 | entry = &leaf1->entries[0]; |
@@ -1370,9 +1479,10 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | |||
1370 | */ | 1479 | */ |
1371 | if (count == blk1->index) { | 1480 | if (count == blk1->index) { |
1372 | tmp = totallen + sizeof(*entry) + | 1481 | tmp = totallen + sizeof(*entry) + |
1373 | xfs_attr_leaf_newentsize(state->args, | 1482 | xfs_attr_leaf_newentsize( |
1374 | state->blocksize, | 1483 | state->args->namelen, |
1375 | NULL); | 1484 | state->args->valuelen, |
1485 | state->blocksize, NULL); | ||
1376 | if (XFS_ATTR_ABS(half - tmp) > lastdelta) | 1486 | if (XFS_ATTR_ABS(half - tmp) > lastdelta) |
1377 | break; | 1487 | break; |
1378 | lastdelta = XFS_ATTR_ABS(half - tmp); | 1488 | lastdelta = XFS_ATTR_ABS(half - tmp); |
@@ -1408,9 +1518,10 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | |||
1408 | totallen -= count * sizeof(*entry); | 1518 | totallen -= count * sizeof(*entry); |
1409 | if (foundit) { | 1519 | if (foundit) { |
1410 | totallen -= sizeof(*entry) + | 1520 | totallen -= sizeof(*entry) + |
1411 | xfs_attr_leaf_newentsize(state->args, | 1521 | xfs_attr_leaf_newentsize( |
1412 | state->blocksize, | 1522 | state->args->namelen, |
1413 | NULL); | 1523 | state->args->valuelen, |
1524 | state->blocksize, NULL); | ||
1414 | } | 1525 | } |
1415 | 1526 | ||
1416 | *countarg = count; | 1527 | *countarg = count; |
@@ -2253,17 +2364,17 @@ xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) | |||
2253 | * a "local" or a "remote" attribute. | 2364 | * a "local" or a "remote" attribute. |
2254 | */ | 2365 | */ |
2255 | int | 2366 | int |
2256 | xfs_attr_leaf_newentsize(xfs_da_args_t *args, int blocksize, int *local) | 2367 | xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local) |
2257 | { | 2368 | { |
2258 | int size; | 2369 | int size; |
2259 | 2370 | ||
2260 | size = XFS_ATTR_LEAF_ENTSIZE_LOCAL(args->namelen, args->valuelen); | 2371 | size = XFS_ATTR_LEAF_ENTSIZE_LOCAL(namelen, valuelen); |
2261 | if (size < XFS_ATTR_LEAF_ENTSIZE_LOCAL_MAX(blocksize)) { | 2372 | if (size < XFS_ATTR_LEAF_ENTSIZE_LOCAL_MAX(blocksize)) { |
2262 | if (local) { | 2373 | if (local) { |
2263 | *local = 1; | 2374 | *local = 1; |
2264 | } | 2375 | } |
2265 | } else { | 2376 | } else { |
2266 | size = XFS_ATTR_LEAF_ENTSIZE_REMOTE(args->namelen); | 2377 | size = XFS_ATTR_LEAF_ENTSIZE_REMOTE(namelen); |
2267 | if (local) { | 2378 | if (local) { |
2268 | *local = 0; | 2379 | *local = 0; |
2269 | } | 2380 | } |