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 --- |