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