]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/xfs/xfs_dir2.c
Updated to mainline v3.16
[karo-tx-linux.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_format.h"
21 #include "xfs_log_format.h"
22 #include "xfs_trans_resv.h"
23 #include "xfs_inum.h"
24 #include "xfs_sb.h"
25 #include "xfs_ag.h"
26 #include "xfs_mount.h"
27 #include "xfs_da_format.h"
28 #include "xfs_da_btree.h"
29 #include "xfs_inode.h"
30 #include "xfs_trans.h"
31 #include "xfs_inode_item.h"
32 #include "xfs_bmap.h"
33 #include "xfs_dir2.h"
34 #include "xfs_dir2_priv.h"
35 #include "xfs_error.h"
36 #include "xfs_trace.h"
37 #include "xfs_dinode.h"
38
39 struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
40
41
42 /*
43  * ASCII case-insensitive (ie. A-Z) support for directories that was
44  * used in IRIX.
45  */
46 STATIC xfs_dahash_t
47 xfs_ascii_ci_hashname(
48         struct xfs_name *name)
49 {
50         xfs_dahash_t    hash;
51         int             i;
52
53         for (i = 0, hash = 0; i < name->len; i++)
54                 hash = tolower(name->name[i]) ^ rol32(hash, 7);
55
56         return hash;
57 }
58
59 STATIC enum xfs_dacmp
60 xfs_ascii_ci_compname(
61         struct xfs_da_args *args,
62         const unsigned char *name,
63         int             len)
64 {
65         enum xfs_dacmp  result;
66         int             i;
67
68         if (args->namelen != len)
69                 return XFS_CMP_DIFFERENT;
70
71         result = XFS_CMP_EXACT;
72         for (i = 0; i < len; i++) {
73                 if (args->name[i] == name[i])
74                         continue;
75                 if (tolower(args->name[i]) != tolower(name[i]))
76                         return XFS_CMP_DIFFERENT;
77                 result = XFS_CMP_CASE;
78         }
79
80         return result;
81 }
82
83 static struct xfs_nameops xfs_ascii_ci_nameops = {
84         .hashname       = xfs_ascii_ci_hashname,
85         .compname       = xfs_ascii_ci_compname,
86 };
87
88 int
89 xfs_da_mount(
90         struct xfs_mount        *mp)
91 {
92         struct xfs_da_geometry  *dageo;
93         int                     nodehdr_size;
94
95
96         ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
97         ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
98                XFS_MAX_BLOCKSIZE);
99
100         mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
101         mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
102
103         nodehdr_size = mp->m_dir_inode_ops->node_hdr_size;
104         mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
105                                     KM_SLEEP | KM_MAYFAIL);
106         mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
107                                      KM_SLEEP | KM_MAYFAIL);
108         if (!mp->m_dir_geo || !mp->m_attr_geo) {
109                 kmem_free(mp->m_dir_geo);
110                 kmem_free(mp->m_attr_geo);
111                 return ENOMEM;
112         }
113
114         /* set up directory geometry */
115         dageo = mp->m_dir_geo;
116         dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
117         dageo->fsblog = mp->m_sb.sb_blocklog;
118         dageo->blksize = 1 << dageo->blklog;
119         dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
120
121         /*
122          * Now we've set up the block conversion variables, we can calculate the
123          * segment block constants using the geometry structure.
124          */
125         dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
126         dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
127         dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
128         dageo->node_ents = (dageo->blksize - nodehdr_size) /
129                                 (uint)sizeof(xfs_da_node_entry_t);
130         dageo->magicpct = (dageo->blksize * 37) / 100;
131
132         /* set up attribute geometry - single fsb only */
133         dageo = mp->m_attr_geo;
134         dageo->blklog = mp->m_sb.sb_blocklog;
135         dageo->fsblog = mp->m_sb.sb_blocklog;
136         dageo->blksize = 1 << dageo->blklog;
137         dageo->fsbcount = 1;
138         dageo->node_ents = (dageo->blksize - nodehdr_size) /
139                                 (uint)sizeof(xfs_da_node_entry_t);
140         dageo->magicpct = (dageo->blksize * 37) / 100;
141
142         if (xfs_sb_version_hasasciici(&mp->m_sb))
143                 mp->m_dirnameops = &xfs_ascii_ci_nameops;
144         else
145                 mp->m_dirnameops = &xfs_default_nameops;
146
147         return 0;
148 }
149
150 void
151 xfs_da_unmount(
152         struct xfs_mount        *mp)
153 {
154         kmem_free(mp->m_dir_geo);
155         kmem_free(mp->m_attr_geo);
156 }
157
158 /*
159  * Return 1 if directory contains only "." and "..".
160  */
161 int
162 xfs_dir_isempty(
163         xfs_inode_t     *dp)
164 {
165         xfs_dir2_sf_hdr_t       *sfp;
166
167         ASSERT(S_ISDIR(dp->i_d.di_mode));
168         if (dp->i_d.di_size == 0)       /* might happen during shutdown. */
169                 return 1;
170         if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
171                 return 0;
172         sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
173         return !sfp->count;
174 }
175
176 /*
177  * Validate a given inode number.
178  */
179 int
180 xfs_dir_ino_validate(
181         xfs_mount_t     *mp,
182         xfs_ino_t       ino)
183 {
184         xfs_agblock_t   agblkno;
185         xfs_agino_t     agino;
186         xfs_agnumber_t  agno;
187         int             ino_ok;
188         int             ioff;
189
190         agno = XFS_INO_TO_AGNO(mp, ino);
191         agblkno = XFS_INO_TO_AGBNO(mp, ino);
192         ioff = XFS_INO_TO_OFFSET(mp, ino);
193         agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
194         ino_ok =
195                 agno < mp->m_sb.sb_agcount &&
196                 agblkno < mp->m_sb.sb_agblocks &&
197                 agblkno != 0 &&
198                 ioff < (1 << mp->m_sb.sb_inopblog) &&
199                 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
200         if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
201                         XFS_RANDOM_DIR_INO_VALIDATE))) {
202                 xfs_warn(mp, "Invalid inode number 0x%Lx",
203                                 (unsigned long long) ino);
204                 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
205                 return XFS_ERROR(EFSCORRUPTED);
206         }
207         return 0;
208 }
209
210 /*
211  * Initialize a directory with its "." and ".." entries.
212  */
213 int
214 xfs_dir_init(
215         xfs_trans_t     *tp,
216         xfs_inode_t     *dp,
217         xfs_inode_t     *pdp)
218 {
219         struct xfs_da_args *args;
220         int             error;
221
222         ASSERT(S_ISDIR(dp->i_d.di_mode));
223         error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
224         if (error)
225                 return error;
226
227         args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
228         if (!args)
229                 return ENOMEM;
230
231         args->geo = dp->i_mount->m_dir_geo;
232         args->dp = dp;
233         args->trans = tp;
234         error = xfs_dir2_sf_create(args, pdp->i_ino);
235         kmem_free(args);
236         return error;
237 }
238
239 /*
240   Enter a name in a directory.
241  */
242 int
243 xfs_dir_createname(
244         xfs_trans_t             *tp,
245         xfs_inode_t             *dp,
246         struct xfs_name         *name,
247         xfs_ino_t               inum,           /* new entry inode number */
248         xfs_fsblock_t           *first,         /* bmap's firstblock */
249         xfs_bmap_free_t         *flist,         /* bmap's freeblock list */
250         xfs_extlen_t            total)          /* bmap's total block count */
251 {
252         struct xfs_da_args      *args;
253         int                     rval;
254         int                     v;              /* type-checking value */
255
256         ASSERT(S_ISDIR(dp->i_d.di_mode));
257         rval = xfs_dir_ino_validate(tp->t_mountp, inum);
258         if (rval)
259                 return rval;
260         XFS_STATS_INC(xs_dir_create);
261
262         args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
263         if (!args)
264                 return ENOMEM;
265
266         args->geo = dp->i_mount->m_dir_geo;
267         args->name = name->name;
268         args->namelen = name->len;
269         args->filetype = name->type;
270         args->hashval = dp->i_mount->m_dirnameops->hashname(name);
271         args->inumber = inum;
272         args->dp = dp;
273         args->firstblock = first;
274         args->flist = flist;
275         args->total = total;
276         args->whichfork = XFS_DATA_FORK;
277         args->trans = tp;
278         args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
279
280         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
281                 rval = xfs_dir2_sf_addname(args);
282                 goto out_free;
283         }
284
285         rval = xfs_dir2_isblock(args, &v);
286         if (rval)
287                 goto out_free;
288         if (v) {
289                 rval = xfs_dir2_block_addname(args);
290                 goto out_free;
291         }
292
293         rval = xfs_dir2_isleaf(args, &v);
294         if (rval)
295                 goto out_free;
296         if (v)
297                 rval = xfs_dir2_leaf_addname(args);
298         else
299                 rval = xfs_dir2_node_addname(args);
300
301 out_free:
302         kmem_free(args);
303         return rval;
304 }
305
306 /*
307  * If doing a CI lookup and case-insensitive match, dup actual name into
308  * args.value. Return EEXIST for success (ie. name found) or an error.
309  */
310 int
311 xfs_dir_cilookup_result(
312         struct xfs_da_args *args,
313         const unsigned char *name,
314         int             len)
315 {
316         if (args->cmpresult == XFS_CMP_DIFFERENT)
317                 return ENOENT;
318         if (args->cmpresult != XFS_CMP_CASE ||
319                                         !(args->op_flags & XFS_DA_OP_CILOOKUP))
320                 return EEXIST;
321
322         args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
323         if (!args->value)
324                 return ENOMEM;
325
326         memcpy(args->value, name, len);
327         args->valuelen = len;
328         return EEXIST;
329 }
330
331 /*
332  * Lookup a name in a directory, give back the inode number.
333  * If ci_name is not NULL, returns the actual name in ci_name if it differs
334  * to name, or ci_name->name is set to NULL for an exact match.
335  */
336
337 int
338 xfs_dir_lookup(
339         xfs_trans_t     *tp,
340         xfs_inode_t     *dp,
341         struct xfs_name *name,
342         xfs_ino_t       *inum,          /* out: inode number */
343         struct xfs_name *ci_name)       /* out: actual name if CI match */
344 {
345         struct xfs_da_args *args;
346         int             rval;
347         int             v;              /* type-checking value */
348
349         ASSERT(S_ISDIR(dp->i_d.di_mode));
350         XFS_STATS_INC(xs_dir_lookup);
351
352         /*
353          * We need to use KM_NOFS here so that lockdep will not throw false
354          * positive deadlock warnings on a non-transactional lookup path. It is
355          * safe to recurse into inode recalim in that case, but lockdep can't
356          * easily be taught about it. Hence KM_NOFS avoids having to add more
357          * lockdep Doing this avoids having to add a bunch of lockdep class
358          * annotations into the reclaim path for the ilock.
359          */
360         args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
361         args->geo = dp->i_mount->m_dir_geo;
362         args->name = name->name;
363         args->namelen = name->len;
364         args->filetype = name->type;
365         args->hashval = dp->i_mount->m_dirnameops->hashname(name);
366         args->dp = dp;
367         args->whichfork = XFS_DATA_FORK;
368         args->trans = tp;
369         args->op_flags = XFS_DA_OP_OKNOENT;
370         if (ci_name)
371                 args->op_flags |= XFS_DA_OP_CILOOKUP;
372
373         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
374                 rval = xfs_dir2_sf_lookup(args);
375                 goto out_check_rval;
376         }
377
378         rval = xfs_dir2_isblock(args, &v);
379         if (rval)
380                 goto out_free;
381         if (v) {
382                 rval = xfs_dir2_block_lookup(args);
383                 goto out_check_rval;
384         }
385
386         rval = xfs_dir2_isleaf(args, &v);
387         if (rval)
388                 goto out_free;
389         if (v)
390                 rval = xfs_dir2_leaf_lookup(args);
391         else
392                 rval = xfs_dir2_node_lookup(args);
393
394 out_check_rval:
395         if (rval == EEXIST)
396                 rval = 0;
397         if (!rval) {
398                 *inum = args->inumber;
399                 if (ci_name) {
400                         ci_name->name = args->value;
401                         ci_name->len = args->valuelen;
402                 }
403         }
404 out_free:
405         kmem_free(args);
406         return rval;
407 }
408
409 /*
410  * Remove an entry from a directory.
411  */
412 int
413 xfs_dir_removename(
414         xfs_trans_t     *tp,
415         xfs_inode_t     *dp,
416         struct xfs_name *name,
417         xfs_ino_t       ino,
418         xfs_fsblock_t   *first,         /* bmap's firstblock */
419         xfs_bmap_free_t *flist,         /* bmap's freeblock list */
420         xfs_extlen_t    total)          /* bmap's total block count */
421 {
422         struct xfs_da_args *args;
423         int             rval;
424         int             v;              /* type-checking value */
425
426         ASSERT(S_ISDIR(dp->i_d.di_mode));
427         XFS_STATS_INC(xs_dir_remove);
428
429         args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
430         if (!args)
431                 return ENOMEM;
432
433         args->geo = dp->i_mount->m_dir_geo;
434         args->name = name->name;
435         args->namelen = name->len;
436         args->filetype = name->type;
437         args->hashval = dp->i_mount->m_dirnameops->hashname(name);
438         args->inumber = ino;
439         args->dp = dp;
440         args->firstblock = first;
441         args->flist = flist;
442         args->total = total;
443         args->whichfork = XFS_DATA_FORK;
444         args->trans = tp;
445
446         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
447                 rval = xfs_dir2_sf_removename(args);
448                 goto out_free;
449         }
450
451         rval = xfs_dir2_isblock(args, &v);
452         if (rval)
453                 goto out_free;
454         if (v) {
455                 rval = xfs_dir2_block_removename(args);
456                 goto out_free;
457         }
458
459         rval = xfs_dir2_isleaf(args, &v);
460         if (rval)
461                 goto out_free;
462         if (v)
463                 rval = xfs_dir2_leaf_removename(args);
464         else
465                 rval = xfs_dir2_node_removename(args);
466 out_free:
467         kmem_free(args);
468         return rval;
469 }
470
471 /*
472  * Replace the inode number of a directory entry.
473  */
474 int
475 xfs_dir_replace(
476         xfs_trans_t     *tp,
477         xfs_inode_t     *dp,
478         struct xfs_name *name,          /* name of entry to replace */
479         xfs_ino_t       inum,           /* new inode number */
480         xfs_fsblock_t   *first,         /* bmap's firstblock */
481         xfs_bmap_free_t *flist,         /* bmap's freeblock list */
482         xfs_extlen_t    total)          /* bmap's total block count */
483 {
484         struct xfs_da_args *args;
485         int             rval;
486         int             v;              /* type-checking value */
487
488         ASSERT(S_ISDIR(dp->i_d.di_mode));
489
490         rval = xfs_dir_ino_validate(tp->t_mountp, inum);
491         if (rval)
492                 return rval;
493
494         args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
495         if (!args)
496                 return ENOMEM;
497
498         args->geo = dp->i_mount->m_dir_geo;
499         args->name = name->name;
500         args->namelen = name->len;
501         args->filetype = name->type;
502         args->hashval = dp->i_mount->m_dirnameops->hashname(name);
503         args->inumber = inum;
504         args->dp = dp;
505         args->firstblock = first;
506         args->flist = flist;
507         args->total = total;
508         args->whichfork = XFS_DATA_FORK;
509         args->trans = tp;
510
511         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
512                 rval = xfs_dir2_sf_replace(args);
513                 goto out_free;
514         }
515
516         rval = xfs_dir2_isblock(args, &v);
517         if (rval)
518                 goto out_free;
519         if (v) {
520                 rval = xfs_dir2_block_replace(args);
521                 goto out_free;
522         }
523
524         rval = xfs_dir2_isleaf(args, &v);
525         if (rval)
526                 goto out_free;
527         if (v)
528                 rval = xfs_dir2_leaf_replace(args);
529         else
530                 rval = xfs_dir2_node_replace(args);
531 out_free:
532         kmem_free(args);
533         return rval;
534 }
535
536 /*
537  * See if this entry can be added to the directory without allocating space.
538  * First checks that the caller couldn't reserve enough space (resblks = 0).
539  */
540 int
541 xfs_dir_canenter(
542         xfs_trans_t     *tp,
543         xfs_inode_t     *dp,
544         struct xfs_name *name,          /* name of entry to add */
545         uint            resblks)
546 {
547         struct xfs_da_args *args;
548         int             rval;
549         int             v;              /* type-checking value */
550
551         if (resblks)
552                 return 0;
553
554         ASSERT(S_ISDIR(dp->i_d.di_mode));
555
556         args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
557         if (!args)
558                 return ENOMEM;
559
560         args->geo = dp->i_mount->m_dir_geo;
561         args->name = name->name;
562         args->namelen = name->len;
563         args->filetype = name->type;
564         args->hashval = dp->i_mount->m_dirnameops->hashname(name);
565         args->dp = dp;
566         args->whichfork = XFS_DATA_FORK;
567         args->trans = tp;
568         args->op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME |
569                                                         XFS_DA_OP_OKNOENT;
570
571         if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
572                 rval = xfs_dir2_sf_addname(args);
573                 goto out_free;
574         }
575
576         rval = xfs_dir2_isblock(args, &v);
577         if (rval)
578                 goto out_free;
579         if (v) {
580                 rval = xfs_dir2_block_addname(args);
581                 goto out_free;
582         }
583
584         rval = xfs_dir2_isleaf(args, &v);
585         if (rval)
586                 goto out_free;
587         if (v)
588                 rval = xfs_dir2_leaf_addname(args);
589         else
590                 rval = xfs_dir2_node_addname(args);
591 out_free:
592         kmem_free(args);
593         return rval;
594 }
595
596 /*
597  * Utility routines.
598  */
599
600 /*
601  * Add a block to the directory.
602  *
603  * This routine is for data and free blocks, not leaf/node blocks which are
604  * handled by xfs_da_grow_inode.
605  */
606 int
607 xfs_dir2_grow_inode(
608         struct xfs_da_args      *args,
609         int                     space,  /* v2 dir's space XFS_DIR2_xxx_SPACE */
610         xfs_dir2_db_t           *dbp)   /* out: block number added */
611 {
612         struct xfs_inode        *dp = args->dp;
613         struct xfs_mount        *mp = dp->i_mount;
614         xfs_fileoff_t           bno;    /* directory offset of new block */
615         int                     count;  /* count of filesystem blocks */
616         int                     error;
617
618         trace_xfs_dir2_grow_inode(args, space);
619
620         /*
621          * Set lowest possible block in the space requested.
622          */
623         bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
624         count = args->geo->fsbcount;
625
626         error = xfs_da_grow_inode_int(args, &bno, count);
627         if (error)
628                 return error;
629
630         *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
631
632         /*
633          * Update file's size if this is the data space and it grew.
634          */
635         if (space == XFS_DIR2_DATA_SPACE) {
636                 xfs_fsize_t     size;           /* directory file (data) size */
637
638                 size = XFS_FSB_TO_B(mp, bno + count);
639                 if (size > dp->i_d.di_size) {
640                         dp->i_d.di_size = size;
641                         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
642                 }
643         }
644         return 0;
645 }
646
647 /*
648  * See if the directory is a single-block form directory.
649  */
650 int
651 xfs_dir2_isblock(
652         struct xfs_da_args      *args,
653         int                     *vp)    /* out: 1 is block, 0 is not block */
654 {
655         xfs_fileoff_t           last;   /* last file offset */
656         int                     rval;
657
658         if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
659                 return rval;
660         rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
661         ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize);
662         *vp = rval;
663         return 0;
664 }
665
666 /*
667  * See if the directory is a single-leaf form directory.
668  */
669 int
670 xfs_dir2_isleaf(
671         struct xfs_da_args      *args,
672         int                     *vp)    /* out: 1 is block, 0 is not block */
673 {
674         xfs_fileoff_t           last;   /* last file offset */
675         int                     rval;
676
677         if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
678                 return rval;
679         *vp = last == args->geo->leafblk + args->geo->fsbcount;
680         return 0;
681 }
682
683 /*
684  * Remove the given block from the directory.
685  * This routine is used for data and free blocks, leaf/node are done
686  * by xfs_da_shrink_inode.
687  */
688 int
689 xfs_dir2_shrink_inode(
690         xfs_da_args_t   *args,
691         xfs_dir2_db_t   db,
692         struct xfs_buf  *bp)
693 {
694         xfs_fileoff_t   bno;            /* directory file offset */
695         xfs_dablk_t     da;             /* directory file offset */
696         int             done;           /* bunmap is finished */
697         xfs_inode_t     *dp;
698         int             error;
699         xfs_mount_t     *mp;
700         xfs_trans_t     *tp;
701
702         trace_xfs_dir2_shrink_inode(args, db);
703
704         dp = args->dp;
705         mp = dp->i_mount;
706         tp = args->trans;
707         da = xfs_dir2_db_to_da(args->geo, db);
708         /*
709          * Unmap the fsblock(s).
710          */
711         if ((error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount,
712                         XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
713                         &done))) {
714                 /*
715                  * ENOSPC actually can happen if we're in a removename with
716                  * no space reservation, and the resulting block removal
717                  * would cause a bmap btree split or conversion from extents
718                  * to btree.  This can only happen for un-fragmented
719                  * directory blocks, since you need to be punching out
720                  * the middle of an extent.
721                  * In this case we need to leave the block in the file,
722                  * and not binval it.
723                  * So the block has to be in a consistent empty state
724                  * and appropriately logged.
725                  * We don't free up the buffer, the caller can tell it
726                  * hasn't happened since it got an error back.
727                  */
728                 return error;
729         }
730         ASSERT(done);
731         /*
732          * Invalidate the buffer from the transaction.
733          */
734         xfs_trans_binval(tp, bp);
735         /*
736          * If it's not a data block, we're done.
737          */
738         if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
739                 return 0;
740         /*
741          * If the block isn't the last one in the directory, we're done.
742          */
743         if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
744                 return 0;
745         bno = da;
746         if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
747                 /*
748                  * This can't really happen unless there's kernel corruption.
749                  */
750                 return error;
751         }
752         if (db == args->geo->datablk)
753                 ASSERT(bno == 0);
754         else
755                 ASSERT(bno > 0);
756         /*
757          * Set the size to the new last block.
758          */
759         dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
760         xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
761         return 0;
762 }