aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr_leaf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
-rw-r--r--fs/xfs/xfs_attr_leaf.c54
1 files changed, 47 insertions, 7 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 9719bbef122c..8eab73e8340a 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -94,7 +94,7 @@ STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
94 * Namespace helper routines 94 * Namespace helper routines
95 *========================================================================*/ 95 *========================================================================*/
96 96
97STATIC inline attrnames_t * 97STATIC_INLINE attrnames_t *
98xfs_attr_flags_namesp(int flags) 98xfs_attr_flags_namesp(int flags)
99{ 99{
100 return ((flags & XFS_ATTR_SECURE) ? &attr_secure: 100 return ((flags & XFS_ATTR_SECURE) ? &attr_secure:
@@ -105,7 +105,7 @@ xfs_attr_flags_namesp(int flags)
105 * If namespace bits don't match return 0. 105 * If namespace bits don't match return 0.
106 * If all match then return 1. 106 * If all match then return 1.
107 */ 107 */
108STATIC inline int 108STATIC_INLINE int
109xfs_attr_namesp_match(int arg_flags, int ondisk_flags) 109xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
110{ 110{
111 return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); 111 return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
@@ -116,7 +116,7 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
116 * then return 0. 116 * then return 0.
117 * If all match or are overridable then return 1. 117 * If all match or are overridable then return 1.
118 */ 118 */
119STATIC inline int 119STATIC_INLINE int
120xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags) 120xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags)
121{ 121{
122 if (((arg_flags & ATTR_SECURE) == 0) != 122 if (((arg_flags & ATTR_SECURE) == 0) !=
@@ -150,6 +150,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
150 int offset; 150 int offset;
151 int minforkoff; /* lower limit on valid forkoff locations */ 151 int minforkoff; /* lower limit on valid forkoff locations */
152 int maxforkoff; /* upper limit on valid forkoff locations */ 152 int maxforkoff; /* upper limit on valid forkoff locations */
153 int dsize;
153 xfs_mount_t *mp = dp->i_mount; 154 xfs_mount_t *mp = dp->i_mount;
154 155
155 offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ 156 offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
@@ -169,8 +170,43 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
169 return 0; 170 return 0;
170 } 171 }
171 172
172 /* data fork btree root can have at least this many key/ptr pairs */ 173 dsize = dp->i_df.if_bytes;
173 minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); 174
175 switch (dp->i_d.di_format) {
176 case XFS_DINODE_FMT_EXTENTS:
177 /*
178 * If there is no attr fork and the data fork is extents,
179 * determine if creating the default attr fork will result
180 * in the extents form migrating to btree. If so, the
181 * minimum offset only needs to be the space required for
182 * the btree root.
183 */
184 if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset)
185 dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
186 break;
187
188 case XFS_DINODE_FMT_BTREE:
189 /*
190 * If have data btree then keep forkoff if we have one,
191 * otherwise we are adding a new attr, so then we set
192 * minforkoff to where the btree root can finish so we have
193 * plenty of room for attrs
194 */
195 if (dp->i_d.di_forkoff) {
196 if (offset < dp->i_d.di_forkoff)
197 return 0;
198 else
199 return dp->i_d.di_forkoff;
200 } else
201 dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);
202 break;
203 }
204
205 /*
206 * A data fork btree root must have space for at least
207 * MINDBTPTRS key/ptr pairs if the data fork is small or empty.
208 */
209 minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
174 minforkoff = roundup(minforkoff, 8) >> 3; 210 minforkoff = roundup(minforkoff, 8) >> 3;
175 211
176 /* attr fork btree root can have at least this many key/ptr pairs */ 212 /* attr fork btree root can have at least this many key/ptr pairs */
@@ -336,7 +372,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
336 */ 372 */
337 totsize -= size; 373 totsize -= size;
338 if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname && 374 if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname &&
339 (mp->m_flags & XFS_MOUNT_ATTR2)) { 375 (mp->m_flags & XFS_MOUNT_ATTR2) &&
376 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) {
340 /* 377 /*
341 * Last attribute now removed, revert to original 378 * Last attribute now removed, revert to original
342 * inode format making all literal area available 379 * inode format making all literal area available
@@ -355,7 +392,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
355 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); 392 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
356 ASSERT(dp->i_d.di_forkoff); 393 ASSERT(dp->i_d.di_forkoff);
357 ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname || 394 ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname ||
358 !(mp->m_flags & XFS_MOUNT_ATTR2)); 395 !(mp->m_flags & XFS_MOUNT_ATTR2) ||
396 dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
359 dp->i_afp->if_ext_max = 397 dp->i_afp->if_ext_max =
360 XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); 398 XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
361 dp->i_df.if_ext_max = 399 dp->i_df.if_ext_max =
@@ -748,6 +786,7 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
748 + be16_to_cpu(name_loc->valuelen); 786 + be16_to_cpu(name_loc->valuelen);
749 } 787 }
750 if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && 788 if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
789 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
751 (bytes == sizeof(struct xfs_attr_sf_hdr))) 790 (bytes == sizeof(struct xfs_attr_sf_hdr)))
752 return(-1); 791 return(-1);
753 return(xfs_attr_shortform_bytesfit(dp, bytes)); 792 return(xfs_attr_shortform_bytesfit(dp, bytes));
@@ -786,6 +825,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
786 825
787 if (forkoff == -1) { 826 if (forkoff == -1) {
788 ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); 827 ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
828 ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
789 829
790 /* 830 /*
791 * Last attribute was removed, revert to original 831 * Last attribute was removed, revert to original