aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c285
1 files changed, 83 insertions, 202 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index b6a82d817a82..2a5c637344b4 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -146,11 +146,6 @@ xfs_readlink(
146} 146}
147 147
148/* 148/*
149 * Flags for xfs_free_eofblocks
150 */
151#define XFS_FREE_EOF_TRYLOCK (1<<0)
152
153/*
154 * This is called by xfs_inactive to free any blocks beyond eof 149 * This is called by xfs_inactive to free any blocks beyond eof
155 * when the link count isn't zero and by xfs_dm_punch_hole() when 150 * when the link count isn't zero and by xfs_dm_punch_hole() when
156 * punching a hole to EOF. 151 * punching a hole to EOF.
@@ -159,7 +154,7 @@ STATIC int
159xfs_free_eofblocks( 154xfs_free_eofblocks(
160 xfs_mount_t *mp, 155 xfs_mount_t *mp,
161 xfs_inode_t *ip, 156 xfs_inode_t *ip,
162 int flags) 157 bool need_iolock)
163{ 158{
164 xfs_trans_t *tp; 159 xfs_trans_t *tp;
165 int error; 160 int error;
@@ -174,7 +169,7 @@ xfs_free_eofblocks(
174 * of the file. If not, then there is nothing to do. 169 * of the file. If not, then there is nothing to do.
175 */ 170 */
176 end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip)); 171 end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
177 last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); 172 last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
178 if (last_fsb <= end_fsb) 173 if (last_fsb <= end_fsb)
179 return 0; 174 return 0;
180 map_len = last_fsb - end_fsb; 175 map_len = last_fsb - end_fsb;
@@ -201,13 +196,11 @@ xfs_free_eofblocks(
201 */ 196 */
202 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 197 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
203 198
204 if (flags & XFS_FREE_EOF_TRYLOCK) { 199 if (need_iolock) {
205 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) { 200 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
206 xfs_trans_cancel(tp, 0); 201 xfs_trans_cancel(tp, 0);
207 return 0; 202 return 0;
208 } 203 }
209 } else {
210 xfs_ilock(ip, XFS_IOLOCK_EXCL);
211 } 204 }
212 205
213 error = xfs_trans_reserve(tp, 0, 206 error = xfs_trans_reserve(tp, 0,
@@ -217,7 +210,8 @@ xfs_free_eofblocks(
217 if (error) { 210 if (error) {
218 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 211 ASSERT(XFS_FORCED_SHUTDOWN(mp));
219 xfs_trans_cancel(tp, 0); 212 xfs_trans_cancel(tp, 0);
220 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 213 if (need_iolock)
214 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
221 return error; 215 return error;
222 } 216 }
223 217
@@ -244,7 +238,10 @@ xfs_free_eofblocks(
244 error = xfs_trans_commit(tp, 238 error = xfs_trans_commit(tp,
245 XFS_TRANS_RELEASE_LOG_RES); 239 XFS_TRANS_RELEASE_LOG_RES);
246 } 240 }
247 xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL); 241
242 xfs_iunlock(ip, XFS_ILOCK_EXCL);
243 if (need_iolock)
244 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
248 } 245 }
249 return error; 246 return error;
250} 247}
@@ -282,23 +279,15 @@ xfs_inactive_symlink_rmt(
282 * free them all in one bunmapi call. 279 * free them all in one bunmapi call.
283 */ 280 */
284 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); 281 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
285 if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 282
286 XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
287 ASSERT(XFS_FORCED_SHUTDOWN(mp));
288 xfs_trans_cancel(tp, 0);
289 *tpp = NULL;
290 return error;
291 }
292 /* 283 /*
293 * Lock the inode, fix the size, and join it to the transaction. 284 * Lock the inode, fix the size, and join it to the transaction.
294 * Hold it so in the normal path, we still have it locked for 285 * Hold it so in the normal path, we still have it locked for
295 * the second transaction. In the error paths we need it 286 * the second transaction. In the error paths we need it
296 * held so the cancel won't rele it, see below. 287 * held so the cancel won't rele it, see below.
297 */ 288 */
298 xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
299 size = (int)ip->i_d.di_size; 289 size = (int)ip->i_d.di_size;
300 ip->i_d.di_size = 0; 290 ip->i_d.di_size = 0;
301 xfs_trans_ijoin(tp, ip, 0);
302 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 291 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
303 /* 292 /*
304 * Find the block(s) so we can inval and unmap them. 293 * Find the block(s) so we can inval and unmap them.
@@ -385,114 +374,14 @@ xfs_inactive_symlink_rmt(
385 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 374 ASSERT(XFS_FORCED_SHUTDOWN(mp));
386 goto error0; 375 goto error0;
387 } 376 }
388 /* 377
389 * Return with the inode locked but not joined to the transaction. 378 xfs_trans_ijoin(tp, ip, 0);
390 */
391 *tpp = tp; 379 *tpp = tp;
392 return 0; 380 return 0;
393 381
394 error1: 382 error1:
395 xfs_bmap_cancel(&free_list); 383 xfs_bmap_cancel(&free_list);
396 error0: 384 error0:
397 /*
398 * Have to come here with the inode locked and either
399 * (held and in the transaction) or (not in the transaction).
400 * If the inode isn't held then cancel would iput it, but
401 * that's wrong since this is inactive and the vnode ref
402 * count is 0 already.
403 * Cancel won't do anything to the inode if held, but it still
404 * needs to be locked until the cancel is done, if it was
405 * joined to the transaction.
406 */
407 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
408 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
409 *tpp = NULL;
410 return error;
411
412}
413
414STATIC int
415xfs_inactive_symlink_local(
416 xfs_inode_t *ip,
417 xfs_trans_t **tpp)
418{
419 int error;
420
421 ASSERT(ip->i_d.di_size <= XFS_IFORK_DSIZE(ip));
422 /*
423 * We're freeing a symlink which fit into
424 * the inode. Just free the memory used
425 * to hold the old symlink.
426 */
427 error = xfs_trans_reserve(*tpp, 0,
428 XFS_ITRUNCATE_LOG_RES(ip->i_mount),
429 0, XFS_TRANS_PERM_LOG_RES,
430 XFS_ITRUNCATE_LOG_COUNT);
431
432 if (error) {
433 xfs_trans_cancel(*tpp, 0);
434 *tpp = NULL;
435 return error;
436 }
437 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
438
439 /*
440 * Zero length symlinks _can_ exist.
441 */
442 if (ip->i_df.if_bytes > 0) {
443 xfs_idata_realloc(ip,
444 -(ip->i_df.if_bytes),
445 XFS_DATA_FORK);
446 ASSERT(ip->i_df.if_bytes == 0);
447 }
448 return 0;
449}
450
451STATIC int
452xfs_inactive_attrs(
453 xfs_inode_t *ip,
454 xfs_trans_t **tpp)
455{
456 xfs_trans_t *tp;
457 int error;
458 xfs_mount_t *mp;
459
460 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
461 tp = *tpp;
462 mp = ip->i_mount;
463 ASSERT(ip->i_d.di_forkoff != 0);
464 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
465 xfs_iunlock(ip, XFS_ILOCK_EXCL);
466 if (error)
467 goto error_unlock;
468
469 error = xfs_attr_inactive(ip);
470 if (error)
471 goto error_unlock;
472
473 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
474 error = xfs_trans_reserve(tp, 0,
475 XFS_IFREE_LOG_RES(mp),
476 0, XFS_TRANS_PERM_LOG_RES,
477 XFS_INACTIVE_LOG_COUNT);
478 if (error)
479 goto error_cancel;
480
481 xfs_ilock(ip, XFS_ILOCK_EXCL);
482 xfs_trans_ijoin(tp, ip, 0);
483 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
484
485 ASSERT(ip->i_d.di_anextents == 0);
486
487 *tpp = tp;
488 return 0;
489
490error_cancel:
491 ASSERT(XFS_FORCED_SHUTDOWN(mp));
492 xfs_trans_cancel(tp, 0);
493error_unlock:
494 *tpp = NULL;
495 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
496 return error; 385 return error;
497} 386}
498 387
@@ -574,8 +463,7 @@ xfs_release(
574 if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE)) 463 if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE))
575 return 0; 464 return 0;
576 465
577 error = xfs_free_eofblocks(mp, ip, 466 error = xfs_free_eofblocks(mp, ip, true);
578 XFS_FREE_EOF_TRYLOCK);
579 if (error) 467 if (error)
580 return error; 468 return error;
581 469
@@ -604,7 +492,7 @@ xfs_inactive(
604 xfs_trans_t *tp; 492 xfs_trans_t *tp;
605 xfs_mount_t *mp; 493 xfs_mount_t *mp;
606 int error; 494 int error;
607 int truncate; 495 int truncate = 0;
608 496
609 /* 497 /*
610 * If the inode is already free, then there can be nothing 498 * If the inode is already free, then there can be nothing
@@ -616,17 +504,6 @@ xfs_inactive(
616 return VN_INACTIVE_CACHE; 504 return VN_INACTIVE_CACHE;
617 } 505 }
618 506
619 /*
620 * Only do a truncate if it's a regular file with
621 * some actual space in it. It's OK to look at the
622 * inode's fields without the lock because we're the
623 * only one with a reference to the inode.
624 */
625 truncate = ((ip->i_d.di_nlink == 0) &&
626 ((ip->i_d.di_size != 0) || XFS_ISIZE(ip) != 0 ||
627 (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
628 S_ISREG(ip->i_d.di_mode));
629
630 mp = ip->i_mount; 507 mp = ip->i_mount;
631 508
632 error = 0; 509 error = 0;
@@ -643,99 +520,100 @@ xfs_inactive(
643 (!(ip->i_d.di_flags & 520 (!(ip->i_d.di_flags &
644 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || 521 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
645 ip->i_delayed_blks != 0))) { 522 ip->i_delayed_blks != 0))) {
646 error = xfs_free_eofblocks(mp, ip, 0); 523 error = xfs_free_eofblocks(mp, ip, false);
647 if (error) 524 if (error)
648 return VN_INACTIVE_CACHE; 525 return VN_INACTIVE_CACHE;
649 } 526 }
650 goto out; 527 goto out;
651 } 528 }
652 529
653 ASSERT(ip->i_d.di_nlink == 0); 530 if (S_ISREG(ip->i_d.di_mode) &&
531 (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
532 ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
533 truncate = 1;
654 534
655 error = xfs_qm_dqattach(ip, 0); 535 error = xfs_qm_dqattach(ip, 0);
656 if (error) 536 if (error)
657 return VN_INACTIVE_CACHE; 537 return VN_INACTIVE_CACHE;
658 538
659 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 539 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
660 if (truncate) { 540 error = xfs_trans_reserve(tp, 0,
661 xfs_ilock(ip, XFS_IOLOCK_EXCL); 541 (truncate || S_ISLNK(ip->i_d.di_mode)) ?
662 542 XFS_ITRUNCATE_LOG_RES(mp) :
663 error = xfs_trans_reserve(tp, 0, 543 XFS_IFREE_LOG_RES(mp),
664 XFS_ITRUNCATE_LOG_RES(mp), 544 0,
665 0, XFS_TRANS_PERM_LOG_RES, 545 XFS_TRANS_PERM_LOG_RES,
666 XFS_ITRUNCATE_LOG_COUNT); 546 XFS_ITRUNCATE_LOG_COUNT);
667 if (error) { 547 if (error) {
668 /* Don't call itruncate_cleanup */ 548 ASSERT(XFS_FORCED_SHUTDOWN(mp));
669 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 549 xfs_trans_cancel(tp, 0);
670 xfs_trans_cancel(tp, 0); 550 return VN_INACTIVE_CACHE;
671 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 551 }
672 return VN_INACTIVE_CACHE;
673 }
674 552
675 xfs_ilock(ip, XFS_ILOCK_EXCL); 553 xfs_ilock(ip, XFS_ILOCK_EXCL);
676 xfs_trans_ijoin(tp, ip, 0); 554 xfs_trans_ijoin(tp, ip, 0);
677 555
556 if (S_ISLNK(ip->i_d.di_mode)) {
557 /*
558 * Zero length symlinks _can_ exist.
559 */
560 if (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) {
561 error = xfs_inactive_symlink_rmt(ip, &tp);
562 if (error)
563 goto out_cancel;
564 } else if (ip->i_df.if_bytes > 0) {
565 xfs_idata_realloc(ip, -(ip->i_df.if_bytes),
566 XFS_DATA_FORK);
567 ASSERT(ip->i_df.if_bytes == 0);
568 }
569 } else if (truncate) {
678 ip->i_d.di_size = 0; 570 ip->i_d.di_size = 0;
679 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 571 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
680 572
681 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); 573 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
682 if (error) { 574 if (error)
683 xfs_trans_cancel(tp, 575 goto out_cancel;
684 XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
685 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
686 return VN_INACTIVE_CACHE;
687 }
688 576
689 ASSERT(ip->i_d.di_nextents == 0); 577 ASSERT(ip->i_d.di_nextents == 0);
690 } else if (S_ISLNK(ip->i_d.di_mode)) { 578 }
691 579
692 /* 580 /*
693 * If we get an error while cleaning up a 581 * If there are attributes associated with the file then blow them away
694 * symlink we bail out. 582 * now. The code calls a routine that recursively deconstructs the
695 */ 583 * attribute fork. We need to just commit the current transaction
696 error = (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) ? 584 * because we can't use it for xfs_attr_inactive().
697 xfs_inactive_symlink_rmt(ip, &tp) : 585 */
698 xfs_inactive_symlink_local(ip, &tp); 586 if (ip->i_d.di_anextents > 0) {
587 ASSERT(ip->i_d.di_forkoff != 0);
699 588
700 if (error) { 589 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
701 ASSERT(tp == NULL); 590 if (error)
702 return VN_INACTIVE_CACHE; 591 goto out_unlock;
703 }
704 592
705 xfs_trans_ijoin(tp, ip, 0); 593 xfs_iunlock(ip, XFS_ILOCK_EXCL);
706 } else { 594
595 error = xfs_attr_inactive(ip);
596 if (error)
597 goto out;
598
599 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
707 error = xfs_trans_reserve(tp, 0, 600 error = xfs_trans_reserve(tp, 0,
708 XFS_IFREE_LOG_RES(mp), 601 XFS_IFREE_LOG_RES(mp),
709 0, XFS_TRANS_PERM_LOG_RES, 602 0, XFS_TRANS_PERM_LOG_RES,
710 XFS_INACTIVE_LOG_COUNT); 603 XFS_INACTIVE_LOG_COUNT);
711 if (error) { 604 if (error) {
712 ASSERT(XFS_FORCED_SHUTDOWN(mp));
713 xfs_trans_cancel(tp, 0); 605 xfs_trans_cancel(tp, 0);
714 return VN_INACTIVE_CACHE; 606 goto out;
715 } 607 }
716 608
717 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 609 xfs_ilock(ip, XFS_ILOCK_EXCL);
718 xfs_trans_ijoin(tp, ip, 0); 610 xfs_trans_ijoin(tp, ip, 0);
719 } 611 }
720 612
721 /* 613 if (ip->i_afp)
722 * If there are attributes associated with the file
723 * then blow them away now. The code calls a routine
724 * that recursively deconstructs the attribute fork.
725 * We need to just commit the current transaction
726 * because we can't use it for xfs_attr_inactive().
727 */
728 if (ip->i_d.di_anextents > 0) {
729 error = xfs_inactive_attrs(ip, &tp);
730 /*
731 * If we got an error, the transaction is already
732 * cancelled, and the inode is unlocked. Just get out.
733 */
734 if (error)
735 return VN_INACTIVE_CACHE;
736 } else if (ip->i_afp) {
737 xfs_idestroy_fork(ip, XFS_ATTR_FORK); 614 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
738 } 615
616 ASSERT(ip->i_d.di_anextents == 0);
739 617
740 /* 618 /*
741 * Free the inode. 619 * Free the inode.
@@ -779,10 +657,13 @@ xfs_inactive(
779 * Release the dquots held by inode, if any. 657 * Release the dquots held by inode, if any.
780 */ 658 */
781 xfs_qm_dqdetach(ip); 659 xfs_qm_dqdetach(ip);
782 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); 660out_unlock:
783 661 xfs_iunlock(ip, XFS_ILOCK_EXCL);
784 out: 662out:
785 return VN_INACTIVE_CACHE; 663 return VN_INACTIVE_CACHE;
664out_cancel:
665 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
666 goto out_unlock;
786} 667}
787 668
788/* 669/*
@@ -2262,10 +2143,10 @@ xfs_change_file_space(
2262 2143
2263 llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len; 2144 llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len;
2264 2145
2265 if ( (bf->l_start < 0) 2146 if (bf->l_start < 0 ||
2266 || (bf->l_start > XFS_MAXIOFFSET(mp)) 2147 bf->l_start > mp->m_super->s_maxbytes ||
2267 || (bf->l_start + llen < 0) 2148 bf->l_start + llen < 0 ||
2268 || (bf->l_start + llen > XFS_MAXIOFFSET(mp))) 2149 bf->l_start + llen > mp->m_super->s_maxbytes)
2269 return XFS_ERROR(EINVAL); 2150 return XFS_ERROR(EINVAL);
2270 2151
2271 bf->l_whence = 0; 2152 bf->l_whence = 0;