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