diff options
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 54 |
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 | ||
97 | STATIC inline attrnames_t * | 97 | STATIC_INLINE attrnames_t * |
98 | xfs_attr_flags_namesp(int flags) | 98 | xfs_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 | */ |
108 | STATIC inline int | 108 | STATIC_INLINE int |
109 | xfs_attr_namesp_match(int arg_flags, int ondisk_flags) | 109 | xfs_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 | */ |
119 | STATIC inline int | 119 | STATIC_INLINE int |
120 | xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags) | 120 | xfs_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 |