Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / fs / xfs / xfs_dir2.c
1 /*
2  * Copyright (c) 2000-2001,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_bit.h"
22 #include "xfs_log.h"
23 #include "xfs_inum.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_dir.h"
28 #include "xfs_dir2.h"
29 #include "xfs_dmapi.h"
30 #include "xfs_mount.h"
31 #include "xfs_da_btree.h"
32 #include "xfs_bmap_btree.h"
33 #include "xfs_alloc_btree.h"
34 #include "xfs_dir_sf.h"
35 #include "xfs_dir2_sf.h"
36 #include "xfs_attr_sf.h"
37 #include "xfs_dinode.h"
38 #include "xfs_inode.h"
39 #include "xfs_inode_item.h"
40 #include "xfs_bmap.h"
41 #include "xfs_dir_leaf.h"
42 #include "xfs_dir2_data.h"
43 #include "xfs_dir2_leaf.h"
44 #include "xfs_dir2_block.h"
45 #include "xfs_dir2_node.h"
46 #include "xfs_dir2_trace.h"
47 #include "xfs_error.h"
48
49 /*
50  * Declarations for interface routines.
51  */
52 static void     xfs_dir2_mount(xfs_mount_t *mp);
53 static int      xfs_dir2_isempty(xfs_inode_t *dp);
54 static int      xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp,
55                               xfs_inode_t *pdp);
56 static int      xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp,
57                                     char *name, int namelen, xfs_ino_t inum,
58                                     xfs_fsblock_t *first,
59                                     xfs_bmap_free_t *flist, xfs_extlen_t total);
60 static int      xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
61                                 int namelen, xfs_ino_t *inum);
62 static int      xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp,
63                                     char *name, int namelen, xfs_ino_t ino,
64                                     xfs_fsblock_t *first,
65                                     xfs_bmap_free_t *flist, xfs_extlen_t total);
66 static int      xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio,
67                                   int *eofp);
68 static int      xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
69                                  int namelen, xfs_ino_t inum,
70                                  xfs_fsblock_t *first, xfs_bmap_free_t *flist,
71                                  xfs_extlen_t total);
72 static int      xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
73                                   int namelen);
74 static int      xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp,
75                                                    xfs_dinode_t *dip);
76
77 /*
78  * Utility routine declarations.
79  */
80 static int      xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
81 static int      xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
82
83 /*
84  * Directory operations vector.
85  */
86 xfs_dirops_t    xfsv2_dirops = {
87         .xd_mount                       = xfs_dir2_mount,
88         .xd_isempty                     = xfs_dir2_isempty,
89         .xd_init                        = xfs_dir2_init,
90         .xd_createname                  = xfs_dir2_createname,
91         .xd_lookup                      = xfs_dir2_lookup,
92         .xd_removename                  = xfs_dir2_removename,
93         .xd_getdents                    = xfs_dir2_getdents,
94         .xd_replace                     = xfs_dir2_replace,
95         .xd_canenter                    = xfs_dir2_canenter,
96         .xd_shortform_validate_ondisk   = xfs_dir2_shortform_validate_ondisk,
97         .xd_shortform_to_single         = xfs_dir2_sf_to_block,
98 };
99
100 /*
101  * Interface routines.
102  */
103
104 /*
105  * Initialize directory-related fields in the mount structure.
106  */
107 static void
108 xfs_dir2_mount(
109         xfs_mount_t     *mp)            /* filesystem mount point */
110 {
111         mp->m_dirversion = 2;
112         ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
113                XFS_MAX_BLOCKSIZE);
114         mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
115         mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
116         mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp));
117         mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
118         mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp));
119         mp->m_attr_node_ents =
120                 (mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
121                 (uint)sizeof(xfs_da_node_entry_t);
122         mp->m_dir_node_ents =
123                 (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) /
124                 (uint)sizeof(xfs_da_node_entry_t);
125         mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
126 }
127
128 /*
129  * Return 1 if directory contains only "." and "..".
130  */
131 static int                              /* return code */
132 xfs_dir2_isempty(
133         xfs_inode_t     *dp)            /* incore inode structure */
134 {
135         xfs_dir2_sf_t   *sfp;           /* shortform directory structure */
136
137         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
138         /*
139          * Might happen during shutdown.
140          */
141         if (dp->i_d.di_size == 0) {
142                 return 1;
143         }
144         if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
145                 return 0;
146         sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
147         return !sfp->hdr.count;
148 }
149
150 /*
151  * Initialize a directory with its "." and ".." entries.
152  */
153 static int                              /* error */
154 xfs_dir2_init(
155         xfs_trans_t     *tp,            /* transaction pointer */
156         xfs_inode_t     *dp,            /* incore directory inode */
157         xfs_inode_t     *pdp)           /* incore parent directory inode */
158 {
159         xfs_da_args_t   args;           /* operation arguments */
160         int             error;          /* error return value */
161
162         memset((char *)&args, 0, sizeof(args));
163         args.dp = dp;
164         args.trans = tp;
165         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
166         if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) {
167                 return error;
168         }
169         return xfs_dir2_sf_create(&args, pdp->i_ino);
170 }
171
172 /*
173   Enter a name in a directory.
174  */
175 static int                                      /* error */
176 xfs_dir2_createname(
177         xfs_trans_t             *tp,            /* transaction pointer */
178         xfs_inode_t             *dp,            /* incore directory inode */
179         char                    *name,          /* new entry name */
180         int                     namelen,        /* new entry name length */
181         xfs_ino_t               inum,           /* new entry inode number */
182         xfs_fsblock_t           *first,         /* bmap's firstblock */
183         xfs_bmap_free_t         *flist,         /* bmap's freeblock list */
184         xfs_extlen_t            total)          /* bmap's total block count */
185 {
186         xfs_da_args_t           args;           /* operation arguments */
187         int                     rval;           /* return value */
188         int                     v;              /* type-checking value */
189
190         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
191         if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
192                 return rval;
193         }
194         XFS_STATS_INC(xs_dir_create);
195         /*
196          * Fill in the arg structure for this request.
197          */
198         args.name = name;
199         args.namelen = namelen;
200         args.hashval = xfs_da_hashname(name, namelen);
201         args.inumber = inum;
202         args.dp = dp;
203         args.firstblock = first;
204         args.flist = flist;
205         args.total = total;
206         args.whichfork = XFS_DATA_FORK;
207         args.trans = tp;
208         args.justcheck = 0;
209         args.addname = args.oknoent = 1;
210         /*
211          * Decide on what work routines to call based on the inode size.
212          */
213         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
214                 rval = xfs_dir2_sf_addname(&args);
215         else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
216                 return rval;
217         } else if (v)
218                 rval = xfs_dir2_block_addname(&args);
219         else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
220                 return rval;
221         } else if (v)
222                 rval = xfs_dir2_leaf_addname(&args);
223         else
224                 rval = xfs_dir2_node_addname(&args);
225         return rval;
226 }
227
228 /*
229  * Lookup a name in a directory, give back the inode number.
230  */
231 static int                              /* error */
232 xfs_dir2_lookup(
233         xfs_trans_t     *tp,            /* transaction pointer */
234         xfs_inode_t     *dp,            /* incore directory inode */
235         char            *name,          /* lookup name */
236         int             namelen,        /* lookup name length */
237         xfs_ino_t       *inum)          /* out: inode number */
238 {
239         xfs_da_args_t   args;           /* operation arguments */
240         int             rval;           /* return value */
241         int             v;              /* type-checking value */
242
243         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
244         XFS_STATS_INC(xs_dir_lookup);
245
246         /*
247          * Fill in the arg structure for this request.
248          */
249         args.name = name;
250         args.namelen = namelen;
251         args.hashval = xfs_da_hashname(name, namelen);
252         args.inumber = 0;
253         args.dp = dp;
254         args.firstblock = NULL;
255         args.flist = NULL;
256         args.total = 0;
257         args.whichfork = XFS_DATA_FORK;
258         args.trans = tp;
259         args.justcheck = args.addname = 0;
260         args.oknoent = 1;
261         /*
262          * Decide on what work routines to call based on the inode size.
263          */
264         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
265                 rval = xfs_dir2_sf_lookup(&args);
266         else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
267                 return rval;
268         } else if (v)
269                 rval = xfs_dir2_block_lookup(&args);
270         else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
271                 return rval;
272         } else if (v)
273                 rval = xfs_dir2_leaf_lookup(&args);
274         else
275                 rval = xfs_dir2_node_lookup(&args);
276         if (rval == EEXIST)
277                 rval = 0;
278         if (rval == 0)
279                 *inum = args.inumber;
280         return rval;
281 }
282
283 /*
284  * Remove an entry from a directory.
285  */
286 static int                              /* error */
287 xfs_dir2_removename(
288         xfs_trans_t     *tp,            /* transaction pointer */
289         xfs_inode_t     *dp,            /* incore directory inode */
290         char            *name,          /* name of entry to remove */
291         int             namelen,        /* name length of entry to remove */
292         xfs_ino_t       ino,            /* inode number of entry to remove */
293         xfs_fsblock_t   *first,         /* bmap's firstblock */
294         xfs_bmap_free_t *flist,         /* bmap's freeblock list */
295         xfs_extlen_t    total)          /* bmap's total block count */
296 {
297         xfs_da_args_t   args;           /* operation arguments */
298         int             rval;           /* return value */
299         int             v;              /* type-checking value */
300
301         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
302         XFS_STATS_INC(xs_dir_remove);
303         /*
304          * Fill in the arg structure for this request.
305          */
306         args.name = name;
307         args.namelen = namelen;
308         args.hashval = xfs_da_hashname(name, namelen);
309         args.inumber = ino;
310         args.dp = dp;
311         args.firstblock = first;
312         args.flist = flist;
313         args.total = total;
314         args.whichfork = XFS_DATA_FORK;
315         args.trans = tp;
316         args.justcheck = args.addname = args.oknoent = 0;
317         /*
318          * Decide on what work routines to call based on the inode size.
319          */
320         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
321                 rval = xfs_dir2_sf_removename(&args);
322         else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
323                 return rval;
324         } else if (v)
325                 rval = xfs_dir2_block_removename(&args);
326         else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
327                 return rval;
328         } else if (v)
329                 rval = xfs_dir2_leaf_removename(&args);
330         else
331                 rval = xfs_dir2_node_removename(&args);
332         return rval;
333 }
334
335 /*
336  * Read a directory.
337  */
338 static int                              /* error */
339 xfs_dir2_getdents(
340         xfs_trans_t     *tp,            /* transaction pointer */
341         xfs_inode_t     *dp,            /* incore directory inode */
342         uio_t           *uio,           /* caller's buffer control */
343         int             *eofp)          /* out: eof reached */
344 {
345         int             alignment;      /* alignment required for ABI */
346         xfs_dirent_t    *dbp;           /* malloc'ed buffer */
347         xfs_dir2_put_t  put;            /* entry formatting routine */
348         int             rval;           /* return value */
349         int             v;              /* type-checking value */
350
351         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
352         XFS_STATS_INC(xs_dir_getdents);
353         /*
354          * If our caller has given us a single contiguous aligned memory buffer,
355          * just work directly within that buffer.  If it's in user memory,
356          * lock it down first.
357          */
358         alignment = sizeof(xfs_off_t) - 1;
359         if ((uio->uio_iovcnt == 1) &&
360             (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
361             ((uio->uio_iov[0].iov_len & alignment) == 0)) {
362                 dbp = NULL;
363                 put = xfs_dir2_put_dirent64_direct;
364         } else {
365                 dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
366                 put = xfs_dir2_put_dirent64_uio;
367         }
368
369         *eofp = 0;
370         /*
371          * Decide on what work routines to call based on the inode size.
372          */
373         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
374                 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
375         else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
376                 ;
377         } else if (v)
378                 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
379         else
380                 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
381         if (dbp != NULL)
382                 kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
383         return rval;
384 }
385
386 /*
387  * Replace the inode number of a directory entry.
388  */
389 static int                              /* error */
390 xfs_dir2_replace(
391         xfs_trans_t     *tp,            /* transaction pointer */
392         xfs_inode_t     *dp,            /* incore directory inode */
393         char            *name,          /* name of entry to replace */
394         int             namelen,        /* name length of entry to replace */
395         xfs_ino_t       inum,           /* new inode number */
396         xfs_fsblock_t   *first,         /* bmap's firstblock */
397         xfs_bmap_free_t *flist,         /* bmap's freeblock list */
398         xfs_extlen_t    total)          /* bmap's total block count */
399 {
400         xfs_da_args_t   args;           /* operation arguments */
401         int             rval;           /* return value */
402         int             v;              /* type-checking value */
403
404         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
405
406         if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
407                 return rval;
408         }
409         /*
410          * Fill in the arg structure for this request.
411          */
412         args.name = name;
413         args.namelen = namelen;
414         args.hashval = xfs_da_hashname(name, namelen);
415         args.inumber = inum;
416         args.dp = dp;
417         args.firstblock = first;
418         args.flist = flist;
419         args.total = total;
420         args.whichfork = XFS_DATA_FORK;
421         args.trans = tp;
422         args.justcheck = args.addname = args.oknoent = 0;
423         /*
424          * Decide on what work routines to call based on the inode size.
425          */
426         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
427                 rval = xfs_dir2_sf_replace(&args);
428         else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
429                 return rval;
430         } else if (v)
431                 rval = xfs_dir2_block_replace(&args);
432         else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
433                 return rval;
434         } else if (v)
435                 rval = xfs_dir2_leaf_replace(&args);
436         else
437                 rval = xfs_dir2_node_replace(&args);
438         return rval;
439 }
440
441 /*
442  * See if this entry can be added to the directory without allocating space.
443  */
444 static int                              /* error */
445 xfs_dir2_canenter(
446         xfs_trans_t     *tp,            /* transaction pointer */
447         xfs_inode_t     *dp,            /* incore directory inode */
448         char            *name,          /* name of entry to add */
449         int             namelen)        /* name length of entry to add */
450 {
451         xfs_da_args_t   args;           /* operation arguments */
452         int             rval;           /* return value */
453         int             v;              /* type-checking value */
454
455         ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
456         /*
457          * Fill in the arg structure for this request.
458          */
459         args.name = name;
460         args.namelen = namelen;
461         args.hashval = xfs_da_hashname(name, namelen);
462         args.inumber = 0;
463         args.dp = dp;
464         args.firstblock = NULL;
465         args.flist = NULL;
466         args.total = 0;
467         args.whichfork = XFS_DATA_FORK;
468         args.trans = tp;
469         args.justcheck = args.addname = args.oknoent = 1;
470         /*
471          * Decide on what work routines to call based on the inode size.
472          */
473         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
474                 rval = xfs_dir2_sf_addname(&args);
475         else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
476                 return rval;
477         } else if (v)
478                 rval = xfs_dir2_block_addname(&args);
479         else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
480                 return rval;
481         } else if (v)
482                 rval = xfs_dir2_leaf_addname(&args);
483         else
484                 rval = xfs_dir2_node_addname(&args);
485         return rval;
486 }
487
488 /*
489  * Dummy routine for shortform inode validation.
490  * Can't really do this.
491  */
492 /* ARGSUSED */
493 static int                              /* error */
494 xfs_dir2_shortform_validate_ondisk(
495         xfs_mount_t     *mp,            /* filesystem mount point */
496         xfs_dinode_t    *dip)           /* ondisk inode */
497 {
498         return 0;
499 }
500
501 /*
502  * Utility routines.
503  */
504
505 /*
506  * Add a block to the directory.
507  * This routine is for data and free blocks, not leaf/node blocks
508  * which are handled by xfs_da_grow_inode.
509  */
510 int                                     /* error */
511 xfs_dir2_grow_inode(
512         xfs_da_args_t   *args,          /* operation arguments */
513         int             space,          /* v2 dir's space XFS_DIR2_xxx_SPACE */
514         xfs_dir2_db_t   *dbp)           /* out: block number added */
515 {
516         xfs_fileoff_t   bno;            /* directory offset of new block */
517         int             count;          /* count of filesystem blocks */
518         xfs_inode_t     *dp;            /* incore directory inode */
519         int             error;          /* error return value */
520         int             got;            /* blocks actually mapped */
521         int             i;              /* temp mapping index */
522         xfs_bmbt_irec_t map;            /* single structure for bmap */
523         int             mapi;           /* mapping index */
524         xfs_bmbt_irec_t *mapp;          /* bmap mapping structure(s) */
525         xfs_mount_t     *mp;            /* filesystem mount point */
526         int             nmap;           /* number of bmap entries */
527         xfs_trans_t     *tp;            /* transaction pointer */
528
529         xfs_dir2_trace_args_s("grow_inode", args, space);
530         dp = args->dp;
531         tp = args->trans;
532         mp = dp->i_mount;
533         /*
534          * Set lowest possible block in the space requested.
535          */
536         bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
537         count = mp->m_dirblkfsbs;
538         /*
539          * Find the first hole for our block.
540          */
541         if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) {
542                 return error;
543         }
544         nmap = 1;
545         ASSERT(args->firstblock != NULL);
546         /*
547          * Try mapping the new block contiguously (one extent).
548          */
549         if ((error = xfs_bmapi(tp, dp, bno, count,
550                         XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
551                         args->firstblock, args->total, &map, &nmap,
552                         args->flist))) {
553                 return error;
554         }
555         ASSERT(nmap <= 1);
556         /*
557          * Got it in 1.
558          */
559         if (nmap == 1) {
560                 mapp = &map;
561                 mapi = 1;
562         }
563         /*
564          * Didn't work and this is a multiple-fsb directory block.
565          * Try again with contiguous flag turned on.
566          */
567         else if (nmap == 0 && count > 1) {
568                 xfs_fileoff_t   b;      /* current file offset */
569
570                 /*
571                  * Space for maximum number of mappings.
572                  */
573                 mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
574                 /*
575                  * Iterate until we get to the end of our block.
576                  */
577                 for (b = bno, mapi = 0; b < bno + count; ) {
578                         int     c;      /* current fsb count */
579
580                         /*
581                          * Can't map more than MAX_NMAP at once.
582                          */
583                         nmap = MIN(XFS_BMAP_MAX_NMAP, count);
584                         c = (int)(bno + count - b);
585                         if ((error = xfs_bmapi(tp, dp, b, c,
586                                         XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
587                                         args->firstblock, args->total,
588                                         &mapp[mapi], &nmap, args->flist))) {
589                                 kmem_free(mapp, sizeof(*mapp) * count);
590                                 return error;
591                         }
592                         if (nmap < 1)
593                                 break;
594                         /*
595                          * Add this bunch into our table, go to the next offset.
596                          */
597                         mapi += nmap;
598                         b = mapp[mapi - 1].br_startoff +
599                             mapp[mapi - 1].br_blockcount;
600                 }
601         }
602         /*
603          * Didn't work.
604          */
605         else {
606                 mapi = 0;
607                 mapp = NULL;
608         }
609         /*
610          * See how many fsb's we got.
611          */
612         for (i = 0, got = 0; i < mapi; i++)
613                 got += mapp[i].br_blockcount;
614         /*
615          * Didn't get enough fsb's, or the first/last block's are wrong.
616          */
617         if (got != count || mapp[0].br_startoff != bno ||
618             mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
619             bno + count) {
620                 if (mapp != &map)
621                         kmem_free(mapp, sizeof(*mapp) * count);
622                 return XFS_ERROR(ENOSPC);
623         }
624         /*
625          * Done with the temporary mapping table.
626          */
627         if (mapp != &map)
628                 kmem_free(mapp, sizeof(*mapp) * count);
629         *dbp = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)bno);
630         /*
631          * Update file's size if this is the data space and it grew.
632          */
633         if (space == XFS_DIR2_DATA_SPACE) {
634                 xfs_fsize_t     size;           /* directory file (data) size */
635
636                 size = XFS_FSB_TO_B(mp, bno + count);
637                 if (size > dp->i_d.di_size) {
638                         dp->i_d.di_size = size;
639                         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
640                 }
641         }
642         return 0;
643 }
644
645 /*
646  * See if the directory is a single-block form directory.
647  */
648 int                                     /* error */
649 xfs_dir2_isblock(
650         xfs_trans_t     *tp,            /* transaction pointer */
651         xfs_inode_t     *dp,            /* incore directory inode */
652         int             *vp)            /* out: 1 is block, 0 is not block */
653 {
654         xfs_fileoff_t   last;           /* last file offset */
655         xfs_mount_t     *mp;            /* filesystem mount point */
656         int             rval;           /* return value */
657
658         mp = dp->i_mount;
659         if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
660                 return rval;
661         }
662         rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
663         ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
664         *vp = rval;
665         return 0;
666 }
667
668 /*
669  * See if the directory is a single-leaf form directory.
670  */
671 int                                     /* error */
672 xfs_dir2_isleaf(
673         xfs_trans_t     *tp,            /* transaction pointer */
674         xfs_inode_t     *dp,            /* incore directory inode */
675         int             *vp)            /* out: 1 is leaf, 0 is not leaf */
676 {
677         xfs_fileoff_t   last;           /* last file offset */
678         xfs_mount_t     *mp;            /* filesystem mount point */
679         int             rval;           /* return value */
680
681         mp = dp->i_mount;
682         if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
683                 return rval;
684         }
685         *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
686         return 0;
687 }
688
689 /*
690  * Getdents put routine for 64-bit ABI, direct form.
691  */
692 static int                                      /* error */
693 xfs_dir2_put_dirent64_direct(
694         xfs_dir2_put_args_t     *pa)            /* argument bundle */
695 {
696         xfs_dirent_t            *idbp;          /* dirent pointer */
697         iovec_t                 *iovp;          /* io vector */
698         int                     namelen;        /* entry name length */
699         int                     reclen;         /* entry total length */
700         uio_t                   *uio;           /* I/O control */
701
702         namelen = pa->namelen;
703         reclen = DIRENTSIZE(namelen);
704         uio = pa->uio;
705         /*
706          * Won't fit in the remaining space.
707          */
708         if (reclen > uio->uio_resid) {
709                 pa->done = 0;
710                 return 0;
711         }
712         iovp = uio->uio_iov;
713         idbp = (xfs_dirent_t *)iovp->iov_base;
714         iovp->iov_base = (char *)idbp + reclen;
715         iovp->iov_len -= reclen;
716         uio->uio_resid -= reclen;
717         idbp->d_reclen = reclen;
718         idbp->d_ino = pa->ino;
719         idbp->d_off = pa->cook;
720         idbp->d_name[namelen] = '\0';
721         pa->done = 1;
722         memcpy(idbp->d_name, pa->name, namelen);
723         return 0;
724 }
725
726 /*
727  * Getdents put routine for 64-bit ABI, uio form.
728  */
729 static int                                      /* error */
730 xfs_dir2_put_dirent64_uio(
731         xfs_dir2_put_args_t     *pa)            /* argument bundle */
732 {
733         xfs_dirent_t            *idbp;          /* dirent pointer */
734         int                     namelen;        /* entry name length */
735         int                     reclen;         /* entry total length */
736         int                     rval;           /* return value */
737         uio_t                   *uio;           /* I/O control */
738
739         namelen = pa->namelen;
740         reclen = DIRENTSIZE(namelen);
741         uio = pa->uio;
742         /*
743          * Won't fit in the remaining space.
744          */
745         if (reclen > uio->uio_resid) {
746                 pa->done = 0;
747                 return 0;
748         }
749         idbp = pa->dbp;
750         idbp->d_reclen = reclen;
751         idbp->d_ino = pa->ino;
752         idbp->d_off = pa->cook;
753         idbp->d_name[namelen] = '\0';
754         memcpy(idbp->d_name, pa->name, namelen);
755         rval = uio_read((caddr_t)idbp, reclen, uio);
756         pa->done = (rval == 0);
757         return rval;
758 }
759
760 /*
761  * Remove the given block from the directory.
762  * This routine is used for data and free blocks, leaf/node are done
763  * by xfs_da_shrink_inode.
764  */
765 int
766 xfs_dir2_shrink_inode(
767         xfs_da_args_t   *args,          /* operation arguments */
768         xfs_dir2_db_t   db,             /* directory block number */
769         xfs_dabuf_t     *bp)            /* block's buffer */
770 {
771         xfs_fileoff_t   bno;            /* directory file offset */
772         xfs_dablk_t     da;             /* directory file offset */
773         int             done;           /* bunmap is finished */
774         xfs_inode_t     *dp;            /* incore directory inode */
775         int             error;          /* error return value */
776         xfs_mount_t     *mp;            /* filesystem mount point */
777         xfs_trans_t     *tp;            /* transaction pointer */
778
779         xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
780         dp = args->dp;
781         mp = dp->i_mount;
782         tp = args->trans;
783         da = XFS_DIR2_DB_TO_DA(mp, db);
784         /*
785          * Unmap the fsblock(s).
786          */
787         if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
788                         XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
789                         &done))) {
790                 /*
791                  * ENOSPC actually can happen if we're in a removename with
792                  * no space reservation, and the resulting block removal
793                  * would cause a bmap btree split or conversion from extents
794                  * to btree.  This can only happen for un-fragmented
795                  * directory blocks, since you need to be punching out
796                  * the middle of an extent.
797                  * In this case we need to leave the block in the file,
798                  * and not binval it.
799                  * So the block has to be in a consistent empty state
800                  * and appropriately logged.
801                  * We don't free up the buffer, the caller can tell it
802                  * hasn't happened since it got an error back.
803                  */
804                 return error;
805         }
806         ASSERT(done);
807         /*
808          * Invalidate the buffer from the transaction.
809          */
810         xfs_da_binval(tp, bp);
811         /*
812          * If it's not a data block, we're done.
813          */
814         if (db >= XFS_DIR2_LEAF_FIRSTDB(mp))
815                 return 0;
816         /*
817          * If the block isn't the last one in the directory, we're done.
818          */
819         if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0))
820                 return 0;
821         bno = da;
822         if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
823                 /*
824                  * This can't really happen unless there's kernel corruption.
825                  */
826                 return error;
827         }
828         if (db == mp->m_dirdatablk)
829                 ASSERT(bno == 0);
830         else
831                 ASSERT(bno > 0);
832         /*
833          * Set the size to the new last block.
834          */
835         dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
836         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
837         return 0;
838 }