aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2005-11-01 18:34:53 -0500
committerNathan Scott <nathans@sgi.com>2005-11-01 18:34:53 -0500
commitd8cc890d4095f1eaa7f411a85051015b21262b12 (patch)
treee13bec06a94a8dc5552dab733e90ef4f4d41fb8b
parentaa82daa06198b27963fe3d6ee8035855b29f6524 (diff)
[XFS] Ondisk format extension for extended attributes (attr2). Basically,
the data/attr forks now grow up/down from either end of the literal area, rather than dividing the literal area into two chunks and growing both upward. Means we can now make much more efficient use of the attribute space, incl. fitting DMF attributes inline in 256 byte inodes, and large jumps in dbench3 performance numbers. It is self enabling, but can be forced on/off via the attr2/noattr2 mount options. SGI-PV: 941645 SGI-Modid: xfs-linux:xfs-kern:23835a Signed-off-by: Nathan Scott <nathans@sgi.com>
-rw-r--r--fs/xfs/xfs_attr.c61
-rw-r--r--fs/xfs/xfs_attr_leaf.c177
-rw-r--r--fs/xfs/xfs_attr_leaf.h14
-rw-r--r--fs/xfs/xfs_bmap.c84
-rw-r--r--fs/xfs/xfs_bmap.h5
-rw-r--r--fs/xfs/xfs_dir.c24
-rw-r--r--fs/xfs/xfs_fs.h3
-rw-r--r--fs/xfs/xfs_fsops.c6
-rw-r--r--fs/xfs/xfs_macros.c17
-rw-r--r--fs/xfs/xfs_mount.c7
-rw-r--r--fs/xfs/xfs_sb.h44
-rw-r--r--fs/xfs/xfs_types.h8
-rw-r--r--fs/xfs/xfs_vfsops.c18
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
203int 203STATIC int
204xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, 204xfs_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 */
470int 471STATIC int
471xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags) 472xfs_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:
822STATIC int 822STATIC int
823xfs_attr_shortform_addname(xfs_da_args_t *args) 823xfs_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 */
127int 133int
134xfs_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 */
176STATIC void
177xfs_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 */
196void
128xfs_attr_shortform_create(xfs_da_args_t *args) 197xfs_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 */
158int 226void
159xfs_attr_shortform_add(xfs_da_args_t *args) 227xfs_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 */
209int 287int
210xfs_attr_shortform_remove(xfs_da_args_t *args) 288xfs_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 */
658int 769int
659xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) 770xfs_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 */
243int xfs_attr_shortform_create(struct xfs_da_args *args); 243void xfs_attr_shortform_create(struct xfs_da_args *args);
244int xfs_attr_shortform_add(struct xfs_da_args *add); 244void xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
245int xfs_attr_shortform_lookup(struct xfs_da_args *args); 245int xfs_attr_shortform_lookup(struct xfs_da_args *args);
246int xfs_attr_shortform_getvalue(struct xfs_da_args *args); 246int xfs_attr_shortform_getvalue(struct xfs_da_args *args);
247int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); 247int xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
248int xfs_attr_shortform_remove(struct xfs_da_args *remove); 248int xfs_attr_shortform_remove(struct xfs_da_args *args);
249int xfs_attr_shortform_list(struct xfs_attr_list_context *context); 249int xfs_attr_shortform_list(struct xfs_attr_list_context *context);
250int xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp); 250int xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp);
251int 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 */
255int xfs_attr_leaf_to_node(struct xfs_da_args *args); 257int xfs_attr_leaf_to_node(struct xfs_da_args *args);
256int xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp, 258int xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp,
257 struct xfs_da_args *args); 259 struct xfs_da_args *args, int forkoff);
258int xfs_attr_leaf_clearflag(struct xfs_da_args *args); 260int xfs_attr_leaf_clearflag(struct xfs_da_args *args);
259int xfs_attr_leaf_setflag(struct xfs_da_args *args); 261int xfs_attr_leaf_setflag(struct xfs_da_args *args);
260int xfs_attr_leaf_flipflags(xfs_da_args_t *args); 262int 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 */
3345STATIC void
3346xfs_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(
3796int /* error code */ 3823int /* error code */
3797xfs_bmap_add_attrfork( 3824xfs_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(
156int /* error code */ 156int /* error code */
157xfs_bmap_add_attrfork( 157xfs_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)
1999void
2000xfs_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)
1999int 2007int
2000xfs_sb_version_hasalign(xfs_sb_t *sbp) 2008xfs_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)
2151int
2152xfs_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
124typedef struct xfs_sb 127typedef 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)
516int 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)
525void 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
1655STATIC unsigned long 1651STATIC unsigned long
1656suffix_strtoul(const char *cp, char **endp, unsigned int base) 1652suffix_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 */
1825printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); 1825printk("XFS: osyncisdsync is now the default, option is deprecated.\n");