| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: lfs_vfsops.c,v 1.347 2015/10/15 06:15:48 dholland Exp $ */ | | 1 | /* $NetBSD: lfs_vfsops.c,v 1.348 2015/10/15 06:25:34 dholland Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007 | | 4 | * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007 |
5 | * The NetBSD Foundation, Inc. | | 5 | * The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Konrad E. Schroder <perseant@hhhh.org>. | | 9 | * by Konrad E. Schroder <perseant@hhhh.org>. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -51,27 +51,27 @@ | | | @@ -51,27 +51,27 @@ |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
58 | * SUCH DAMAGE. | | 58 | * SUCH DAMAGE. |
59 | * | | 59 | * |
60 | * @(#)lfs_vfsops.c 8.20 (Berkeley) 6/10/95 | | 60 | * @(#)lfs_vfsops.c 8.20 (Berkeley) 6/10/95 |
61 | */ | | 61 | */ |
62 | | | 62 | |
63 | #include <sys/cdefs.h> | | 63 | #include <sys/cdefs.h> |
64 | __KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.347 2015/10/15 06:15:48 dholland Exp $"); | | 64 | __KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.348 2015/10/15 06:25:34 dholland Exp $"); |
65 | | | 65 | |
66 | #if defined(_KERNEL_OPT) | | 66 | #if defined(_KERNEL_OPT) |
67 | #include "opt_lfs.h" | | 67 | #include "opt_lfs.h" |
68 | #include "opt_quota.h" | | 68 | #include "opt_quota.h" |
69 | #endif | | 69 | #endif |
70 | | | 70 | |
71 | #include <sys/param.h> | | 71 | #include <sys/param.h> |
72 | #include <sys/systm.h> | | 72 | #include <sys/systm.h> |
73 | #include <sys/namei.h> | | 73 | #include <sys/namei.h> |
74 | #include <sys/proc.h> | | 74 | #include <sys/proc.h> |
75 | #include <sys/kernel.h> | | 75 | #include <sys/kernel.h> |
76 | #include <sys/vnode.h> | | 76 | #include <sys/vnode.h> |
77 | #include <sys/mount.h> | | 77 | #include <sys/mount.h> |
| @@ -819,163 +819,228 @@ lfs_mount(struct mount *mp, const char * | | | @@ -819,163 +819,228 @@ lfs_mount(struct mount *mp, const char * |
819 | } | | 819 | } |
820 | | | 820 | |
821 | error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, | | 821 | error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, |
822 | UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l); | | 822 | UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l); |
823 | if (error == 0) | | 823 | if (error == 0) |
824 | lfs_sb_setfsmnt(fs, mp->mnt_stat.f_mntonname); | | 824 | lfs_sb_setfsmnt(fs, mp->mnt_stat.f_mntonname); |
825 | return error; | | 825 | return error; |
826 | | | 826 | |
827 | fail: | | 827 | fail: |
828 | vrele(devvp); | | 828 | vrele(devvp); |
829 | return (error); | | 829 | return (error); |
830 | } | | 830 | } |
831 | | | 831 | |
| | | 832 | /* |
| | | 833 | * Helper for mountfs. Note that the fs pointer may be a dummy one |
| | | 834 | * pointing into a superblock buffer. (Which is gross; see below.) |
| | | 835 | */ |
| | | 836 | static int |
| | | 837 | lfs_checkmagic(struct lfs *fs) |
| | | 838 | { |
| | | 839 | switch (fs->lfs_dlfs_u.u_32.dlfs_magic) { |
| | | 840 | case LFS_MAGIC: |
| | | 841 | fs->lfs_is64 = false; |
| | | 842 | fs->lfs_dobyteswap = false; |
| | | 843 | break; |
| | | 844 | case LFS64_MAGIC: |
| | | 845 | fs->lfs_is64 = true; |
| | | 846 | fs->lfs_dobyteswap = false; |
| | | 847 | break; |
| | | 848 | #ifdef LFS_EI |
| | | 849 | case LFS_MAGIC_SWAPPED: |
| | | 850 | fs->lfs_is64 = false; |
| | | 851 | fs->lfs_dobyteswap = true; |
| | | 852 | break; |
| | | 853 | case LFS64_MAGIC_SWAPPED: |
| | | 854 | fs->lfs_is64 = true; |
| | | 855 | fs->lfs_dobyteswap = true; |
| | | 856 | break; |
| | | 857 | #endif |
| | | 858 | default: |
| | | 859 | /* XXX needs translation */ |
| | | 860 | return EINVAL; |
| | | 861 | } |
| | | 862 | return 0; |
| | | 863 | } |
832 | | | 864 | |
833 | /* | | 865 | /* |
834 | * Common code for mount and mountroot | | 866 | * Common code for mount and mountroot |
835 | * LFS specific | | 867 | * LFS specific |
836 | */ | | 868 | */ |
837 | int | | 869 | int |
838 | lfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) | | 870 | lfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) |
839 | { | | 871 | { |
840 | struct dlfs *tdfs, *dfs, *adfs; | | 872 | struct lfs *primarysb, *altsb, *thesb; |
| | | 873 | struct buf *primarybuf, *altbuf; |
841 | struct lfs *fs; | | 874 | struct lfs *fs; |
842 | struct ulfsmount *ump; | | 875 | struct ulfsmount *ump; |
843 | struct vnode *vp; | | 876 | struct vnode *vp; |
844 | struct buf *bp, *abp; | | | |
845 | dev_t dev; | | 877 | dev_t dev; |
846 | int error, i, ronly, fsbsize; | | 878 | int error, i, ronly, fsbsize; |
847 | kauth_cred_t cred; | | 879 | kauth_cred_t cred; |
848 | CLEANERINFO *cip; | | 880 | CLEANERINFO *cip; |
849 | SEGUSE *sup; | | 881 | SEGUSE *sup; |
850 | daddr_t sb_addr; | | 882 | daddr_t sb_addr; |
851 | | | 883 | |
852 | cred = l ? l->l_cred : NOCRED; | | 884 | cred = l ? l->l_cred : NOCRED; |
853 | | | 885 | |
854 | /* The superblock is supposed to be 512 bytes. */ | | 886 | /* The superblock is supposed to be 512 bytes. */ |
855 | __CTASSERT(sizeof(struct dlfs) == DEV_BSIZE); | | 887 | __CTASSERT(sizeof(struct dlfs) == DEV_BSIZE); |
856 | | | 888 | |
857 | /* | | 889 | /* |
858 | * Flush out any old buffers remaining from a previous use. | | 890 | * Flush out any old buffers remaining from a previous use. |
859 | */ | | 891 | */ |
860 | vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); | | 892 | vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); |
861 | error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0); | | 893 | error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0); |
862 | VOP_UNLOCK(devvp); | | 894 | VOP_UNLOCK(devvp); |
863 | if (error) | | 895 | if (error) |
864 | return (error); | | 896 | return (error); |
865 | | | 897 | |
866 | ronly = (mp->mnt_flag & MNT_RDONLY) != 0; | | 898 | ronly = (mp->mnt_flag & MNT_RDONLY) != 0; |
867 | | | 899 | |
868 | /* Don't free random space on error. */ | | 900 | /* Don't free random space on error. */ |
869 | bp = NULL; | | 901 | primarybuf = NULL; |
870 | abp = NULL; | | 902 | altbuf = NULL; |
871 | ump = NULL; | | 903 | ump = NULL; |
872 | | | 904 | |
873 | sb_addr = LFS_LABELPAD / DEV_BSIZE; | | 905 | sb_addr = LFS_LABELPAD / DEV_BSIZE; |
874 | while (1) { | | 906 | while (1) { |
875 | /* Read in the superblock. */ | | 907 | /* |
876 | error = bread(devvp, sb_addr, LFS_SBPAD, 0, &bp); | | 908 | * Read in the superblock. |
| | | 909 | * |
| | | 910 | * Note that because LFS_SBPAD is substantially larger |
| | | 911 | * (8K) than the actual on-disk superblock (512 bytes) |
| | | 912 | * the buffer contains enough space to be used as a |
| | | 913 | * whole struct lfs (in-memory superblock) - we do this |
| | | 914 | * only so we can set and use the is64 and dobyteswap |
| | | 915 | * members. XXX this is gross and the logic here should |
| | | 916 | * be reworked. |
| | | 917 | */ |
| | | 918 | error = bread(devvp, sb_addr, LFS_SBPAD, 0, &primarybuf); |
877 | if (error) | | 919 | if (error) |
878 | goto out; | | 920 | goto out; |
879 | dfs = (struct dlfs *)bp->b_data; | | 921 | primarysb = (struct lfs *)primarybuf->b_data; |
880 | | | 922 | |
881 | /* Check the basics. */ | | 923 | /* Check the basics. */ |
882 | if (dfs->dlfs_magic != LFS_MAGIC || dfs->dlfs_bsize > MAXBSIZE || | | 924 | error = lfs_checkmagic(primarysb); |
883 | dfs->dlfs_version > LFS_VERSION || | | 925 | if (error) { |
884 | dfs->dlfs_bsize < sizeof(struct dlfs)) { | | 926 | DLOG((DLOG_MOUNT, "lfs_mountfs: primary superblock wrong magic\n")); |
| | | 927 | goto out; |
| | | 928 | } |
| | | 929 | if (lfs_sb_getbsize(primarysb) > MAXBSIZE || |
| | | 930 | lfs_sb_getversion(primarysb) > LFS_VERSION || |
| | | 931 | lfs_sb_getbsize(primarysb) < sizeof(struct dlfs)) { |
885 | DLOG((DLOG_MOUNT, "lfs_mountfs: primary superblock sanity failed\n")); | | 932 | DLOG((DLOG_MOUNT, "lfs_mountfs: primary superblock sanity failed\n")); |
886 | error = EINVAL; /* XXX needs translation */ | | 933 | /* XXX needs translation */ |
| | | 934 | error = EINVAL; |
887 | goto out; | | 935 | goto out; |
888 | } | | 936 | } |
889 | if (dfs->dlfs_inodefmt > LFS_MAXINODEFMT) { | | 937 | if (lfs_sb_getinodefmt(primarysb) > LFS_MAXINODEFMT) { |
890 | DLOG((DLOG_MOUNT, "lfs_mountfs: unknown inode format %d\n", | | 938 | DLOG((DLOG_MOUNT, "lfs_mountfs: unknown inode format %d\n", |
891 | dfs->dlfs_inodefmt)); | | 939 | lfs_sb_getinodefmt(primarysb))); |
892 | error = EINVAL; | | 940 | error = EINVAL; |
893 | goto out; | | 941 | goto out; |
894 | } | | 942 | } |
895 | | | 943 | |
896 | if (dfs->dlfs_version == 1) | | 944 | if (lfs_sb_getversion(primarysb) == 1) |
897 | fsbsize = DEV_BSIZE; | | 945 | fsbsize = DEV_BSIZE; |
898 | else { | | 946 | else { |
899 | fsbsize = 1 << dfs->dlfs_ffshift; | | 947 | fsbsize = 1 << lfs_sb_getffshift(primarysb); |
900 | /* | | 948 | /* |
901 | * Could be, if the frag size is large enough, that we | | 949 | * Could be, if the frag size is large enough, that we |
902 | * don't have the "real" primary superblock. If that's | | 950 | * don't have the "real" primary superblock. If that's |
903 | * the case, get the real one, and try again. | | 951 | * the case, get the real one, and try again. |
904 | */ | | 952 | */ |
905 | if (sb_addr != (dfs->dlfs_sboffs[0] << (dfs->dlfs_ffshift - DEV_BSHIFT))) { | | 953 | if (sb_addr != (lfs_sb_getsboff(primarysb, 0) << (lfs_sb_getffshift(primarysb) - DEV_BSHIFT))) { |
906 | DLOG((DLOG_MOUNT, "lfs_mountfs: sb daddr" | | 954 | DLOG((DLOG_MOUNT, "lfs_mountfs: sb daddr" |
907 | " 0x%llx is not right, trying 0x%llx\n", | | 955 | " 0x%llx is not right, trying 0x%llx\n", |
908 | (long long)sb_addr, | | 956 | (long long)sb_addr, |
909 | (long long)(dfs->dlfs_sboffs[0] << (dfs->dlfs_ffshift - DEV_BSHIFT)))); | | 957 | (long long)(lfs_sb_getsboff(primarysb, 0) << (lfs_sb_getffshift(primarysb) - DEV_BSHIFT)))); |
910 | sb_addr = dfs->dlfs_sboffs[0] << (dfs->dlfs_ffshift - DEV_BSHIFT); | | 958 | sb_addr = lfs_sb_getsboff(primarysb, 0) << (lfs_sb_getffshift(primarysb) - DEV_BSHIFT); |
911 | brelse(bp, 0); | | 959 | brelse(primarybuf, BC_INVAL); |
912 | continue; | | 960 | continue; |
913 | } | | 961 | } |
914 | } | | 962 | } |
915 | break; | | 963 | break; |
916 | } | | 964 | } |
917 | | | 965 | |
918 | /* | | 966 | /* |
919 | * Check the second superblock to see which is newer; then mount | | 967 | * Check the second superblock to see which is newer; then mount |
920 | * using the older of the two. This is necessary to ensure that | | 968 | * using the older of the two. This is necessary to ensure that |
921 | * the filesystem is valid if it was not unmounted cleanly. | | 969 | * the filesystem is valid if it was not unmounted cleanly. |
922 | */ | | 970 | */ |
923 | | | 971 | |
924 | if (dfs->dlfs_sboffs[1] && | | 972 | if (lfs_sb_getsboff(primarysb, 1) && |
925 | dfs->dlfs_sboffs[1] - LFS_LABELPAD / fsbsize > LFS_SBPAD / fsbsize) | | 973 | lfs_sb_getsboff(primarysb, 1) - LFS_LABELPAD / fsbsize > LFS_SBPAD / fsbsize) |
926 | { | | 974 | { |
927 | error = bread(devvp, dfs->dlfs_sboffs[1] * (fsbsize / DEV_BSIZE), | | 975 | error = bread(devvp, lfs_sb_getsboff(primarysb, 1) * (fsbsize / DEV_BSIZE), |
928 | LFS_SBPAD, 0, &abp); | | 976 | LFS_SBPAD, 0, &altbuf); |
929 | if (error) | | 977 | if (error) |
930 | goto out; | | 978 | goto out; |
931 | adfs = (struct dlfs *)abp->b_data; | | 979 | altsb = (struct lfs *)altbuf->b_data; |
932 | | | 980 | |
933 | if (dfs->dlfs_version == 1) { | | 981 | /* |
934 | /* 1s resolution comparison */ | | 982 | * Note: this used to do the sanity check only if the |
935 | if (adfs->dlfs_tstamp < dfs->dlfs_tstamp) | | 983 | * timestamp/serial comparison required use of altsb; |
936 | tdfs = adfs; | | 984 | * this way is less tolerant, but if altsb is corrupted |
937 | else | | 985 | * enough that the magic number, version, and blocksize |
938 | tdfs = dfs; | | 986 | * are bogus, why would the timestamp or serial fields |
939 | } else { | | 987 | * mean anything either? If this kind of thing happens, |
940 | /* monotonic infinite-resolution comparison */ | | 988 | * you need to fsck anyway. |
941 | if (adfs->dlfs_serial < dfs->dlfs_serial) | | 989 | */ |
942 | tdfs = adfs; | | 990 | |
943 | else | | 991 | error = lfs_checkmagic(altsb); |
944 | tdfs = dfs; | | 992 | if (error) |
945 | } | | 993 | goto out; |
946 | | | 994 | |
947 | /* Check the basics. */ | | 995 | /* Check the basics. */ |
948 | if (tdfs->dlfs_magic != LFS_MAGIC || | | 996 | if (lfs_sb_getbsize(altsb) > MAXBSIZE || |
949 | tdfs->dlfs_bsize > MAXBSIZE || | | 997 | lfs_sb_getversion(altsb) > LFS_VERSION || |
950 | tdfs->dlfs_version > LFS_VERSION || | | 998 | lfs_sb_getbsize(altsb) < sizeof(struct dlfs)) { |
951 | tdfs->dlfs_bsize < sizeof(struct dlfs)) { | | | |
952 | DLOG((DLOG_MOUNT, "lfs_mountfs: alt superblock" | | 999 | DLOG((DLOG_MOUNT, "lfs_mountfs: alt superblock" |
953 | " sanity failed\n")); | | 1000 | " sanity failed\n")); |
954 | error = EINVAL; /* XXX needs translation */ | | 1001 | error = EINVAL; /* XXX needs translation */ |
955 | goto out; | | 1002 | goto out; |
956 | } | | 1003 | } |
| | | 1004 | |
| | | 1005 | if (lfs_sb_getversion(primarysb) == 1) { |
| | | 1006 | /* 1s resolution comparison */ |
| | | 1007 | if (lfs_sb_gettstamp(altsb) < lfs_sb_gettstamp(primarysb)) |
| | | 1008 | thesb = altsb; |
| | | 1009 | else |
| | | 1010 | thesb = primarysb; |
| | | 1011 | } else { |
| | | 1012 | /* monotonic infinite-resolution comparison */ |
| | | 1013 | if (lfs_sb_getserial(altsb) < lfs_sb_getserial(primarysb)) |
| | | 1014 | thesb = altsb; |
| | | 1015 | else |
| | | 1016 | thesb = primarysb; |
| | | 1017 | } |
957 | } else { | | 1018 | } else { |
958 | DLOG((DLOG_MOUNT, "lfs_mountfs: invalid alt superblock" | | 1019 | DLOG((DLOG_MOUNT, "lfs_mountfs: invalid alt superblock location" |
959 | " daddr=0x%x\n", dfs->dlfs_sboffs[1])); | | 1020 | " daddr=0x%x\n", lfs_sb_getsboff(primarysb, 1))); |
960 | error = EINVAL; | | 1021 | error = EINVAL; |
961 | goto out; | | 1022 | goto out; |
962 | } | | 1023 | } |
963 | | | 1024 | |
964 | /* Allocate the mount structure, copy the superblock into it. */ | | 1025 | /* |
| | | 1026 | * Allocate the mount structure, copy the superblock into it. |
| | | 1027 | * Note that the 32-bit and 64-bit superblocks are the same size. |
| | | 1028 | */ |
965 | fs = kmem_zalloc(sizeof(struct lfs), KM_SLEEP); | | 1029 | fs = kmem_zalloc(sizeof(struct lfs), KM_SLEEP); |
966 | memcpy(&fs->lfs_dlfs_u.u_32, tdfs, sizeof(struct dlfs)); | | 1030 | memcpy(&fs->lfs_dlfs_u.u_32, &thesb->lfs_dlfs_u.u_32, |
967 | fs->lfs_is64 = false; /* XXX notyet */ | | 1031 | sizeof(struct dlfs)); |
968 | fs->lfs_dobyteswap = false; /* XXX notyet */ | | 1032 | fs->lfs_is64 = thesb->lfs_is64; |
| | | 1033 | fs->lfs_dobyteswap = thesb->lfs_dobyteswap; |
969 | fs->lfs_hasolddirfmt = false; /* set for real below */ | | 1034 | fs->lfs_hasolddirfmt = false; /* set for real below */ |
970 | | | 1035 | |
971 | /* Compatibility */ | | 1036 | /* Compatibility */ |
972 | if (lfs_sb_getversion(fs) < 2) { | | 1037 | if (lfs_sb_getversion(fs) < 2) { |
973 | lfs_sb_setsumsize(fs, LFS_V1_SUMMARY_SIZE); | | 1038 | lfs_sb_setsumsize(fs, LFS_V1_SUMMARY_SIZE); |
974 | lfs_sb_setibsize(fs, lfs_sb_getbsize(fs)); | | 1039 | lfs_sb_setibsize(fs, lfs_sb_getbsize(fs)); |
975 | lfs_sb_sets0addr(fs, lfs_sb_getsboff(fs, 0)); | | 1040 | lfs_sb_sets0addr(fs, lfs_sb_getsboff(fs, 0)); |
976 | lfs_sb_settstamp(fs, lfs_sb_getotstamp(fs)); | | 1041 | lfs_sb_settstamp(fs, lfs_sb_getotstamp(fs)); |
977 | lfs_sb_setfsbtodb(fs, 0); | | 1042 | lfs_sb_setfsbtodb(fs, 0); |
978 | } | | 1043 | } |
979 | if (lfs_sb_getresvseg(fs) == 0) | | 1044 | if (lfs_sb_getresvseg(fs) == 0) |
980 | lfs_sb_setresvseg(fs, MIN(lfs_sb_getminfreeseg(fs) - 1, \ | | 1045 | lfs_sb_setresvseg(fs, MIN(lfs_sb_getminfreeseg(fs) - 1, \ |
981 | MAX(MIN_RESV_SEGS, lfs_sb_getminfreeseg(fs) / 2 + 1))); | | 1046 | MAX(MIN_RESV_SEGS, lfs_sb_getminfreeseg(fs) / 2 + 1))); |
| @@ -995,35 +1060,30 @@ lfs_mountfs(struct vnode *devvp, struct | | | @@ -995,35 +1060,30 @@ lfs_mountfs(struct vnode *devvp, struct |
995 | goto out; | | 1060 | goto out; |
996 | } | | 1061 | } |
997 | | | 1062 | |
998 | /* Before rolling forward, lock so vget will sleep for other procs */ | | 1063 | /* Before rolling forward, lock so vget will sleep for other procs */ |
999 | if (l != NULL) { | | 1064 | if (l != NULL) { |
1000 | fs->lfs_flags = LFS_NOTYET; | | 1065 | fs->lfs_flags = LFS_NOTYET; |
1001 | fs->lfs_rfpid = l->l_proc->p_pid; | | 1066 | fs->lfs_rfpid = l->l_proc->p_pid; |
1002 | } | | 1067 | } |
1003 | | | 1068 | |
1004 | ump = kmem_zalloc(sizeof(*ump), KM_SLEEP); | | 1069 | ump = kmem_zalloc(sizeof(*ump), KM_SLEEP); |
1005 | ump->um_lfs = fs; | | 1070 | ump->um_lfs = fs; |
1006 | ump->um_fstype = ULFS1; | | 1071 | ump->um_fstype = ULFS1; |
1007 | /* ump->um_cleaner_thread = NULL; */ | | 1072 | /* ump->um_cleaner_thread = NULL; */ |
1008 | if (sizeof(struct lfs) < LFS_SBPAD) { /* XXX why? */ | | 1073 | brelse(primarybuf, BC_INVAL); |
1009 | brelse(bp, BC_INVAL); | | 1074 | brelse(altbuf, BC_INVAL); |
1010 | brelse(abp, BC_INVAL); | | 1075 | primarybuf = NULL; |
1011 | } else { | | 1076 | altbuf = NULL; |
1012 | brelse(bp, 0); | | | |
1013 | brelse(abp, 0); | | | |
1014 | } | | | |
1015 | bp = NULL; | | | |
1016 | abp = NULL; | | | |
1017 | | | 1077 | |
1018 | | | 1078 | |
1019 | /* Set up the I/O information */ | | 1079 | /* Set up the I/O information */ |
1020 | fs->lfs_devbsize = DEV_BSIZE; | | 1080 | fs->lfs_devbsize = DEV_BSIZE; |
1021 | fs->lfs_iocount = 0; | | 1081 | fs->lfs_iocount = 0; |
1022 | fs->lfs_diropwait = 0; | | 1082 | fs->lfs_diropwait = 0; |
1023 | fs->lfs_activesb = 0; | | 1083 | fs->lfs_activesb = 0; |
1024 | lfs_sb_setuinodes(fs, 0); | | 1084 | lfs_sb_setuinodes(fs, 0); |
1025 | fs->lfs_ravail = 0; | | 1085 | fs->lfs_ravail = 0; |
1026 | fs->lfs_favail = 0; | | 1086 | fs->lfs_favail = 0; |
1027 | fs->lfs_sbactive = 0; | | 1087 | fs->lfs_sbactive = 0; |
1028 | | | 1088 | |
1029 | /* Set up the ifile and lock aflags */ | | 1089 | /* Set up the ifile and lock aflags */ |
| @@ -1112,26 +1172,27 @@ lfs_mountfs(struct vnode *devvp, struct | | | @@ -1112,26 +1172,27 @@ lfs_mountfs(struct vnode *devvp, struct |
1112 | lfs_order_freelist(fs); | | 1172 | lfs_order_freelist(fs); |
1113 | | | 1173 | |
1114 | /* Set up segment usage flags for the autocleaner. */ | | 1174 | /* Set up segment usage flags for the autocleaner. */ |
1115 | fs->lfs_nactive = 0; | | 1175 | fs->lfs_nactive = 0; |
1116 | fs->lfs_suflags = malloc(2 * sizeof(u_int32_t *), | | 1176 | fs->lfs_suflags = malloc(2 * sizeof(u_int32_t *), |
1117 | M_SEGMENT, M_WAITOK); | | 1177 | M_SEGMENT, M_WAITOK); |
1118 | fs->lfs_suflags[0] = malloc(lfs_sb_getnseg(fs) * sizeof(u_int32_t), | | 1178 | fs->lfs_suflags[0] = malloc(lfs_sb_getnseg(fs) * sizeof(u_int32_t), |
1119 | M_SEGMENT, M_WAITOK); | | 1179 | M_SEGMENT, M_WAITOK); |
1120 | fs->lfs_suflags[1] = malloc(lfs_sb_getnseg(fs) * sizeof(u_int32_t), | | 1180 | fs->lfs_suflags[1] = malloc(lfs_sb_getnseg(fs) * sizeof(u_int32_t), |
1121 | M_SEGMENT, M_WAITOK); | | 1181 | M_SEGMENT, M_WAITOK); |
1122 | memset(fs->lfs_suflags[1], 0, lfs_sb_getnseg(fs) * sizeof(u_int32_t)); | | 1182 | memset(fs->lfs_suflags[1], 0, lfs_sb_getnseg(fs) * sizeof(u_int32_t)); |
1123 | for (i = 0; i < lfs_sb_getnseg(fs); i++) { | | 1183 | for (i = 0; i < lfs_sb_getnseg(fs); i++) { |
1124 | int changed; | | 1184 | int changed; |
| | | 1185 | struct buf *bp; |
1125 | | | 1186 | |
1126 | LFS_SEGENTRY(sup, fs, i, bp); | | 1187 | LFS_SEGENTRY(sup, fs, i, bp); |
1127 | changed = 0; | | 1188 | changed = 0; |
1128 | if (!ronly) { | | 1189 | if (!ronly) { |
1129 | if (sup->su_nbytes == 0 && | | 1190 | if (sup->su_nbytes == 0 && |
1130 | !(sup->su_flags & SEGUSE_EMPTY)) { | | 1191 | !(sup->su_flags & SEGUSE_EMPTY)) { |
1131 | sup->su_flags |= SEGUSE_EMPTY; | | 1192 | sup->su_flags |= SEGUSE_EMPTY; |
1132 | ++changed; | | 1193 | ++changed; |
1133 | } else if (!(sup->su_nbytes == 0) && | | 1194 | } else if (!(sup->su_nbytes == 0) && |
1134 | (sup->su_flags & SEGUSE_EMPTY)) { | | 1195 | (sup->su_flags & SEGUSE_EMPTY)) { |
1135 | sup->su_flags &= ~SEGUSE_EMPTY; | | 1196 | sup->su_flags &= ~SEGUSE_EMPTY; |
1136 | ++changed; | | 1197 | ++changed; |
1137 | } | | 1198 | } |
| @@ -1208,63 +1269,71 @@ lfs_mountfs(struct vnode *devvp, struct | | | @@ -1208,63 +1269,71 @@ lfs_mountfs(struct vnode *devvp, struct |
1208 | lfs_sb_setpflags(fs, lfs_sb_getpflags(fs) & ~LFS_PF_CLEAN); | | 1269 | lfs_sb_setpflags(fs, lfs_sb_getpflags(fs) & ~LFS_PF_CLEAN); |
1209 | lfs_writesuper(fs, lfs_sb_getsboff(fs, 0)); | | 1270 | lfs_writesuper(fs, lfs_sb_getsboff(fs, 0)); |
1210 | lfs_writesuper(fs, lfs_sb_getsboff(fs, 1)); | | 1271 | lfs_writesuper(fs, lfs_sb_getsboff(fs, 1)); |
1211 | } | | 1272 | } |
1212 | | | 1273 | |
1213 | /* Allow vget now that roll-forward is complete */ | | 1274 | /* Allow vget now that roll-forward is complete */ |
1214 | fs->lfs_flags &= ~(LFS_NOTYET); | | 1275 | fs->lfs_flags &= ~(LFS_NOTYET); |
1215 | wakeup(&fs->lfs_flags); | | 1276 | wakeup(&fs->lfs_flags); |
1216 | | | 1277 | |
1217 | /* | | 1278 | /* |
1218 | * Initialize the ifile cleaner info with information from | | 1279 | * Initialize the ifile cleaner info with information from |
1219 | * the superblock. | | 1280 | * the superblock. |
1220 | */ | | 1281 | */ |
1221 | LFS_CLEANERINFO(cip, fs, bp); | | 1282 | { |
1222 | lfs_ci_setclean(fs, cip, lfs_sb_getnclean(fs)); | | 1283 | struct buf *bp; |
1223 | lfs_ci_setdirty(fs, cip, lfs_sb_getnseg(fs) - lfs_sb_getnclean(fs)); | | 1284 | |
1224 | lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs)); | | 1285 | LFS_CLEANERINFO(cip, fs, bp); |
1225 | lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); | | 1286 | lfs_ci_setclean(fs, cip, lfs_sb_getnclean(fs)); |
1226 | (void) LFS_BWRITE_LOG(bp); /* Ifile */ | | 1287 | lfs_ci_setdirty(fs, cip, lfs_sb_getnseg(fs) - lfs_sb_getnclean(fs)); |
| | | 1288 | lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs)); |
| | | 1289 | lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); |
| | | 1290 | (void) LFS_BWRITE_LOG(bp); /* Ifile */ |
| | | 1291 | } |
1227 | | | 1292 | |
1228 | /* | | 1293 | /* |
1229 | * Mark the current segment as ACTIVE, since we're going to | | 1294 | * Mark the current segment as ACTIVE, since we're going to |
1230 | * be writing to it. | | 1295 | * be writing to it. |
1231 | */ | | 1296 | */ |
1232 | LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, lfs_sb_getoffset(fs)), bp); | | 1297 | { |
1233 | sup->su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; | | 1298 | struct buf *bp; |
1234 | fs->lfs_nactive++; | | 1299 | |
1235 | LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, lfs_sb_getoffset(fs)), bp); /* Ifile */ | | 1300 | LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, lfs_sb_getoffset(fs)), bp); |
| | | 1301 | sup->su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; |
| | | 1302 | fs->lfs_nactive++; |
| | | 1303 | LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, lfs_sb_getoffset(fs)), bp); /* Ifile */ |
| | | 1304 | } |
1236 | | | 1305 | |
1237 | /* Now that roll-forward is done, unlock the Ifile */ | | 1306 | /* Now that roll-forward is done, unlock the Ifile */ |
1238 | vput(vp); | | 1307 | vput(vp); |
1239 | | | 1308 | |
1240 | /* Start the pagedaemon-anticipating daemon */ | | 1309 | /* Start the pagedaemon-anticipating daemon */ |
1241 | mutex_enter(&lfs_lock); | | 1310 | mutex_enter(&lfs_lock); |
1242 | if (lfs_writer_daemon == 0 && lfs_writer_lid == 0 && | | 1311 | if (lfs_writer_daemon == 0 && lfs_writer_lid == 0 && |
1243 | kthread_create(PRI_BIO, 0, NULL, | | 1312 | kthread_create(PRI_BIO, 0, NULL, |
1244 | lfs_writerd, NULL, NULL, "lfs_writer") != 0) | | 1313 | lfs_writerd, NULL, NULL, "lfs_writer") != 0) |
1245 | panic("fork lfs_writer"); | | 1314 | panic("fork lfs_writer"); |
1246 | mutex_exit(&lfs_lock); | | 1315 | mutex_exit(&lfs_lock); |
1247 | | | 1316 | |
1248 | printf("WARNING: the log-structured file system is experimental\n" | | 1317 | printf("WARNING: the log-structured file system is experimental\n" |
1249 | "WARNING: it may cause system crashes and/or corrupt data\n"); | | 1318 | "WARNING: it may cause system crashes and/or corrupt data\n"); |
1250 | | | 1319 | |
1251 | return (0); | | 1320 | return (0); |
1252 | | | 1321 | |
1253 | out: | | 1322 | out: |
1254 | if (bp) | | 1323 | if (primarybuf) |
1255 | brelse(bp, 0); | | 1324 | brelse(primarybuf, BC_INVAL); |
1256 | if (abp) | | 1325 | if (altbuf) |
1257 | brelse(abp, 0); | | 1326 | brelse(altbuf, BC_INVAL); |
1258 | if (ump) { | | 1327 | if (ump) { |
1259 | kmem_free(ump->um_lfs, sizeof(struct lfs)); | | 1328 | kmem_free(ump->um_lfs, sizeof(struct lfs)); |
1260 | kmem_free(ump, sizeof(*ump)); | | 1329 | kmem_free(ump, sizeof(*ump)); |
1261 | mp->mnt_data = NULL; | | 1330 | mp->mnt_data = NULL; |
1262 | } | | 1331 | } |
1263 | | | 1332 | |
1264 | return (error); | | 1333 | return (error); |
1265 | } | | 1334 | } |
1266 | | | 1335 | |
1267 | /* | | 1336 | /* |
1268 | * unmount system call | | 1337 | * unmount system call |
1269 | */ | | 1338 | */ |
1270 | int | | 1339 | int |