aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_symlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_symlink.c')
-rw-r--r--fs/xfs/xfs_symlink.c61
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 */
588int 593STATIC int
589xfs_inactive_symlink_rmt( 594xfs_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 */
732int
733xfs_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}