diff options
-rw-r--r-- | fs/xfs/xfs_attr.c | 61 | ||||
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 177 | ||||
-rw-r--r-- | fs/xfs/xfs_attr_leaf.h | 14 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap.c | 84 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap.h | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_dir.c | 24 | ||||
-rw-r--r-- | fs/xfs/xfs_fs.h | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_fsops.c | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_macros.c | 17 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 7 | ||||
-rw-r--r-- | fs/xfs/xfs_sb.h | 44 | ||||
-rw-r--r-- | fs/xfs/xfs_types.h | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_vfsops.c | 18 |
13 files changed, 354 insertions, 114 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index ce9f673f2b4c..c2939b8f8d24 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -200,7 +200,7 @@ xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp, | |||
200 | return(error); | 200 | return(error); |
201 | } | 201 | } |
202 | 202 | ||
203 | int | 203 | STATIC int |
204 | xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, | 204 | xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, |
205 | char *value, int valuelen, int flags) | 205 | char *value, int valuelen, int flags) |
206 | { | 206 | { |
@@ -220,12 +220,18 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, | |||
220 | return (error); | 220 | return (error); |
221 | 221 | ||
222 | /* | 222 | /* |
223 | * Determine space new attribute will use, and if it would be | ||
224 | * "local" or "remote" (note: local != inline). | ||
225 | */ | ||
226 | size = xfs_attr_leaf_newentsize(namelen, valuelen, | ||
227 | mp->m_sb.sb_blocksize, &local); | ||
228 | |||
229 | /* | ||
223 | * If the inode doesn't have an attribute fork, add one. | 230 | * If the inode doesn't have an attribute fork, add one. |
224 | * (inode must not be locked when we call this routine) | 231 | * (inode must not be locked when we call this routine) |
225 | */ | 232 | */ |
226 | if (XFS_IFORK_Q(dp) == 0) { | 233 | if (XFS_IFORK_Q(dp) == 0) { |
227 | error = xfs_bmap_add_attrfork(dp, rsvd); | 234 | if ((error = xfs_bmap_add_attrfork(dp, size, rsvd))) |
228 | if (error) | ||
229 | return(error); | 235 | return(error); |
230 | } | 236 | } |
231 | 237 | ||
@@ -243,14 +249,9 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, | |||
243 | args.firstblock = &firstblock; | 249 | args.firstblock = &firstblock; |
244 | args.flist = &flist; | 250 | args.flist = &flist; |
245 | args.whichfork = XFS_ATTR_FORK; | 251 | args.whichfork = XFS_ATTR_FORK; |
252 | args.addname = 1; | ||
246 | args.oknoent = 1; | 253 | args.oknoent = 1; |
247 | 254 | ||
248 | /* Determine space new attribute will use, and if it will be inline | ||
249 | * or out of line. | ||
250 | */ | ||
251 | size = xfs_attr_leaf_newentsize(namelen, valuelen, | ||
252 | mp->m_sb.sb_blocksize, &local); | ||
253 | |||
254 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); | 255 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); |
255 | if (local) { | 256 | if (local) { |
256 | if (size > (mp->m_sb.sb_blocksize >> 1)) { | 257 | if (size > (mp->m_sb.sb_blocksize >> 1)) { |
@@ -322,7 +323,7 @@ xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, | |||
322 | * Build initial attribute list (if required). | 323 | * Build initial attribute list (if required). |
323 | */ | 324 | */ |
324 | if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) | 325 | if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) |
325 | (void)xfs_attr_shortform_create(&args); | 326 | xfs_attr_shortform_create(&args); |
326 | 327 | ||
327 | /* | 328 | /* |
328 | * Try to add the attr to the attribute list in | 329 | * Try to add the attr to the attribute list in |
@@ -467,7 +468,7 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags, | |||
467 | * Generic handler routine to remove a name from an attribute list. | 468 | * Generic handler routine to remove a name from an attribute list. |
468 | * Transitions attribute list from Btree to shortform as necessary. | 469 | * Transitions attribute list from Btree to shortform as necessary. |
469 | */ | 470 | */ |
470 | int | 471 | STATIC int |
471 | xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags) | 472 | xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags) |
472 | { | 473 | { |
473 | xfs_da_args_t args; | 474 | xfs_da_args_t args; |
@@ -523,7 +524,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags) | |||
523 | XFS_ATTRRM_LOG_COUNT))) { | 524 | XFS_ATTRRM_LOG_COUNT))) { |
524 | xfs_trans_cancel(args.trans, 0); | 525 | xfs_trans_cancel(args.trans, 0); |
525 | return(error); | 526 | return(error); |
526 | |||
527 | } | 527 | } |
528 | 528 | ||
529 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 529 | xfs_ilock(dp, XFS_ILOCK_EXCL); |
@@ -822,7 +822,7 @@ out: | |||
822 | STATIC int | 822 | STATIC int |
823 | xfs_attr_shortform_addname(xfs_da_args_t *args) | 823 | xfs_attr_shortform_addname(xfs_da_args_t *args) |
824 | { | 824 | { |
825 | int newsize, retval; | 825 | int newsize, forkoff, retval; |
826 | 826 | ||
827 | retval = xfs_attr_shortform_lookup(args); | 827 | retval = xfs_attr_shortform_lookup(args); |
828 | if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { | 828 | if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { |
@@ -834,16 +834,18 @@ xfs_attr_shortform_addname(xfs_da_args_t *args) | |||
834 | ASSERT(retval == 0); | 834 | ASSERT(retval == 0); |
835 | } | 835 | } |
836 | 836 | ||
837 | if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX || | ||
838 | args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX) | ||
839 | return(XFS_ERROR(ENOSPC)); | ||
840 | |||
837 | newsize = XFS_ATTR_SF_TOTSIZE(args->dp); | 841 | newsize = XFS_ATTR_SF_TOTSIZE(args->dp); |
838 | newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); | 842 | newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); |
839 | if ((newsize <= XFS_IFORK_ASIZE(args->dp)) && | 843 | |
840 | (args->namelen < XFS_ATTR_SF_ENTSIZE_MAX) && | 844 | forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize); |
841 | (args->valuelen < XFS_ATTR_SF_ENTSIZE_MAX)) { | 845 | if (!forkoff) |
842 | retval = xfs_attr_shortform_add(args); | ||
843 | ASSERT(retval == 0); | ||
844 | } else { | ||
845 | return(XFS_ERROR(ENOSPC)); | 846 | return(XFS_ERROR(ENOSPC)); |
846 | } | 847 | |
848 | xfs_attr_shortform_add(args, forkoff); | ||
847 | return(0); | 849 | return(0); |
848 | } | 850 | } |
849 | 851 | ||
@@ -863,7 +865,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
863 | { | 865 | { |
864 | xfs_inode_t *dp; | 866 | xfs_inode_t *dp; |
865 | xfs_dabuf_t *bp; | 867 | xfs_dabuf_t *bp; |
866 | int retval, error, committed; | 868 | int retval, error, committed, forkoff; |
867 | 869 | ||
868 | /* | 870 | /* |
869 | * Read the (only) block in the attribute list in. | 871 | * Read the (only) block in the attribute list in. |
@@ -1006,9 +1008,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
1006 | /* | 1008 | /* |
1007 | * If the result is small enough, shrink it all into the inode. | 1009 | * If the result is small enough, shrink it all into the inode. |
1008 | */ | 1010 | */ |
1009 | if (xfs_attr_shortform_allfit(bp, dp)) { | 1011 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { |
1010 | XFS_BMAP_INIT(args->flist, args->firstblock); | 1012 | XFS_BMAP_INIT(args->flist, args->firstblock); |
1011 | error = xfs_attr_leaf_to_shortform(bp, args); | 1013 | error = xfs_attr_leaf_to_shortform(bp, args, forkoff); |
1012 | /* bp is gone due to xfs_da_shrink_inode */ | 1014 | /* bp is gone due to xfs_da_shrink_inode */ |
1013 | if (!error) { | 1015 | if (!error) { |
1014 | error = xfs_bmap_finish(&args->trans, | 1016 | error = xfs_bmap_finish(&args->trans, |
@@ -1060,8 +1062,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1060 | { | 1062 | { |
1061 | xfs_inode_t *dp; | 1063 | xfs_inode_t *dp; |
1062 | xfs_dabuf_t *bp; | 1064 | xfs_dabuf_t *bp; |
1063 | int committed; | 1065 | int error, committed, forkoff; |
1064 | int error; | ||
1065 | 1066 | ||
1066 | /* | 1067 | /* |
1067 | * Remove the attribute. | 1068 | * Remove the attribute. |
@@ -1086,9 +1087,9 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1086 | /* | 1087 | /* |
1087 | * If the result is small enough, shrink it all into the inode. | 1088 | * If the result is small enough, shrink it all into the inode. |
1088 | */ | 1089 | */ |
1089 | if (xfs_attr_shortform_allfit(bp, dp)) { | 1090 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { |
1090 | XFS_BMAP_INIT(args->flist, args->firstblock); | 1091 | XFS_BMAP_INIT(args->flist, args->firstblock); |
1091 | error = xfs_attr_leaf_to_shortform(bp, args); | 1092 | error = xfs_attr_leaf_to_shortform(bp, args, forkoff); |
1092 | /* bp is gone due to xfs_da_shrink_inode */ | 1093 | /* bp is gone due to xfs_da_shrink_inode */ |
1093 | if (!error) { | 1094 | if (!error) { |
1094 | error = xfs_bmap_finish(&args->trans, args->flist, | 1095 | error = xfs_bmap_finish(&args->trans, args->flist, |
@@ -1459,7 +1460,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1459 | xfs_da_state_blk_t *blk; | 1460 | xfs_da_state_blk_t *blk; |
1460 | xfs_inode_t *dp; | 1461 | xfs_inode_t *dp; |
1461 | xfs_dabuf_t *bp; | 1462 | xfs_dabuf_t *bp; |
1462 | int retval, error, committed; | 1463 | int retval, error, committed, forkoff; |
1463 | 1464 | ||
1464 | /* | 1465 | /* |
1465 | * Tie a string around our finger to remind us where we are. | 1466 | * Tie a string around our finger to remind us where we are. |
@@ -1580,9 +1581,9 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1580 | bp->data)->hdr.info.magic, ARCH_CONVERT) | 1581 | bp->data)->hdr.info.magic, ARCH_CONVERT) |
1581 | == XFS_ATTR_LEAF_MAGIC); | 1582 | == XFS_ATTR_LEAF_MAGIC); |
1582 | 1583 | ||
1583 | if (xfs_attr_shortform_allfit(bp, dp)) { | 1584 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { |
1584 | XFS_BMAP_INIT(args->flist, args->firstblock); | 1585 | XFS_BMAP_INIT(args->flist, args->firstblock); |
1585 | error = xfs_attr_leaf_to_shortform(bp, args); | 1586 | error = xfs_attr_leaf_to_shortform(bp, args, forkoff); |
1586 | /* bp is gone due to xfs_da_shrink_inode */ | 1587 | /* bp is gone due to xfs_da_shrink_inode */ |
1587 | if (!error) { | 1588 | if (!error) { |
1588 | error = xfs_bmap_finish(&args->trans, | 1589 | error = xfs_bmap_finish(&args->trans, |
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index e13eaa521436..50598b121683 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -118,13 +118,82 @@ STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context, | |||
118 | 118 | ||
119 | 119 | ||
120 | /*======================================================================== | 120 | /*======================================================================== |
121 | * External routines when dirsize < XFS_LITINO(mp). | 121 | * External routines when attribute fork size < XFS_LITINO(mp). |
122 | *========================================================================*/ | 122 | *========================================================================*/ |
123 | 123 | ||
124 | /* | 124 | /* |
125 | * Create the initial contents of a shortform attribute list. | 125 | * Query whether the requested number of additional bytes of extended |
126 | * attribute space will be able to fit inline. | ||
127 | * Returns zero if not, else the di_forkoff fork offset to be used in the | ||
128 | * literal area for attribute data once the new bytes have been added. | ||
129 | * | ||
130 | * di_forkoff must be 8 byte aligned, hence is stored as a >>3 value; | ||
131 | * special case for dev/uuid inodes, they have fixed size data forks. | ||
126 | */ | 132 | */ |
127 | int | 133 | int |
134 | xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | ||
135 | { | ||
136 | int offset; | ||
137 | int minforkoff; /* lower limit on valid forkoff locations */ | ||
138 | int maxforkoff; /* upper limit on valid forkoff locations */ | ||
139 | xfs_mount_t *mp = dp->i_mount; | ||
140 | |||
141 | if (unlikely(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) { | ||
142 | if (bytes <= XFS_IFORK_ASIZE(dp)) | ||
143 | return mp->m_attroffset >> 3; | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ | ||
148 | |||
149 | switch (dp->i_d.di_format) { | ||
150 | case XFS_DINODE_FMT_DEV: | ||
151 | minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; | ||
152 | return (offset >= minforkoff) ? minforkoff : 0; | ||
153 | case XFS_DINODE_FMT_UUID: | ||
154 | minforkoff = roundup(sizeof(uuid_t), 8) >> 3; | ||
155 | return (offset >= minforkoff) ? minforkoff : 0; | ||
156 | } | ||
157 | |||
158 | /* data fork btree root can have at least this many key/ptr pairs */ | ||
159 | minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); | ||
160 | minforkoff = roundup(minforkoff, 8) >> 3; | ||
161 | |||
162 | /* attr fork btree root can have at least this many key/ptr pairs */ | ||
163 | maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); | ||
164 | maxforkoff = maxforkoff >> 3; /* rounded down */ | ||
165 | |||
166 | if (offset >= minforkoff && offset < maxforkoff) | ||
167 | return offset; | ||
168 | if (offset >= maxforkoff) | ||
169 | return maxforkoff; | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Switch on the ATTR2 superblock bit (implies also FEATURES2) | ||
175 | */ | ||
176 | STATIC void | ||
177 | xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp) | ||
178 | { | ||
179 | unsigned long s; | ||
180 | |||
181 | if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR) && | ||
182 | !(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) { | ||
183 | s = XFS_SB_LOCK(mp); | ||
184 | if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) { | ||
185 | XFS_SB_VERSION_ADDATTR2(&mp->m_sb); | ||
186 | XFS_SB_UNLOCK(mp, s); | ||
187 | xfs_mod_sb(tp, XFS_SB_VERSIONNUM | XFS_SB_FEATURES2); | ||
188 | } else | ||
189 | XFS_SB_UNLOCK(mp, s); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * Create the initial contents of a shortform attribute list. | ||
195 | */ | ||
196 | void | ||
128 | xfs_attr_shortform_create(xfs_da_args_t *args) | 197 | xfs_attr_shortform_create(xfs_da_args_t *args) |
129 | { | 198 | { |
130 | xfs_attr_sf_hdr_t *hdr; | 199 | xfs_attr_sf_hdr_t *hdr; |
@@ -148,29 +217,37 @@ xfs_attr_shortform_create(xfs_da_args_t *args) | |||
148 | hdr->count = 0; | 217 | hdr->count = 0; |
149 | INT_SET(hdr->totsize, ARCH_CONVERT, sizeof(*hdr)); | 218 | INT_SET(hdr->totsize, ARCH_CONVERT, sizeof(*hdr)); |
150 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); | 219 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); |
151 | return(0); | ||
152 | } | 220 | } |
153 | 221 | ||
154 | /* | 222 | /* |
155 | * Add a name/value pair to the shortform attribute list. | 223 | * Add a name/value pair to the shortform attribute list. |
156 | * Overflow from the inode has already been checked for. | 224 | * Overflow from the inode has already been checked for. |
157 | */ | 225 | */ |
158 | int | 226 | void |
159 | xfs_attr_shortform_add(xfs_da_args_t *args) | 227 | xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) |
160 | { | 228 | { |
161 | xfs_attr_shortform_t *sf; | 229 | xfs_attr_shortform_t *sf; |
162 | xfs_attr_sf_entry_t *sfe; | 230 | xfs_attr_sf_entry_t *sfe; |
163 | int i, offset, size; | 231 | int i, offset, size; |
232 | xfs_mount_t *mp; | ||
164 | xfs_inode_t *dp; | 233 | xfs_inode_t *dp; |
165 | xfs_ifork_t *ifp; | 234 | xfs_ifork_t *ifp; |
166 | 235 | ||
167 | dp = args->dp; | 236 | dp = args->dp; |
237 | mp = dp->i_mount; | ||
238 | dp->i_d.di_forkoff = forkoff; | ||
239 | dp->i_df.if_ext_max = | ||
240 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
241 | dp->i_afp->if_ext_max = | ||
242 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
243 | |||
168 | ifp = dp->i_afp; | 244 | ifp = dp->i_afp; |
169 | ASSERT(ifp->if_flags & XFS_IFINLINE); | 245 | ASSERT(ifp->if_flags & XFS_IFINLINE); |
170 | sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; | 246 | sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; |
171 | sfe = &sf->list[0]; | 247 | sfe = &sf->list[0]; |
172 | for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); | 248 | for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); |
173 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { | 249 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { |
250 | #ifdef DEBUG | ||
174 | if (sfe->namelen != args->namelen) | 251 | if (sfe->namelen != args->namelen) |
175 | continue; | 252 | continue; |
176 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) | 253 | if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
@@ -181,7 +258,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args) | |||
181 | if (((args->flags & ATTR_ROOT) != 0) != | 258 | if (((args->flags & ATTR_ROOT) != 0) != |
182 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) | 259 | ((sfe->flags & XFS_ATTR_ROOT) != 0)) |
183 | continue; | 260 | continue; |
184 | return(XFS_ERROR(EEXIST)); | 261 | ASSERT(0); |
262 | #endif | ||
185 | } | 263 | } |
186 | 264 | ||
187 | offset = (char *)sfe - (char *)sf; | 265 | offset = (char *)sfe - (char *)sf; |
@@ -200,11 +278,11 @@ xfs_attr_shortform_add(xfs_da_args_t *args) | |||
200 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, size); | 278 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, size); |
201 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); | 279 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); |
202 | 280 | ||
203 | return(0); | 281 | xfs_sbversion_add_attr2(mp, args->trans); |
204 | } | 282 | } |
205 | 283 | ||
206 | /* | 284 | /* |
207 | * Remove a name from the shortform attribute list structure. | 285 | * Remove an attribute from the shortform attribute list structure. |
208 | */ | 286 | */ |
209 | int | 287 | int |
210 | xfs_attr_shortform_remove(xfs_da_args_t *args) | 288 | xfs_attr_shortform_remove(xfs_da_args_t *args) |
@@ -212,17 +290,16 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
212 | xfs_attr_shortform_t *sf; | 290 | xfs_attr_shortform_t *sf; |
213 | xfs_attr_sf_entry_t *sfe; | 291 | xfs_attr_sf_entry_t *sfe; |
214 | int base, size=0, end, totsize, i; | 292 | int base, size=0, end, totsize, i; |
293 | xfs_mount_t *mp; | ||
215 | xfs_inode_t *dp; | 294 | xfs_inode_t *dp; |
216 | 295 | ||
217 | /* | ||
218 | * Remove the attribute. | ||
219 | */ | ||
220 | dp = args->dp; | 296 | dp = args->dp; |
297 | mp = dp->i_mount; | ||
221 | base = sizeof(xfs_attr_sf_hdr_t); | 298 | base = sizeof(xfs_attr_sf_hdr_t); |
222 | sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; | 299 | sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; |
223 | sfe = &sf->list[0]; | 300 | sfe = &sf->list[0]; |
224 | for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); | 301 | end = INT_GET(sf->hdr.count, ARCH_CONVERT); |
225 | sfe = XFS_ATTR_SF_NEXTENTRY(sfe), | 302 | for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), |
226 | base += size, i++) { | 303 | base += size, i++) { |
227 | size = XFS_ATTR_SF_ENTSIZE(sfe); | 304 | size = XFS_ATTR_SF_ENTSIZE(sfe); |
228 | if (sfe->namelen != args->namelen) | 305 | if (sfe->namelen != args->namelen) |
@@ -237,19 +314,51 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
237 | continue; | 314 | continue; |
238 | break; | 315 | break; |
239 | } | 316 | } |
240 | if (i == INT_GET(sf->hdr.count, ARCH_CONVERT)) | 317 | if (i == end) |
241 | return(XFS_ERROR(ENOATTR)); | 318 | return(XFS_ERROR(ENOATTR)); |
242 | 319 | ||
320 | /* | ||
321 | * Fix up the attribute fork data, covering the hole | ||
322 | */ | ||
243 | end = base + size; | 323 | end = base + size; |
244 | totsize = INT_GET(sf->hdr.totsize, ARCH_CONVERT); | 324 | totsize = INT_GET(sf->hdr.totsize, ARCH_CONVERT); |
245 | if (end != totsize) { | 325 | if (end != totsize) |
246 | memmove(&((char *)sf)[base], &((char *)sf)[end], | 326 | memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end); |
247 | totsize - end); | ||
248 | } | ||
249 | INT_MOD(sf->hdr.count, ARCH_CONVERT, -1); | 327 | INT_MOD(sf->hdr.count, ARCH_CONVERT, -1); |
250 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, -size); | 328 | INT_MOD(sf->hdr.totsize, ARCH_CONVERT, -size); |
251 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); | 329 | |
252 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); | 330 | /* |
331 | * Fix up the start offset of the attribute fork | ||
332 | */ | ||
333 | totsize -= size; | ||
334 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname) { | ||
335 | /* | ||
336 | * Last attribute now removed, revert to original | ||
337 | * inode format making all literal area available | ||
338 | * to the data fork once more. | ||
339 | */ | ||
340 | xfs_idestroy_fork(dp, XFS_ATTR_FORK); | ||
341 | dp->i_d.di_forkoff = 0; | ||
342 | dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | ||
343 | ASSERT(dp->i_d.di_anextents == 0); | ||
344 | ASSERT(dp->i_afp == NULL); | ||
345 | dp->i_df.if_ext_max = | ||
346 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
347 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); | ||
348 | } else { | ||
349 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); | ||
350 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); | ||
351 | ASSERT(dp->i_d.di_forkoff); | ||
352 | ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname); | ||
353 | dp->i_afp->if_ext_max = | ||
354 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
355 | dp->i_df.if_ext_max = | ||
356 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
357 | xfs_trans_log_inode(args->trans, dp, | ||
358 | XFS_ILOG_CORE | XFS_ILOG_ADATA); | ||
359 | } | ||
360 | |||
361 | xfs_sbversion_add_attr2(mp, args->trans); | ||
253 | 362 | ||
254 | return(0); | 363 | return(0); |
255 | } | 364 | } |
@@ -649,14 +758,16 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) | |||
649 | + name_loc->namelen | 758 | + name_loc->namelen |
650 | + INT_GET(name_loc->valuelen, ARCH_CONVERT); | 759 | + INT_GET(name_loc->valuelen, ARCH_CONVERT); |
651 | } | 760 | } |
652 | return( bytes < XFS_IFORK_ASIZE(dp) ); | 761 | if (bytes == sizeof(struct xfs_attr_sf_hdr)) |
762 | return(-1); | ||
763 | return(xfs_attr_shortform_bytesfit(dp, bytes)); | ||
653 | } | 764 | } |
654 | 765 | ||
655 | /* | 766 | /* |
656 | * Convert a leaf attribute list to shortform attribute list | 767 | * Convert a leaf attribute list to shortform attribute list |
657 | */ | 768 | */ |
658 | int | 769 | int |
659 | xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) | 770 | xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) |
660 | { | 771 | { |
661 | xfs_attr_leafblock_t *leaf; | 772 | xfs_attr_leafblock_t *leaf; |
662 | xfs_attr_leaf_entry_t *entry; | 773 | xfs_attr_leaf_entry_t *entry; |
@@ -683,9 +794,25 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
683 | error = xfs_da_shrink_inode(args, 0, bp); | 794 | error = xfs_da_shrink_inode(args, 0, bp); |
684 | if (error) | 795 | if (error) |
685 | goto out; | 796 | goto out; |
686 | error = xfs_attr_shortform_create(args); | 797 | |
687 | if (error) | 798 | if (forkoff == -1) { |
799 | /* | ||
800 | * Last attribute was removed, revert to original | ||
801 | * inode format making all literal area available | ||
802 | * to the data fork once more. | ||
803 | */ | ||
804 | xfs_idestroy_fork(dp, XFS_ATTR_FORK); | ||
805 | dp->i_d.di_forkoff = 0; | ||
806 | dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | ||
807 | ASSERT(dp->i_d.di_anextents == 0); | ||
808 | ASSERT(dp->i_afp == NULL); | ||
809 | dp->i_df.if_ext_max = | ||
810 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
811 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); | ||
688 | goto out; | 812 | goto out; |
813 | } | ||
814 | |||
815 | xfs_attr_shortform_create(args); | ||
689 | 816 | ||
690 | /* | 817 | /* |
691 | * Copy the attributes | 818 | * Copy the attributes |
@@ -713,7 +840,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) | |||
713 | nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); | 840 | nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); |
714 | nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : | 841 | nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : |
715 | ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); | 842 | ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); |
716 | xfs_attr_shortform_add(&nargs); | 843 | xfs_attr_shortform_add(&nargs, forkoff); |
717 | } | 844 | } |
718 | error = 0; | 845 | error = 0; |
719 | 846 | ||
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index b99f0491061c..326802f80d54 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h | |||
@@ -238,23 +238,25 @@ typedef struct xfs_attr_inactive_list { | |||
238 | *========================================================================*/ | 238 | *========================================================================*/ |
239 | 239 | ||
240 | /* | 240 | /* |
241 | * Internal routines when dirsize < XFS_LITINO(mp). | 241 | * Internal routines when attribute fork size < XFS_LITINO(mp). |
242 | */ | 242 | */ |
243 | int xfs_attr_shortform_create(struct xfs_da_args *args); | 243 | void xfs_attr_shortform_create(struct xfs_da_args *args); |
244 | int xfs_attr_shortform_add(struct xfs_da_args *add); | 244 | void xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff); |
245 | int xfs_attr_shortform_lookup(struct xfs_da_args *args); | 245 | int xfs_attr_shortform_lookup(struct xfs_da_args *args); |
246 | int xfs_attr_shortform_getvalue(struct xfs_da_args *args); | 246 | int xfs_attr_shortform_getvalue(struct xfs_da_args *args); |
247 | int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); | 247 | int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); |
248 | int xfs_attr_shortform_remove(struct xfs_da_args *remove); | 248 | int xfs_attr_shortform_remove(struct xfs_da_args *args); |
249 | int xfs_attr_shortform_list(struct xfs_attr_list_context *context); | 249 | int xfs_attr_shortform_list(struct xfs_attr_list_context *context); |
250 | int xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp); | 250 | int xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp); |
251 | int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); | ||
252 | |||
251 | 253 | ||
252 | /* | 254 | /* |
253 | * Internal routines when dirsize == XFS_LBSIZE(mp). | 255 | * Internal routines when attribute fork size == XFS_LBSIZE(mp). |
254 | */ | 256 | */ |
255 | int xfs_attr_leaf_to_node(struct xfs_da_args *args); | 257 | int xfs_attr_leaf_to_node(struct xfs_da_args *args); |
256 | int xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp, | 258 | int xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp, |
257 | struct xfs_da_args *args); | 259 | struct xfs_da_args *args, int forkoff); |
258 | int xfs_attr_leaf_clearflag(struct xfs_da_args *args); | 260 | int xfs_attr_leaf_clearflag(struct xfs_da_args *args); |
259 | int xfs_attr_leaf_setflag(struct xfs_da_args *args); | 261 | int xfs_attr_leaf_setflag(struct xfs_da_args *args); |
260 | int xfs_attr_leaf_flipflags(xfs_da_args_t *args); | 262 | int xfs_attr_leaf_flipflags(xfs_da_args_t *args); |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 26645d267f1b..3e013530d00d 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -62,6 +62,7 @@ | |||
62 | #include "xfs_error.h" | 62 | #include "xfs_error.h" |
63 | #include "xfs_da_btree.h" | 63 | #include "xfs_da_btree.h" |
64 | #include "xfs_dir_leaf.h" | 64 | #include "xfs_dir_leaf.h" |
65 | #include "xfs_attr_leaf.h" | ||
65 | #include "xfs_bit.h" | 66 | #include "xfs_bit.h" |
66 | #include "xfs_rw.h" | 67 | #include "xfs_rw.h" |
67 | #include "xfs_quota.h" | 68 | #include "xfs_quota.h" |
@@ -3337,6 +3338,29 @@ xfs_bmap_insert_exlist( | |||
3337 | } | 3338 | } |
3338 | 3339 | ||
3339 | /* | 3340 | /* |
3341 | * Helper routine to reset inode di_forkoff field when switching | ||
3342 | * attribute fork from local to extent format - we reset it where | ||
3343 | * possible to make space available for inline data fork extents. | ||
3344 | */ | ||
3345 | STATIC void | ||
3346 | xfs_bmap_forkoff_reset( | ||
3347 | xfs_mount_t *mp, | ||
3348 | xfs_inode_t *ip, | ||
3349 | int whichfork) | ||
3350 | { | ||
3351 | if (whichfork == XFS_ATTR_FORK && | ||
3352 | (ip->i_d.di_format != XFS_DINODE_FMT_DEV) && | ||
3353 | (ip->i_d.di_format != XFS_DINODE_FMT_UUID) && | ||
3354 | ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) { | ||
3355 | ip->i_d.di_forkoff = mp->m_attroffset >> 3; | ||
3356 | ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / | ||
3357 | (uint)sizeof(xfs_bmbt_rec_t); | ||
3358 | ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) / | ||
3359 | (uint)sizeof(xfs_bmbt_rec_t); | ||
3360 | } | ||
3361 | } | ||
3362 | |||
3363 | /* | ||
3340 | * Convert a local file to an extents file. | 3364 | * Convert a local file to an extents file. |
3341 | * This code is out of bounds for data forks of regular files, | 3365 | * This code is out of bounds for data forks of regular files, |
3342 | * since the file data needs to get logged so things will stay consistent. | 3366 | * since the file data needs to get logged so things will stay consistent. |
@@ -3403,6 +3427,7 @@ xfs_bmap_local_to_extents( | |||
3403 | memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data, | 3427 | memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data, |
3404 | ifp->if_bytes); | 3428 | ifp->if_bytes); |
3405 | xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); | 3429 | xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); |
3430 | xfs_bmap_forkoff_reset(args.mp, ip, whichfork); | ||
3406 | xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); | 3431 | xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); |
3407 | xfs_iext_realloc(ip, 1, whichfork); | 3432 | xfs_iext_realloc(ip, 1, whichfork); |
3408 | ep = ifp->if_u1.if_extents; | 3433 | ep = ifp->if_u1.if_extents; |
@@ -3413,8 +3438,10 @@ xfs_bmap_local_to_extents( | |||
3413 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip, | 3438 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip, |
3414 | XFS_TRANS_DQ_BCOUNT, 1L); | 3439 | XFS_TRANS_DQ_BCOUNT, 1L); |
3415 | flags |= XFS_ILOG_FEXT(whichfork); | 3440 | flags |= XFS_ILOG_FEXT(whichfork); |
3416 | } else | 3441 | } else { |
3417 | ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); | 3442 | ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); |
3443 | xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork); | ||
3444 | } | ||
3418 | ifp->if_flags &= ~XFS_IFINLINE; | 3445 | ifp->if_flags &= ~XFS_IFINLINE; |
3419 | ifp->if_flags |= XFS_IFEXTENTS; | 3446 | ifp->if_flags |= XFS_IFEXTENTS; |
3420 | XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); | 3447 | XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); |
@@ -3796,22 +3823,24 @@ xfs_bunmap_trace( | |||
3796 | int /* error code */ | 3823 | int /* error code */ |
3797 | xfs_bmap_add_attrfork( | 3824 | xfs_bmap_add_attrfork( |
3798 | xfs_inode_t *ip, /* incore inode pointer */ | 3825 | xfs_inode_t *ip, /* incore inode pointer */ |
3799 | int rsvd) /* OK to allocated reserved blocks in trans */ | 3826 | int size, /* space new attribute needs */ |
3827 | int rsvd) /* xact may use reserved blks */ | ||
3800 | { | 3828 | { |
3801 | int blks; /* space reservation */ | ||
3802 | int committed; /* xaction was committed */ | ||
3803 | int error; /* error return value */ | ||
3804 | xfs_fsblock_t firstblock; /* 1st block/ag allocated */ | 3829 | xfs_fsblock_t firstblock; /* 1st block/ag allocated */ |
3805 | xfs_bmap_free_t flist; /* freed extent list */ | 3830 | xfs_bmap_free_t flist; /* freed extent list */ |
3806 | int logflags; /* logging flags */ | ||
3807 | xfs_mount_t *mp; /* mount structure */ | 3831 | xfs_mount_t *mp; /* mount structure */ |
3808 | unsigned long s; /* spinlock spl value */ | ||
3809 | xfs_trans_t *tp; /* transaction pointer */ | 3832 | xfs_trans_t *tp; /* transaction pointer */ |
3833 | unsigned long s; /* spinlock spl value */ | ||
3834 | int blks; /* space reservation */ | ||
3835 | int version = 1; /* superblock attr version */ | ||
3836 | int committed; /* xaction was committed */ | ||
3837 | int logflags; /* logging flags */ | ||
3838 | int error; /* error return value */ | ||
3810 | 3839 | ||
3840 | ASSERT(XFS_IFORK_Q(ip) == 0); | ||
3811 | ASSERT(ip->i_df.if_ext_max == | 3841 | ASSERT(ip->i_df.if_ext_max == |
3812 | XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t)); | 3842 | XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t)); |
3813 | if (XFS_IFORK_Q(ip)) | 3843 | |
3814 | return 0; | ||
3815 | mp = ip->i_mount; | 3844 | mp = ip->i_mount; |
3816 | ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); | 3845 | ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); |
3817 | tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK); | 3846 | tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK); |
@@ -3853,7 +3882,11 @@ xfs_bmap_add_attrfork( | |||
3853 | case XFS_DINODE_FMT_LOCAL: | 3882 | case XFS_DINODE_FMT_LOCAL: |
3854 | case XFS_DINODE_FMT_EXTENTS: | 3883 | case XFS_DINODE_FMT_EXTENTS: |
3855 | case XFS_DINODE_FMT_BTREE: | 3884 | case XFS_DINODE_FMT_BTREE: |
3856 | ip->i_d.di_forkoff = mp->m_attroffset >> 3; | 3885 | ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size); |
3886 | if (!ip->i_d.di_forkoff) | ||
3887 | ip->i_d.di_forkoff = mp->m_attroffset >> 3; | ||
3888 | else if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) | ||
3889 | version = 2; | ||
3857 | break; | 3890 | break; |
3858 | default: | 3891 | default: |
3859 | ASSERT(0); | 3892 | ASSERT(0); |
@@ -3890,12 +3923,21 @@ xfs_bmap_add_attrfork( | |||
3890 | xfs_trans_log_inode(tp, ip, logflags); | 3923 | xfs_trans_log_inode(tp, ip, logflags); |
3891 | if (error) | 3924 | if (error) |
3892 | goto error2; | 3925 | goto error2; |
3893 | if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) { | 3926 | if (!XFS_SB_VERSION_HASATTR(&mp->m_sb) || |
3927 | (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2)) { | ||
3928 | logflags = 0; | ||
3894 | s = XFS_SB_LOCK(mp); | 3929 | s = XFS_SB_LOCK(mp); |
3895 | if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) { | 3930 | if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) { |
3896 | XFS_SB_VERSION_ADDATTR(&mp->m_sb); | 3931 | XFS_SB_VERSION_ADDATTR(&mp->m_sb); |
3932 | logflags |= XFS_SB_VERSIONNUM; | ||
3933 | } | ||
3934 | if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2) { | ||
3935 | XFS_SB_VERSION_ADDATTR2(&mp->m_sb); | ||
3936 | logflags |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2); | ||
3937 | } | ||
3938 | if (logflags) { | ||
3897 | XFS_SB_UNLOCK(mp, s); | 3939 | XFS_SB_UNLOCK(mp, s); |
3898 | xfs_mod_sb(tp, XFS_SB_VERSIONNUM); | 3940 | xfs_mod_sb(tp, logflags); |
3899 | } else | 3941 | } else |
3900 | XFS_SB_UNLOCK(mp, s); | 3942 | XFS_SB_UNLOCK(mp, s); |
3901 | } | 3943 | } |
@@ -3988,13 +4030,19 @@ xfs_bmap_compute_maxlevels( | |||
3988 | * (a signed 32-bit number, xfs_extnum_t), or by di_anextents | 4030 | * (a signed 32-bit number, xfs_extnum_t), or by di_anextents |
3989 | * (a signed 16-bit number, xfs_aextnum_t). | 4031 | * (a signed 16-bit number, xfs_aextnum_t). |
3990 | */ | 4032 | */ |
3991 | maxleafents = (whichfork == XFS_DATA_FORK) ? MAXEXTNUM : MAXAEXTNUM; | 4033 | if (whichfork == XFS_DATA_FORK) { |
4034 | maxleafents = MAXEXTNUM; | ||
4035 | sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ? | ||
4036 | mp->m_attroffset : XFS_BMDR_SPACE_CALC(MINDBTPTRS); | ||
4037 | } else { | ||
4038 | maxleafents = MAXAEXTNUM; | ||
4039 | sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ? | ||
4040 | mp->m_sb.sb_inodesize - mp->m_attroffset : | ||
4041 | XFS_BMDR_SPACE_CALC(MINABTPTRS); | ||
4042 | } | ||
4043 | maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0); | ||
3992 | minleafrecs = mp->m_bmap_dmnr[0]; | 4044 | minleafrecs = mp->m_bmap_dmnr[0]; |
3993 | minnoderecs = mp->m_bmap_dmnr[1]; | 4045 | minnoderecs = mp->m_bmap_dmnr[1]; |
3994 | sz = (whichfork == XFS_DATA_FORK) ? | ||
3995 | mp->m_attroffset : | ||
3996 | mp->m_sb.sb_inodesize - mp->m_attroffset; | ||
3997 | maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0); | ||
3998 | maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; | 4046 | maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; |
3999 | for (level = 1; maxblocks > 1; level++) { | 4047 | for (level = 1; maxblocks > 1; level++) { |
4000 | if (maxblocks <= maxrootrecs) | 4048 | if (maxblocks <= maxrootrecs) |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index e6d22ec9b2e4..e42d1b7777e1 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -156,7 +156,8 @@ xfs_bmap_trace_exlist( | |||
156 | int /* error code */ | 156 | int /* error code */ |
157 | xfs_bmap_add_attrfork( | 157 | xfs_bmap_add_attrfork( |
158 | struct xfs_inode *ip, /* incore inode pointer */ | 158 | struct xfs_inode *ip, /* incore inode pointer */ |
159 | int rsvd); /* flag for reserved block allocation */ | 159 | int size, /* space needed for new attribute */ |
160 | int rsvd); /* flag for reserved block allocation */ | ||
160 | 161 | ||
161 | /* | 162 | /* |
162 | * Add the extent to the list of extents to be free at transaction end. | 163 | * Add the extent to the list of extents to be free at transaction end. |
diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index ba30bc7682f2..53787f35338b 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -192,11 +192,23 @@ xfs_dir_mount(xfs_mount_t *mp) | |||
192 | uint shortcount, leafcount, count; | 192 | uint shortcount, leafcount, count; |
193 | 193 | ||
194 | mp->m_dirversion = 1; | 194 | mp->m_dirversion = 1; |
195 | shortcount = (mp->m_attroffset - (uint)sizeof(xfs_dir_sf_hdr_t)) / | 195 | if (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) { |
196 | (uint)sizeof(xfs_dir_sf_entry_t); | 196 | shortcount = (mp->m_attroffset - |
197 | leafcount = (XFS_LBSIZE(mp) - (uint)sizeof(xfs_dir_leaf_hdr_t)) / | 197 | (uint)sizeof(xfs_dir_sf_hdr_t)) / |
198 | ((uint)sizeof(xfs_dir_leaf_entry_t) + | 198 | (uint)sizeof(xfs_dir_sf_entry_t); |
199 | (uint)sizeof(xfs_dir_leaf_name_t)); | 199 | leafcount = (XFS_LBSIZE(mp) - |
200 | (uint)sizeof(xfs_dir_leaf_hdr_t)) / | ||
201 | ((uint)sizeof(xfs_dir_leaf_entry_t) + | ||
202 | (uint)sizeof(xfs_dir_leaf_name_t)); | ||
203 | } else { | ||
204 | shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) - | ||
205 | (uint)sizeof(xfs_dir_sf_hdr_t)) / | ||
206 | (uint)sizeof(xfs_dir_sf_entry_t); | ||
207 | leafcount = (XFS_LBSIZE(mp) - | ||
208 | (uint)sizeof(xfs_dir_leaf_hdr_t)) / | ||
209 | ((uint)sizeof(xfs_dir_leaf_entry_t) + | ||
210 | (uint)sizeof(xfs_dir_leaf_name_t)); | ||
211 | } | ||
200 | count = shortcount > leafcount ? shortcount : leafcount; | 212 | count = shortcount > leafcount ? shortcount : leafcount; |
201 | mp->m_dircook_elog = xfs_da_log2_roundup(count + 1); | 213 | mp->m_dircook_elog = xfs_da_log2_roundup(count + 1); |
202 | ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog); | 214 | ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog); |
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 095af0a5cff3..7bf2e92b8c0b 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 1995-2003 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 1995-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2.1 of the GNU Lesser General Public License | 5 | * under the terms of version 2.1 of the GNU Lesser General Public License |
@@ -251,6 +251,7 @@ typedef struct xfs_fsop_resblks { | |||
251 | #define XFS_FSOP_GEOM_FLAGS_DIRV2 0x0080 /* directory version 2 */ | 251 | #define XFS_FSOP_GEOM_FLAGS_DIRV2 0x0080 /* directory version 2 */ |
252 | #define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ | 252 | #define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ |
253 | #define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ | 253 | #define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ |
254 | #define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ | ||
254 | 255 | ||
255 | 256 | ||
256 | /* | 257 | /* |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index ca535d613190..67522f2bcee8 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -110,7 +110,9 @@ xfs_fs_geometry( | |||
110 | (XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ? | 110 | (XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ? |
111 | XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) | | 111 | XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) | |
112 | (XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ? | 112 | (XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ? |
113 | XFS_FSOP_GEOM_FLAGS_SECTOR : 0); | 113 | XFS_FSOP_GEOM_FLAGS_SECTOR : 0) | |
114 | (XFS_SB_VERSION_HASATTR2(&mp->m_sb) ? | ||
115 | XFS_FSOP_GEOM_FLAGS_ATTR2 : 0); | ||
114 | geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ? | 116 | geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ? |
115 | mp->m_sb.sb_logsectsize : BBSIZE; | 117 | mp->m_sb.sb_logsectsize : BBSIZE; |
116 | geo->rtsectsize = mp->m_sb.sb_blocksize; | 118 | geo->rtsectsize = mp->m_sb.sb_blocksize; |
diff --git a/fs/xfs/xfs_macros.c b/fs/xfs/xfs_macros.c index 698c2cd62858..c715da13b2fe 100644 --- a/fs/xfs/xfs_macros.c +++ b/fs/xfs/xfs_macros.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -1995,6 +1995,14 @@ xfs_sb_version_addshared(xfs_sb_t *sbp) | |||
1995 | } | 1995 | } |
1996 | #endif | 1996 | #endif |
1997 | 1997 | ||
1998 | #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_SB_VERSION_ADDATTR2) | ||
1999 | void | ||
2000 | xfs_sb_version_addattr2(xfs_sb_t *sbp) | ||
2001 | { | ||
2002 | XFS_SB_VERSION_ADDATTR2(sbp); | ||
2003 | } | ||
2004 | #endif | ||
2005 | |||
1998 | #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_SB_VERSION_HASALIGN) | 2006 | #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_SB_VERSION_HASALIGN) |
1999 | int | 2007 | int |
2000 | xfs_sb_version_hasalign(xfs_sb_t *sbp) | 2008 | xfs_sb_version_hasalign(xfs_sb_t *sbp) |
@@ -2139,3 +2147,10 @@ xfs_sb_version_hasmorebits(xfs_sb_t *sbp) | |||
2139 | } | 2147 | } |
2140 | #endif | 2148 | #endif |
2141 | 2149 | ||
2150 | #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_SB_VERSION_HASATTR2) | ||
2151 | int | ||
2152 | xfs_sb_version_hasattr2(xfs_sb_t *sbp) | ||
2153 | { | ||
2154 | return XFS_SB_VERSION_HASATTR2(sbp); | ||
2155 | } | ||
2156 | #endif | ||
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 12f10d5c3d99..a93ef802db6b 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -584,12 +584,13 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) | |||
584 | ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048); | 584 | ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048); |
585 | switch (sbp->sb_inodesize) { | 585 | switch (sbp->sb_inodesize) { |
586 | case 256: | 586 | case 256: |
587 | mp->m_attroffset = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(2); | 587 | mp->m_attroffset = XFS_LITINO(mp) - |
588 | XFS_BMDR_SPACE_CALC(MINABTPTRS); | ||
588 | break; | 589 | break; |
589 | case 512: | 590 | case 512: |
590 | case 1024: | 591 | case 1024: |
591 | case 2048: | 592 | case 2048: |
592 | mp->m_attroffset = XFS_BMDR_SPACE_CALC(12); | 593 | mp->m_attroffset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS); |
593 | break; | 594 | break; |
594 | default: | 595 | default: |
595 | ASSERT(0); | 596 | ASSERT(0); |
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h index ad090a834ced..01c5a5ff230e 100644 --- a/fs/xfs/xfs_sb.h +++ b/fs/xfs/xfs_sb.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -72,7 +72,8 @@ struct xfs_mount; | |||
72 | XFS_SB_VERSION_DALIGNBIT | \ | 72 | XFS_SB_VERSION_DALIGNBIT | \ |
73 | XFS_SB_VERSION_SHAREDBIT | \ | 73 | XFS_SB_VERSION_SHAREDBIT | \ |
74 | XFS_SB_VERSION_LOGV2BIT | \ | 74 | XFS_SB_VERSION_LOGV2BIT | \ |
75 | XFS_SB_VERSION_SECTORBIT) | 75 | XFS_SB_VERSION_SECTORBIT | \ |
76 | XFS_SB_VERSION_MOREBITSBIT) | ||
76 | #define XFS_SB_VERSION_OKSASHBITS \ | 77 | #define XFS_SB_VERSION_OKSASHBITS \ |
77 | (XFS_SB_VERSION_NUMBITS | \ | 78 | (XFS_SB_VERSION_NUMBITS | \ |
78 | XFS_SB_VERSION_REALFBITS | \ | 79 | XFS_SB_VERSION_REALFBITS | \ |
@@ -103,12 +104,15 @@ struct xfs_mount; | |||
103 | */ | 104 | */ |
104 | #define XFS_SB_VERSION2_REALFBITS 0x00ffffff /* Mask: features */ | 105 | #define XFS_SB_VERSION2_REALFBITS 0x00ffffff /* Mask: features */ |
105 | #define XFS_SB_VERSION2_RESERVED1BIT 0x00000001 | 106 | #define XFS_SB_VERSION2_RESERVED1BIT 0x00000001 |
107 | #define XFS_SB_VERSION2_RESERVED2BIT 0x00000002 | ||
108 | #define XFS_SB_VERSION2_RESERVED4BIT 0x00000004 | ||
109 | #define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */ | ||
106 | #define XFS_SB_VERSION2_SASHFBITS 0xff000000 /* Mask: features that | 110 | #define XFS_SB_VERSION2_SASHFBITS 0xff000000 /* Mask: features that |
107 | require changing | 111 | require changing |
108 | PROM and SASH */ | 112 | PROM and SASH */ |
109 | 113 | ||
110 | #define XFS_SB_VERSION2_OKREALFBITS \ | 114 | #define XFS_SB_VERSION2_OKREALFBITS \ |
111 | (0) | 115 | (XFS_SB_VERSION2_ATTR2BIT) |
112 | #define XFS_SB_VERSION2_OKSASHFBITS \ | 116 | #define XFS_SB_VERSION2_OKSASHFBITS \ |
113 | (0) | 117 | (0) |
114 | #define XFS_SB_VERSION2_OKREALBITS \ | 118 | #define XFS_SB_VERSION2_OKREALBITS \ |
@@ -118,8 +122,7 @@ struct xfs_mount; | |||
118 | /* | 122 | /* |
119 | * mkfs macro to set up sb_features2 word | 123 | * mkfs macro to set up sb_features2 word |
120 | */ | 124 | */ |
121 | #define XFS_SB_VERSION2_MKFS(xyz) \ | 125 | #define XFS_SB_VERSION2_MKFS(resvd1, sbcntr) 0 |
122 | ((xyz) ? 0 : 0) | ||
123 | 126 | ||
124 | typedef struct xfs_sb | 127 | typedef struct xfs_sb |
125 | { | 128 | { |
@@ -176,7 +179,7 @@ typedef struct xfs_sb | |||
176 | __uint8_t sb_logsectlog; /* log2 of the log sector size */ | 179 | __uint8_t sb_logsectlog; /* log2 of the log sector size */ |
177 | __uint16_t sb_logsectsize; /* sector size for the log, bytes */ | 180 | __uint16_t sb_logsectsize; /* sector size for the log, bytes */ |
178 | __uint32_t sb_logsunit; /* stripe unit size for the log */ | 181 | __uint32_t sb_logsunit; /* stripe unit size for the log */ |
179 | __uint32_t sb_features2; /* additonal feature bits */ | 182 | __uint32_t sb_features2; /* additional feature bits */ |
180 | } xfs_sb_t; | 183 | } xfs_sb_t; |
181 | 184 | ||
182 | /* | 185 | /* |
@@ -216,12 +219,15 @@ typedef enum { | |||
216 | #define XFS_SB_SHARED_VN XFS_SB_MVAL(SHARED_VN) | 219 | #define XFS_SB_SHARED_VN XFS_SB_MVAL(SHARED_VN) |
217 | #define XFS_SB_UNIT XFS_SB_MVAL(UNIT) | 220 | #define XFS_SB_UNIT XFS_SB_MVAL(UNIT) |
218 | #define XFS_SB_WIDTH XFS_SB_MVAL(WIDTH) | 221 | #define XFS_SB_WIDTH XFS_SB_MVAL(WIDTH) |
222 | #define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2) | ||
219 | #define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT) | 223 | #define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT) |
220 | #define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1) | 224 | #define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1) |
221 | #define XFS_SB_MOD_BITS \ | 225 | #define XFS_SB_MOD_BITS \ |
222 | (XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \ | 226 | (XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \ |
223 | XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \ | 227 | XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \ |
224 | XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH) | 228 | XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \ |
229 | XFS_SB_FEATURES2) | ||
230 | |||
225 | 231 | ||
226 | /* | 232 | /* |
227 | * Misc. Flags - warning - these will be cleared by xfs_repair unless | 233 | * Misc. Flags - warning - these will be cleared by xfs_repair unless |
@@ -500,13 +506,31 @@ int xfs_sb_version_hasmorebits(xfs_sb_t *sbp); | |||
500 | /* | 506 | /* |
501 | * sb_features2 bit version macros. | 507 | * sb_features2 bit version macros. |
502 | * | 508 | * |
503 | * For example, for a bit defined as XFS_SB_VERSION2_YBIT, has a macro: | 509 | * For example, for a bit defined as XFS_SB_VERSION2_FUNBIT, has a macro: |
504 | * | 510 | * |
505 | * SB_VERSION_HASYBIT(xfs_sb_t *sbp) | 511 | * SB_VERSION_HASFUNBIT(xfs_sb_t *sbp) |
506 | * ((XFS_SB_VERSION_HASMOREBITS(sbp) && | 512 | * ((XFS_SB_VERSION_HASMOREBITS(sbp) && |
507 | * ((sbp)->sb_versionnum & XFS_SB_VERSION2_YBIT) | 513 | * ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT) |
508 | */ | 514 | */ |
515 | #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASATTR2) | ||
516 | int xfs_sb_version_hasattr2(xfs_sb_t *sbp); | ||
517 | #define XFS_SB_VERSION_HASATTR2(sbp) xfs_sb_version_hasattr2(sbp) | ||
518 | #else | ||
519 | #define XFS_SB_VERSION_HASATTR2(sbp) \ | ||
520 | ((XFS_SB_VERSION_HASMOREBITS(sbp)) && \ | ||
521 | ((sbp)->sb_features2 & XFS_SB_VERSION2_ATTR2BIT)) | ||
522 | #endif | ||
509 | 523 | ||
524 | #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_ADDATTR2) | ||
525 | void xfs_sb_version_addattr2(xfs_sb_t *sbp); | ||
526 | #define XFS_SB_VERSION_ADDATTR2(sbp) xfs_sb_version_addattr2(sbp) | ||
527 | #else | ||
528 | #define XFS_SB_VERSION_ADDATTR2(sbp) \ | ||
529 | ((sbp)->sb_versionnum = \ | ||
530 | ((sbp)->sb_versionnum | XFS_SB_VERSION_MOREBITSBIT), \ | ||
531 | ((sbp)->sb_features2 = \ | ||
532 | ((sbp)->sb_features2 | XFS_SB_VERSION2_ATTR2BIT))) | ||
533 | #endif | ||
510 | /* | 534 | /* |
511 | * end of superblock version macros | 535 | * end of superblock version macros |
512 | */ | 536 | */ |
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index 16f5371ce102..33a888e6b3f2 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -154,6 +154,12 @@ typedef __uint8_t xfs_arch_t; /* architecture of an xfs fs */ | |||
154 | #define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */ | 154 | #define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */ |
155 | 155 | ||
156 | /* | 156 | /* |
157 | * Min numbers of data/attr fork btree root pointers. | ||
158 | */ | ||
159 | #define MINDBTPTRS 3 | ||
160 | #define MINABTPTRS 2 | ||
161 | |||
162 | /* | ||
157 | * MAXNAMELEN is the length (including the terminating null) of | 163 | * MAXNAMELEN is the length (including the terminating null) of |
158 | * the longest permissible file (component) name. | 164 | * the longest permissible file (component) name. |
159 | */ | 165 | */ |
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 7227baee8994..07779c5ab42f 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -268,19 +268,14 @@ xfs_start_flags( | |||
268 | #endif | 268 | #endif |
269 | if (ap->flags & XFSMNT_NOATIME) | 269 | if (ap->flags & XFSMNT_NOATIME) |
270 | mp->m_flags |= XFS_MOUNT_NOATIME; | 270 | mp->m_flags |= XFS_MOUNT_NOATIME; |
271 | |||
272 | if (ap->flags & XFSMNT_RETERR) | 271 | if (ap->flags & XFSMNT_RETERR) |
273 | mp->m_flags |= XFS_MOUNT_RETERR; | 272 | mp->m_flags |= XFS_MOUNT_RETERR; |
274 | |||
275 | if (ap->flags & XFSMNT_NOALIGN) | 273 | if (ap->flags & XFSMNT_NOALIGN) |
276 | mp->m_flags |= XFS_MOUNT_NOALIGN; | 274 | mp->m_flags |= XFS_MOUNT_NOALIGN; |
277 | |||
278 | if (ap->flags & XFSMNT_SWALLOC) | 275 | if (ap->flags & XFSMNT_SWALLOC) |
279 | mp->m_flags |= XFS_MOUNT_SWALLOC; | 276 | mp->m_flags |= XFS_MOUNT_SWALLOC; |
280 | |||
281 | if (ap->flags & XFSMNT_OSYNCISOSYNC) | 277 | if (ap->flags & XFSMNT_OSYNCISOSYNC) |
282 | mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; | 278 | mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; |
283 | |||
284 | if (ap->flags & XFSMNT_32BITINODES) | 279 | if (ap->flags & XFSMNT_32BITINODES) |
285 | mp->m_flags |= (XFS_MOUNT_32BITINODES | XFS_MOUNT_32BITINOOPT); | 280 | mp->m_flags |= (XFS_MOUNT_32BITINODES | XFS_MOUNT_32BITINOOPT); |
286 | 281 | ||
@@ -300,15 +295,14 @@ xfs_start_flags( | |||
300 | 295 | ||
301 | if (ap->flags & XFSMNT_IHASHSIZE) | 296 | if (ap->flags & XFSMNT_IHASHSIZE) |
302 | mp->m_flags |= XFS_MOUNT_IHASHSIZE; | 297 | mp->m_flags |= XFS_MOUNT_IHASHSIZE; |
303 | |||
304 | if (ap->flags & XFSMNT_IDELETE) | 298 | if (ap->flags & XFSMNT_IDELETE) |
305 | mp->m_flags |= XFS_MOUNT_IDELETE; | 299 | mp->m_flags |= XFS_MOUNT_IDELETE; |
306 | |||
307 | if (ap->flags & XFSMNT_DIRSYNC) | 300 | if (ap->flags & XFSMNT_DIRSYNC) |
308 | mp->m_flags |= XFS_MOUNT_DIRSYNC; | 301 | mp->m_flags |= XFS_MOUNT_DIRSYNC; |
309 | |||
310 | if (ap->flags & XFSMNT_COMPAT_IOSIZE) | 302 | if (ap->flags & XFSMNT_COMPAT_IOSIZE) |
311 | mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; | 303 | mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; |
304 | if (ap->flags & XFSMNT_COMPAT_ATTR) | ||
305 | mp->m_flags |= XFS_MOUNT_COMPAT_ATTR; | ||
312 | 306 | ||
313 | /* | 307 | /* |
314 | * no recovery flag requires a read-only mount | 308 | * no recovery flag requires a read-only mount |
@@ -1643,7 +1637,7 @@ xfs_vget( | |||
1643 | #define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */ | 1637 | #define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */ |
1644 | #define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ | 1638 | #define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ |
1645 | #define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and | 1639 | #define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and |
1646 | unwritten extent conversion */ | 1640 | * unwritten extent conversion */ |
1647 | #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ | 1641 | #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ |
1648 | #define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */ | 1642 | #define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */ |
1649 | #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ | 1643 | #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ |
@@ -1651,6 +1645,8 @@ xfs_vget( | |||
1651 | #define MNTOPT_LARGEIO "largeio" /* report large I/O sizes in stat() */ | 1645 | #define MNTOPT_LARGEIO "largeio" /* report large I/O sizes in stat() */ |
1652 | #define MNTOPT_NOLARGEIO "nolargeio" /* do not report large I/O sizes | 1646 | #define MNTOPT_NOLARGEIO "nolargeio" /* do not report large I/O sizes |
1653 | * in stat(). */ | 1647 | * in stat(). */ |
1648 | #define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */ | ||
1649 | #define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */ | ||
1654 | 1650 | ||
1655 | STATIC unsigned long | 1651 | STATIC unsigned long |
1656 | suffix_strtoul(const char *cp, char **endp, unsigned int base) | 1652 | suffix_strtoul(const char *cp, char **endp, unsigned int base) |
@@ -1820,6 +1816,10 @@ xfs_parseargs( | |||
1820 | args->flags &= ~XFSMNT_COMPAT_IOSIZE; | 1816 | args->flags &= ~XFSMNT_COMPAT_IOSIZE; |
1821 | } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) { | 1817 | } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) { |
1822 | args->flags |= XFSMNT_COMPAT_IOSIZE; | 1818 | args->flags |= XFSMNT_COMPAT_IOSIZE; |
1819 | } else if (!strcmp(this_char, MNTOPT_ATTR2)) { | ||
1820 | args->flags &= ~XFSMNT_COMPAT_ATTR; | ||
1821 | } else if (!strcmp(this_char, MNTOPT_NOATTR2)) { | ||
1822 | args->flags |= XFSMNT_COMPAT_ATTR; | ||
1823 | } else if (!strcmp(this_char, "osyncisdsync")) { | 1823 | } else if (!strcmp(this_char, "osyncisdsync")) { |
1824 | /* no-op, this is now the default */ | 1824 | /* no-op, this is now the default */ |
1825 | printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); | 1825 | printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); |