diff options
Diffstat (limited to 'fs/xfs/xfs_symlink.c')
-rw-r--r-- | fs/xfs/xfs_symlink.c | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 195a403e1522..f4895b662fcb 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c | |||
@@ -358,7 +358,9 @@ xfs_symlink( | |||
358 | int n; | 358 | int n; |
359 | xfs_buf_t *bp; | 359 | xfs_buf_t *bp; |
360 | prid_t prid; | 360 | prid_t prid; |
361 | struct xfs_dquot *udqp, *gdqp; | 361 | struct xfs_dquot *udqp = NULL; |
362 | struct xfs_dquot *gdqp = NULL; | ||
363 | struct xfs_dquot *pdqp = NULL; | ||
362 | uint resblks; | 364 | uint resblks; |
363 | 365 | ||
364 | *ipp = NULL; | 366 | *ipp = NULL; |
@@ -385,7 +387,7 @@ xfs_symlink( | |||
385 | * Make sure that we have allocated dquot(s) on disk. | 387 | * Make sure that we have allocated dquot(s) on disk. |
386 | */ | 388 | */ |
387 | error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, | 389 | error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, |
388 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); | 390 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); |
389 | if (error) | 391 | if (error) |
390 | goto std_return; | 392 | goto std_return; |
391 | 393 | ||
@@ -426,7 +428,8 @@ xfs_symlink( | |||
426 | /* | 428 | /* |
427 | * Reserve disk quota : blocks and inode. | 429 | * Reserve disk quota : blocks and inode. |
428 | */ | 430 | */ |
429 | error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); | 431 | error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, |
432 | pdqp, resblks, 1, 0); | ||
430 | if (error) | 433 | if (error) |
431 | goto error_return; | 434 | goto error_return; |
432 | 435 | ||
@@ -464,7 +467,7 @@ xfs_symlink( | |||
464 | /* | 467 | /* |
465 | * Also attach the dquot(s) to it, if applicable. | 468 | * Also attach the dquot(s) to it, if applicable. |
466 | */ | 469 | */ |
467 | xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); | 470 | xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); |
468 | 471 | ||
469 | if (resblks) | 472 | if (resblks) |
470 | resblks -= XFS_IALLOC_SPACE_RES(mp); | 473 | resblks -= XFS_IALLOC_SPACE_RES(mp); |
@@ -562,6 +565,7 @@ xfs_symlink( | |||
562 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 565 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
563 | xfs_qm_dqrele(udqp); | 566 | xfs_qm_dqrele(udqp); |
564 | xfs_qm_dqrele(gdqp); | 567 | xfs_qm_dqrele(gdqp); |
568 | xfs_qm_dqrele(pdqp); | ||
565 | 569 | ||
566 | *ipp = ip; | 570 | *ipp = ip; |
567 | return 0; | 571 | return 0; |
@@ -575,6 +579,7 @@ xfs_symlink( | |||
575 | xfs_trans_cancel(tp, cancel_flags); | 579 | xfs_trans_cancel(tp, cancel_flags); |
576 | xfs_qm_dqrele(udqp); | 580 | xfs_qm_dqrele(udqp); |
577 | xfs_qm_dqrele(gdqp); | 581 | xfs_qm_dqrele(gdqp); |
582 | xfs_qm_dqrele(pdqp); | ||
578 | 583 | ||
579 | if (unlock_dp_on_error) | 584 | if (unlock_dp_on_error) |
580 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 585 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
@@ -585,7 +590,7 @@ xfs_symlink( | |||
585 | /* | 590 | /* |
586 | * Free a symlink that has blocks associated with it. | 591 | * Free a symlink that has blocks associated with it. |
587 | */ | 592 | */ |
588 | int | 593 | STATIC int |
589 | xfs_inactive_symlink_rmt( | 594 | xfs_inactive_symlink_rmt( |
590 | xfs_inode_t *ip, | 595 | xfs_inode_t *ip, |
591 | xfs_trans_t **tpp) | 596 | xfs_trans_t **tpp) |
@@ -606,7 +611,7 @@ xfs_inactive_symlink_rmt( | |||
606 | 611 | ||
607 | tp = *tpp; | 612 | tp = *tpp; |
608 | mp = ip->i_mount; | 613 | mp = ip->i_mount; |
609 | ASSERT(ip->i_d.di_size > XFS_IFORK_DSIZE(ip)); | 614 | ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS); |
610 | /* | 615 | /* |
611 | * We're freeing a symlink that has some | 616 | * We're freeing a symlink that has some |
612 | * blocks allocated to it. Free the | 617 | * blocks allocated to it. Free the |
@@ -720,3 +725,47 @@ xfs_inactive_symlink_rmt( | |||
720 | error0: | 725 | error0: |
721 | return error; | 726 | return error; |
722 | } | 727 | } |
728 | |||
729 | /* | ||
730 | * xfs_inactive_symlink - free a symlink | ||
731 | */ | ||
732 | int | ||
733 | xfs_inactive_symlink( | ||
734 | struct xfs_inode *ip, | ||
735 | struct xfs_trans **tp) | ||
736 | { | ||
737 | struct xfs_mount *mp = ip->i_mount; | ||
738 | int pathlen; | ||
739 | |||
740 | trace_xfs_inactive_symlink(ip); | ||
741 | |||
742 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
743 | |||
744 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
745 | return XFS_ERROR(EIO); | ||
746 | |||
747 | /* | ||
748 | * Zero length symlinks _can_ exist. | ||
749 | */ | ||
750 | pathlen = (int)ip->i_d.di_size; | ||
751 | if (!pathlen) | ||
752 | return 0; | ||
753 | |||
754 | if (pathlen < 0 || pathlen > MAXPATHLEN) { | ||
755 | xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", | ||
756 | __func__, (unsigned long long)ip->i_ino, pathlen); | ||
757 | ASSERT(0); | ||
758 | return XFS_ERROR(EFSCORRUPTED); | ||
759 | } | ||
760 | |||
761 | if (ip->i_df.if_flags & XFS_IFINLINE) { | ||
762 | if (ip->i_df.if_bytes > 0) | ||
763 | xfs_idata_realloc(ip, -(ip->i_df.if_bytes), | ||
764 | XFS_DATA_FORK); | ||
765 | ASSERT(ip->i_df.if_bytes == 0); | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | /* remove the remote symlink */ | ||
770 | return xfs_inactive_symlink_rmt(ip, tp); | ||
771 | } | ||