Deleted Added
sdiff udiff text old ( 172836 ) new ( 173464 )
full compact
1/*-
2 * Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
3 *
4 * The soft updates code is derived from the appendix of a University
5 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
6 * "Soft Updates: A Solution to the Metadata Update Problem in File
7 * Systems", CSE-TR-254-95, August 1995).
8 *

--- 25 unchanged lines hidden (view full) ---

34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)ffs_softdep.c 9.59 (McKusick) 6/21/00
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sys/ufs/ffs/ffs_softdep.c 173464 2007-11-08 17:21:51Z obrien $");
43
44/*
45 * For now we want the safety net that the INVARIANTS and DEBUG flags provide.
46 */
47#ifndef DEBUG
48#define DEBUG
49#endif
50
51#include <sys/param.h>
52#include <sys/kernel.h>
53#include <sys/systm.h>
54#include <sys/bio.h>

--- 2719 unchanged lines hidden (view full) ---

2774 (flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp) == 0) {
2775 ip = VTOI(vp);
2776 DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + \
2777 freeblks->fb_chkcnt - blocksreleased);
2778 ip->i_flag |= IN_CHANGE;
2779 vput(vp);
2780 }
2781
2782#ifdef INVARIANTS
2783 if (freeblks->fb_chkcnt != blocksreleased &&
2784 ((fs->fs_flags & FS_UNCLEAN) == 0 || (flags & LK_NOWAIT) != 0))
2785 printf("handle_workitem_freeblocks: block count\n");
2786 if (allerror)
2787 softdep_error("handle_workitem_freeblks", allerror);
2788#endif /* INVARIANTS */
2789
2790 ACQUIRE_LOCK(&lk);
2791 WORKITEM_FREE(freeblks, D_FREEBLKS);
2792 FREE_LOCK(&lk);
2793}
2794
2795/*
2796 * Release blocks associated with the inode ip and stored in the indirect

--- 1110 unchanged lines hidden (view full) ---

3907 inodedep->id_savedextsize = 0;
3908 if (TAILQ_EMPTY(&inodedep->id_inoupdt))
3909 return;
3910 /*
3911 * Set the dependencies to busy.
3912 */
3913 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
3914 adp = TAILQ_NEXT(adp, ad_next)) {
3915#ifdef INVARIANTS
3916 if (deplist != 0 && prevlbn >= adp->ad_lbn)
3917 panic("softdep_write_inodeblock: lbn order");
3918 prevlbn = adp->ad_lbn;
3919 if (adp->ad_lbn < NDADDR &&
3920 dp->di_db[adp->ad_lbn] != adp->ad_newblkno)
3921 panic("%s: direct pointer #%jd mismatch %d != %jd",
3922 "softdep_write_inodeblock",
3923 (intmax_t)adp->ad_lbn,

--- 5 unchanged lines hidden (view full) ---

3929 "softdep_write_inodeblock",
3930 (intmax_t)adp->ad_lbn - NDADDR,
3931 dp->di_ib[adp->ad_lbn - NDADDR],
3932 (intmax_t)adp->ad_newblkno);
3933 deplist |= 1 << adp->ad_lbn;
3934 if ((adp->ad_state & ATTACHED) == 0)
3935 panic("softdep_write_inodeblock: Unknown state 0x%x",
3936 adp->ad_state);
3937#endif /* INVARIANTS */
3938 adp->ad_state &= ~ATTACHED;
3939 adp->ad_state |= UNDONE;
3940 }
3941 /*
3942 * The on-disk inode cannot claim to be any larger than the last
3943 * fragment that has been written. Otherwise, the on-disk inode
3944 * might have fragments that were not the last block in the file
3945 * which would corrupt the filesystem.
3946 */
3947 for (lastadp = NULL, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
3948 lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)) {
3949 if (adp->ad_lbn >= NDADDR)
3950 break;
3951 dp->di_db[adp->ad_lbn] = adp->ad_oldblkno;
3952 /* keep going until hitting a rollback to a frag */
3953 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
3954 continue;
3955 dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
3956 for (i = adp->ad_lbn + 1; i < NDADDR; i++) {
3957#ifdef INVARIANTS
3958 if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0)
3959 panic("softdep_write_inodeblock: lost dep1");
3960#endif /* INVARIANTS */
3961 dp->di_db[i] = 0;
3962 }
3963 for (i = 0; i < NIADDR; i++) {
3964#ifdef INVARIANTS
3965 if (dp->di_ib[i] != 0 &&
3966 (deplist & ((1 << NDADDR) << i)) == 0)
3967 panic("softdep_write_inodeblock: lost dep2");
3968#endif /* INVARIANTS */
3969 dp->di_ib[i] = 0;
3970 }
3971 return;
3972 }
3973 /*
3974 * If we have zero'ed out the last allocated block of the file,
3975 * roll back the size to the last currently allocated block.
3976 * We know that this last allocated block is a full-sized as

--- 74 unchanged lines hidden (view full) ---

4051 if (TAILQ_EMPTY(&inodedep->id_inoupdt) &&
4052 TAILQ_EMPTY(&inodedep->id_extupdt))
4053 return;
4054 /*
4055 * Set the ext data dependencies to busy.
4056 */
4057 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_extupdt); adp;
4058 adp = TAILQ_NEXT(adp, ad_next)) {
4059#ifdef INVARIANTS
4060 if (deplist != 0 && prevlbn >= adp->ad_lbn)
4061 panic("softdep_write_inodeblock: lbn order");
4062 prevlbn = adp->ad_lbn;
4063 if (dp->di_extb[adp->ad_lbn] != adp->ad_newblkno)
4064 panic("%s: direct pointer #%jd mismatch %jd != %jd",
4065 "softdep_write_inodeblock",
4066 (intmax_t)adp->ad_lbn,
4067 (intmax_t)dp->di_extb[adp->ad_lbn],
4068 (intmax_t)adp->ad_newblkno);
4069 deplist |= 1 << adp->ad_lbn;
4070 if ((adp->ad_state & ATTACHED) == 0)
4071 panic("softdep_write_inodeblock: Unknown state 0x%x",
4072 adp->ad_state);
4073#endif /* INVARIANTS */
4074 adp->ad_state &= ~ATTACHED;
4075 adp->ad_state |= UNDONE;
4076 }
4077 /*
4078 * The on-disk inode cannot claim to be any larger than the last
4079 * fragment that has been written. Otherwise, the on-disk inode
4080 * might have fragments that were not the last block in the ext
4081 * data which would corrupt the filesystem.
4082 */
4083 for (lastadp = NULL, adp = TAILQ_FIRST(&inodedep->id_extupdt); adp;
4084 lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)) {
4085 dp->di_extb[adp->ad_lbn] = adp->ad_oldblkno;
4086 /* keep going until hitting a rollback to a frag */
4087 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
4088 continue;
4089 dp->di_extsize = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
4090 for (i = adp->ad_lbn + 1; i < NXADDR; i++) {
4091#ifdef INVARIANTS
4092 if (dp->di_extb[i] != 0 && (deplist & (1 << i)) == 0)
4093 panic("softdep_write_inodeblock: lost dep1");
4094#endif /* INVARIANTS */
4095 dp->di_extb[i] = 0;
4096 }
4097 lastadp = NULL;
4098 break;
4099 }
4100 /*
4101 * If we have zero'ed out the last allocated block of the ext
4102 * data, roll back the size to the last currently allocated block.

--- 7 unchanged lines hidden (view full) ---

4110 break;
4111 dp->di_extsize = (i + 1) * fs->fs_bsize;
4112 }
4113 /*
4114 * Set the file data dependencies to busy.
4115 */
4116 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
4117 adp = TAILQ_NEXT(adp, ad_next)) {
4118#ifdef INVARIANTS
4119 if (deplist != 0 && prevlbn >= adp->ad_lbn)
4120 panic("softdep_write_inodeblock: lbn order");
4121 prevlbn = adp->ad_lbn;
4122 if (adp->ad_lbn < NDADDR &&
4123 dp->di_db[adp->ad_lbn] != adp->ad_newblkno)
4124 panic("%s: direct pointer #%jd mismatch %jd != %jd",
4125 "softdep_write_inodeblock",
4126 (intmax_t)adp->ad_lbn,

--- 5 unchanged lines hidden (view full) ---

4132 "softdep_write_inodeblock:",
4133 (intmax_t)adp->ad_lbn - NDADDR,
4134 (intmax_t)dp->di_ib[adp->ad_lbn - NDADDR],
4135 (intmax_t)adp->ad_newblkno);
4136 deplist |= 1 << adp->ad_lbn;
4137 if ((adp->ad_state & ATTACHED) == 0)
4138 panic("softdep_write_inodeblock: Unknown state 0x%x",
4139 adp->ad_state);
4140#endif /* INVARIANTS */
4141 adp->ad_state &= ~ATTACHED;
4142 adp->ad_state |= UNDONE;
4143 }
4144 /*
4145 * The on-disk inode cannot claim to be any larger than the last
4146 * fragment that has been written. Otherwise, the on-disk inode
4147 * might have fragments that were not the last block in the file
4148 * which would corrupt the filesystem.
4149 */
4150 for (lastadp = NULL, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
4151 lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)) {
4152 if (adp->ad_lbn >= NDADDR)
4153 break;
4154 dp->di_db[adp->ad_lbn] = adp->ad_oldblkno;
4155 /* keep going until hitting a rollback to a frag */
4156 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
4157 continue;
4158 dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
4159 for (i = adp->ad_lbn + 1; i < NDADDR; i++) {
4160#ifdef INVARIANTS
4161 if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0)
4162 panic("softdep_write_inodeblock: lost dep2");
4163#endif /* INVARIANTS */
4164 dp->di_db[i] = 0;
4165 }
4166 for (i = 0; i < NIADDR; i++) {
4167#ifdef INVARIANTS
4168 if (dp->di_ib[i] != 0 &&
4169 (deplist & ((1 << NDADDR) << i)) == 0)
4170 panic("softdep_write_inodeblock: lost dep3");
4171#endif /* INVARIANTS */
4172 dp->di_ib[i] = 0;
4173 }
4174 return;
4175 }
4176 /*
4177 * If we have zero'ed out the last allocated block of the file,
4178 * roll back the size to the last currently allocated block.
4179 * We know that this last allocated block is a full-sized as

--- 2117 unchanged lines hidden ---