xfs_extfree_item.c 14.8 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2 3
 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
L
Linus Torvalds 已提交
4
 *
5 6
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
L
Linus Torvalds 已提交
7 8
 * published by the Free Software Foundation.
 *
9 10 11 12
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
L
Linus Torvalds 已提交
13
 *
14 15 16
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
L
Linus Torvalds 已提交
17 18
 */
#include "xfs.h"
19
#include "xfs_fs.h"
20
#include "xfs_format.h"
21 22
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
23
#include "xfs_bit.h"
L
Linus Torvalds 已提交
24
#include "xfs_mount.h"
25
#include "xfs_trans.h"
L
Linus Torvalds 已提交
26
#include "xfs_trans_priv.h"
27
#include "xfs_buf_item.h"
L
Linus Torvalds 已提交
28
#include "xfs_extfree_item.h"
C
Christoph Hellwig 已提交
29
#include "xfs_log.h"
30 31
#include "xfs_btree.h"
#include "xfs_rmap.h"
L
Linus Torvalds 已提交
32 33 34 35 36


kmem_zone_t	*xfs_efi_zone;
kmem_zone_t	*xfs_efd_zone;

37 38 39 40
static inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip)
{
	return container_of(lip, struct xfs_efi_log_item, efi_item);
}
L
Linus Torvalds 已提交
41

42
void
43 44
xfs_efi_item_free(
	struct xfs_efi_log_item	*efip)
45
{
46
	kmem_free(efip->efi_item.li_lv_shadow);
47
	if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS)
48
		kmem_free(efip);
49
	else
50 51
		kmem_zone_free(xfs_efi_zone, efip);
}
L
Linus Torvalds 已提交
52 53 54 55 56 57

/*
 * This returns the number of iovecs needed to log the given efi item.
 * We only need 1 iovec for an efi item.  It just logs the efi_log_format
 * structure.
 */
58 59 60 61 62 63 64 65 66
static inline int
xfs_efi_item_sizeof(
	struct xfs_efi_log_item *efip)
{
	return sizeof(struct xfs_efi_log_format) +
	       (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t);
}

STATIC void
67
xfs_efi_item_size(
68 69 70
	struct xfs_log_item	*lip,
	int			*nvecs,
	int			*nbytes)
L
Linus Torvalds 已提交
71
{
72 73
	*nvecs += 1;
	*nbytes += xfs_efi_item_sizeof(EFI_ITEM(lip));
L
Linus Torvalds 已提交
74 75 76 77 78 79 80 81 82 83
}

/*
 * This is called to fill in the vector of log iovecs for the
 * given efi log item. We use only 1 iovec, and we point that
 * at the efi_log_format structure embedded in the efi item.
 * It is at this point that we assert that all of the extent
 * slots in the efi item have been filled.
 */
STATIC void
84 85
xfs_efi_item_format(
	struct xfs_log_item	*lip,
86
	struct xfs_log_vec	*lv)
L
Linus Torvalds 已提交
87
{
88
	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);
89
	struct xfs_log_iovec	*vecp = NULL;
L
Linus Torvalds 已提交
90

91 92
	ASSERT(atomic_read(&efip->efi_next_extent) ==
				efip->efi_format.efi_nextents);
L
Linus Torvalds 已提交
93 94 95 96

	efip->efi_format.efi_type = XFS_LI_EFI;
	efip->efi_format.efi_size = 1;

97
	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT,
C
Christoph Hellwig 已提交
98 99
			&efip->efi_format,
			xfs_efi_item_sizeof(efip));
L
Linus Torvalds 已提交
100 101 102 103 104 105 106
}


/*
 * Pinning has no meaning for an efi item, so just return.
 */
STATIC void
107 108
xfs_efi_item_pin(
	struct xfs_log_item	*lip)
L
Linus Torvalds 已提交
109 110 111 112
{
}

/*
113 114 115 116 117 118
 * The unpin operation is the last place an EFI is manipulated in the log. It is
 * either inserted in the AIL or aborted in the event of a log I/O error. In
 * either case, the EFI transaction has been successfully committed to make it
 * this far. Therefore, we expect whoever committed the EFI to either construct
 * and commit the EFD or drop the EFD's reference in the event of error. Simply
 * drop the log's EFI reference now that the log is done with it.
L
Linus Torvalds 已提交
119 120
 */
STATIC void
121 122 123
xfs_efi_item_unpin(
	struct xfs_log_item	*lip,
	int			remove)
L
Linus Torvalds 已提交
124
{
125
	struct xfs_efi_log_item	*efip = EFI_ITEM(lip);
126
	xfs_efi_release(efip);
L
Linus Torvalds 已提交
127 128 129
}

/*
130 131 132 133 134
 * Efi items have no locking or pushing.  However, since EFIs are pulled from
 * the AIL when their corresponding EFDs are committed to disk, their situation
 * is very similar to being pinned.  Return XFS_ITEM_PINNED so that the caller
 * will eventually flush the log.  This should help in getting the EFI out of
 * the AIL.
L
Linus Torvalds 已提交
135 136
 */
STATIC uint
137 138 139
xfs_efi_item_push(
	struct xfs_log_item	*lip,
	struct list_head	*buffer_list)
L
Linus Torvalds 已提交
140 141 142 143
{
	return XFS_ITEM_PINNED;
}

144 145 146 147 148
/*
 * The EFI has been either committed or aborted if the transaction has been
 * cancelled. If the transaction was cancelled, an EFD isn't going to be
 * constructed and thus we free the EFI here directly.
 */
L
Linus Torvalds 已提交
149
STATIC void
150 151
xfs_efi_item_unlock(
	struct xfs_log_item	*lip)
L
Linus Torvalds 已提交
152
{
153 154
	if (lip->li_flags & XFS_LI_ABORTED)
		xfs_efi_item_free(EFI_ITEM(lip));
L
Linus Torvalds 已提交
155 156 157
}

/*
158
 * The EFI is logged only once and cannot be moved in the log, so simply return
159
 * the lsn at which it's been logged.
L
Linus Torvalds 已提交
160 161
 */
STATIC xfs_lsn_t
162 163 164
xfs_efi_item_committed(
	struct xfs_log_item	*lip,
	xfs_lsn_t		lsn)
L
Linus Torvalds 已提交
165 166 167 168 169 170 171 172 173 174 175 176
{
	return lsn;
}

/*
 * The EFI dependency tracking op doesn't do squat.  It can't because
 * it doesn't know where the free extent is coming from.  The dependency
 * tracking has to be handled by the "enclosing" metadata object.  For
 * example, for inodes, the inode is locked throughout the extent freeing
 * so the dependency should be recorded there.
 */
STATIC void
177 178 179
xfs_efi_item_committing(
	struct xfs_log_item	*lip,
	xfs_lsn_t		lsn)
L
Linus Torvalds 已提交
180 181 182 183 184 185
{
}

/*
 * This is the ops vector shared by all efi log items.
 */
C
Christoph Hellwig 已提交
186
static const struct xfs_item_ops xfs_efi_item_ops = {
187 188 189 190 191 192 193 194
	.iop_size	= xfs_efi_item_size,
	.iop_format	= xfs_efi_item_format,
	.iop_pin	= xfs_efi_item_pin,
	.iop_unpin	= xfs_efi_item_unpin,
	.iop_unlock	= xfs_efi_item_unlock,
	.iop_committed	= xfs_efi_item_committed,
	.iop_push	= xfs_efi_item_push,
	.iop_committing = xfs_efi_item_committing
L
Linus Torvalds 已提交
195 196 197 198 199 200
};


/*
 * Allocate and initialize an efi item with the given number of extents.
 */
201 202 203 204
struct xfs_efi_log_item *
xfs_efi_init(
	struct xfs_mount	*mp,
	uint			nextents)
L
Linus Torvalds 已提交
205 206

{
207
	struct xfs_efi_log_item	*efip;
L
Linus Torvalds 已提交
208 209 210 211 212 213
	uint			size;

	ASSERT(nextents > 0);
	if (nextents > XFS_EFI_MAX_FAST_EXTENTS) {
		size = (uint)(sizeof(xfs_efi_log_item_t) +
			((nextents - 1) * sizeof(xfs_extent_t)));
214
		efip = kmem_zalloc(size, KM_SLEEP);
L
Linus Torvalds 已提交
215
	} else {
216
		efip = kmem_zone_zalloc(xfs_efi_zone, KM_SLEEP);
L
Linus Torvalds 已提交
217 218
	}

219
	xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops);
L
Linus Torvalds 已提交
220
	efip->efi_format.efi_nextents = nextents;
221
	efip->efi_format.efi_id = (uintptr_t)(void *)efip;
222
	atomic_set(&efip->efi_next_extent, 0);
223
	atomic_set(&efip->efi_refcount, 2);
L
Linus Torvalds 已提交
224

225
	return efip;
L
Linus Torvalds 已提交
226 227
}

228 229 230 231 232 233 234 235 236 237
/*
 * Copy an EFI format buffer from the given buf, and into the destination
 * EFI format structure.
 * The given buffer can be in 32 bit or 64 bit form (which has different padding),
 * one of which will be the native format for this kernel.
 * It will handle the conversion of formats if necessary.
 */
int
xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
{
238
	xfs_efi_log_format_t *src_efi_fmt = buf->i_addr;
239 240 241 242 243 244 245 246 247 248 249 250
	uint i;
	uint len = sizeof(xfs_efi_log_format_t) + 
		(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t);  
	uint len32 = sizeof(xfs_efi_log_format_32_t) + 
		(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t);  
	uint len64 = sizeof(xfs_efi_log_format_64_t) + 
		(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t);  

	if (buf->i_len == len) {
		memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len);
		return 0;
	} else if (buf->i_len == len32) {
251
		xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr;
252 253 254 255 256 257 258 259 260 261 262 263 264

		dst_efi_fmt->efi_type     = src_efi_fmt_32->efi_type;
		dst_efi_fmt->efi_size     = src_efi_fmt_32->efi_size;
		dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
		dst_efi_fmt->efi_id       = src_efi_fmt_32->efi_id;
		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
			dst_efi_fmt->efi_extents[i].ext_start =
				src_efi_fmt_32->efi_extents[i].ext_start;
			dst_efi_fmt->efi_extents[i].ext_len =
				src_efi_fmt_32->efi_extents[i].ext_len;
		}
		return 0;
	} else if (buf->i_len == len64) {
265
		xfs_efi_log_format_64_t *src_efi_fmt_64 = buf->i_addr;
266 267 268 269 270 271 272 273 274 275 276 277 278

		dst_efi_fmt->efi_type     = src_efi_fmt_64->efi_type;
		dst_efi_fmt->efi_size     = src_efi_fmt_64->efi_size;
		dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
		dst_efi_fmt->efi_id       = src_efi_fmt_64->efi_id;
		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
			dst_efi_fmt->efi_extents[i].ext_start =
				src_efi_fmt_64->efi_extents[i].ext_start;
			dst_efi_fmt->efi_extents[i].ext_len =
				src_efi_fmt_64->efi_extents[i].ext_len;
		}
		return 0;
	}
D
Dave Chinner 已提交
279
	return -EFSCORRUPTED;
280 281
}

L
Linus Torvalds 已提交
282
/*
283 284 285 286 287
 * Freeing the efi requires that we remove it from the AIL if it has already
 * been placed there. However, the EFI may not yet have been placed in the AIL
 * when called by xfs_efi_release() from EFD processing due to the ordering of
 * committed vs unpin operations in bulk insert operations. Hence the reference
 * count to ensure only the last caller frees the EFI.
L
Linus Torvalds 已提交
288 289
 */
void
290 291
xfs_efi_release(
	struct xfs_efi_log_item	*efip)
L
Linus Torvalds 已提交
292
{
293
	if (atomic_dec_and_test(&efip->efi_refcount)) {
294
		xfs_trans_ail_remove(&efip->efi_item, SHUTDOWN_LOG_IO_ERROR);
295 296
		xfs_efi_item_free(efip);
	}
L
Linus Torvalds 已提交
297 298
}

299
static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip)
300
{
301 302
	return container_of(lip, struct xfs_efd_log_item, efd_item);
}
L
Linus Torvalds 已提交
303

304 305 306
STATIC void
xfs_efd_item_free(struct xfs_efd_log_item *efdp)
{
307
	kmem_free(efdp->efd_item.li_lv_shadow);
308
	if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS)
309
		kmem_free(efdp);
310
	else
311 312
		kmem_zone_free(xfs_efd_zone, efdp);
}
L
Linus Torvalds 已提交
313 314 315 316 317 318

/*
 * This returns the number of iovecs needed to log the given efd item.
 * We only need 1 iovec for an efd item.  It just logs the efd_log_format
 * structure.
 */
319 320 321 322 323 324 325 326 327
static inline int
xfs_efd_item_sizeof(
	struct xfs_efd_log_item *efdp)
{
	return sizeof(xfs_efd_log_format_t) +
	       (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t);
}

STATIC void
328
xfs_efd_item_size(
329 330 331
	struct xfs_log_item	*lip,
	int			*nvecs,
	int			*nbytes)
L
Linus Torvalds 已提交
332
{
333 334
	*nvecs += 1;
	*nbytes += xfs_efd_item_sizeof(EFD_ITEM(lip));
L
Linus Torvalds 已提交
335 336 337 338 339 340 341 342 343 344
}

/*
 * This is called to fill in the vector of log iovecs for the
 * given efd log item. We use only 1 iovec, and we point that
 * at the efd_log_format structure embedded in the efd item.
 * It is at this point that we assert that all of the extent
 * slots in the efd item have been filled.
 */
STATIC void
345 346
xfs_efd_item_format(
	struct xfs_log_item	*lip,
347
	struct xfs_log_vec	*lv)
L
Linus Torvalds 已提交
348
{
349
	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);
350
	struct xfs_log_iovec	*vecp = NULL;
L
Linus Torvalds 已提交
351 352 353 354 355 356

	ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents);

	efdp->efd_format.efd_type = XFS_LI_EFD;
	efdp->efd_format.efd_size = 1;

357
	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT,
C
Christoph Hellwig 已提交
358 359
			&efdp->efd_format,
			xfs_efd_item_sizeof(efdp));
L
Linus Torvalds 已提交
360 361 362 363 364 365
}

/*
 * Pinning has no meaning for an efd item, so just return.
 */
STATIC void
366 367
xfs_efd_item_pin(
	struct xfs_log_item	*lip)
L
Linus Torvalds 已提交
368 369 370 371 372 373 374 375
{
}

/*
 * Since pinning has no meaning for an efd item, unpinning does
 * not either.
 */
STATIC void
376 377 378
xfs_efd_item_unpin(
	struct xfs_log_item	*lip,
	int			remove)
L
Linus Torvalds 已提交
379 380 381 382
{
}

/*
383 384
 * There isn't much you can do to push on an efd item.  It is simply stuck
 * waiting for the log to be flushed to disk.
L
Linus Torvalds 已提交
385 386
 */
STATIC uint
387 388 389
xfs_efd_item_push(
	struct xfs_log_item	*lip,
	struct list_head	*buffer_list)
L
Linus Torvalds 已提交
390
{
391
	return XFS_ITEM_PINNED;
L
Linus Torvalds 已提交
392 393
}

394 395 396 397
/*
 * The EFD is either committed or aborted if the transaction is cancelled. If
 * the transaction is cancelled, drop our reference to the EFI and free the EFD.
 */
L
Linus Torvalds 已提交
398
STATIC void
399 400
xfs_efd_item_unlock(
	struct xfs_log_item	*lip)
L
Linus Torvalds 已提交
401
{
402 403 404 405 406 407
	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);

	if (lip->li_flags & XFS_LI_ABORTED) {
		xfs_efi_release(efdp->efd_efip);
		xfs_efd_item_free(efdp);
	}
L
Linus Torvalds 已提交
408 409 410
}

/*
411 412 413 414
 * When the efd item is committed to disk, all we need to do is delete our
 * reference to our partner efi item and then free ourselves. Since we're
 * freeing ourselves we must return -1 to keep the transaction code from further
 * referencing this item.
L
Linus Torvalds 已提交
415 416
 */
STATIC xfs_lsn_t
417 418 419
xfs_efd_item_committed(
	struct xfs_log_item	*lip,
	xfs_lsn_t		lsn)
L
Linus Torvalds 已提交
420
{
421 422
	struct xfs_efd_log_item	*efdp = EFD_ITEM(lip);

L
Linus Torvalds 已提交
423
	/*
424 425 426 427
	 * Drop the EFI reference regardless of whether the EFD has been
	 * aborted. Once the EFD transaction is constructed, it is the sole
	 * responsibility of the EFD to release the EFI (even if the EFI is
	 * aborted due to log I/O error).
L
Linus Torvalds 已提交
428
	 */
429
	xfs_efi_release(efdp->efd_efip);
430
	xfs_efd_item_free(efdp);
431

L
Linus Torvalds 已提交
432 433 434 435 436 437 438 439 440 441 442
	return (xfs_lsn_t)-1;
}

/*
 * The EFD dependency tracking op doesn't do squat.  It can't because
 * it doesn't know where the free extent is coming from.  The dependency
 * tracking has to be handled by the "enclosing" metadata object.  For
 * example, for inodes, the inode is locked throughout the extent freeing
 * so the dependency should be recorded there.
 */
STATIC void
443 444 445
xfs_efd_item_committing(
	struct xfs_log_item	*lip,
	xfs_lsn_t		lsn)
L
Linus Torvalds 已提交
446 447 448 449 450 451
{
}

/*
 * This is the ops vector shared by all efd log items.
 */
C
Christoph Hellwig 已提交
452
static const struct xfs_item_ops xfs_efd_item_ops = {
453 454 455 456 457 458 459 460
	.iop_size	= xfs_efd_item_size,
	.iop_format	= xfs_efd_item_format,
	.iop_pin	= xfs_efd_item_pin,
	.iop_unpin	= xfs_efd_item_unpin,
	.iop_unlock	= xfs_efd_item_unlock,
	.iop_committed	= xfs_efd_item_committed,
	.iop_push	= xfs_efd_item_push,
	.iop_committing = xfs_efd_item_committing
L
Linus Torvalds 已提交
461 462 463 464 465
};

/*
 * Allocate and initialize an efd item with the given number of extents.
 */
466 467 468 469 470
struct xfs_efd_log_item *
xfs_efd_init(
	struct xfs_mount	*mp,
	struct xfs_efi_log_item	*efip,
	uint			nextents)
L
Linus Torvalds 已提交
471 472

{
473
	struct xfs_efd_log_item	*efdp;
L
Linus Torvalds 已提交
474 475 476 477 478 479
	uint			size;

	ASSERT(nextents > 0);
	if (nextents > XFS_EFD_MAX_FAST_EXTENTS) {
		size = (uint)(sizeof(xfs_efd_log_item_t) +
			((nextents - 1) * sizeof(xfs_extent_t)));
480
		efdp = kmem_zalloc(size, KM_SLEEP);
L
Linus Torvalds 已提交
481
	} else {
482
		efdp = kmem_zone_zalloc(xfs_efd_zone, KM_SLEEP);
L
Linus Torvalds 已提交
483 484
	}

485
	xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops);
L
Linus Torvalds 已提交
486 487 488 489
	efdp->efd_efip = efip;
	efdp->efd_format.efd_nextents = nextents;
	efdp->efd_format.efd_efi_id = efip->efi_format.efi_id;

490
	return efdp;
L
Linus Torvalds 已提交
491
}
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507

/*
 * Process an extent free intent item that was recovered from
 * the log.  We need to free the extents that it describes.
 */
int
xfs_efi_recover(
	struct xfs_mount	*mp,
	struct xfs_efi_log_item	*efip)
{
	struct xfs_efd_log_item	*efdp;
	struct xfs_trans	*tp;
	int			i;
	int			error = 0;
	xfs_extent_t		*extp;
	xfs_fsblock_t		startblock_fsb;
508
	struct xfs_owner_info	oinfo;
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539

	ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags));

	/*
	 * First check the validity of the extents described by the
	 * EFI.  If any are bad, then assume that all are bad and
	 * just toss the EFI.
	 */
	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
		extp = &(efip->efi_format.efi_extents[i]);
		startblock_fsb = XFS_BB_TO_FSB(mp,
				   XFS_FSB_TO_DADDR(mp, extp->ext_start));
		if ((startblock_fsb == 0) ||
		    (extp->ext_len == 0) ||
		    (startblock_fsb >= mp->m_sb.sb_dblocks) ||
		    (extp->ext_len >= mp->m_sb.sb_agblocks)) {
			/*
			 * This will pull the EFI from the AIL and
			 * free the memory associated with it.
			 */
			set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
			xfs_efi_release(efip);
			return -EIO;
		}
	}

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
	if (error)
		return error;
	efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);

540
	xfs_rmap_skip_owner_update(&oinfo);
541 542 543
	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
		extp = &(efip->efi_format.efi_extents[i]);
		error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
544
					      extp->ext_len, &oinfo);
545 546 547 548 549 550 551 552 553 554 555 556 557
		if (error)
			goto abort_error;

	}

	set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
	error = xfs_trans_commit(tp);
	return error;

abort_error:
	xfs_trans_cancel(tp);
	return error;
}