xfs: use generic get_unaligned_beXX helpers
[linux-2.6-block.git] / fs / xfs / xfs_dir2_sf.c
1 /*
2  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_log.h"
22 #include "xfs_inum.h"
23 #include "xfs_trans.h"
24 #include "xfs_sb.h"
25 #include "xfs_ag.h"
26 #include "xfs_dir2.h"
27 #include "xfs_mount.h"
28 #include "xfs_da_btree.h"
29 #include "xfs_bmap_btree.h"
30 #include "xfs_dir2_sf.h"
31 #include "xfs_dinode.h"
32 #include "xfs_inode.h"
33 #include "xfs_inode_item.h"
34 #include "xfs_error.h"
35 #include "xfs_dir2_data.h"
36 #include "xfs_dir2_leaf.h"
37 #include "xfs_dir2_block.h"
38 #include "xfs_trace.h"
39
40 /*
41  * Prototypes for internal functions.
42  */
43 static void xfs_dir2_sf_addname_easy(xfs_da_args_t *args,
44                                      xfs_dir2_sf_entry_t *sfep,
45                                      xfs_dir2_data_aoff_t offset,
46                                      int new_isize);
47 static void xfs_dir2_sf_addname_hard(xfs_da_args_t *args, int objchange,
48                                      int new_isize);
49 static int xfs_dir2_sf_addname_pick(xfs_da_args_t *args, int objchange,
50                                     xfs_dir2_sf_entry_t **sfepp,
51                                     xfs_dir2_data_aoff_t *offsetp);
52 #ifdef DEBUG
53 static void xfs_dir2_sf_check(xfs_da_args_t *args);
54 #else
55 #define xfs_dir2_sf_check(args)
56 #endif /* DEBUG */
57 #if XFS_BIG_INUMS
58 static void xfs_dir2_sf_toino4(xfs_da_args_t *args);
59 static void xfs_dir2_sf_toino8(xfs_da_args_t *args);
60 #endif /* XFS_BIG_INUMS */
61
62 /*
63  * Inode numbers in short-form directories can come in two versions,
64  * either 4 bytes or 8 bytes wide.  These helpers deal with the
65  * two forms transparently by looking at the headers i8count field.
66  *
67  * For 64-bit inode number the most significant byte must be zero.
68  */
69 static xfs_ino_t
70 xfs_dir2_sf_get_ino(
71         struct xfs_dir2_sf_hdr  *hdr,
72         xfs_dir2_inou_t         *from)
73 {
74         if (hdr->i8count)
75                 return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
76         else
77                 return get_unaligned_be32(&from->i4.i);
78 }
79
80 static void
81 xfs_dir2_sf_put_ino(
82         struct xfs_dir2_sf_hdr  *hdr,
83         xfs_dir2_inou_t         *to,
84         xfs_ino_t               ino)
85 {
86         ASSERT((ino & 0xff00000000000000ULL) == 0);
87
88         if (hdr->i8count)
89                 put_unaligned_be64(ino, &to->i8.i);
90         else
91                 put_unaligned_be32(ino, &to->i4.i);
92 }
93
94 xfs_ino_t
95 xfs_dir2_sf_get_parent_ino(
96         struct xfs_dir2_sf_hdr  *hdr)
97 {
98         return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
99 }
100
101 static void
102 xfs_dir2_sf_put_parent_ino(
103         struct xfs_dir2_sf_hdr  *hdr,
104         xfs_ino_t               ino)
105 {
106         xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
107 }
108
109 /*
110  * In short-form directory entries the inode numbers are stored at variable
111  * offset behind the entry name.  The inode numbers may only be accessed
112  * through the helpers below.
113  */
114 static xfs_dir2_inou_t *
115 xfs_dir2_sfe_inop(
116         struct xfs_dir2_sf_entry *sfep)
117 {
118         return (xfs_dir2_inou_t *)&sfep->name[sfep->namelen];
119 }
120
121 xfs_ino_t
122 xfs_dir2_sfe_get_ino(
123         struct xfs_dir2_sf_hdr  *hdr,
124         struct xfs_dir2_sf_entry *sfep)
125 {
126         return xfs_dir2_sf_get_ino(hdr, xfs_dir2_sfe_inop(sfep));
127 }
128
129 static void
130 xfs_dir2_sfe_put_ino(
131         struct xfs_dir2_sf_hdr  *hdr,
132         struct xfs_dir2_sf_entry *sfep,
133         xfs_ino_t               ino)
134 {
135         xfs_dir2_sf_put_ino(hdr, xfs_dir2_sfe_inop(sfep), ino);
136 }
137
138 /*
139  * Given a block directory (dp/block), calculate its size as a shortform (sf)
140  * directory and a header for the sf directory, if it will fit it the
141  * space currently present in the inode.  If it won't fit, the output
142  * size is too big (but not accurate).
143  */
144 int                                             /* size for sf form */
145 xfs_dir2_block_sfsize(
146         xfs_inode_t             *dp,            /* incore inode pointer */
147         xfs_dir2_data_hdr_t     *hdr,           /* block directory data */
148         xfs_dir2_sf_hdr_t       *sfhp)          /* output: header for sf form */
149 {
150         xfs_dir2_dataptr_t      addr;           /* data entry address */
151         xfs_dir2_leaf_entry_t   *blp;           /* leaf area of the block */
152         xfs_dir2_block_tail_t   *btp;           /* tail area of the block */
153         int                     count;          /* shortform entry count */
154         xfs_dir2_data_entry_t   *dep;           /* data entry in the block */
155         int                     i;              /* block entry index */
156         int                     i8count;        /* count of big-inode entries */
157         int                     isdot;          /* entry is "." */
158         int                     isdotdot;       /* entry is ".." */
159         xfs_mount_t             *mp;            /* mount structure pointer */
160         int                     namelen;        /* total name bytes */
161         xfs_ino_t               parent = 0;     /* parent inode number */
162         int                     size=0;         /* total computed size */
163
164         mp = dp->i_mount;
165
166         count = i8count = namelen = 0;
167         btp = xfs_dir2_block_tail_p(mp, hdr);
168         blp = xfs_dir2_block_leaf_p(btp);
169
170         /*
171          * Iterate over the block's data entries by using the leaf pointers.
172          */
173         for (i = 0; i < be32_to_cpu(btp->count); i++) {
174                 if ((addr = be32_to_cpu(blp[i].address)) == XFS_DIR2_NULL_DATAPTR)
175                         continue;
176                 /*
177                  * Calculate the pointer to the entry at hand.
178                  */
179                 dep = (xfs_dir2_data_entry_t *)
180                       ((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr));
181                 /*
182                  * Detect . and .., so we can special-case them.
183                  * . is not included in sf directories.
184                  * .. is included by just the parent inode number.
185                  */
186                 isdot = dep->namelen == 1 && dep->name[0] == '.';
187                 isdotdot =
188                         dep->namelen == 2 &&
189                         dep->name[0] == '.' && dep->name[1] == '.';
190 #if XFS_BIG_INUMS
191                 if (!isdot)
192                         i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM;
193 #endif
194                 if (!isdot && !isdotdot) {
195                         count++;
196                         namelen += dep->namelen;
197                 } else if (isdotdot)
198                         parent = be64_to_cpu(dep->inumber);
199                 /*
200                  * Calculate the new size, see if we should give up yet.
201                  */
202                 size = xfs_dir2_sf_hdr_size(i8count) +          /* header */
203                        count +                                  /* namelen */
204                        count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
205                        namelen +                                /* name */
206                        (i8count ?                               /* inumber */
207                                 (uint)sizeof(xfs_dir2_ino8_t) * count :
208                                 (uint)sizeof(xfs_dir2_ino4_t) * count);
209                 if (size > XFS_IFORK_DSIZE(dp))
210                         return size;            /* size value is a failure */
211         }
212         /*
213          * Create the output header, if it worked.
214          */
215         sfhp->count = count;
216         sfhp->i8count = i8count;
217         xfs_dir2_sf_put_parent_ino(sfhp, parent);
218         return size;
219 }
220
221 /*
222  * Convert a block format directory to shortform.
223  * Caller has already checked that it will fit, and built us a header.
224  */
225 int                                             /* error */
226 xfs_dir2_block_to_sf(
227         xfs_da_args_t           *args,          /* operation arguments */
228         xfs_dabuf_t             *bp,            /* block buffer */
229         int                     size,           /* shortform directory size */
230         xfs_dir2_sf_hdr_t       *sfhp)          /* shortform directory hdr */
231 {
232         xfs_dir2_data_hdr_t     *hdr;           /* block header */
233         xfs_dir2_block_tail_t   *btp;           /* block tail pointer */
234         xfs_dir2_data_entry_t   *dep;           /* data entry pointer */
235         xfs_inode_t             *dp;            /* incore directory inode */
236         xfs_dir2_data_unused_t  *dup;           /* unused data pointer */
237         char                    *endptr;        /* end of data entries */
238         int                     error;          /* error return value */
239         int                     logflags;       /* inode logging flags */
240         xfs_mount_t             *mp;            /* filesystem mount point */
241         char                    *ptr;           /* current data pointer */
242         xfs_dir2_sf_entry_t     *sfep;          /* shortform entry */
243         xfs_dir2_sf_hdr_t       *sfp;           /* shortform directory header */
244
245         trace_xfs_dir2_block_to_sf(args);
246
247         dp = args->dp;
248         mp = dp->i_mount;
249
250         /*
251          * Make a copy of the block data, so we can shrink the inode
252          * and add local data.
253          */
254         hdr = kmem_alloc(mp->m_dirblksize, KM_SLEEP);
255         memcpy(hdr, bp->data, mp->m_dirblksize);
256         logflags = XFS_ILOG_CORE;
257         if ((error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp))) {
258                 ASSERT(error != ENOSPC);
259                 goto out;
260         }
261
262         /*
263          * The buffer is now unconditionally gone, whether
264          * xfs_dir2_shrink_inode worked or not.
265          *
266          * Convert the inode to local format.
267          */
268         dp->i_df.if_flags &= ~XFS_IFEXTENTS;
269         dp->i_df.if_flags |= XFS_IFINLINE;
270         dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
271         ASSERT(dp->i_df.if_bytes == 0);
272         xfs_idata_realloc(dp, size, XFS_DATA_FORK);
273         logflags |= XFS_ILOG_DDATA;
274         /*
275          * Copy the header into the newly allocate local space.
276          */
277         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
278         memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
279         dp->i_d.di_size = size;
280         /*
281          * Set up to loop over the block's entries.
282          */
283         btp = xfs_dir2_block_tail_p(mp, hdr);
284         ptr = (char *)(hdr + 1);
285         endptr = (char *)xfs_dir2_block_leaf_p(btp);
286         sfep = xfs_dir2_sf_firstentry(sfp);
287         /*
288          * Loop over the active and unused entries.
289          * Stop when we reach the leaf/tail portion of the block.
290          */
291         while (ptr < endptr) {
292                 /*
293                  * If it's unused, just skip over it.
294                  */
295                 dup = (xfs_dir2_data_unused_t *)ptr;
296                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
297                         ptr += be16_to_cpu(dup->length);
298                         continue;
299                 }
300                 dep = (xfs_dir2_data_entry_t *)ptr;
301                 /*
302                  * Skip .
303                  */
304                 if (dep->namelen == 1 && dep->name[0] == '.')
305                         ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino);
306                 /*
307                  * Skip .., but make sure the inode number is right.
308                  */
309                 else if (dep->namelen == 2 &&
310                          dep->name[0] == '.' && dep->name[1] == '.')
311                         ASSERT(be64_to_cpu(dep->inumber) ==
312                                xfs_dir2_sf_get_parent_ino(sfp));
313                 /*
314                  * Normal entry, copy it into shortform.
315                  */
316                 else {
317                         sfep->namelen = dep->namelen;
318                         xfs_dir2_sf_put_offset(sfep,
319                                 (xfs_dir2_data_aoff_t)
320                                 ((char *)dep - (char *)hdr));
321                         memcpy(sfep->name, dep->name, dep->namelen);
322                         xfs_dir2_sfe_put_ino(sfp, sfep,
323                                              be64_to_cpu(dep->inumber));
324
325                         sfep = xfs_dir2_sf_nextentry(sfp, sfep);
326                 }
327                 ptr += xfs_dir2_data_entsize(dep->namelen);
328         }
329         ASSERT((char *)sfep - (char *)sfp == size);
330         xfs_dir2_sf_check(args);
331 out:
332         xfs_trans_log_inode(args->trans, dp, logflags);
333         kmem_free(hdr);
334         return error;
335 }
336
337 /*
338  * Add a name to a shortform directory.
339  * There are two algorithms, "easy" and "hard" which we decide on
340  * before changing anything.
341  * Convert to block form if necessary, if the new entry won't fit.
342  */
343 int                                             /* error */
344 xfs_dir2_sf_addname(
345         xfs_da_args_t           *args)          /* operation arguments */
346 {
347         int                     add_entsize;    /* size of the new entry */
348         xfs_inode_t             *dp;            /* incore directory inode */
349         int                     error;          /* error return value */
350         int                     incr_isize;     /* total change in size */
351         int                     new_isize;      /* di_size after adding name */
352         int                     objchange;      /* changing to 8-byte inodes */
353         xfs_dir2_data_aoff_t    offset = 0;     /* offset for new entry */
354         int                     old_isize;      /* di_size before adding name */
355         int                     pick;           /* which algorithm to use */
356         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
357         xfs_dir2_sf_entry_t     *sfep = NULL;   /* shortform entry */
358
359         trace_xfs_dir2_sf_addname(args);
360
361         ASSERT(xfs_dir2_sf_lookup(args) == ENOENT);
362         dp = args->dp;
363         ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
364         /*
365          * Make sure the shortform value has some of its header.
366          */
367         if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
368                 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
369                 return XFS_ERROR(EIO);
370         }
371         ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
372         ASSERT(dp->i_df.if_u1.if_data != NULL);
373         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
374         ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
375         /*
376          * Compute entry (and change in) size.
377          */
378         add_entsize = xfs_dir2_sf_entsize(sfp, args->namelen);
379         incr_isize = add_entsize;
380         objchange = 0;
381 #if XFS_BIG_INUMS
382         /*
383          * Do we have to change to 8 byte inodes?
384          */
385         if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) {
386                 /*
387                  * Yes, adjust the entry size and the total size.
388                  */
389                 add_entsize +=
390                         (uint)sizeof(xfs_dir2_ino8_t) -
391                         (uint)sizeof(xfs_dir2_ino4_t);
392                 incr_isize +=
393                         (sfp->count + 2) *
394                         ((uint)sizeof(xfs_dir2_ino8_t) -
395                          (uint)sizeof(xfs_dir2_ino4_t));
396                 objchange = 1;
397         }
398 #endif
399         old_isize = (int)dp->i_d.di_size;
400         new_isize = old_isize + incr_isize;
401         /*
402          * Won't fit as shortform any more (due to size),
403          * or the pick routine says it won't (due to offset values).
404          */
405         if (new_isize > XFS_IFORK_DSIZE(dp) ||
406             (pick =
407              xfs_dir2_sf_addname_pick(args, objchange, &sfep, &offset)) == 0) {
408                 /*
409                  * Just checking or no space reservation, it doesn't fit.
410                  */
411                 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
412                         return XFS_ERROR(ENOSPC);
413                 /*
414                  * Convert to block form then add the name.
415                  */
416                 error = xfs_dir2_sf_to_block(args);
417                 if (error)
418                         return error;
419                 return xfs_dir2_block_addname(args);
420         }
421         /*
422          * Just checking, it fits.
423          */
424         if (args->op_flags & XFS_DA_OP_JUSTCHECK)
425                 return 0;
426         /*
427          * Do it the easy way - just add it at the end.
428          */
429         if (pick == 1)
430                 xfs_dir2_sf_addname_easy(args, sfep, offset, new_isize);
431         /*
432          * Do it the hard way - look for a place to insert the new entry.
433          * Convert to 8 byte inode numbers first if necessary.
434          */
435         else {
436                 ASSERT(pick == 2);
437 #if XFS_BIG_INUMS
438                 if (objchange)
439                         xfs_dir2_sf_toino8(args);
440 #endif
441                 xfs_dir2_sf_addname_hard(args, objchange, new_isize);
442         }
443         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
444         return 0;
445 }
446
447 /*
448  * Add the new entry the "easy" way.
449  * This is copying the old directory and adding the new entry at the end.
450  * Since it's sorted by "offset" we need room after the last offset
451  * that's already there, and then room to convert to a block directory.
452  * This is already checked by the pick routine.
453  */
454 static void
455 xfs_dir2_sf_addname_easy(
456         xfs_da_args_t           *args,          /* operation arguments */
457         xfs_dir2_sf_entry_t     *sfep,          /* pointer to new entry */
458         xfs_dir2_data_aoff_t    offset,         /* offset to use for new ent */
459         int                     new_isize)      /* new directory size */
460 {
461         int                     byteoff;        /* byte offset in sf dir */
462         xfs_inode_t             *dp;            /* incore directory inode */
463         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
464
465         dp = args->dp;
466
467         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
468         byteoff = (int)((char *)sfep - (char *)sfp);
469         /*
470          * Grow the in-inode space.
471          */
472         xfs_idata_realloc(dp, xfs_dir2_sf_entsize(sfp, args->namelen),
473                 XFS_DATA_FORK);
474         /*
475          * Need to set up again due to realloc of the inode data.
476          */
477         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
478         sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + byteoff);
479         /*
480          * Fill in the new entry.
481          */
482         sfep->namelen = args->namelen;
483         xfs_dir2_sf_put_offset(sfep, offset);
484         memcpy(sfep->name, args->name, sfep->namelen);
485         xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber);
486         /*
487          * Update the header and inode.
488          */
489         sfp->count++;
490 #if XFS_BIG_INUMS
491         if (args->inumber > XFS_DIR2_MAX_SHORT_INUM)
492                 sfp->i8count++;
493 #endif
494         dp->i_d.di_size = new_isize;
495         xfs_dir2_sf_check(args);
496 }
497
498 /*
499  * Add the new entry the "hard" way.
500  * The caller has already converted to 8 byte inode numbers if necessary,
501  * in which case we need to leave the i8count at 1.
502  * Find a hole that the new entry will fit into, and copy
503  * the first part of the entries, the new entry, and the last part of
504  * the entries.
505  */
506 /* ARGSUSED */
507 static void
508 xfs_dir2_sf_addname_hard(
509         xfs_da_args_t           *args,          /* operation arguments */
510         int                     objchange,      /* changing inode number size */
511         int                     new_isize)      /* new directory size */
512 {
513         int                     add_datasize;   /* data size need for new ent */
514         char                    *buf;           /* buffer for old */
515         xfs_inode_t             *dp;            /* incore directory inode */
516         int                     eof;            /* reached end of old dir */
517         int                     nbytes;         /* temp for byte copies */
518         xfs_dir2_data_aoff_t    new_offset;     /* next offset value */
519         xfs_dir2_data_aoff_t    offset;         /* current offset value */
520         int                     old_isize;      /* previous di_size */
521         xfs_dir2_sf_entry_t     *oldsfep;       /* entry in original dir */
522         xfs_dir2_sf_hdr_t       *oldsfp;        /* original shortform dir */
523         xfs_dir2_sf_entry_t     *sfep;          /* entry in new dir */
524         xfs_dir2_sf_hdr_t       *sfp;           /* new shortform dir */
525
526         /*
527          * Copy the old directory to the stack buffer.
528          */
529         dp = args->dp;
530
531         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
532         old_isize = (int)dp->i_d.di_size;
533         buf = kmem_alloc(old_isize, KM_SLEEP);
534         oldsfp = (xfs_dir2_sf_hdr_t *)buf;
535         memcpy(oldsfp, sfp, old_isize);
536         /*
537          * Loop over the old directory finding the place we're going
538          * to insert the new entry.
539          * If it's going to end up at the end then oldsfep will point there.
540          */
541         for (offset = XFS_DIR2_DATA_FIRST_OFFSET,
542               oldsfep = xfs_dir2_sf_firstentry(oldsfp),
543               add_datasize = xfs_dir2_data_entsize(args->namelen),
544               eof = (char *)oldsfep == &buf[old_isize];
545              !eof;
546              offset = new_offset + xfs_dir2_data_entsize(oldsfep->namelen),
547               oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep),
548               eof = (char *)oldsfep == &buf[old_isize]) {
549                 new_offset = xfs_dir2_sf_get_offset(oldsfep);
550                 if (offset + add_datasize <= new_offset)
551                         break;
552         }
553         /*
554          * Get rid of the old directory, then allocate space for
555          * the new one.  We do this so xfs_idata_realloc won't copy
556          * the data.
557          */
558         xfs_idata_realloc(dp, -old_isize, XFS_DATA_FORK);
559         xfs_idata_realloc(dp, new_isize, XFS_DATA_FORK);
560         /*
561          * Reset the pointer since the buffer was reallocated.
562          */
563         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
564         /*
565          * Copy the first part of the directory, including the header.
566          */
567         nbytes = (int)((char *)oldsfep - (char *)oldsfp);
568         memcpy(sfp, oldsfp, nbytes);
569         sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + nbytes);
570         /*
571          * Fill in the new entry, and update the header counts.
572          */
573         sfep->namelen = args->namelen;
574         xfs_dir2_sf_put_offset(sfep, offset);
575         memcpy(sfep->name, args->name, sfep->namelen);
576         xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber);
577         sfp->count++;
578 #if XFS_BIG_INUMS
579         if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
580                 sfp->i8count++;
581 #endif
582         /*
583          * If there's more left to copy, do that.
584          */
585         if (!eof) {
586                 sfep = xfs_dir2_sf_nextentry(sfp, sfep);
587                 memcpy(sfep, oldsfep, old_isize - nbytes);
588         }
589         kmem_free(buf);
590         dp->i_d.di_size = new_isize;
591         xfs_dir2_sf_check(args);
592 }
593
594 /*
595  * Decide if the new entry will fit at all.
596  * If it will fit, pick between adding the new entry to the end (easy)
597  * or somewhere else (hard).
598  * Return 0 (won't fit), 1 (easy), 2 (hard).
599  */
600 /*ARGSUSED*/
601 static int                                      /* pick result */
602 xfs_dir2_sf_addname_pick(
603         xfs_da_args_t           *args,          /* operation arguments */
604         int                     objchange,      /* inode # size changes */
605         xfs_dir2_sf_entry_t     **sfepp,        /* out(1): new entry ptr */
606         xfs_dir2_data_aoff_t    *offsetp)       /* out(1): new offset */
607 {
608         xfs_inode_t             *dp;            /* incore directory inode */
609         int                     holefit;        /* found hole it will fit in */
610         int                     i;              /* entry number */
611         xfs_mount_t             *mp;            /* filesystem mount point */
612         xfs_dir2_data_aoff_t    offset;         /* data block offset */
613         xfs_dir2_sf_entry_t     *sfep;          /* shortform entry */
614         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
615         int                     size;           /* entry's data size */
616         int                     used;           /* data bytes used */
617
618         dp = args->dp;
619         mp = dp->i_mount;
620
621         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
622         size = xfs_dir2_data_entsize(args->namelen);
623         offset = XFS_DIR2_DATA_FIRST_OFFSET;
624         sfep = xfs_dir2_sf_firstentry(sfp);
625         holefit = 0;
626         /*
627          * Loop over sf entries.
628          * Keep track of data offset and whether we've seen a place
629          * to insert the new entry.
630          */
631         for (i = 0; i < sfp->count; i++) {
632                 if (!holefit)
633                         holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
634                 offset = xfs_dir2_sf_get_offset(sfep) +
635                          xfs_dir2_data_entsize(sfep->namelen);
636                 sfep = xfs_dir2_sf_nextentry(sfp, sfep);
637         }
638         /*
639          * Calculate data bytes used excluding the new entry, if this
640          * was a data block (block form directory).
641          */
642         used = offset +
643                (sfp->count + 3) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
644                (uint)sizeof(xfs_dir2_block_tail_t);
645         /*
646          * If it won't fit in a block form then we can't insert it,
647          * we'll go back, convert to block, then try the insert and convert
648          * to leaf.
649          */
650         if (used + (holefit ? 0 : size) > mp->m_dirblksize)
651                 return 0;
652         /*
653          * If changing the inode number size, do it the hard way.
654          */
655 #if XFS_BIG_INUMS
656         if (objchange) {
657                 return 2;
658         }
659 #else
660         ASSERT(objchange == 0);
661 #endif
662         /*
663          * If it won't fit at the end then do it the hard way (use the hole).
664          */
665         if (used + size > mp->m_dirblksize)
666                 return 2;
667         /*
668          * Do it the easy way.
669          */
670         *sfepp = sfep;
671         *offsetp = offset;
672         return 1;
673 }
674
675 #ifdef DEBUG
676 /*
677  * Check consistency of shortform directory, assert if bad.
678  */
679 static void
680 xfs_dir2_sf_check(
681         xfs_da_args_t           *args)          /* operation arguments */
682 {
683         xfs_inode_t             *dp;            /* incore directory inode */
684         int                     i;              /* entry number */
685         int                     i8count;        /* number of big inode#s */
686         xfs_ino_t               ino;            /* entry inode number */
687         int                     offset;         /* data offset */
688         xfs_dir2_sf_entry_t     *sfep;          /* shortform dir entry */
689         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
690
691         dp = args->dp;
692
693         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
694         offset = XFS_DIR2_DATA_FIRST_OFFSET;
695         ino = xfs_dir2_sf_get_parent_ino(sfp);
696         i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
697
698         for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
699              i < sfp->count;
700              i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
701                 ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
702                 ino = xfs_dir2_sfe_get_ino(sfp, sfep);
703                 i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
704                 offset =
705                         xfs_dir2_sf_get_offset(sfep) +
706                         xfs_dir2_data_entsize(sfep->namelen);
707         }
708         ASSERT(i8count == sfp->i8count);
709         ASSERT(XFS_BIG_INUMS || i8count == 0);
710         ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size);
711         ASSERT(offset +
712                (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
713                (uint)sizeof(xfs_dir2_block_tail_t) <=
714                dp->i_mount->m_dirblksize);
715 }
716 #endif  /* DEBUG */
717
718 /*
719  * Create a new (shortform) directory.
720  */
721 int                                     /* error, always 0 */
722 xfs_dir2_sf_create(
723         xfs_da_args_t   *args,          /* operation arguments */
724         xfs_ino_t       pino)           /* parent inode number */
725 {
726         xfs_inode_t     *dp;            /* incore directory inode */
727         int             i8count;        /* parent inode is an 8-byte number */
728         xfs_dir2_sf_hdr_t *sfp;         /* shortform structure */
729         int             size;           /* directory size */
730
731         trace_xfs_dir2_sf_create(args);
732
733         dp = args->dp;
734
735         ASSERT(dp != NULL);
736         ASSERT(dp->i_d.di_size == 0);
737         /*
738          * If it's currently a zero-length extent file,
739          * convert it to local format.
740          */
741         if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
742                 dp->i_df.if_flags &= ~XFS_IFEXTENTS;    /* just in case */
743                 dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
744                 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
745                 dp->i_df.if_flags |= XFS_IFINLINE;
746         }
747         ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
748         ASSERT(dp->i_df.if_bytes == 0);
749         i8count = pino > XFS_DIR2_MAX_SHORT_INUM;
750         size = xfs_dir2_sf_hdr_size(i8count);
751         /*
752          * Make a buffer for the data.
753          */
754         xfs_idata_realloc(dp, size, XFS_DATA_FORK);
755         /*
756          * Fill in the header,
757          */
758         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
759         sfp->i8count = i8count;
760         /*
761          * Now can put in the inode number, since i8count is set.
762          */
763         xfs_dir2_sf_put_parent_ino(sfp, pino);
764         sfp->count = 0;
765         dp->i_d.di_size = size;
766         xfs_dir2_sf_check(args);
767         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
768         return 0;
769 }
770
771 int                                             /* error */
772 xfs_dir2_sf_getdents(
773         xfs_inode_t             *dp,            /* incore directory inode */
774         void                    *dirent,
775         xfs_off_t               *offset,
776         filldir_t               filldir)
777 {
778         int                     i;              /* shortform entry number */
779         xfs_mount_t             *mp;            /* filesystem mount point */
780         xfs_dir2_dataptr_t      off;            /* current entry's offset */
781         xfs_dir2_sf_entry_t     *sfep;          /* shortform directory entry */
782         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
783         xfs_dir2_dataptr_t      dot_offset;
784         xfs_dir2_dataptr_t      dotdot_offset;
785         xfs_ino_t               ino;
786
787         mp = dp->i_mount;
788
789         ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
790         /*
791          * Give up if the directory is way too short.
792          */
793         if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
794                 ASSERT(XFS_FORCED_SHUTDOWN(mp));
795                 return XFS_ERROR(EIO);
796         }
797
798         ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
799         ASSERT(dp->i_df.if_u1.if_data != NULL);
800
801         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
802
803         ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
804
805         /*
806          * If the block number in the offset is out of range, we're done.
807          */
808         if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk)
809                 return 0;
810
811         /*
812          * Precalculate offsets for . and .. as we will always need them.
813          *
814          * XXX(hch): the second argument is sometimes 0 and sometimes
815          * mp->m_dirdatablk.
816          */
817         dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
818                                              XFS_DIR2_DATA_DOT_OFFSET);
819         dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
820                                                 XFS_DIR2_DATA_DOTDOT_OFFSET);
821
822         /*
823          * Put . entry unless we're starting past it.
824          */
825         if (*offset <= dot_offset) {
826                 if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, dp->i_ino, DT_DIR)) {
827                         *offset = dot_offset & 0x7fffffff;
828                         return 0;
829                 }
830         }
831
832         /*
833          * Put .. entry unless we're starting past it.
834          */
835         if (*offset <= dotdot_offset) {
836                 ino = xfs_dir2_sf_get_parent_ino(sfp);
837                 if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) {
838                         *offset = dotdot_offset & 0x7fffffff;
839                         return 0;
840                 }
841         }
842
843         /*
844          * Loop while there are more entries and put'ing works.
845          */
846         sfep = xfs_dir2_sf_firstentry(sfp);
847         for (i = 0; i < sfp->count; i++) {
848                 off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
849                                 xfs_dir2_sf_get_offset(sfep));
850
851                 if (*offset > off) {
852                         sfep = xfs_dir2_sf_nextentry(sfp, sfep);
853                         continue;
854                 }
855
856                 ino = xfs_dir2_sfe_get_ino(sfp, sfep);
857                 if (filldir(dirent, (char *)sfep->name, sfep->namelen,
858                             off & 0x7fffffff, ino, DT_UNKNOWN)) {
859                         *offset = off & 0x7fffffff;
860                         return 0;
861                 }
862                 sfep = xfs_dir2_sf_nextentry(sfp, sfep);
863         }
864
865         *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
866                         0x7fffffff;
867         return 0;
868 }
869
870 /*
871  * Lookup an entry in a shortform directory.
872  * Returns EEXIST if found, ENOENT if not found.
873  */
874 int                                             /* error */
875 xfs_dir2_sf_lookup(
876         xfs_da_args_t           *args)          /* operation arguments */
877 {
878         xfs_inode_t             *dp;            /* incore directory inode */
879         int                     i;              /* entry index */
880         int                     error;
881         xfs_dir2_sf_entry_t     *sfep;          /* shortform directory entry */
882         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
883         enum xfs_dacmp          cmp;            /* comparison result */
884         xfs_dir2_sf_entry_t     *ci_sfep;       /* case-insens. entry */
885
886         trace_xfs_dir2_sf_lookup(args);
887
888         xfs_dir2_sf_check(args);
889         dp = args->dp;
890
891         ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
892         /*
893          * Bail out if the directory is way too short.
894          */
895         if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
896                 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
897                 return XFS_ERROR(EIO);
898         }
899         ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
900         ASSERT(dp->i_df.if_u1.if_data != NULL);
901         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
902         ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
903         /*
904          * Special case for .
905          */
906         if (args->namelen == 1 && args->name[0] == '.') {
907                 args->inumber = dp->i_ino;
908                 args->cmpresult = XFS_CMP_EXACT;
909                 return XFS_ERROR(EEXIST);
910         }
911         /*
912          * Special case for ..
913          */
914         if (args->namelen == 2 &&
915             args->name[0] == '.' && args->name[1] == '.') {
916                 args->inumber = xfs_dir2_sf_get_parent_ino(sfp);
917                 args->cmpresult = XFS_CMP_EXACT;
918                 return XFS_ERROR(EEXIST);
919         }
920         /*
921          * Loop over all the entries trying to match ours.
922          */
923         ci_sfep = NULL;
924         for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
925                                 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
926                 /*
927                  * Compare name and if it's an exact match, return the inode
928                  * number. If it's the first case-insensitive match, store the
929                  * inode number and continue looking for an exact match.
930                  */
931                 cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name,
932                                                                 sfep->namelen);
933                 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
934                         args->cmpresult = cmp;
935                         args->inumber = xfs_dir2_sfe_get_ino(sfp, sfep);
936                         if (cmp == XFS_CMP_EXACT)
937                                 return XFS_ERROR(EEXIST);
938                         ci_sfep = sfep;
939                 }
940         }
941         ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
942         /*
943          * Here, we can only be doing a lookup (not a rename or replace).
944          * If a case-insensitive match was not found, return ENOENT.
945          */
946         if (!ci_sfep)
947                 return XFS_ERROR(ENOENT);
948         /* otherwise process the CI match as required by the caller */
949         error = xfs_dir_cilookup_result(args, ci_sfep->name, ci_sfep->namelen);
950         return XFS_ERROR(error);
951 }
952
953 /*
954  * Remove an entry from a shortform directory.
955  */
956 int                                             /* error */
957 xfs_dir2_sf_removename(
958         xfs_da_args_t           *args)
959 {
960         int                     byteoff;        /* offset of removed entry */
961         xfs_inode_t             *dp;            /* incore directory inode */
962         int                     entsize;        /* this entry's size */
963         int                     i;              /* shortform entry index */
964         int                     newsize;        /* new inode size */
965         int                     oldsize;        /* old inode size */
966         xfs_dir2_sf_entry_t     *sfep;          /* shortform directory entry */
967         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
968
969         trace_xfs_dir2_sf_removename(args);
970
971         dp = args->dp;
972
973         ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
974         oldsize = (int)dp->i_d.di_size;
975         /*
976          * Bail out if the directory is way too short.
977          */
978         if (oldsize < offsetof(xfs_dir2_sf_hdr_t, parent)) {
979                 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
980                 return XFS_ERROR(EIO);
981         }
982         ASSERT(dp->i_df.if_bytes == oldsize);
983         ASSERT(dp->i_df.if_u1.if_data != NULL);
984         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
985         ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->i8count));
986         /*
987          * Loop over the old directory entries.
988          * Find the one we're deleting.
989          */
990         for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
991                                 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
992                 if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
993                                                                 XFS_CMP_EXACT) {
994                         ASSERT(xfs_dir2_sfe_get_ino(sfp, sfep) ==
995                                args->inumber);
996                         break;
997                 }
998         }
999         /*
1000          * Didn't find it.
1001          */
1002         if (i == sfp->count)
1003                 return XFS_ERROR(ENOENT);
1004         /*
1005          * Calculate sizes.
1006          */
1007         byteoff = (int)((char *)sfep - (char *)sfp);
1008         entsize = xfs_dir2_sf_entsize(sfp, args->namelen);
1009         newsize = oldsize - entsize;
1010         /*
1011          * Copy the part if any after the removed entry, sliding it down.
1012          */
1013         if (byteoff + entsize < oldsize)
1014                 memmove((char *)sfp + byteoff, (char *)sfp + byteoff + entsize,
1015                         oldsize - (byteoff + entsize));
1016         /*
1017          * Fix up the header and file size.
1018          */
1019         sfp->count--;
1020         dp->i_d.di_size = newsize;
1021         /*
1022          * Reallocate, making it smaller.
1023          */
1024         xfs_idata_realloc(dp, newsize - oldsize, XFS_DATA_FORK);
1025         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
1026 #if XFS_BIG_INUMS
1027         /*
1028          * Are we changing inode number size?
1029          */
1030         if (args->inumber > XFS_DIR2_MAX_SHORT_INUM) {
1031                 if (sfp->i8count == 1)
1032                         xfs_dir2_sf_toino4(args);
1033                 else
1034                         sfp->i8count--;
1035         }
1036 #endif
1037         xfs_dir2_sf_check(args);
1038         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
1039         return 0;
1040 }
1041
1042 /*
1043  * Replace the inode number of an entry in a shortform directory.
1044  */
1045 int                                             /* error */
1046 xfs_dir2_sf_replace(
1047         xfs_da_args_t           *args)          /* operation arguments */
1048 {
1049         xfs_inode_t             *dp;            /* incore directory inode */
1050         int                     i;              /* entry index */
1051 #if XFS_BIG_INUMS || defined(DEBUG)
1052         xfs_ino_t               ino=0;          /* entry old inode number */
1053 #endif
1054 #if XFS_BIG_INUMS
1055         int                     i8elevated;     /* sf_toino8 set i8count=1 */
1056 #endif
1057         xfs_dir2_sf_entry_t     *sfep;          /* shortform directory entry */
1058         xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
1059
1060         trace_xfs_dir2_sf_replace(args);
1061
1062         dp = args->dp;
1063
1064         ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
1065         /*
1066          * Bail out if the shortform directory is way too small.
1067          */
1068         if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
1069                 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
1070                 return XFS_ERROR(EIO);
1071         }
1072         ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
1073         ASSERT(dp->i_df.if_u1.if_data != NULL);
1074         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
1075         ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
1076 #if XFS_BIG_INUMS
1077         /*
1078          * New inode number is large, and need to convert to 8-byte inodes.
1079          */
1080         if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) {
1081                 int     error;                  /* error return value */
1082                 int     newsize;                /* new inode size */
1083
1084                 newsize =
1085                         dp->i_df.if_bytes +
1086                         (sfp->count + 1) *
1087                         ((uint)sizeof(xfs_dir2_ino8_t) -
1088                          (uint)sizeof(xfs_dir2_ino4_t));
1089                 /*
1090                  * Won't fit as shortform, convert to block then do replace.
1091                  */
1092                 if (newsize > XFS_IFORK_DSIZE(dp)) {
1093                         error = xfs_dir2_sf_to_block(args);
1094                         if (error) {
1095                                 return error;
1096                         }
1097                         return xfs_dir2_block_replace(args);
1098                 }
1099                 /*
1100                  * Still fits, convert to 8-byte now.
1101                  */
1102                 xfs_dir2_sf_toino8(args);
1103                 i8elevated = 1;
1104                 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
1105         } else
1106                 i8elevated = 0;
1107 #endif
1108         ASSERT(args->namelen != 1 || args->name[0] != '.');
1109         /*
1110          * Replace ..'s entry.
1111          */
1112         if (args->namelen == 2 &&
1113             args->name[0] == '.' && args->name[1] == '.') {
1114 #if XFS_BIG_INUMS || defined(DEBUG)
1115                 ino = xfs_dir2_sf_get_parent_ino(sfp);
1116                 ASSERT(args->inumber != ino);
1117 #endif
1118                 xfs_dir2_sf_put_parent_ino(sfp, args->inumber);
1119         }
1120         /*
1121          * Normal entry, look for the name.
1122          */
1123         else {
1124                 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
1125                                 i < sfp->count;
1126                                 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
1127                         if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
1128                                                                 XFS_CMP_EXACT) {
1129 #if XFS_BIG_INUMS || defined(DEBUG)
1130                                 ino = xfs_dir2_sfe_get_ino(sfp, sfep);
1131                                 ASSERT(args->inumber != ino);
1132 #endif
1133                                 xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber);
1134                                 break;
1135                         }
1136                 }
1137                 /*
1138                  * Didn't find it.
1139                  */
1140                 if (i == sfp->count) {
1141                         ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
1142 #if XFS_BIG_INUMS
1143                         if (i8elevated)
1144                                 xfs_dir2_sf_toino4(args);
1145 #endif
1146                         return XFS_ERROR(ENOENT);
1147                 }
1148         }
1149 #if XFS_BIG_INUMS
1150         /*
1151          * See if the old number was large, the new number is small.
1152          */
1153         if (ino > XFS_DIR2_MAX_SHORT_INUM &&
1154             args->inumber <= XFS_DIR2_MAX_SHORT_INUM) {
1155                 /*
1156                  * And the old count was one, so need to convert to small.
1157                  */
1158                 if (sfp->i8count == 1)
1159                         xfs_dir2_sf_toino4(args);
1160                 else
1161                         sfp->i8count--;
1162         }
1163         /*
1164          * See if the old number was small, the new number is large.
1165          */
1166         if (ino <= XFS_DIR2_MAX_SHORT_INUM &&
1167             args->inumber > XFS_DIR2_MAX_SHORT_INUM) {
1168                 /*
1169                  * add to the i8count unless we just converted to 8-byte
1170                  * inodes (which does an implied i8count = 1)
1171                  */
1172                 ASSERT(sfp->i8count != 0);
1173                 if (!i8elevated)
1174                         sfp->i8count++;
1175         }
1176 #endif
1177         xfs_dir2_sf_check(args);
1178         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
1179         return 0;
1180 }
1181
1182 #if XFS_BIG_INUMS
1183 /*
1184  * Convert from 8-byte inode numbers to 4-byte inode numbers.
1185  * The last 8-byte inode number is gone, but the count is still 1.
1186  */
1187 static void
1188 xfs_dir2_sf_toino4(
1189         xfs_da_args_t           *args)          /* operation arguments */
1190 {
1191         char                    *buf;           /* old dir's buffer */
1192         xfs_inode_t             *dp;            /* incore directory inode */
1193         int                     i;              /* entry index */
1194         int                     newsize;        /* new inode size */
1195         xfs_dir2_sf_entry_t     *oldsfep;       /* old sf entry */
1196         xfs_dir2_sf_hdr_t       *oldsfp;        /* old sf directory */
1197         int                     oldsize;        /* old inode size */
1198         xfs_dir2_sf_entry_t     *sfep;          /* new sf entry */
1199         xfs_dir2_sf_hdr_t       *sfp;           /* new sf directory */
1200
1201         trace_xfs_dir2_sf_toino4(args);
1202
1203         dp = args->dp;
1204
1205         /*
1206          * Copy the old directory to the buffer.
1207          * Then nuke it from the inode, and add the new buffer to the inode.
1208          * Don't want xfs_idata_realloc copying the data here.
1209          */
1210         oldsize = dp->i_df.if_bytes;
1211         buf = kmem_alloc(oldsize, KM_SLEEP);
1212         oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
1213         ASSERT(oldsfp->i8count == 1);
1214         memcpy(buf, oldsfp, oldsize);
1215         /*
1216          * Compute the new inode size.
1217          */
1218         newsize =
1219                 oldsize -
1220                 (oldsfp->count + 1) *
1221                 ((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t));
1222         xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK);
1223         xfs_idata_realloc(dp, newsize, XFS_DATA_FORK);
1224         /*
1225          * Reset our pointers, the data has moved.
1226          */
1227         oldsfp = (xfs_dir2_sf_hdr_t *)buf;
1228         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
1229         /*
1230          * Fill in the new header.
1231          */
1232         sfp->count = oldsfp->count;
1233         sfp->i8count = 0;
1234         xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp));
1235         /*
1236          * Copy the entries field by field.
1237          */
1238         for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1239                     oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1240              i < sfp->count;
1241              i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
1242                   oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
1243                 sfep->namelen = oldsfep->namelen;
1244                 sfep->offset = oldsfep->offset;
1245                 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1246                 xfs_dir2_sfe_put_ino(sfp, sfep,
1247                         xfs_dir2_sfe_get_ino(oldsfp, oldsfep));
1248         }
1249         /*
1250          * Clean up the inode.
1251          */
1252         kmem_free(buf);
1253         dp->i_d.di_size = newsize;
1254         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
1255 }
1256
1257 /*
1258  * Convert from 4-byte inode numbers to 8-byte inode numbers.
1259  * The new 8-byte inode number is not there yet, we leave with the
1260  * count 1 but no corresponding entry.
1261  */
1262 static void
1263 xfs_dir2_sf_toino8(
1264         xfs_da_args_t           *args)          /* operation arguments */
1265 {
1266         char                    *buf;           /* old dir's buffer */
1267         xfs_inode_t             *dp;            /* incore directory inode */
1268         int                     i;              /* entry index */
1269         int                     newsize;        /* new inode size */
1270         xfs_dir2_sf_entry_t     *oldsfep;       /* old sf entry */
1271         xfs_dir2_sf_hdr_t       *oldsfp;        /* old sf directory */
1272         int                     oldsize;        /* old inode size */
1273         xfs_dir2_sf_entry_t     *sfep;          /* new sf entry */
1274         xfs_dir2_sf_hdr_t       *sfp;           /* new sf directory */
1275
1276         trace_xfs_dir2_sf_toino8(args);
1277
1278         dp = args->dp;
1279
1280         /*
1281          * Copy the old directory to the buffer.
1282          * Then nuke it from the inode, and add the new buffer to the inode.
1283          * Don't want xfs_idata_realloc copying the data here.
1284          */
1285         oldsize = dp->i_df.if_bytes;
1286         buf = kmem_alloc(oldsize, KM_SLEEP);
1287         oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
1288         ASSERT(oldsfp->i8count == 0);
1289         memcpy(buf, oldsfp, oldsize);
1290         /*
1291          * Compute the new inode size.
1292          */
1293         newsize =
1294                 oldsize +
1295                 (oldsfp->count + 1) *
1296                 ((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t));
1297         xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK);
1298         xfs_idata_realloc(dp, newsize, XFS_DATA_FORK);
1299         /*
1300          * Reset our pointers, the data has moved.
1301          */
1302         oldsfp = (xfs_dir2_sf_hdr_t *)buf;
1303         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
1304         /*
1305          * Fill in the new header.
1306          */
1307         sfp->count = oldsfp->count;
1308         sfp->i8count = 1;
1309         xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp));
1310         /*
1311          * Copy the entries field by field.
1312          */
1313         for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1314                     oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1315              i < sfp->count;
1316              i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
1317                   oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
1318                 sfep->namelen = oldsfep->namelen;
1319                 sfep->offset = oldsfep->offset;
1320                 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1321                 xfs_dir2_sfe_put_ino(sfp, sfep,
1322                         xfs_dir2_sfe_get_ino(oldsfp, oldsfep));
1323         }
1324         /*
1325          * Clean up the inode.
1326          */
1327         kmem_free(buf);
1328         dp->i_d.di_size = newsize;
1329         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
1330 }
1331 #endif  /* XFS_BIG_INUMS */