blob: d337ecd4e3be937ed95f951d57a23de140fd00cd [file] [log] [blame]
Dave Chinner0b61f8a2018-06-05 19:42:14 -07001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
Nathan Scott7b718762005-11-02 14:58:39 +11003 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
Dave Chinnercbc8adf2013-04-03 16:11:21 +11004 * Copyright (c) 2013 Red Hat, Inc.
Nathan Scott7b718762005-11-02 14:58:39 +11005 * All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007#include "xfs.h"
Nathan Scotta844f452005-11-02 14:38:42 +11008#include "xfs_fs.h"
Darrick J. Wong5467b342019-06-28 19:25:35 -07009#include "xfs_shared.h"
Dave Chinnera4fbe6a2013-10-23 10:51:50 +110010#include "xfs_format.h"
Dave Chinner239880e2013-10-23 10:50:10 +110011#include "xfs_log_format.h"
12#include "xfs_trans_resv.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include "xfs_mount.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include "xfs_inode.h"
15#include "xfs_bmap.h"
Dave Chinner2b9ab5a2013-08-12 20:49:37 +100016#include "xfs_dir2.h"
Christoph Hellwig57926642011-07-13 13:43:48 +020017#include "xfs_dir2_priv.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include "xfs_error.h"
Christoph Hellwig0b1b2132009-12-14 23:14:59 +000019#include "xfs_trace.h"
Dave Chinner239880e2013-10-23 10:50:10 +110020#include "xfs_trans.h"
Dave Chinnercbc8adf2013-04-03 16:11:21 +110021#include "xfs_buf_item.h"
Brian Fostera45086e2015-10-12 15:59:25 +110022#include "xfs_log.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
24/*
25 * Function declarations.
26 */
Dave Chinner1d9025e2012-06-22 18:50:14 +100027static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args,
28 int index);
Linus Torvalds1da177e2005-04-16 15:20:36 -070029static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state,
30 xfs_da_state_blk_t *blk1,
31 xfs_da_state_blk_t *blk2);
Dave Chinner1d9025e2012-06-22 18:50:14 +100032static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp,
Linus Torvalds1da177e2005-04-16 15:20:36 -070033 int index, xfs_da_state_blk_t *dblk,
34 int *rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Dave Chinner24df33b2013-04-12 07:30:21 +100036/*
37 * Check internal consistency of a leafn block.
38 */
39#ifdef DEBUG
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080040static xfs_failaddr_t
Dave Chinner24df33b2013-04-12 07:30:21 +100041xfs_dir3_leafn_check(
Dave Chinner41419562013-10-29 22:11:50 +110042 struct xfs_inode *dp,
Dave Chinner24df33b2013-04-12 07:30:21 +100043 struct xfs_buf *bp)
44{
45 struct xfs_dir2_leaf *leaf = bp->b_addr;
46 struct xfs_dir3_icleaf_hdr leafhdr;
47
Christoph Hellwig51842552019-11-08 14:57:49 -080048 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf);
Dave Chinner24df33b2013-04-12 07:30:21 +100049
50 if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) {
51 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
52 if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080053 return __this_address;
Dave Chinner24df33b2013-04-12 07:30:21 +100054 } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC)
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080055 return __this_address;
Dave Chinner24df33b2013-04-12 07:30:21 +100056
Christoph Hellwig5ba30912019-11-08 14:57:52 -080057 return xfs_dir3_leaf_check_int(dp->i_mount, &leafhdr, leaf);
Dave Chinner24df33b2013-04-12 07:30:21 +100058}
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080059
60static inline void
61xfs_dir3_leaf_check(
62 struct xfs_inode *dp,
63 struct xfs_buf *bp)
64{
65 xfs_failaddr_t fa;
66
67 fa = xfs_dir3_leafn_check(dp, bp);
68 if (!fa)
69 return;
70 xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
Darrick J. Wong2551a532018-06-04 10:23:54 -070071 bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
72 fa);
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080073 ASSERT(0);
74}
Dave Chinner24df33b2013-04-12 07:30:21 +100075#else
Dave Chinner41419562013-10-29 22:11:50 +110076#define xfs_dir3_leaf_check(dp, bp)
Dave Chinner24df33b2013-04-12 07:30:21 +100077#endif
78
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080079static xfs_failaddr_t
Dave Chinnercbc8adf2013-04-03 16:11:21 +110080xfs_dir3_free_verify(
Dave Chinner20252072012-11-12 22:54:13 +110081 struct xfs_buf *bp)
82{
Christoph Hellwigdbd329f12019-06-28 19:27:29 -070083 struct xfs_mount *mp = bp->b_mount;
Dave Chinner20252072012-11-12 22:54:13 +110084 struct xfs_dir2_free_hdr *hdr = bp->b_addr;
Dave Chinner20252072012-11-12 22:54:13 +110085
Brian Foster39708c22019-02-07 10:45:48 -080086 if (!xfs_verify_magic(bp, hdr->magic))
87 return __this_address;
88
Dave Chinnercbc8adf2013-04-03 16:11:21 +110089 if (xfs_sb_version_hascrc(&mp->m_sb)) {
90 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
91
Eric Sandeence748ea2015-07-29 11:53:31 +100092 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080093 return __this_address;
Dave Chinnercbc8adf2013-04-03 16:11:21 +110094 if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080095 return __this_address;
Brian Fostera45086e2015-10-12 15:59:25 +110096 if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
Darrick J. Wonga6a781a2018-01-08 10:51:03 -080097 return __this_address;
Dave Chinnercbc8adf2013-04-03 16:11:21 +110098 }
99
100 /* XXX: should bounds check the xfs_dir3_icfree_hdr here */
101
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800102 return NULL;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100103}
104
105static void
106xfs_dir3_free_read_verify(
107 struct xfs_buf *bp)
108{
Christoph Hellwigdbd329f12019-06-28 19:27:29 -0700109 struct xfs_mount *mp = bp->b_mount;
Darrick J. Wongbc1a09b2018-01-08 10:51:03 -0800110 xfs_failaddr_t fa;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100111
Eric Sandeence5028c2014-02-27 15:23:10 +1100112 if (xfs_sb_version_hascrc(&mp->m_sb) &&
113 !xfs_buf_verify_cksum(bp, XFS_DIR3_FREE_CRC_OFF))
Darrick J. Wongbc1a09b2018-01-08 10:51:03 -0800114 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
115 else {
116 fa = xfs_dir3_free_verify(bp);
117 if (fa)
118 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
119 }
Dave Chinner612cfbf2012-11-14 17:52:32 +1100120}
Dave Chinner20252072012-11-12 22:54:13 +1100121
Dave Chinner612cfbf2012-11-14 17:52:32 +1100122static void
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100123xfs_dir3_free_write_verify(
Dave Chinner1813dd62012-11-14 17:54:40 +1100124 struct xfs_buf *bp)
125{
Christoph Hellwigdbd329f12019-06-28 19:27:29 -0700126 struct xfs_mount *mp = bp->b_mount;
Carlos Maiolinofb1755a2018-01-24 13:38:48 -0800127 struct xfs_buf_log_item *bip = bp->b_log_item;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100128 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
Darrick J. Wongbc1a09b2018-01-08 10:51:03 -0800129 xfs_failaddr_t fa;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100130
Darrick J. Wongbc1a09b2018-01-08 10:51:03 -0800131 fa = xfs_dir3_free_verify(bp);
132 if (fa) {
133 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100134 return;
135 }
136
137 if (!xfs_sb_version_hascrc(&mp->m_sb))
138 return;
139
140 if (bip)
141 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
142
Eric Sandeenf1dbcd72014-02-27 15:18:23 +1100143 xfs_buf_update_cksum(bp, XFS_DIR3_FREE_CRC_OFF);
Dave Chinner1813dd62012-11-14 17:54:40 +1100144}
145
Dave Chinnerd75afeb2013-04-03 16:11:29 +1100146const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
Eric Sandeen233135b2016-01-04 16:10:19 +1100147 .name = "xfs_dir3_free",
Brian Foster39708c22019-02-07 10:45:48 -0800148 .magic = { cpu_to_be32(XFS_DIR2_FREE_MAGIC),
149 cpu_to_be32(XFS_DIR3_FREE_MAGIC) },
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100150 .verify_read = xfs_dir3_free_read_verify,
151 .verify_write = xfs_dir3_free_write_verify,
Darrick J. Wongb5572592018-01-08 10:51:08 -0800152 .verify_struct = xfs_dir3_free_verify,
Dave Chinner1813dd62012-11-14 17:54:40 +1100153};
Dave Chinner20252072012-11-12 22:54:13 +1100154
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800155/* Everything ok in the free block header? */
Darrick J. Wongbc1a09b2018-01-08 10:51:03 -0800156static xfs_failaddr_t
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800157xfs_dir3_free_header_check(
158 struct xfs_inode *dp,
159 xfs_dablk_t fbno,
160 struct xfs_buf *bp)
161{
162 struct xfs_mount *mp = dp->i_mount;
163 unsigned int firstdb;
164 int maxbests;
165
166 maxbests = dp->d_ops->free_max_bests(mp->m_dir_geo);
167 firstdb = (xfs_dir2_da_to_db(mp->m_dir_geo, fbno) -
168 xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) *
169 maxbests;
170 if (xfs_sb_version_hascrc(&mp->m_sb)) {
171 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
172
173 if (be32_to_cpu(hdr3->firstdb) != firstdb)
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800174 return __this_address;
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800175 if (be32_to_cpu(hdr3->nvalid) > maxbests)
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800176 return __this_address;
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800177 if (be32_to_cpu(hdr3->nvalid) < be32_to_cpu(hdr3->nused))
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800178 return __this_address;
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800179 } else {
180 struct xfs_dir2_free_hdr *hdr = bp->b_addr;
181
182 if (be32_to_cpu(hdr->firstdb) != firstdb)
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800183 return __this_address;
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800184 if (be32_to_cpu(hdr->nvalid) > maxbests)
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800185 return __this_address;
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800186 if (be32_to_cpu(hdr->nvalid) < be32_to_cpu(hdr->nused))
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800187 return __this_address;
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800188 }
Darrick J. Wonga6a781a2018-01-08 10:51:03 -0800189 return NULL;
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800190}
Dave Chinner612cfbf2012-11-14 17:52:32 +1100191
Dave Chinner20252072012-11-12 22:54:13 +1100192static int
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100193__xfs_dir3_free_read(
Dave Chinner20252072012-11-12 22:54:13 +1100194 struct xfs_trans *tp,
195 struct xfs_inode *dp,
196 xfs_dablk_t fbno,
197 xfs_daddr_t mappedbno,
198 struct xfs_buf **bpp)
199{
Darrick J. Wongbc1a09b2018-01-08 10:51:03 -0800200 xfs_failaddr_t fa;
Dave Chinnerd75afeb2013-04-03 16:11:29 +1100201 int err;
202
203 err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100204 XFS_DATA_FORK, &xfs_dir3_free_buf_ops);
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800205 if (err || !*bpp)
206 return err;
207
208 /* Check things that we can't do in the verifier. */
Darrick J. Wongbc1a09b2018-01-08 10:51:03 -0800209 fa = xfs_dir3_free_header_check(dp, fbno, *bpp);
210 if (fa) {
211 xfs_verifier_error(*bpp, -EFSCORRUPTED, fa);
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800212 xfs_trans_brelse(tp, *bpp);
213 return -EFSCORRUPTED;
214 }
Dave Chinnerd75afeb2013-04-03 16:11:29 +1100215
216 /* try read returns without an error or *bpp if it lands in a hole */
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800217 if (tp)
Dave Chinner61fe1352013-04-03 16:11:30 +1100218 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_FREE_BUF);
Darrick J. Wongde14c5f2017-02-02 15:14:00 -0800219
220 return 0;
Dave Chinner20252072012-11-12 22:54:13 +1100221}
222
Christoph Hellwig5ba30912019-11-08 14:57:52 -0800223void
224xfs_dir2_free_hdr_from_disk(
225 struct xfs_mount *mp,
226 struct xfs_dir3_icfree_hdr *to,
227 struct xfs_dir2_free *from)
228{
229 if (xfs_sb_version_hascrc(&mp->m_sb)) {
230 struct xfs_dir3_free *from3 = (struct xfs_dir3_free *)from;
231
232 to->magic = be32_to_cpu(from3->hdr.hdr.magic);
233 to->firstdb = be32_to_cpu(from3->hdr.firstdb);
234 to->nvalid = be32_to_cpu(from3->hdr.nvalid);
235 to->nused = be32_to_cpu(from3->hdr.nused);
236
237 ASSERT(to->magic == XFS_DIR3_FREE_MAGIC);
238 } else {
239 to->magic = be32_to_cpu(from->hdr.magic);
240 to->firstdb = be32_to_cpu(from->hdr.firstdb);
241 to->nvalid = be32_to_cpu(from->hdr.nvalid);
242 to->nused = be32_to_cpu(from->hdr.nused);
243 ASSERT(to->magic == XFS_DIR2_FREE_MAGIC);
244 }
245}
246
Dave Chinner20252072012-11-12 22:54:13 +1100247int
248xfs_dir2_free_read(
249 struct xfs_trans *tp,
250 struct xfs_inode *dp,
251 xfs_dablk_t fbno,
252 struct xfs_buf **bpp)
253{
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100254 return __xfs_dir3_free_read(tp, dp, fbno, -1, bpp);
Dave Chinner20252072012-11-12 22:54:13 +1100255}
256
257static int
258xfs_dir2_free_try_read(
259 struct xfs_trans *tp,
260 struct xfs_inode *dp,
261 xfs_dablk_t fbno,
262 struct xfs_buf **bpp)
263{
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100264 return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp);
265}
266
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100267static int
268xfs_dir3_free_get_buf(
Dave Chinner2998ab1d2014-06-06 15:07:53 +1000269 xfs_da_args_t *args,
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100270 xfs_dir2_db_t fbno,
271 struct xfs_buf **bpp)
272{
Dave Chinner2998ab1d2014-06-06 15:07:53 +1000273 struct xfs_trans *tp = args->trans;
274 struct xfs_inode *dp = args->dp;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100275 struct xfs_mount *mp = dp->i_mount;
276 struct xfs_buf *bp;
277 int error;
278 struct xfs_dir3_icfree_hdr hdr;
279
Dave Chinner2998ab1d2014-06-06 15:07:53 +1000280 error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, fbno),
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100281 -1, &bp, XFS_DATA_FORK);
282 if (error)
283 return error;
284
Dave Chinner61fe1352013-04-03 16:11:30 +1100285 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_FREE_BUF);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100286 bp->b_ops = &xfs_dir3_free_buf_ops;
287
288 /*
289 * Initialize the new block to be empty, and remember
290 * its first slot as our empty slot.
291 */
Dave Chinnere400d272013-05-28 18:37:17 +1000292 memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr));
293 memset(&hdr, 0, sizeof(hdr));
294
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100295 if (xfs_sb_version_hascrc(&mp->m_sb)) {
296 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
297
298 hdr.magic = XFS_DIR3_FREE_MAGIC;
Dave Chinnere400d272013-05-28 18:37:17 +1000299
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100300 hdr3->hdr.blkno = cpu_to_be64(bp->b_bn);
301 hdr3->hdr.owner = cpu_to_be64(dp->i_ino);
Eric Sandeence748ea2015-07-29 11:53:31 +1000302 uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid);
Dave Chinnere400d272013-05-28 18:37:17 +1000303 } else
304 hdr.magic = XFS_DIR2_FREE_MAGIC;
Dave Chinner01ba43b2013-10-29 22:11:52 +1100305 dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100306 *bpp = bp;
307 return 0;
Dave Chinner20252072012-11-12 22:54:13 +1100308}
309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310/*
311 * Log entries from a freespace block.
312 */
Eric Sandeen5d77c0d2009-11-19 15:52:00 +0000313STATIC void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314xfs_dir2_free_log_bests(
Dave Chinnerbc851782014-06-06 15:20:54 +1000315 struct xfs_da_args *args,
Dave Chinner1d9025e2012-06-22 18:50:14 +1000316 struct xfs_buf *bp,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 int first, /* first entry to log */
318 int last) /* last entry to log */
319{
320 xfs_dir2_free_t *free; /* freespace structure */
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100321 __be16 *bests;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Dave Chinner1d9025e2012-06-22 18:50:14 +1000323 free = bp->b_addr;
Dave Chinnerbc851782014-06-06 15:20:54 +1000324 bests = args->dp->d_ops->free_bests_p(free);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100325 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
326 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
Dave Chinnerbc851782014-06-06 15:20:54 +1000327 xfs_trans_log_buf(args->trans, bp,
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100328 (uint)((char *)&bests[first] - (char *)free),
329 (uint)((char *)&bests[last] - (char *)free +
330 sizeof(bests[0]) - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331}
332
333/*
334 * Log header from a freespace block.
335 */
336static void
337xfs_dir2_free_log_header(
Dave Chinnerbc851782014-06-06 15:20:54 +1000338 struct xfs_da_args *args,
Dave Chinner1d9025e2012-06-22 18:50:14 +1000339 struct xfs_buf *bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340{
Dave Chinner836a94a2013-08-12 20:49:44 +1000341#ifdef DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 xfs_dir2_free_t *free; /* freespace structure */
343
Dave Chinner1d9025e2012-06-22 18:50:14 +1000344 free = bp->b_addr;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100345 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
346 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
Dave Chinner836a94a2013-08-12 20:49:44 +1000347#endif
Dave Chinnerbc851782014-06-06 15:20:54 +1000348 xfs_trans_log_buf(args->trans, bp, 0,
349 args->dp->d_ops->free_hdr_size - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350}
351
352/*
353 * Convert a leaf-format directory to a node-format directory.
354 * We need to change the magic number of the leaf block, and copy
355 * the freespace table out of the leaf block into its own block.
356 */
357int /* error */
358xfs_dir2_leaf_to_node(
359 xfs_da_args_t *args, /* operation arguments */
Dave Chinner1d9025e2012-06-22 18:50:14 +1000360 struct xfs_buf *lbp) /* leaf buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
362 xfs_inode_t *dp; /* incore directory inode */
363 int error; /* error return value */
Dave Chinner1d9025e2012-06-22 18:50:14 +1000364 struct xfs_buf *fbp; /* freespace buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 xfs_dir2_db_t fdb; /* freespace block number */
366 xfs_dir2_free_t *free; /* freespace structure */
Nathan Scott68b3a102006-03-17 17:27:19 +1100367 __be16 *from; /* pointer to freespace entry */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 int i; /* leaf freespace index */
369 xfs_dir2_leaf_t *leaf; /* leaf structure */
370 xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 int n; /* count of live freespc ents */
372 xfs_dir2_data_off_t off; /* freespace entry value */
Nathan Scott0ba962e2006-03-17 17:27:07 +1100373 __be16 *to; /* pointer to freespace entry */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 xfs_trans_t *tp; /* transaction pointer */
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100375 struct xfs_dir3_icfree_hdr freehdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Christoph Hellwig0b1b2132009-12-14 23:14:59 +0000377 trace_xfs_dir2_leaf_to_node(args);
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 dp = args->dp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 tp = args->trans;
381 /*
382 * Add a freespace block to the directory.
383 */
384 if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) {
385 return error;
386 }
Dave Chinner30028032014-06-06 15:08:18 +1000387 ASSERT(fdb == xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /*
389 * Get the buffer for the new freespace block.
390 */
Dave Chinner2998ab1d2014-06-06 15:07:53 +1000391 error = xfs_dir3_free_get_buf(args, fdb, &fbp);
Dave Chinnerb0f539d2012-11-14 17:53:49 +1100392 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 return error;
Dave Chinnerb0f539d2012-11-14 17:53:49 +1100394
Dave Chinner1d9025e2012-06-22 18:50:14 +1000395 free = fbp->b_addr;
Christoph Hellwig5ba30912019-11-08 14:57:52 -0800396 xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free);
Dave Chinner1d9025e2012-06-22 18:50:14 +1000397 leaf = lbp->b_addr;
Dave Chinner8f661932014-06-06 15:15:59 +1000398 ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
Darrick J. Wong3f883f52018-03-06 17:08:31 -0800399 if (be32_to_cpu(ltp->bestcount) >
Darrick J. Wonga5155b82019-11-02 09:40:53 -0700400 (uint)dp->i_d.di_size / args->geo->blksize) {
401 xfs_buf_corruption_error(lbp);
Darrick J. Wong3f883f52018-03-06 17:08:31 -0800402 return -EFSCORRUPTED;
Darrick J. Wonga5155b82019-11-02 09:40:53 -0700403 }
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100404
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 /*
406 * Copy freespace entries from the leaf block to the new block.
407 * Count active entries.
408 */
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100409 from = xfs_dir2_leaf_bests_p(ltp);
Dave Chinner24dd0f52013-10-30 13:48:41 -0500410 to = dp->d_ops->free_bests_p(free);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100411 for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
Nathan Scott68b3a102006-03-17 17:27:19 +1100412 if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 n++;
Nathan Scott0ba962e2006-03-17 17:27:07 +1100414 *to = cpu_to_be16(off);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 }
Dave Chinnerb0f539d2012-11-14 17:53:49 +1100416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 /*
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100418 * Now initialize the freespace block header.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 */
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100420 freehdr.nused = n;
421 freehdr.nvalid = be32_to_cpu(ltp->bestcount);
422
Dave Chinner01ba43b2013-10-29 22:11:52 +1100423 dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
Dave Chinnerbc851782014-06-06 15:20:54 +1000424 xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1);
425 xfs_dir2_free_log_header(args, fbp);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100426
Dave Chinner24df33b2013-04-12 07:30:21 +1000427 /*
428 * Converting the leaf to a leafnode is just a matter of changing the
429 * magic number and the ops. Do the change directly to the buffer as
430 * it's less work (and less code) than decoding the header to host
431 * format and back again.
432 */
433 if (leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC))
434 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
435 else
436 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
437 lbp->b_ops = &xfs_dir3_leafn_buf_ops;
Dave Chinner61fe1352013-04-03 16:11:30 +1100438 xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF);
Dave Chinnerbc851782014-06-06 15:20:54 +1000439 xfs_dir3_leaf_log_header(args, lbp);
Dave Chinner41419562013-10-29 22:11:50 +1100440 xfs_dir3_leaf_check(dp, lbp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 return 0;
442}
443
444/*
445 * Add a leaf entry to a leaf block in a node-form directory.
446 * The other work necessary is done from the caller.
447 */
448static int /* error */
449xfs_dir2_leafn_add(
Dave Chinner1d9025e2012-06-22 18:50:14 +1000450 struct xfs_buf *bp, /* leaf buffer */
Darrick J. Wong79622c7ce2019-03-07 16:50:11 -0800451 struct xfs_da_args *args, /* operation arguments */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 int index) /* insertion pt for new entry */
453{
Darrick J. Wong79622c7ce2019-03-07 16:50:11 -0800454 struct xfs_dir3_icleaf_hdr leafhdr;
455 struct xfs_inode *dp = args->dp;
456 struct xfs_dir2_leaf *leaf = bp->b_addr;
457 struct xfs_dir2_leaf_entry *lep;
458 struct xfs_dir2_leaf_entry *ents;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 int compact; /* compacting stale leaves */
Darrick J. Wong79622c7ce2019-03-07 16:50:11 -0800460 int highstale = 0; /* next stale entry */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 int lfloghigh; /* high leaf entry logging */
462 int lfloglow; /* low leaf entry logging */
Darrick J. Wong79622c7ce2019-03-07 16:50:11 -0800463 int lowstale = 0; /* previous stale entry */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
Christoph Hellwig0b1b2132009-12-14 23:14:59 +0000465 trace_xfs_dir2_leafn_add(args, index);
466
Christoph Hellwig51842552019-11-08 14:57:49 -0800467 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf);
Christoph Hellwig787b0892019-11-08 14:57:50 -0800468 ents = leafhdr.ents;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 /*
471 * Quick check just to make sure we are not going to index
472 * into other peoples memory
473 */
Darrick J. Wonga5155b82019-11-02 09:40:53 -0700474 if (index < 0) {
475 xfs_buf_corruption_error(bp);
Dave Chinner24513372014-06-25 14:58:08 +1000476 return -EFSCORRUPTED;
Darrick J. Wonga5155b82019-11-02 09:40:53 -0700477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479 /*
480 * If there are already the maximum number of leaf entries in
481 * the block, if there are no stale entries it won't fit.
482 * Caller will do a split. If there are stale entries we'll do
483 * a compact.
484 */
485
Christoph Hellwig478c7832019-11-08 14:57:51 -0800486 if (leafhdr.count == args->geo->leaf_max_ents) {
Dave Chinner24df33b2013-04-12 07:30:21 +1000487 if (!leafhdr.stale)
Dave Chinner24513372014-06-25 14:58:08 +1000488 return -ENOSPC;
Dave Chinner24df33b2013-04-12 07:30:21 +1000489 compact = leafhdr.stale > 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 } else
491 compact = 0;
Dave Chinner24df33b2013-04-12 07:30:21 +1000492 ASSERT(index == 0 || be32_to_cpu(ents[index - 1].hashval) <= args->hashval);
493 ASSERT(index == leafhdr.count ||
494 be32_to_cpu(ents[index].hashval) >= args->hashval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
Barry Naujok6a178102008-05-21 16:42:05 +1000496 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 return 0;
498
499 /*
500 * Compact out all but one stale leaf entry. Leaves behind
501 * the entry closest to index.
502 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000503 if (compact)
504 xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale,
505 &highstale, &lfloglow, &lfloghigh);
506 else if (leafhdr.stale) {
507 /*
508 * Set impossible logging indices for this case.
509 */
510 lfloglow = leafhdr.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 lfloghigh = -1;
512 }
Christoph Hellwig4fb44c82011-07-08 14:34:59 +0200513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 /*
515 * Insert the new entry, log everything.
516 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000517 lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale,
Christoph Hellwig4fb44c82011-07-08 14:34:59 +0200518 highstale, &lfloglow, &lfloghigh);
519
Nathan Scott3c1f9c12006-03-17 17:28:18 +1100520 lep->hashval = cpu_to_be32(args->hashval);
Dave Chinner30028032014-06-06 15:08:18 +1000521 lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(args->geo,
Nathan Scott3c1f9c12006-03-17 17:28:18 +1100522 args->blkno, args->index));
Dave Chinner24df33b2013-04-12 07:30:21 +1000523
Christoph Hellwig163fbbb2019-11-08 14:57:50 -0800524 xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf, &leafhdr);
Dave Chinnerbc851782014-06-06 15:20:54 +1000525 xfs_dir3_leaf_log_header(args, bp);
Christoph Hellwig787b0892019-11-08 14:57:50 -0800526 xfs_dir3_leaf_log_ents(args, &leafhdr, bp, lfloglow, lfloghigh);
Dave Chinner41419562013-10-29 22:11:50 +1100527 xfs_dir3_leaf_check(dp, bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 return 0;
529}
530
531#ifdef DEBUG
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100532static void
533xfs_dir2_free_hdr_check(
Dave Chinner01ba43b2013-10-29 22:11:52 +1100534 struct xfs_inode *dp,
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100535 struct xfs_buf *bp,
536 xfs_dir2_db_t db)
537{
538 struct xfs_dir3_icfree_hdr hdr;
539
Christoph Hellwig5ba30912019-11-08 14:57:52 -0800540 xfs_dir2_free_hdr_from_disk(dp->i_mount, &hdr, bp->b_addr);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100541
Dave Chinner8f661932014-06-06 15:15:59 +1000542 ASSERT((hdr.firstdb %
543 dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100544 ASSERT(hdr.firstdb <= db);
545 ASSERT(db < hdr.firstdb + hdr.nvalid);
546}
547#else
Dave Chinner01ba43b2013-10-29 22:11:52 +1100548#define xfs_dir2_free_hdr_check(dp, bp, db)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549#endif /* DEBUG */
550
551/*
552 * Return the last hash value in the leaf.
553 * Stale entries are ok.
554 */
555xfs_dahash_t /* hash value */
Darrick J. Wong8e8877e2017-06-16 11:00:13 -0700556xfs_dir2_leaf_lasthash(
Dave Chinner41419562013-10-29 22:11:50 +1100557 struct xfs_inode *dp,
Dave Chinner1d9025e2012-06-22 18:50:14 +1000558 struct xfs_buf *bp, /* leaf buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 int *count) /* count of entries in leaf */
560{
Dave Chinner24df33b2013-04-12 07:30:21 +1000561 struct xfs_dir3_icleaf_hdr leafhdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Christoph Hellwig787b0892019-11-08 14:57:50 -0800563 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, bp->b_addr);
Dave Chinner24df33b2013-04-12 07:30:21 +1000564
565 ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
Darrick J. Wong8e8877e2017-06-16 11:00:13 -0700566 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
567 leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
568 leafhdr.magic == XFS_DIR3_LEAF1_MAGIC);
Dave Chinner24df33b2013-04-12 07:30:21 +1000569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 if (count)
Dave Chinner24df33b2013-04-12 07:30:21 +1000571 *count = leafhdr.count;
572 if (!leafhdr.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 return 0;
Christoph Hellwig787b0892019-11-08 14:57:50 -0800574 return be32_to_cpu(leafhdr.ents[leafhdr.count - 1].hashval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575}
576
577/*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000578 * Look up a leaf entry for space to add a name in a node-format leaf block.
579 * The extrablk in state is a freespace block.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000581STATIC int
582xfs_dir2_leafn_lookup_for_addname(
Dave Chinner1d9025e2012-06-22 18:50:14 +1000583 struct xfs_buf *bp, /* leaf buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 xfs_da_args_t *args, /* operation arguments */
585 int *indexp, /* out: leaf entry index */
586 xfs_da_state_t *state) /* state to fill in */
587{
Dave Chinner1d9025e2012-06-22 18:50:14 +1000588 struct xfs_buf *curbp = NULL; /* current data/free buffer */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000589 xfs_dir2_db_t curdb = -1; /* current data block number */
590 xfs_dir2_db_t curfdb = -1; /* current free block number */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 xfs_inode_t *dp; /* incore directory inode */
592 int error; /* error return value */
593 int fi; /* free entry index */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000594 xfs_dir2_free_t *free = NULL; /* free block structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 int index; /* leaf entry index */
596 xfs_dir2_leaf_t *leaf; /* leaf structure */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000597 int length; /* length of new data entry */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 xfs_dir2_leaf_entry_t *lep; /* leaf entry */
599 xfs_mount_t *mp; /* filesystem mount point */
600 xfs_dir2_db_t newdb; /* new data block number */
601 xfs_dir2_db_t newfdb; /* new free block number */
602 xfs_trans_t *tp; /* transaction pointer */
Dave Chinner24df33b2013-04-12 07:30:21 +1000603 struct xfs_dir3_icleaf_hdr leafhdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
605 dp = args->dp;
606 tp = args->trans;
607 mp = dp->i_mount;
Dave Chinner1d9025e2012-06-22 18:50:14 +1000608 leaf = bp->b_addr;
Christoph Hellwig51842552019-11-08 14:57:49 -0800609 xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
Dave Chinner24df33b2013-04-12 07:30:21 +1000610
Dave Chinner41419562013-10-29 22:11:50 +1100611 xfs_dir3_leaf_check(dp, bp);
Dave Chinner24df33b2013-04-12 07:30:21 +1000612 ASSERT(leafhdr.count > 0);
613
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 /*
615 * Look up the hash value in the leaf entries.
616 */
617 index = xfs_dir2_leaf_search_hash(args, bp);
618 /*
619 * Do we have a buffer coming in?
620 */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000621 if (state->extravalid) {
622 /* If so, it's a free block buffer, get the block number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 curbp = state->extrablk.bp;
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000624 curfdb = state->extrablk.blkno;
Dave Chinner1d9025e2012-06-22 18:50:14 +1000625 free = curbp->b_addr;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100626 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
627 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 }
Dave Chinner9d23fc82013-10-29 22:11:48 +1100629 length = dp->d_ops->data_entsize(args->namelen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 /*
631 * Loop over leaf entries with the right hash value.
632 */
Christoph Hellwig787b0892019-11-08 14:57:50 -0800633 for (lep = &leafhdr.ents[index];
Dave Chinner24df33b2013-04-12 07:30:21 +1000634 index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval;
635 lep++, index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 /*
637 * Skip stale leaf entries.
638 */
Nathan Scott3c1f9c12006-03-17 17:28:18 +1100639 if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 continue;
641 /*
642 * Pull the data block number from the entry.
643 */
Dave Chinner30028032014-06-06 15:08:18 +1000644 newdb = xfs_dir2_dataptr_to_db(args->geo,
645 be32_to_cpu(lep->address));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 /*
647 * For addname, we're looking for a place to put the new entry.
648 * We want to use a data block with an entry of equal
649 * hash value to ours if there is one with room.
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000650 *
651 * If this block isn't the data block we already have
652 * in hand, take a look at it.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000654 if (newdb != curdb) {
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100655 __be16 *bests;
656
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000657 curdb = newdb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 /*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000659 * Convert the data block to the free block
660 * holding its freespace information.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 */
Dave Chinner8f661932014-06-06 15:15:59 +1000662 newfdb = dp->d_ops->db_to_fdb(args->geo, newdb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 /*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000664 * If it's not the one we have in hand, read it in.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000666 if (newfdb != curfdb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 /*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000668 * If we had one before, drop it.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 */
670 if (curbp)
Dave Chinner1d9025e2012-06-22 18:50:14 +1000671 xfs_trans_brelse(tp, curbp);
Dave Chinner20252072012-11-12 22:54:13 +1100672
673 error = xfs_dir2_free_read(tp, dp,
Dave Chinner2998ab1d2014-06-06 15:07:53 +1000674 xfs_dir2_db_to_da(args->geo,
675 newfdb),
Dave Chinner20252072012-11-12 22:54:13 +1100676 &curbp);
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000677 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 return error;
Dave Chinner1d9025e2012-06-22 18:50:14 +1000679 free = curbp->b_addr;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100680
Dave Chinner01ba43b2013-10-29 22:11:52 +1100681 xfs_dir2_free_hdr_check(dp, curbp, curdb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 }
683 /*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000684 * Get the index for our entry.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 */
Dave Chinner8f661932014-06-06 15:15:59 +1000686 fi = dp->d_ops->db_to_fdindex(args->geo, curdb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 /*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000688 * If it has room, return it.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 */
Dave Chinner24dd0f52013-10-30 13:48:41 -0500690 bests = dp->d_ops->free_bests_p(free);
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100691 if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) {
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000692 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
693 XFS_ERRLEVEL_LOW, mp);
694 if (curfdb != newfdb)
Dave Chinner1d9025e2012-06-22 18:50:14 +1000695 xfs_trans_brelse(tp, curbp);
Dave Chinner24513372014-06-25 14:58:08 +1000696 return -EFSCORRUPTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 }
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000698 curfdb = newfdb;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100699 if (be16_to_cpu(bests[fi]) >= length)
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000700 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 }
702 }
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000703 /* Didn't find any space */
704 fi = -1;
705out:
Barry Naujok6a178102008-05-21 16:42:05 +1000706 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000707 if (curbp) {
708 /* Giving back a free block. */
709 state->extravalid = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 state->extrablk.bp = curbp;
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000711 state->extrablk.index = fi;
712 state->extrablk.blkno = curfdb;
Dave Chinnercbc8adf2013-04-03 16:11:21 +1100713
714 /*
715 * Important: this magic number is not in the buffer - it's for
716 * buffer type information and therefore only the free/data type
717 * matters here, not whether CRCs are enabled or not.
718 */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000719 state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
720 } else {
721 state->extravalid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 }
723 /*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000724 * Return the index, that will be the insertion point.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 */
726 *indexp = index;
Dave Chinner24513372014-06-25 14:58:08 +1000727 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
729
730/*
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000731 * Look up a leaf entry in a node-format leaf block.
732 * The extrablk in state a data block.
733 */
734STATIC int
735xfs_dir2_leafn_lookup_for_entry(
Dave Chinner1d9025e2012-06-22 18:50:14 +1000736 struct xfs_buf *bp, /* leaf buffer */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000737 xfs_da_args_t *args, /* operation arguments */
738 int *indexp, /* out: leaf entry index */
739 xfs_da_state_t *state) /* state to fill in */
740{
Dave Chinner1d9025e2012-06-22 18:50:14 +1000741 struct xfs_buf *curbp = NULL; /* current data/free buffer */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000742 xfs_dir2_db_t curdb = -1; /* current data block number */
743 xfs_dir2_data_entry_t *dep; /* data block entry */
744 xfs_inode_t *dp; /* incore directory inode */
745 int error; /* error return value */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000746 int index; /* leaf entry index */
747 xfs_dir2_leaf_t *leaf; /* leaf structure */
748 xfs_dir2_leaf_entry_t *lep; /* leaf entry */
749 xfs_mount_t *mp; /* filesystem mount point */
750 xfs_dir2_db_t newdb; /* new data block number */
751 xfs_trans_t *tp; /* transaction pointer */
Barry Naujok5163f952008-05-21 16:41:01 +1000752 enum xfs_dacmp cmp; /* comparison result */
Dave Chinner24df33b2013-04-12 07:30:21 +1000753 struct xfs_dir3_icleaf_hdr leafhdr;
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000754
755 dp = args->dp;
756 tp = args->trans;
757 mp = dp->i_mount;
Dave Chinner1d9025e2012-06-22 18:50:14 +1000758 leaf = bp->b_addr;
Christoph Hellwig51842552019-11-08 14:57:49 -0800759 xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
Dave Chinner24df33b2013-04-12 07:30:21 +1000760
Dave Chinner41419562013-10-29 22:11:50 +1100761 xfs_dir3_leaf_check(dp, bp);
Darrick J. Wonga5155b82019-11-02 09:40:53 -0700762 if (leafhdr.count <= 0) {
763 xfs_buf_corruption_error(bp);
Darrick J. Wong858b44d2019-08-11 15:52:26 -0700764 return -EFSCORRUPTED;
Darrick J. Wonga5155b82019-11-02 09:40:53 -0700765 }
Dave Chinner24df33b2013-04-12 07:30:21 +1000766
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000767 /*
768 * Look up the hash value in the leaf entries.
769 */
770 index = xfs_dir2_leaf_search_hash(args, bp);
771 /*
772 * Do we have a buffer coming in?
773 */
774 if (state->extravalid) {
775 curbp = state->extrablk.bp;
776 curdb = state->extrablk.blkno;
777 }
778 /*
779 * Loop over leaf entries with the right hash value.
780 */
Christoph Hellwig787b0892019-11-08 14:57:50 -0800781 for (lep = &leafhdr.ents[index];
Dave Chinner24df33b2013-04-12 07:30:21 +1000782 index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval;
783 lep++, index++) {
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000784 /*
785 * Skip stale leaf entries.
786 */
787 if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
788 continue;
789 /*
790 * Pull the data block number from the entry.
791 */
Dave Chinner30028032014-06-06 15:08:18 +1000792 newdb = xfs_dir2_dataptr_to_db(args->geo,
793 be32_to_cpu(lep->address));
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000794 /*
795 * Not adding a new entry, so we really want to find
796 * the name given to us.
797 *
798 * If it's a different data block, go get it.
799 */
800 if (newdb != curdb) {
801 /*
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000802 * If we had a block before that we aren't saving
803 * for a CI name, drop it
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000804 */
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000805 if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT ||
806 curdb != state->extrablk.blkno))
Dave Chinner1d9025e2012-06-22 18:50:14 +1000807 xfs_trans_brelse(tp, curbp);
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000808 /*
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000809 * If needing the block that is saved with a CI match,
810 * use it otherwise read in the new data block.
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000811 */
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000812 if (args->cmpresult != XFS_CMP_DIFFERENT &&
813 newdb == state->extrablk.blkno) {
814 ASSERT(state->extravalid);
815 curbp = state->extrablk.bp;
816 } else {
Dave Chinner33363fe2013-04-03 16:11:22 +1100817 error = xfs_dir3_data_read(tp, dp,
Dave Chinner2998ab1d2014-06-06 15:07:53 +1000818 xfs_dir2_db_to_da(args->geo,
819 newdb),
Dave Chinnere4813572012-11-12 22:54:14 +1100820 -1, &curbp);
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000821 if (error)
822 return error;
823 }
Dave Chinner33363fe2013-04-03 16:11:22 +1100824 xfs_dir3_data_check(dp, curbp);
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000825 curdb = newdb;
826 }
827 /*
828 * Point to the data entry.
829 */
Dave Chinner1d9025e2012-06-22 18:50:14 +1000830 dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr +
Dave Chinner30028032014-06-06 15:08:18 +1000831 xfs_dir2_dataptr_to_off(args->geo,
832 be32_to_cpu(lep->address)));
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000833 /*
Barry Naujok5163f952008-05-21 16:41:01 +1000834 * Compare the entry and if it's an exact match, return
835 * EEXIST immediately. If it's the first case-insensitive
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000836 * match, store the block & inode number and continue looking.
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000837 */
Barry Naujok5163f952008-05-21 16:41:01 +1000838 cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
839 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000840 /* If there is a CI match block, drop it */
841 if (args->cmpresult != XFS_CMP_DIFFERENT &&
842 curdb != state->extrablk.blkno)
Dave Chinner1d9025e2012-06-22 18:50:14 +1000843 xfs_trans_brelse(tp, state->extrablk.bp);
Barry Naujok5163f952008-05-21 16:41:01 +1000844 args->cmpresult = cmp;
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000845 args->inumber = be64_to_cpu(dep->inumber);
Dave Chinner9d23fc82013-10-29 22:11:48 +1100846 args->filetype = dp->d_ops->data_get_ftype(dep);
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000847 *indexp = index;
848 state->extravalid = 1;
849 state->extrablk.bp = curbp;
850 state->extrablk.blkno = curdb;
851 state->extrablk.index = (int)((char *)dep -
Dave Chinner1d9025e2012-06-22 18:50:14 +1000852 (char *)curbp->b_addr);
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000853 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
Dave Chinner33363fe2013-04-03 16:11:22 +1100854 curbp->b_ops = &xfs_dir3_data_buf_ops;
Dave Chinner61fe1352013-04-03 16:11:30 +1100855 xfs_trans_buf_set_type(tp, curbp, XFS_BLFT_DIR_DATA_BUF);
Barry Naujok5163f952008-05-21 16:41:01 +1000856 if (cmp == XFS_CMP_EXACT)
Dave Chinner24513372014-06-25 14:58:08 +1000857 return -EEXIST;
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000858 }
859 }
Dave Chinner24df33b2013-04-12 07:30:21 +1000860 ASSERT(index == leafhdr.count || (args->op_flags & XFS_DA_OP_OKNOENT));
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000861 if (curbp) {
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000862 if (args->cmpresult == XFS_CMP_DIFFERENT) {
863 /* Giving back last used data block. */
864 state->extravalid = 1;
865 state->extrablk.bp = curbp;
866 state->extrablk.index = -1;
867 state->extrablk.blkno = curdb;
868 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
Dave Chinner33363fe2013-04-03 16:11:22 +1100869 curbp->b_ops = &xfs_dir3_data_buf_ops;
Dave Chinner61fe1352013-04-03 16:11:30 +1100870 xfs_trans_buf_set_type(tp, curbp, XFS_BLFT_DIR_DATA_BUF);
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000871 } else {
872 /* If the curbp is not the CI match block, drop it */
873 if (state->extrablk.bp != curbp)
Dave Chinner1d9025e2012-06-22 18:50:14 +1000874 xfs_trans_brelse(tp, curbp);
Barry Naujok90bb7ab2008-06-23 13:25:38 +1000875 }
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000876 } else {
877 state->extravalid = 0;
878 }
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000879 *indexp = index;
Dave Chinner24513372014-06-25 14:58:08 +1000880 return -ENOENT;
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000881}
882
883/*
884 * Look up a leaf entry in a node-format leaf block.
885 * If this is an addname then the extrablk in state is a freespace block,
886 * otherwise it's a data block.
887 */
888int
889xfs_dir2_leafn_lookup_int(
Dave Chinner1d9025e2012-06-22 18:50:14 +1000890 struct xfs_buf *bp, /* leaf buffer */
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000891 xfs_da_args_t *args, /* operation arguments */
892 int *indexp, /* out: leaf entry index */
893 xfs_da_state_t *state) /* state to fill in */
894{
Barry Naujok6a178102008-05-21 16:42:05 +1000895 if (args->op_flags & XFS_DA_OP_ADDNAME)
Barry Naujokf9f6dce2008-04-17 16:49:43 +1000896 return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp,
897 state);
898 return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state);
899}
900
901/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 * Move count leaf entries from source to destination leaf.
903 * Log entries and headers. Stale entries are preserved.
904 */
905static void
Dave Chinner24df33b2013-04-12 07:30:21 +1000906xfs_dir3_leafn_moveents(
907 xfs_da_args_t *args, /* operation arguments */
908 struct xfs_buf *bp_s, /* source */
909 struct xfs_dir3_icleaf_hdr *shdr,
910 struct xfs_dir2_leaf_entry *sents,
911 int start_s,/* source leaf index */
912 struct xfs_buf *bp_d, /* destination */
913 struct xfs_dir3_icleaf_hdr *dhdr,
914 struct xfs_dir2_leaf_entry *dents,
915 int start_d,/* destination leaf index */
916 int count) /* count of leaves to copy */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917{
Dave Chinner24df33b2013-04-12 07:30:21 +1000918 int stale; /* count stale leaves copied */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Christoph Hellwig0b1b2132009-12-14 23:14:59 +0000920 trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count);
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 /*
923 * Silently return if nothing to do.
924 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000925 if (count == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 return;
Dave Chinner24df33b2013-04-12 07:30:21 +1000927
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 /*
929 * If the destination index is not the end of the current
930 * destination leaf entries, open up a hole in the destination
931 * to hold the new entries.
932 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000933 if (start_d < dhdr->count) {
934 memmove(&dents[start_d + count], &dents[start_d],
935 (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t));
Christoph Hellwig787b0892019-11-08 14:57:50 -0800936 xfs_dir3_leaf_log_ents(args, dhdr, bp_d, start_d + count,
Dave Chinner24df33b2013-04-12 07:30:21 +1000937 count + dhdr->count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939 /*
940 * If the source has stale leaves, count the ones in the copy range
941 * so we can update the header correctly.
942 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000943 if (shdr->stale) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 int i; /* temp leaf index */
945
946 for (i = start_s, stale = 0; i < start_s + count; i++) {
Dave Chinner24df33b2013-04-12 07:30:21 +1000947 if (sents[i].address ==
948 cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 stale++;
950 }
951 } else
952 stale = 0;
953 /*
954 * Copy the leaf entries from source to destination.
955 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000956 memcpy(&dents[start_d], &sents[start_s],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 count * sizeof(xfs_dir2_leaf_entry_t));
Christoph Hellwig787b0892019-11-08 14:57:50 -0800958 xfs_dir3_leaf_log_ents(args, dhdr, bp_d, start_d, start_d + count - 1);
Dave Chinner24df33b2013-04-12 07:30:21 +1000959
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 /*
961 * If there are source entries after the ones we copied,
962 * delete the ones we copied by sliding the next ones down.
963 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000964 if (start_s + count < shdr->count) {
965 memmove(&sents[start_s], &sents[start_s + count],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 count * sizeof(xfs_dir2_leaf_entry_t));
Christoph Hellwig787b0892019-11-08 14:57:50 -0800967 xfs_dir3_leaf_log_ents(args, shdr, bp_s, start_s,
968 start_s + count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 }
Dave Chinner24df33b2013-04-12 07:30:21 +1000970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 /*
972 * Update the headers and log them.
973 */
Dave Chinner24df33b2013-04-12 07:30:21 +1000974 shdr->count -= count;
975 shdr->stale -= stale;
976 dhdr->count += count;
977 dhdr->stale += stale;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978}
979
980/*
981 * Determine the sort order of two leaf blocks.
982 * Returns 1 if both are valid and leaf2 should be before leaf1, else 0.
983 */
984int /* sort order */
985xfs_dir2_leafn_order(
Dave Chinner41419562013-10-29 22:11:50 +1100986 struct xfs_inode *dp,
Dave Chinner24df33b2013-04-12 07:30:21 +1000987 struct xfs_buf *leaf1_bp, /* leaf1 buffer */
988 struct xfs_buf *leaf2_bp) /* leaf2 buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989{
Dave Chinner24df33b2013-04-12 07:30:21 +1000990 struct xfs_dir2_leaf *leaf1 = leaf1_bp->b_addr;
991 struct xfs_dir2_leaf *leaf2 = leaf2_bp->b_addr;
992 struct xfs_dir2_leaf_entry *ents1;
993 struct xfs_dir2_leaf_entry *ents2;
994 struct xfs_dir3_icleaf_hdr hdr1;
995 struct xfs_dir3_icleaf_hdr hdr2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
Christoph Hellwig51842552019-11-08 14:57:49 -0800997 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1);
998 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2);
Christoph Hellwig787b0892019-11-08 14:57:50 -0800999 ents1 = hdr1.ents;
1000 ents2 = hdr2.ents;
Dave Chinner24df33b2013-04-12 07:30:21 +10001001
1002 if (hdr1.count > 0 && hdr2.count > 0 &&
1003 (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) ||
1004 be32_to_cpu(ents2[hdr2.count - 1].hashval) <
1005 be32_to_cpu(ents1[hdr1.count - 1].hashval)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 return 1;
1007 return 0;
1008}
1009
1010/*
1011 * Rebalance leaf entries between two leaf blocks.
1012 * This is actually only called when the second block is new,
1013 * though the code deals with the general case.
1014 * A new entry will be inserted in one of the blocks, and that
1015 * entry is taken into account when balancing.
1016 */
1017static void
1018xfs_dir2_leafn_rebalance(
1019 xfs_da_state_t *state, /* btree cursor */
1020 xfs_da_state_blk_t *blk1, /* first btree block */
1021 xfs_da_state_blk_t *blk2) /* second btree block */
1022{
1023 xfs_da_args_t *args; /* operation arguments */
1024 int count; /* count (& direction) leaves */
1025 int isleft; /* new goes in left leaf */
1026 xfs_dir2_leaf_t *leaf1; /* first leaf structure */
1027 xfs_dir2_leaf_t *leaf2; /* second leaf structure */
1028 int mid; /* midpoint leaf index */
Dave Chinner742ae1e2013-04-30 21:39:34 +10001029#if defined(DEBUG) || defined(XFS_WARN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 int oldstale; /* old count of stale leaves */
1031#endif
1032 int oldsum; /* old total leaf count */
Gustavo A. R. Silvae4e542a2018-07-17 14:25:01 -07001033 int swap_blocks; /* swapped leaf blocks */
Dave Chinner24df33b2013-04-12 07:30:21 +10001034 struct xfs_dir2_leaf_entry *ents1;
1035 struct xfs_dir2_leaf_entry *ents2;
1036 struct xfs_dir3_icleaf_hdr hdr1;
1037 struct xfs_dir3_icleaf_hdr hdr2;
Dave Chinner41419562013-10-29 22:11:50 +11001038 struct xfs_inode *dp = state->args->dp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
1040 args = state->args;
1041 /*
1042 * If the block order is wrong, swap the arguments.
1043 */
Gustavo A. R. Silvae4e542a2018-07-17 14:25:01 -07001044 swap_blocks = xfs_dir2_leafn_order(dp, blk1->bp, blk2->bp);
1045 if (swap_blocks)
1046 swap(blk1, blk2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Dave Chinner1d9025e2012-06-22 18:50:14 +10001048 leaf1 = blk1->bp->b_addr;
1049 leaf2 = blk2->bp->b_addr;
Christoph Hellwig51842552019-11-08 14:57:49 -08001050 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1);
1051 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2);
Christoph Hellwig787b0892019-11-08 14:57:50 -08001052 ents1 = hdr1.ents;
1053 ents2 = hdr2.ents;
Dave Chinner24df33b2013-04-12 07:30:21 +10001054
1055 oldsum = hdr1.count + hdr2.count;
Dave Chinner742ae1e2013-04-30 21:39:34 +10001056#if defined(DEBUG) || defined(XFS_WARN)
Dave Chinner24df33b2013-04-12 07:30:21 +10001057 oldstale = hdr1.stale + hdr2.stale;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058#endif
1059 mid = oldsum >> 1;
Dave Chinner24df33b2013-04-12 07:30:21 +10001060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 /*
1062 * If the old leaf count was odd then the new one will be even,
1063 * so we need to divide the new count evenly.
1064 */
1065 if (oldsum & 1) {
1066 xfs_dahash_t midhash; /* middle entry hash value */
1067
Dave Chinner24df33b2013-04-12 07:30:21 +10001068 if (mid >= hdr1.count)
1069 midhash = be32_to_cpu(ents2[mid - hdr1.count].hashval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 else
Dave Chinner24df33b2013-04-12 07:30:21 +10001071 midhash = be32_to_cpu(ents1[mid].hashval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 isleft = args->hashval <= midhash;
1073 }
1074 /*
1075 * If the old count is even then the new count is odd, so there's
1076 * no preferred side for the new entry.
1077 * Pick the left one.
1078 */
1079 else
1080 isleft = 1;
1081 /*
1082 * Calculate moved entry count. Positive means left-to-right,
1083 * negative means right-to-left. Then move the entries.
1084 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001085 count = hdr1.count - mid + (isleft == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if (count > 0)
Dave Chinner24df33b2013-04-12 07:30:21 +10001087 xfs_dir3_leafn_moveents(args, blk1->bp, &hdr1, ents1,
1088 hdr1.count - count, blk2->bp,
1089 &hdr2, ents2, 0, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 else if (count < 0)
Dave Chinner24df33b2013-04-12 07:30:21 +10001091 xfs_dir3_leafn_moveents(args, blk2->bp, &hdr2, ents2, 0,
1092 blk1->bp, &hdr1, ents1,
1093 hdr1.count, count);
1094
1095 ASSERT(hdr1.count + hdr2.count == oldsum);
1096 ASSERT(hdr1.stale + hdr2.stale == oldstale);
1097
1098 /* log the changes made when moving the entries */
Christoph Hellwig163fbbb2019-11-08 14:57:50 -08001099 xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf1, &hdr1);
1100 xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf2, &hdr2);
Dave Chinnerbc851782014-06-06 15:20:54 +10001101 xfs_dir3_leaf_log_header(args, blk1->bp);
1102 xfs_dir3_leaf_log_header(args, blk2->bp);
Dave Chinner24df33b2013-04-12 07:30:21 +10001103
Dave Chinner41419562013-10-29 22:11:50 +11001104 xfs_dir3_leaf_check(dp, blk1->bp);
1105 xfs_dir3_leaf_check(dp, blk2->bp);
Dave Chinner24df33b2013-04-12 07:30:21 +10001106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 /*
1108 * Mark whether we're inserting into the old or new leaf.
1109 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001110 if (hdr1.count < hdr2.count)
Gustavo A. R. Silvae4e542a2018-07-17 14:25:01 -07001111 state->inleaf = swap_blocks;
Dave Chinner24df33b2013-04-12 07:30:21 +10001112 else if (hdr1.count > hdr2.count)
Gustavo A. R. Silvae4e542a2018-07-17 14:25:01 -07001113 state->inleaf = !swap_blocks;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 else
Gustavo A. R. Silvae4e542a2018-07-17 14:25:01 -07001115 state->inleaf = swap_blocks ^ (blk1->index <= hdr1.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 /*
1117 * Adjust the expected index for insertion.
1118 */
1119 if (!state->inleaf)
Dave Chinner24df33b2013-04-12 07:30:21 +10001120 blk2->index = blk1->index - hdr1.count;
Barry Naujokf9f6dce2008-04-17 16:49:43 +10001121
1122 /*
1123 * Finally sanity check just to make sure we are not returning a
1124 * negative index
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 */
Dave Chinner41419562013-10-29 22:11:50 +11001126 if (blk2->index < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 state->inleaf = 1;
1128 blk2->index = 0;
Dave Chinner41419562013-10-29 22:11:50 +11001129 xfs_alert(dp->i_mount,
Eric Sandeen08e96e12013-10-11 20:59:05 -05001130 "%s: picked the wrong leaf? reverting original leaf: blk1->index %d",
Dave Chinner0b932cc2011-03-07 10:08:35 +11001131 __func__, blk1->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 }
1133}
1134
Dave Chinner20252072012-11-12 22:54:13 +11001135static int
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001136xfs_dir3_data_block_free(
Dave Chinner20252072012-11-12 22:54:13 +11001137 xfs_da_args_t *args,
1138 struct xfs_dir2_data_hdr *hdr,
1139 struct xfs_dir2_free *free,
1140 xfs_dir2_db_t fdb,
1141 int findex,
1142 struct xfs_buf *fbp,
1143 int longest)
1144{
Dave Chinner20252072012-11-12 22:54:13 +11001145 int logfree = 0;
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001146 __be16 *bests;
1147 struct xfs_dir3_icfree_hdr freehdr;
Dave Chinner01ba43b2013-10-29 22:11:52 +11001148 struct xfs_inode *dp = args->dp;
Dave Chinner20252072012-11-12 22:54:13 +11001149
Christoph Hellwig5ba30912019-11-08 14:57:52 -08001150 xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free);
Dave Chinner24dd0f52013-10-30 13:48:41 -05001151 bests = dp->d_ops->free_bests_p(free);
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001152 if (hdr) {
Dave Chinner20252072012-11-12 22:54:13 +11001153 /*
1154 * Data block is not empty, just set the free entry to the new
1155 * value.
1156 */
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001157 bests[findex] = cpu_to_be16(longest);
Dave Chinnerbc851782014-06-06 15:20:54 +10001158 xfs_dir2_free_log_bests(args, fbp, findex, findex);
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001159 return 0;
1160 }
1161
1162 /* One less used entry in the free table. */
1163 freehdr.nused--;
1164
1165 /*
1166 * If this was the last entry in the table, we can trim the table size
1167 * back. There might be other entries at the end referring to
1168 * non-existent data blocks, get those too.
1169 */
1170 if (findex == freehdr.nvalid - 1) {
1171 int i; /* free entry index */
1172
1173 for (i = findex - 1; i >= 0; i--) {
1174 if (bests[i] != cpu_to_be16(NULLDATAOFF))
1175 break;
1176 }
1177 freehdr.nvalid = i + 1;
1178 logfree = 0;
1179 } else {
1180 /* Not the last entry, just punch it out. */
1181 bests[findex] = cpu_to_be16(NULLDATAOFF);
Dave Chinner20252072012-11-12 22:54:13 +11001182 logfree = 1;
1183 }
1184
Dave Chinner01ba43b2013-10-29 22:11:52 +11001185 dp->d_ops->free_hdr_to_disk(free, &freehdr);
Dave Chinnerbc851782014-06-06 15:20:54 +10001186 xfs_dir2_free_log_header(args, fbp);
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001187
1188 /*
1189 * If there are no useful entries left in the block, get rid of the
1190 * block if we can.
1191 */
1192 if (!freehdr.nused) {
1193 int error;
1194
1195 error = xfs_dir2_shrink_inode(args, fdb, fbp);
1196 if (error == 0) {
1197 fbp = NULL;
1198 logfree = 0;
Dave Chinner24513372014-06-25 14:58:08 +10001199 } else if (error != -ENOSPC || args->total != 0)
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001200 return error;
1201 /*
1202 * It's possible to get ENOSPC if there is no
1203 * space reservation. In this case some one
1204 * else will eventually get rid of this block.
1205 */
1206 }
1207
Dave Chinner20252072012-11-12 22:54:13 +11001208 /* Log the free entry that changed, unless we got rid of it. */
1209 if (logfree)
Dave Chinnerbc851782014-06-06 15:20:54 +10001210 xfs_dir2_free_log_bests(args, fbp, findex, findex);
Dave Chinner20252072012-11-12 22:54:13 +11001211 return 0;
1212}
1213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214/*
1215 * Remove an entry from a node directory.
1216 * This removes the leaf entry and the data entry,
1217 * and updates the free block if necessary.
1218 */
1219static int /* error */
1220xfs_dir2_leafn_remove(
1221 xfs_da_args_t *args, /* operation arguments */
Dave Chinner1d9025e2012-06-22 18:50:14 +10001222 struct xfs_buf *bp, /* leaf buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 int index, /* leaf entry index */
1224 xfs_da_state_blk_t *dblk, /* data block */
1225 int *rval) /* resulting block needs join */
1226{
Christoph Hellwigc2066e22011-07-08 14:35:38 +02001227 xfs_dir2_data_hdr_t *hdr; /* data block header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 xfs_dir2_db_t db; /* data block number */
Dave Chinner1d9025e2012-06-22 18:50:14 +10001229 struct xfs_buf *dbp; /* data block buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 xfs_dir2_data_entry_t *dep; /* data block entry */
1231 xfs_inode_t *dp; /* incore directory inode */
1232 xfs_dir2_leaf_t *leaf; /* leaf structure */
1233 xfs_dir2_leaf_entry_t *lep; /* leaf entry */
1234 int longest; /* longest data free entry */
1235 int off; /* data block entry offset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 int needlog; /* need to log data header */
1237 int needscan; /* need to rescan data frees */
1238 xfs_trans_t *tp; /* transaction pointer */
Dave Chinner33363fe2013-04-03 16:11:22 +11001239 struct xfs_dir2_data_free *bf; /* bestfree table */
Dave Chinner24df33b2013-04-12 07:30:21 +10001240 struct xfs_dir3_icleaf_hdr leafhdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Christoph Hellwig0b1b2132009-12-14 23:14:59 +00001242 trace_xfs_dir2_leafn_remove(args, index);
1243
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 dp = args->dp;
1245 tp = args->trans;
Dave Chinner1d9025e2012-06-22 18:50:14 +10001246 leaf = bp->b_addr;
Christoph Hellwig51842552019-11-08 14:57:49 -08001247 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf);
Dave Chinner24df33b2013-04-12 07:30:21 +10001248
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 /*
1250 * Point to the entry we're removing.
1251 */
Christoph Hellwig787b0892019-11-08 14:57:50 -08001252 lep = &leafhdr.ents[index];
Dave Chinner24df33b2013-04-12 07:30:21 +10001253
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 /*
1255 * Extract the data block and offset from the entry.
1256 */
Dave Chinner30028032014-06-06 15:08:18 +10001257 db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 ASSERT(dblk->blkno == db);
Dave Chinner30028032014-06-06 15:08:18 +10001259 off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 ASSERT(dblk->index == off);
Dave Chinner24df33b2013-04-12 07:30:21 +10001261
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 /*
1263 * Kill the leaf entry by marking it stale.
1264 * Log the leaf block changes.
1265 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001266 leafhdr.stale++;
Christoph Hellwig163fbbb2019-11-08 14:57:50 -08001267 xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf, &leafhdr);
Dave Chinnerbc851782014-06-06 15:20:54 +10001268 xfs_dir3_leaf_log_header(args, bp);
Dave Chinner24df33b2013-04-12 07:30:21 +10001269
Nathan Scott3c1f9c12006-03-17 17:28:18 +11001270 lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
Christoph Hellwig787b0892019-11-08 14:57:50 -08001271 xfs_dir3_leaf_log_ents(args, &leafhdr, bp, index, index);
Dave Chinner24df33b2013-04-12 07:30:21 +10001272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 /*
1274 * Make the data entry free. Keep track of the longest freespace
1275 * in the data block in case it changes.
1276 */
1277 dbp = dblk->bp;
Dave Chinner1d9025e2012-06-22 18:50:14 +10001278 hdr = dbp->b_addr;
Christoph Hellwigc2066e22011-07-08 14:35:38 +02001279 dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
Dave Chinner2ca98772013-10-29 22:11:49 +11001280 bf = dp->d_ops->data_bestfree_p(hdr);
Dave Chinner33363fe2013-04-03 16:11:22 +11001281 longest = be16_to_cpu(bf[0].length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 needlog = needscan = 0;
Dave Chinnerbc851782014-06-06 15:20:54 +10001283 xfs_dir2_data_make_free(args, dbp, off,
Dave Chinner9d23fc82013-10-29 22:11:48 +11001284 dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 /*
1286 * Rescan the data block freespaces for bestfree.
1287 * Log the data block header if needed.
1288 */
1289 if (needscan)
Dave Chinner9d23fc82013-10-29 22:11:48 +11001290 xfs_dir2_data_freescan(dp, hdr, &needlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 if (needlog)
Dave Chinnerbc851782014-06-06 15:20:54 +10001292 xfs_dir2_data_log_header(args, dbp);
Dave Chinner33363fe2013-04-03 16:11:22 +11001293 xfs_dir3_data_check(dp, dbp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 /*
1295 * If the longest data block freespace changes, need to update
1296 * the corresponding freeblock entry.
1297 */
Dave Chinner33363fe2013-04-03 16:11:22 +11001298 if (longest < be16_to_cpu(bf[0].length)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 int error; /* error return value */
Dave Chinner1d9025e2012-06-22 18:50:14 +10001300 struct xfs_buf *fbp; /* freeblock buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 xfs_dir2_db_t fdb; /* freeblock block number */
1302 int findex; /* index in freeblock entries */
1303 xfs_dir2_free_t *free; /* freeblock structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
1305 /*
1306 * Convert the data block number to a free block,
1307 * read in the free block.
1308 */
Dave Chinner8f661932014-06-06 15:15:59 +10001309 fdb = dp->d_ops->db_to_fdb(args->geo, db);
Dave Chinner2998ab1d2014-06-06 15:07:53 +10001310 error = xfs_dir2_free_read(tp, dp,
1311 xfs_dir2_db_to_da(args->geo, fdb),
Dave Chinner20252072012-11-12 22:54:13 +11001312 &fbp);
Dave Chinner4bb20a82012-11-12 22:54:10 +11001313 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 return error;
Dave Chinner1d9025e2012-06-22 18:50:14 +10001315 free = fbp->b_addr;
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001316#ifdef DEBUG
1317 {
1318 struct xfs_dir3_icfree_hdr freehdr;
Christoph Hellwig5ba30912019-11-08 14:57:52 -08001319
1320 xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free);
Dave Chinner8f661932014-06-06 15:15:59 +10001321 ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) *
Dave Chinner30028032014-06-06 15:08:18 +10001322 (fdb - xfs_dir2_byte_to_db(args->geo,
1323 XFS_DIR2_FREE_OFFSET)));
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001324 }
1325#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 /*
1327 * Calculate which entry we need to fix.
1328 */
Dave Chinner8f661932014-06-06 15:15:59 +10001329 findex = dp->d_ops->db_to_fdindex(args->geo, db);
Dave Chinner33363fe2013-04-03 16:11:22 +11001330 longest = be16_to_cpu(bf[0].length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 /*
1332 * If the data block is now empty we can get rid of it
1333 * (usually).
1334 */
Dave Chinner8f661932014-06-06 15:15:59 +10001335 if (longest == args->geo->blksize -
Dave Chinner1c9a5b22013-10-30 09:15:02 +11001336 dp->d_ops->data_entry_offset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 /*
1338 * Try to punch out the data block.
1339 */
1340 error = xfs_dir2_shrink_inode(args, db, dbp);
1341 if (error == 0) {
1342 dblk->bp = NULL;
Christoph Hellwigc2066e22011-07-08 14:35:38 +02001343 hdr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 }
1345 /*
1346 * We can get ENOSPC if there's no space reservation.
1347 * In this case just drop the buffer and some one else
1348 * will eventually get rid of the empty block.
1349 */
Dave Chinner24513372014-06-25 14:58:08 +10001350 else if (!(error == -ENOSPC && args->total == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 return error;
1352 }
1353 /*
1354 * If we got rid of the data block, we can eliminate that entry
1355 * in the free block.
1356 */
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001357 error = xfs_dir3_data_block_free(args, hdr, free,
Dave Chinner20252072012-11-12 22:54:13 +11001358 fdb, findex, fbp, longest);
1359 if (error)
1360 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 }
Dave Chinner20252072012-11-12 22:54:13 +11001362
Dave Chinner41419562013-10-29 22:11:50 +11001363 xfs_dir3_leaf_check(dp, bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 /*
Malcolm Parsons9da096f2009-03-29 09:55:42 +02001365 * Return indication of whether this leaf block is empty enough
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 * to justify trying to join it with a neighbor.
1367 */
Christoph Hellwig545910b2019-11-08 14:57:51 -08001368 *rval = (args->geo->leaf_hdr_size +
Christoph Hellwig787b0892019-11-08 14:57:50 -08001369 (uint)sizeof(leafhdr.ents) * (leafhdr.count - leafhdr.stale)) <
Dave Chinnered358c02014-06-06 15:18:10 +10001370 args->geo->magicpct;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 return 0;
1372}
1373
1374/*
1375 * Split the leaf entries in the old block into old and new blocks.
1376 */
1377int /* error */
1378xfs_dir2_leafn_split(
1379 xfs_da_state_t *state, /* btree cursor */
1380 xfs_da_state_blk_t *oldblk, /* original block */
1381 xfs_da_state_blk_t *newblk) /* newly created block */
1382{
1383 xfs_da_args_t *args; /* operation arguments */
1384 xfs_dablk_t blkno; /* new leaf block number */
1385 int error; /* error return value */
Dave Chinner41419562013-10-29 22:11:50 +11001386 struct xfs_inode *dp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388 /*
1389 * Allocate space for a new leaf node.
1390 */
1391 args = state->args;
Dave Chinner41419562013-10-29 22:11:50 +11001392 dp = args->dp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC);
1394 error = xfs_da_grow_inode(args, &blkno);
1395 if (error) {
1396 return error;
1397 }
1398 /*
1399 * Initialize the new leaf block.
1400 */
Dave Chinner2998ab1d2014-06-06 15:07:53 +10001401 error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(args->geo, blkno),
Dave Chinner24df33b2013-04-12 07:30:21 +10001402 &newblk->bp, XFS_DIR2_LEAFN_MAGIC);
1403 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 return error;
Dave Chinner24df33b2013-04-12 07:30:21 +10001405
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 newblk->blkno = blkno;
1407 newblk->magic = XFS_DIR2_LEAFN_MAGIC;
1408 /*
1409 * Rebalance the entries across the two leaves, link the new
1410 * block into the leaves.
1411 */
1412 xfs_dir2_leafn_rebalance(state, oldblk, newblk);
Dave Chinnerf5ea1102013-04-24 18:58:02 +10001413 error = xfs_da3_blk_link(state, oldblk, newblk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (error) {
1415 return error;
1416 }
1417 /*
1418 * Insert the new entry in the correct block.
1419 */
1420 if (state->inleaf)
1421 error = xfs_dir2_leafn_add(oldblk->bp, args, oldblk->index);
1422 else
1423 error = xfs_dir2_leafn_add(newblk->bp, args, newblk->index);
1424 /*
1425 * Update last hashval in each block since we added the name.
1426 */
Darrick J. Wong8e8877e2017-06-16 11:00:13 -07001427 oldblk->hashval = xfs_dir2_leaf_lasthash(dp, oldblk->bp, NULL);
1428 newblk->hashval = xfs_dir2_leaf_lasthash(dp, newblk->bp, NULL);
Dave Chinner41419562013-10-29 22:11:50 +11001429 xfs_dir3_leaf_check(dp, oldblk->bp);
1430 xfs_dir3_leaf_check(dp, newblk->bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 return error;
1432}
1433
1434/*
1435 * Check a leaf block and its neighbors to see if the block should be
1436 * collapsed into one or the other neighbor. Always keep the block
1437 * with the smaller block number.
1438 * If the current block is over 50% full, don't try to join it, return 0.
1439 * If the block is empty, fill in the state structure and return 2.
1440 * If it can be collapsed, fill in the state structure and return 1.
1441 * If nothing can be done, return 0.
1442 */
1443int /* error */
1444xfs_dir2_leafn_toosmall(
1445 xfs_da_state_t *state, /* btree cursor */
1446 int *action) /* resulting action to take */
1447{
1448 xfs_da_state_blk_t *blk; /* leaf block */
1449 xfs_dablk_t blkno; /* leaf block number */
Dave Chinner1d9025e2012-06-22 18:50:14 +10001450 struct xfs_buf *bp; /* leaf buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 int bytes; /* bytes in use */
1452 int count; /* leaf live entry count */
1453 int error; /* error return value */
1454 int forward; /* sibling block direction */
1455 int i; /* sibling counter */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 xfs_dir2_leaf_t *leaf; /* leaf structure */
1457 int rval; /* result from path_shift */
Dave Chinner24df33b2013-04-12 07:30:21 +10001458 struct xfs_dir3_icleaf_hdr leafhdr;
1459 struct xfs_dir2_leaf_entry *ents;
Dave Chinner41419562013-10-29 22:11:50 +11001460 struct xfs_inode *dp = state->args->dp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 /*
1463 * Check for the degenerate case of the block being over 50% full.
1464 * If so, it's not worth even looking to see if we might be able
1465 * to coalesce with a sibling.
1466 */
1467 blk = &state->path.blk[state->path.active - 1];
Dave Chinner24df33b2013-04-12 07:30:21 +10001468 leaf = blk->bp->b_addr;
Christoph Hellwig51842552019-11-08 14:57:49 -08001469 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf);
Christoph Hellwig787b0892019-11-08 14:57:50 -08001470 ents = leafhdr.ents;
Dave Chinner41419562013-10-29 22:11:50 +11001471 xfs_dir3_leaf_check(dp, blk->bp);
Dave Chinner24df33b2013-04-12 07:30:21 +10001472
1473 count = leafhdr.count - leafhdr.stale;
Christoph Hellwig545910b2019-11-08 14:57:51 -08001474 bytes = state->args->geo->leaf_hdr_size + count * sizeof(ents[0]);
Dave Chinnerb2a21e72014-06-06 15:22:04 +10001475 if (bytes > (state->args->geo->blksize >> 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 /*
1477 * Blk over 50%, don't try to join.
1478 */
1479 *action = 0;
1480 return 0;
1481 }
1482 /*
1483 * Check for the degenerate case of the block being empty.
1484 * If the block is empty, we'll simply delete it, no need to
1485 * coalesce it with a sibling block. We choose (arbitrarily)
1486 * to merge with the forward block unless it is NULL.
1487 */
1488 if (count == 0) {
1489 /*
1490 * Make altpath point to the block we want to keep and
1491 * path point to the block we want to drop (this one).
1492 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001493 forward = (leafhdr.forw != 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 memcpy(&state->altpath, &state->path, sizeof(state->path));
Dave Chinnerf5ea1102013-04-24 18:58:02 +10001495 error = xfs_da3_path_shift(state, &state->altpath, forward, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 &rval);
1497 if (error)
1498 return error;
1499 *action = rval ? 2 : 0;
1500 return 0;
1501 }
1502 /*
1503 * Examine each sibling block to see if we can coalesce with
1504 * at least 25% free space to spare. We need to figure out
1505 * whether to merge with the forward or the backward block.
1506 * We prefer coalescing with the lower numbered sibling so as
1507 * to shrink a directory over time.
1508 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001509 forward = leafhdr.forw < leafhdr.back;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 for (i = 0, bp = NULL; i < 2; forward = !forward, i++) {
Dave Chinner24df33b2013-04-12 07:30:21 +10001511 struct xfs_dir3_icleaf_hdr hdr2;
1512
1513 blkno = forward ? leafhdr.forw : leafhdr.back;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 if (blkno == 0)
1515 continue;
1516 /*
1517 * Read the sibling leaf block.
1518 */
Dave Chinner41419562013-10-29 22:11:50 +11001519 error = xfs_dir3_leafn_read(state->args->trans, dp,
Dave Chinnere6f76672012-11-12 22:54:15 +11001520 blkno, -1, &bp);
Dave Chinner4bb20a82012-11-12 22:54:10 +11001521 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 return error;
Dave Chinnere6f76672012-11-12 22:54:15 +11001523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 /*
1525 * Count bytes in the two blocks combined.
1526 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001527 count = leafhdr.count - leafhdr.stale;
Dave Chinnerb2a21e72014-06-06 15:22:04 +10001528 bytes = state->args->geo->blksize -
1529 (state->args->geo->blksize >> 2);
Dave Chinner24df33b2013-04-12 07:30:21 +10001530
Dave Chinner1d9025e2012-06-22 18:50:14 +10001531 leaf = bp->b_addr;
Christoph Hellwig51842552019-11-08 14:57:49 -08001532 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf);
Christoph Hellwig787b0892019-11-08 14:57:50 -08001533 ents = hdr2.ents;
Dave Chinner24df33b2013-04-12 07:30:21 +10001534 count += hdr2.count - hdr2.stale;
1535 bytes -= count * sizeof(ents[0]);
1536
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 /*
1538 * Fits with at least 25% to spare.
1539 */
1540 if (bytes >= 0)
1541 break;
Dave Chinner1d9025e2012-06-22 18:50:14 +10001542 xfs_trans_brelse(state->args->trans, bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 }
1544 /*
1545 * Didn't like either block, give up.
1546 */
1547 if (i >= 2) {
1548 *action = 0;
1549 return 0;
1550 }
Dave Chinner1d9025e2012-06-22 18:50:14 +10001551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 /*
1553 * Make altpath point to the block we want to keep (the lower
1554 * numbered block) and path point to the block we want to drop.
1555 */
1556 memcpy(&state->altpath, &state->path, sizeof(state->path));
1557 if (blkno < blk->blkno)
Dave Chinnerf5ea1102013-04-24 18:58:02 +10001558 error = xfs_da3_path_shift(state, &state->altpath, forward, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 &rval);
1560 else
Dave Chinnerf5ea1102013-04-24 18:58:02 +10001561 error = xfs_da3_path_shift(state, &state->path, forward, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 &rval);
1563 if (error) {
1564 return error;
1565 }
1566 *action = rval ? 0 : 1;
1567 return 0;
1568}
1569
1570/*
1571 * Move all the leaf entries from drop_blk to save_blk.
1572 * This is done as part of a join operation.
1573 */
1574void
1575xfs_dir2_leafn_unbalance(
1576 xfs_da_state_t *state, /* cursor */
1577 xfs_da_state_blk_t *drop_blk, /* dead block */
1578 xfs_da_state_blk_t *save_blk) /* surviving block */
1579{
1580 xfs_da_args_t *args; /* operation arguments */
1581 xfs_dir2_leaf_t *drop_leaf; /* dead leaf structure */
1582 xfs_dir2_leaf_t *save_leaf; /* surviving leaf structure */
Dave Chinner24df33b2013-04-12 07:30:21 +10001583 struct xfs_dir3_icleaf_hdr savehdr;
1584 struct xfs_dir3_icleaf_hdr drophdr;
1585 struct xfs_dir2_leaf_entry *sents;
1586 struct xfs_dir2_leaf_entry *dents;
Dave Chinner41419562013-10-29 22:11:50 +11001587 struct xfs_inode *dp = state->args->dp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
1589 args = state->args;
1590 ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
1591 ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC);
Dave Chinner1d9025e2012-06-22 18:50:14 +10001592 drop_leaf = drop_blk->bp->b_addr;
1593 save_leaf = save_blk->bp->b_addr;
Dave Chinner24df33b2013-04-12 07:30:21 +10001594
Christoph Hellwig51842552019-11-08 14:57:49 -08001595 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &savehdr, save_leaf);
1596 xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &drophdr, drop_leaf);
Christoph Hellwig787b0892019-11-08 14:57:50 -08001597 sents = savehdr.ents;
1598 dents = drophdr.ents;
Dave Chinner24df33b2013-04-12 07:30:21 +10001599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 /*
1601 * If there are any stale leaf entries, take this opportunity
1602 * to purge them.
1603 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001604 if (drophdr.stale)
1605 xfs_dir3_leaf_compact(args, &drophdr, drop_blk->bp);
1606 if (savehdr.stale)
1607 xfs_dir3_leaf_compact(args, &savehdr, save_blk->bp);
1608
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 /*
1610 * Move the entries from drop to the appropriate end of save.
1611 */
Dave Chinner24df33b2013-04-12 07:30:21 +10001612 drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval);
Dave Chinner41419562013-10-29 22:11:50 +11001613 if (xfs_dir2_leafn_order(dp, save_blk->bp, drop_blk->bp))
Dave Chinner24df33b2013-04-12 07:30:21 +10001614 xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0,
1615 save_blk->bp, &savehdr, sents, 0,
1616 drophdr.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 else
Dave Chinner24df33b2013-04-12 07:30:21 +10001618 xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0,
1619 save_blk->bp, &savehdr, sents,
1620 savehdr.count, drophdr.count);
1621 save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval);
1622
1623 /* log the changes made when moving the entries */
Christoph Hellwig163fbbb2019-11-08 14:57:50 -08001624 xfs_dir2_leaf_hdr_to_disk(dp->i_mount, save_leaf, &savehdr);
1625 xfs_dir2_leaf_hdr_to_disk(dp->i_mount, drop_leaf, &drophdr);
Dave Chinnerbc851782014-06-06 15:20:54 +10001626 xfs_dir3_leaf_log_header(args, save_blk->bp);
1627 xfs_dir3_leaf_log_header(args, drop_blk->bp);
Dave Chinner24df33b2013-04-12 07:30:21 +10001628
Dave Chinner41419562013-10-29 22:11:50 +11001629 xfs_dir3_leaf_check(dp, save_blk->bp);
1630 xfs_dir3_leaf_check(dp, drop_blk->bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631}
1632
1633/*
Dave Chinnera07258a2019-08-29 09:04:06 -07001634 * Add a new data block to the directory at the free space index that the caller
1635 * has specified.
1636 */
1637static int
1638xfs_dir2_node_add_datablk(
1639 struct xfs_da_args *args,
1640 struct xfs_da_state_blk *fblk,
1641 xfs_dir2_db_t *dbno,
1642 struct xfs_buf **dbpp,
1643 struct xfs_buf **fbpp,
1644 int *findex)
1645{
1646 struct xfs_inode *dp = args->dp;
1647 struct xfs_trans *tp = args->trans;
1648 struct xfs_mount *mp = dp->i_mount;
1649 struct xfs_dir3_icfree_hdr freehdr;
1650 struct xfs_dir2_data_free *bf;
1651 struct xfs_dir2_data_hdr *hdr;
1652 struct xfs_dir2_free *free = NULL;
1653 xfs_dir2_db_t fbno;
1654 struct xfs_buf *fbp;
1655 struct xfs_buf *dbp;
1656 __be16 *bests = NULL;
1657 int error;
1658
1659 /* Not allowed to allocate, return failure. */
Dave Chinner0e822252019-08-29 09:04:07 -07001660 if (args->total == 0)
Dave Chinnera07258a2019-08-29 09:04:06 -07001661 return -ENOSPC;
1662
1663 /* Allocate and initialize the new data block. */
1664 error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, dbno);
1665 if (error)
1666 return error;
1667 error = xfs_dir3_data_init(args, *dbno, &dbp);
1668 if (error)
1669 return error;
1670
1671 /*
1672 * Get the freespace block corresponding to the data block
1673 * that was just allocated.
1674 */
1675 fbno = dp->d_ops->db_to_fdb(args->geo, *dbno);
1676 error = xfs_dir2_free_try_read(tp, dp,
1677 xfs_dir2_db_to_da(args->geo, fbno), &fbp);
1678 if (error)
1679 return error;
1680
1681 /*
1682 * If there wasn't a freespace block, the read will
1683 * return a NULL fbp. Allocate and initialize a new one.
1684 */
1685 if (!fbp) {
1686 error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fbno);
1687 if (error)
1688 return error;
1689
1690 if (dp->d_ops->db_to_fdb(args->geo, *dbno) != fbno) {
1691 xfs_alert(mp,
1692"%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld",
1693 __func__, (unsigned long long)dp->i_ino,
1694 (long long)dp->d_ops->db_to_fdb(args->geo, *dbno),
1695 (long long)*dbno, (long long)fbno);
1696 if (fblk) {
1697 xfs_alert(mp,
1698 " fblk "PTR_FMT" blkno %llu index %d magic 0x%x",
1699 fblk, (unsigned long long)fblk->blkno,
1700 fblk->index, fblk->magic);
1701 } else {
1702 xfs_alert(mp, " ... fblk is NULL");
1703 }
1704 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
1705 return -EFSCORRUPTED;
1706 }
1707
1708 /* Get a buffer for the new block. */
1709 error = xfs_dir3_free_get_buf(args, fbno, &fbp);
1710 if (error)
1711 return error;
1712 free = fbp->b_addr;
1713 bests = dp->d_ops->free_bests_p(free);
Christoph Hellwig5ba30912019-11-08 14:57:52 -08001714 xfs_dir2_free_hdr_from_disk(mp, &freehdr, free);
Dave Chinnera07258a2019-08-29 09:04:06 -07001715
1716 /* Remember the first slot as our empty slot. */
1717 freehdr.firstdb = (fbno - xfs_dir2_byte_to_db(args->geo,
1718 XFS_DIR2_FREE_OFFSET)) *
1719 dp->d_ops->free_max_bests(args->geo);
1720 } else {
1721 free = fbp->b_addr;
1722 bests = dp->d_ops->free_bests_p(free);
Christoph Hellwig5ba30912019-11-08 14:57:52 -08001723 xfs_dir2_free_hdr_from_disk(mp, &freehdr, free);
Dave Chinnera07258a2019-08-29 09:04:06 -07001724 }
1725
1726 /* Set the freespace block index from the data block number. */
1727 *findex = dp->d_ops->db_to_fdindex(args->geo, *dbno);
1728
1729 /* Extend the freespace table if the new data block is off the end. */
1730 if (*findex >= freehdr.nvalid) {
1731 ASSERT(*findex < dp->d_ops->free_max_bests(args->geo));
1732 freehdr.nvalid = *findex + 1;
1733 bests[*findex] = cpu_to_be16(NULLDATAOFF);
1734 }
1735
1736 /*
1737 * If this entry was for an empty data block (this should always be
1738 * true) then update the header.
1739 */
1740 if (bests[*findex] == cpu_to_be16(NULLDATAOFF)) {
1741 freehdr.nused++;
1742 dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr);
1743 xfs_dir2_free_log_header(args, fbp);
1744 }
1745
1746 /* Update the freespace value for the new block in the table. */
1747 hdr = dbp->b_addr;
1748 bf = dp->d_ops->data_bestfree_p(hdr);
1749 bests[*findex] = bf[0].length;
1750
1751 *dbpp = dbp;
1752 *fbpp = fbp;
1753 return 0;
1754}
1755
Dave Chinner0e822252019-08-29 09:04:07 -07001756static int
1757xfs_dir2_node_find_freeblk(
1758 struct xfs_da_args *args,
1759 struct xfs_da_state_blk *fblk,
1760 xfs_dir2_db_t *dbnop,
1761 struct xfs_buf **fbpp,
1762 int *findexp,
1763 int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764{
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001765 struct xfs_dir3_icfree_hdr freehdr;
Dave Chinner0e822252019-08-29 09:04:07 -07001766 struct xfs_dir2_free *free = NULL;
1767 struct xfs_inode *dp = args->dp;
1768 struct xfs_trans *tp = args->trans;
1769 struct xfs_buf *fbp = NULL;
Dave Chinner756c6f02019-08-29 09:04:08 -07001770 xfs_dir2_db_t firstfbno;
Dave Chinner0e822252019-08-29 09:04:07 -07001771 xfs_dir2_db_t lastfbno;
1772 xfs_dir2_db_t ifbno = -1;
1773 xfs_dir2_db_t dbno = -1;
Dave Chinner756c6f02019-08-29 09:04:08 -07001774 xfs_dir2_db_t fbno;
Dave Chinner0e822252019-08-29 09:04:07 -07001775 xfs_fileoff_t fo;
Dave Chinner610125a2019-08-29 09:04:07 -07001776 __be16 *bests = NULL;
1777 int findex = 0;
Dave Chinner0e822252019-08-29 09:04:07 -07001778 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 /*
1781 * If we came in with a freespace block that means that lookup
1782 * found an entry with our hash value. This is the freespace
1783 * block for that data entry.
1784 */
1785 if (fblk) {
1786 fbp = fblk->bp;
Dave Chinner1d9025e2012-06-22 18:50:14 +10001787 free = fbp->b_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 findex = fblk->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 if (findex >= 0) {
Dave Chinner0e822252019-08-29 09:04:07 -07001790 /* caller already found the freespace for us. */
1791 bests = dp->d_ops->free_bests_p(free);
Christoph Hellwig5ba30912019-11-08 14:57:52 -08001792 xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr,
1793 free);
Dave Chinner0e822252019-08-29 09:04:07 -07001794
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001795 ASSERT(findex < freehdr.nvalid);
1796 ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF);
1797 ASSERT(be16_to_cpu(bests[findex]) >= length);
1798 dbno = freehdr.firstdb + findex;
Dave Chinnera07258a2019-08-29 09:04:06 -07001799 goto found_block;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 }
Dave Chinner0e822252019-08-29 09:04:07 -07001801
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001802 /*
Dave Chinner0e822252019-08-29 09:04:07 -07001803 * The data block looked at didn't have enough room.
1804 * We'll start at the beginning of the freespace entries.
Dave Chinnercbc8adf2013-04-03 16:11:21 +11001805 */
Dave Chinner0e822252019-08-29 09:04:07 -07001806 ifbno = fblk->blkno;
Dave Chinner610125a2019-08-29 09:04:07 -07001807 xfs_trans_brelse(tp, fbp);
1808 fbp = NULL;
1809 fblk->bp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 }
Dave Chinner0e822252019-08-29 09:04:07 -07001811
1812 /*
1813 * If we don't have a data block yet, we're going to scan the freespace
Dave Chinner610125a2019-08-29 09:04:07 -07001814 * data for a data block with enough free space in it.
Dave Chinner0e822252019-08-29 09:04:07 -07001815 */
1816 error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK);
1817 if (error)
1818 return error;
1819 lastfbno = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo);
Dave Chinner756c6f02019-08-29 09:04:08 -07001820 firstfbno = xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET);
Dave Chinner0e822252019-08-29 09:04:07 -07001821
Dave Chinner756c6f02019-08-29 09:04:08 -07001822 for (fbno = lastfbno - 1; fbno >= firstfbno; fbno--) {
Dave Chinner610125a2019-08-29 09:04:07 -07001823 /* If it's ifbno we already looked at it. */
1824 if (fbno == ifbno)
1825 continue;
1826
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 /*
Dave Chinner610125a2019-08-29 09:04:07 -07001828 * Read the block. There can be holes in the freespace blocks,
1829 * so this might not succeed. This should be really rare, so
1830 * there's no reason to avoid it.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 */
Dave Chinner610125a2019-08-29 09:04:07 -07001832 error = xfs_dir2_free_try_read(tp, dp,
1833 xfs_dir2_db_to_da(args->geo, fbno),
1834 &fbp);
1835 if (error)
1836 return error;
1837 if (!fbp)
1838 continue;
1839
1840 free = fbp->b_addr;
Dave Chinner24dd0f52013-10-30 13:48:41 -05001841 bests = dp->d_ops->free_bests_p(free);
Christoph Hellwig5ba30912019-11-08 14:57:52 -08001842 xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free);
Dave Chinner610125a2019-08-29 09:04:07 -07001843
1844 /* Scan the free entry array for a large enough free space. */
Dave Chinner756c6f02019-08-29 09:04:08 -07001845 for (findex = freehdr.nvalid - 1; findex >= 0; findex--) {
Dave Chinner610125a2019-08-29 09:04:07 -07001846 if (be16_to_cpu(bests[findex]) != NULLDATAOFF &&
1847 be16_to_cpu(bests[findex]) >= length) {
1848 dbno = freehdr.firstdb + findex;
1849 goto found_block;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 }
1851 }
Dave Chinner610125a2019-08-29 09:04:07 -07001852
1853 /* Didn't find free space, go on to next free block */
1854 xfs_trans_brelse(tp, fbp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 }
Dave Chinner610125a2019-08-29 09:04:07 -07001856
Dave Chinner0e822252019-08-29 09:04:07 -07001857found_block:
1858 *dbnop = dbno;
1859 *fbpp = fbp;
1860 *findexp = findex;
1861 return 0;
1862}
1863
1864
1865/*
1866 * Add the data entry for a node-format directory name addition.
1867 * The leaf entry is added in xfs_dir2_leafn_add.
1868 * We may enter with a freespace block that the lookup found.
1869 */
1870static int
1871xfs_dir2_node_addname_int(
1872 struct xfs_da_args *args, /* operation arguments */
1873 struct xfs_da_state_blk *fblk) /* optional freespace block */
1874{
1875 struct xfs_dir2_data_unused *dup; /* data unused entry pointer */
1876 struct xfs_dir2_data_entry *dep; /* data entry pointer */
1877 struct xfs_dir2_data_hdr *hdr; /* data block header */
1878 struct xfs_dir2_data_free *bf;
1879 struct xfs_dir2_free *free = NULL; /* freespace block structure */
1880 struct xfs_trans *tp = args->trans;
1881 struct xfs_inode *dp = args->dp;
1882 struct xfs_buf *dbp; /* data block buffer */
1883 struct xfs_buf *fbp; /* freespace buffer */
1884 xfs_dir2_data_aoff_t aoff;
1885 xfs_dir2_db_t dbno; /* data block number */
1886 int error; /* error return value */
1887 int findex; /* freespace entry index */
1888 int length; /* length of the new entry */
1889 int logfree = 0; /* need to log free entry */
1890 int needlog = 0; /* need to log data header */
1891 int needscan = 0; /* need to rescan data frees */
1892 __be16 *tagp; /* data entry tag pointer */
1893 __be16 *bests;
1894
1895 length = dp->d_ops->data_entsize(args->namelen);
1896 error = xfs_dir2_node_find_freeblk(args, fblk, &dbno, &fbp, &findex,
1897 length);
1898 if (error)
1899 return error;
1900
1901 /*
1902 * Now we know if we must allocate blocks, so if we are checking whether
1903 * we can insert without allocation then we can return now.
1904 */
1905 if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
1906 if (dbno == -1)
1907 return -ENOSPC;
1908 return 0;
1909 }
Dave Chinnera07258a2019-08-29 09:04:06 -07001910
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 /*
1912 * If we don't have a data block, we need to allocate one and make
1913 * the freespace entries refer to it.
1914 */
Dave Chinnera07258a2019-08-29 09:04:06 -07001915 if (dbno == -1) {
Dave Chinnera07258a2019-08-29 09:04:06 -07001916 /* we're going to have to log the free block index later */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 logfree = 1;
Dave Chinner0e822252019-08-29 09:04:07 -07001918 error = xfs_dir2_node_add_datablk(args, fblk, &dbno, &dbp, &fbp,
1919 &findex);
Dave Chinnera07258a2019-08-29 09:04:06 -07001920 } else {
Dave Chinnera07258a2019-08-29 09:04:06 -07001921 /* Read the data block in. */
Dave Chinner2998ab1d2014-06-06 15:07:53 +10001922 error = xfs_dir3_data_read(tp, dp,
1923 xfs_dir2_db_to_da(args->geo, dbno),
Dave Chinnere4813572012-11-12 22:54:14 +11001924 -1, &dbp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 }
Dave Chinner0e822252019-08-29 09:04:07 -07001926 if (error)
1927 return error;
Dave Chinnera07258a2019-08-29 09:04:06 -07001928
1929 /* setup for data block up now */
1930 hdr = dbp->b_addr;
1931 bf = dp->d_ops->data_bestfree_p(hdr);
Dave Chinner33363fe2013-04-03 16:11:22 +11001932 ASSERT(be16_to_cpu(bf[0].length) >= length);
Dave Chinnera07258a2019-08-29 09:04:06 -07001933
1934 /* Point to the existing unused space. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 dup = (xfs_dir2_data_unused_t *)
Dave Chinner33363fe2013-04-03 16:11:22 +11001936 ((char *)hdr + be16_to_cpu(bf[0].offset));
Dave Chinnera07258a2019-08-29 09:04:06 -07001937
1938 /* Mark the first part of the unused space, inuse for us. */
Darrick J. Wong6915ef32018-03-23 10:06:51 -07001939 aoff = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
1940 error = xfs_dir2_data_use_free(args, dbp, dup, aoff, length,
1941 &needlog, &needscan);
1942 if (error) {
1943 xfs_trans_brelse(tp, dbp);
1944 return error;
1945 }
Dave Chinnera07258a2019-08-29 09:04:06 -07001946
1947 /* Fill in the new entry and log it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 dep = (xfs_dir2_data_entry_t *)dup;
Christoph Hellwigff9901c2006-06-09 14:48:37 +10001949 dep->inumber = cpu_to_be64(args->inumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 dep->namelen = args->namelen;
1951 memcpy(dep->name, args->name, dep->namelen);
Dave Chinner9d23fc82013-10-29 22:11:48 +11001952 dp->d_ops->data_put_ftype(dep, args->filetype);
1953 tagp = dp->d_ops->data_entry_tag_p(dep);
Christoph Hellwigc2066e22011-07-08 14:35:38 +02001954 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
Dave Chinnerbc851782014-06-06 15:20:54 +10001955 xfs_dir2_data_log_entry(args, dbp, dep);
Dave Chinnera07258a2019-08-29 09:04:06 -07001956
1957 /* Rescan the freespace and log the data block if needed. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 if (needscan)
Dave Chinner9d23fc82013-10-29 22:11:48 +11001959 xfs_dir2_data_freescan(dp, hdr, &needlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 if (needlog)
Dave Chinnerbc851782014-06-06 15:20:54 +10001961 xfs_dir2_data_log_header(args, dbp);
Dave Chinnera07258a2019-08-29 09:04:06 -07001962
1963 /* If the freespace block entry is now wrong, update it. */
Dave Chinner0e822252019-08-29 09:04:07 -07001964 free = fbp->b_addr;
Dave Chinnera07258a2019-08-29 09:04:06 -07001965 bests = dp->d_ops->free_bests_p(free);
1966 if (bests[findex] != bf[0].length) {
Dave Chinner33363fe2013-04-03 16:11:22 +11001967 bests[findex] = bf[0].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 logfree = 1;
1969 }
Dave Chinnera07258a2019-08-29 09:04:06 -07001970
1971 /* Log the freespace entry if needed. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 if (logfree)
Dave Chinnerbc851782014-06-06 15:20:54 +10001973 xfs_dir2_free_log_bests(args, fbp, findex, findex);
Dave Chinnera07258a2019-08-29 09:04:06 -07001974
1975 /* Return the data block and offset in args. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 args->blkno = (xfs_dablk_t)dbno;
Nathan Scott3d693c62006-03-17 17:28:27 +11001977 args->index = be16_to_cpu(*tagp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 return 0;
1979}
1980
1981/*
Dave Chinneraee7754b2019-08-29 09:04:06 -07001982 * Top-level node form directory addname routine.
1983 */
1984int /* error */
1985xfs_dir2_node_addname(
1986 xfs_da_args_t *args) /* operation arguments */
1987{
1988 xfs_da_state_blk_t *blk; /* leaf block for insert */
1989 int error; /* error return value */
1990 int rval; /* sub-return value */
1991 xfs_da_state_t *state; /* btree cursor */
1992
1993 trace_xfs_dir2_node_addname(args);
1994
1995 /*
1996 * Allocate and initialize the state (btree cursor).
1997 */
1998 state = xfs_da_state_alloc();
1999 state->args = args;
2000 state->mp = args->dp->i_mount;
2001 /*
2002 * Look up the name. We're not supposed to find it, but
2003 * this gives us the insertion point.
2004 */
2005 error = xfs_da3_node_lookup_int(state, &rval);
2006 if (error)
2007 rval = error;
2008 if (rval != -ENOENT) {
2009 goto done;
2010 }
2011 /*
2012 * Add the data entry to a data block.
2013 * Extravalid is set to a freeblock found by lookup.
2014 */
2015 rval = xfs_dir2_node_addname_int(args,
2016 state->extravalid ? &state->extrablk : NULL);
2017 if (rval) {
2018 goto done;
2019 }
2020 blk = &state->path.blk[state->path.active - 1];
2021 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
2022 /*
2023 * Add the new leaf entry.
2024 */
2025 rval = xfs_dir2_leafn_add(blk->bp, args, blk->index);
2026 if (rval == 0) {
2027 /*
2028 * It worked, fix the hash values up the btree.
2029 */
2030 if (!(args->op_flags & XFS_DA_OP_JUSTCHECK))
2031 xfs_da3_fixhashpath(state, &state->path);
2032 } else {
2033 /*
2034 * It didn't work, we need to split the leaf block.
2035 */
2036 if (args->total == 0) {
2037 ASSERT(rval == -ENOSPC);
2038 goto done;
2039 }
2040 /*
2041 * Split the leaf block and insert the new entry.
2042 */
2043 rval = xfs_da3_split(state);
2044 }
2045done:
2046 xfs_da_state_free(state);
2047 return rval;
2048}
2049
2050/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 * Lookup an entry in a node-format directory.
Dave Chinnerf5ea1102013-04-24 18:58:02 +10002052 * All the real work happens in xfs_da3_node_lookup_int.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 * The only real output is the inode number of the entry.
2054 */
2055int /* error */
2056xfs_dir2_node_lookup(
2057 xfs_da_args_t *args) /* operation arguments */
2058{
2059 int error; /* error return value */
2060 int i; /* btree level */
2061 int rval; /* operation return value */
2062 xfs_da_state_t *state; /* btree cursor */
2063
Christoph Hellwig0b1b2132009-12-14 23:14:59 +00002064 trace_xfs_dir2_node_lookup(args);
2065
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 /*
2067 * Allocate and initialize the btree cursor.
2068 */
2069 state = xfs_da_state_alloc();
2070 state->args = args;
2071 state->mp = args->dp->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 /*
2073 * Fill in the path to the entry in the cursor.
2074 */
Dave Chinnerf5ea1102013-04-24 18:58:02 +10002075 error = xfs_da3_node_lookup_int(state, &rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 if (error)
2077 rval = error;
Dave Chinner24513372014-06-25 14:58:08 +10002078 else if (rval == -ENOENT && args->cmpresult == XFS_CMP_CASE) {
2079 /* If a CI match, dup the actual name and return -EEXIST */
Barry Naujok384f3ce2008-05-21 16:58:22 +10002080 xfs_dir2_data_entry_t *dep;
2081
Dave Chinner1d9025e2012-06-22 18:50:14 +10002082 dep = (xfs_dir2_data_entry_t *)
2083 ((char *)state->extrablk.bp->b_addr +
2084 state->extrablk.index);
Barry Naujok384f3ce2008-05-21 16:58:22 +10002085 rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
2086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 /*
2088 * Release the btree blocks and leaf block.
2089 */
2090 for (i = 0; i < state->path.active; i++) {
Dave Chinner1d9025e2012-06-22 18:50:14 +10002091 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 state->path.blk[i].bp = NULL;
2093 }
2094 /*
2095 * Release the data block if we have it.
2096 */
2097 if (state->extravalid && state->extrablk.bp) {
Dave Chinner1d9025e2012-06-22 18:50:14 +10002098 xfs_trans_brelse(args->trans, state->extrablk.bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 state->extrablk.bp = NULL;
2100 }
2101 xfs_da_state_free(state);
2102 return rval;
2103}
2104
2105/*
2106 * Remove an entry from a node-format directory.
2107 */
2108int /* error */
2109xfs_dir2_node_removename(
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002110 struct xfs_da_args *args) /* operation arguments */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111{
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002112 struct xfs_da_state_blk *blk; /* leaf block */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 int error; /* error return value */
2114 int rval; /* operation return value */
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002115 struct xfs_da_state *state; /* btree cursor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
Christoph Hellwig0b1b2132009-12-14 23:14:59 +00002117 trace_xfs_dir2_node_removename(args);
2118
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 /*
2120 * Allocate and initialize the btree cursor.
2121 */
2122 state = xfs_da_state_alloc();
2123 state->args = args;
2124 state->mp = args->dp->i_mount;
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002125
2126 /* Look up the entry we're deleting, set up the cursor. */
Dave Chinnerf5ea1102013-04-24 18:58:02 +10002127 error = xfs_da3_node_lookup_int(state, &rval);
Barry Naujok5163f952008-05-21 16:41:01 +10002128 if (error)
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002129 goto out_free;
2130
2131 /* Didn't find it, upper layer screwed up. */
Dave Chinner24513372014-06-25 14:58:08 +10002132 if (rval != -EEXIST) {
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002133 error = rval;
2134 goto out_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 }
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002136
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 blk = &state->path.blk[state->path.active - 1];
2138 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
2139 ASSERT(state->extravalid);
2140 /*
2141 * Remove the leaf and data entries.
2142 * Extrablk refers to the data block.
2143 */
2144 error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
2145 &state->extrablk, &rval);
Barry Naujok5163f952008-05-21 16:41:01 +10002146 if (error)
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002147 goto out_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 /*
2149 * Fix the hash values up the btree.
2150 */
Dave Chinnerf5ea1102013-04-24 18:58:02 +10002151 xfs_da3_fixhashpath(state, &state->path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 /*
2153 * If we need to join leaf blocks, do it.
2154 */
2155 if (rval && state->path.active > 1)
Dave Chinnerf5ea1102013-04-24 18:58:02 +10002156 error = xfs_da3_join(state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 /*
2158 * If no errors so far, try conversion to leaf format.
2159 */
2160 if (!error)
2161 error = xfs_dir2_node_to_leaf(state);
Mark Tinguely3a8c9202013-10-05 21:48:25 -05002162out_free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 xfs_da_state_free(state);
2164 return error;
2165}
2166
2167/*
2168 * Replace an entry's inode number in a node-format directory.
2169 */
2170int /* error */
2171xfs_dir2_node_replace(
2172 xfs_da_args_t *args) /* operation arguments */
2173{
2174 xfs_da_state_blk_t *blk; /* leaf block */
Christoph Hellwigc2066e22011-07-08 14:35:38 +02002175 xfs_dir2_data_hdr_t *hdr; /* data block header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 xfs_dir2_data_entry_t *dep; /* data entry changed */
2177 int error; /* error return value */
2178 int i; /* btree level */
2179 xfs_ino_t inum; /* new inode number */
Jan Kara03754232015-08-25 10:05:13 +10002180 int ftype; /* new file type */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 int rval; /* internal return value */
2182 xfs_da_state_t *state; /* btree cursor */
2183
Christoph Hellwig0b1b2132009-12-14 23:14:59 +00002184 trace_xfs_dir2_node_replace(args);
2185
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 /*
2187 * Allocate and initialize the btree cursor.
2188 */
2189 state = xfs_da_state_alloc();
2190 state->args = args;
2191 state->mp = args->dp->i_mount;
Jan Kara03754232015-08-25 10:05:13 +10002192
2193 /*
2194 * We have to save new inode number and ftype since
2195 * xfs_da3_node_lookup_int() is going to overwrite them
2196 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 inum = args->inumber;
Jan Kara03754232015-08-25 10:05:13 +10002198 ftype = args->filetype;
2199
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 /*
2201 * Lookup the entry to change in the btree.
2202 */
Dave Chinnerf5ea1102013-04-24 18:58:02 +10002203 error = xfs_da3_node_lookup_int(state, &rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 if (error) {
2205 rval = error;
2206 }
2207 /*
2208 * It should be found, since the vnodeops layer has looked it up
2209 * and locked it. But paranoia is good.
2210 */
Dave Chinner24513372014-06-25 14:58:08 +10002211 if (rval == -EEXIST) {
Christoph Hellwig787b0892019-11-08 14:57:50 -08002212 struct xfs_dir3_icleaf_hdr leafhdr;
2213
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 /*
2215 * Find the leaf entry.
2216 */
2217 blk = &state->path.blk[state->path.active - 1];
2218 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 ASSERT(state->extravalid);
Christoph Hellwig787b0892019-11-08 14:57:50 -08002220
2221 xfs_dir2_leaf_hdr_from_disk(state->mp, &leafhdr,
2222 blk->bp->b_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 /*
2224 * Point to the data entry.
2225 */
Dave Chinner1d9025e2012-06-22 18:50:14 +10002226 hdr = state->extrablk.bp->b_addr;
Dave Chinner33363fe2013-04-03 16:11:22 +11002227 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
2228 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 dep = (xfs_dir2_data_entry_t *)
Christoph Hellwigc2066e22011-07-08 14:35:38 +02002230 ((char *)hdr +
Dave Chinner30028032014-06-06 15:08:18 +10002231 xfs_dir2_dataptr_to_off(args->geo,
Christoph Hellwig787b0892019-11-08 14:57:50 -08002232 be32_to_cpu(leafhdr.ents[blk->index].address)));
Christoph Hellwigff9901c2006-06-09 14:48:37 +10002233 ASSERT(inum != be64_to_cpu(dep->inumber));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 /*
2235 * Fill in the new inode number and log the entry.
2236 */
Christoph Hellwigff9901c2006-06-09 14:48:37 +10002237 dep->inumber = cpu_to_be64(inum);
Jan Kara03754232015-08-25 10:05:13 +10002238 args->dp->d_ops->data_put_ftype(dep, ftype);
Dave Chinnerbc851782014-06-06 15:20:54 +10002239 xfs_dir2_data_log_entry(args, state->extrablk.bp, dep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 rval = 0;
2241 }
2242 /*
2243 * Didn't find it, and we're holding a data block. Drop it.
2244 */
2245 else if (state->extravalid) {
Dave Chinner1d9025e2012-06-22 18:50:14 +10002246 xfs_trans_brelse(args->trans, state->extrablk.bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 state->extrablk.bp = NULL;
2248 }
2249 /*
2250 * Release all the buffers in the cursor.
2251 */
2252 for (i = 0; i < state->path.active; i++) {
Dave Chinner1d9025e2012-06-22 18:50:14 +10002253 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 state->path.blk[i].bp = NULL;
2255 }
2256 xfs_da_state_free(state);
2257 return rval;
2258}
2259
2260/*
2261 * Trim off a trailing empty freespace block.
2262 * Return (in rvalp) 1 if we did it, 0 if not.
2263 */
2264int /* error */
2265xfs_dir2_node_trim_free(
2266 xfs_da_args_t *args, /* operation arguments */
2267 xfs_fileoff_t fo, /* free block number */
2268 int *rvalp) /* out: did something */
2269{
Dave Chinner1d9025e2012-06-22 18:50:14 +10002270 struct xfs_buf *bp; /* freespace buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 xfs_inode_t *dp; /* incore directory inode */
2272 int error; /* error return code */
2273 xfs_dir2_free_t *free; /* freespace structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 xfs_trans_t *tp; /* transaction pointer */
Dave Chinnercbc8adf2013-04-03 16:11:21 +11002275 struct xfs_dir3_icfree_hdr freehdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276
2277 dp = args->dp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 tp = args->trans;
Christoph Hellwig355cced2016-03-15 11:44:18 +11002279
2280 *rvalp = 0;
2281
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 /*
2283 * Read the freespace block.
2284 */
Dave Chinner20252072012-11-12 22:54:13 +11002285 error = xfs_dir2_free_try_read(tp, dp, fo, &bp);
Dave Chinner4bb20a82012-11-12 22:54:10 +11002286 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 /*
2289 * There can be holes in freespace. If fo is a hole, there's
2290 * nothing to do.
2291 */
Dave Chinner20252072012-11-12 22:54:13 +11002292 if (!bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 return 0;
Dave Chinner1d9025e2012-06-22 18:50:14 +10002294 free = bp->b_addr;
Christoph Hellwig5ba30912019-11-08 14:57:52 -08002295 xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free);
Dave Chinnercbc8adf2013-04-03 16:11:21 +11002296
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 /*
2298 * If there are used entries, there's nothing to do.
2299 */
Dave Chinnercbc8adf2013-04-03 16:11:21 +11002300 if (freehdr.nused > 0) {
Dave Chinner1d9025e2012-06-22 18:50:14 +10002301 xfs_trans_brelse(tp, bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 return 0;
2303 }
2304 /*
2305 * Blow the block away.
2306 */
Dave Chinner2998ab1d2014-06-06 15:07:53 +10002307 error = xfs_dir2_shrink_inode(args,
2308 xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo), bp);
2309 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 /*
2311 * Can't fail with ENOSPC since that only happens with no
2312 * space reservation, when breaking up an extent into two
2313 * pieces. This is the last block of an extent.
2314 */
Dave Chinner24513372014-06-25 14:58:08 +10002315 ASSERT(error != -ENOSPC);
Dave Chinner1d9025e2012-06-22 18:50:14 +10002316 xfs_trans_brelse(tp, bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 return error;
2318 }
2319 /*
2320 * Return that we succeeded.
2321 */
2322 *rvalp = 1;
2323 return 0;
2324}