summaryrefslogtreecommitdiff
path: root/ufs/hyper.c
diff options
context:
space:
mode:
Diffstat (limited to 'ufs/hyper.c')
-rw-r--r--ufs/hyper.c414
1 files changed, 0 insertions, 414 deletions
diff --git a/ufs/hyper.c b/ufs/hyper.c
deleted file mode 100644
index 95013895..00000000
--- a/ufs/hyper.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/* Fetching and storing the hypermetadata (superblock and cg summary info).
- Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "ufs.h"
-#include <string.h>
-#include <stdio.h>
-#include <error.h>
-#include <hurd/store.h>
-
-static int ufs_clean; /* fs clean before we started writing? */
-
-static int oldformat;
-
-void *zeroblock;
-
-struct fs *sblock;
-struct csum *csum;
-
-void
-swab_sblock (struct fs *sblock)
-{
- int i, j;
-
- sblock->fs_sblkno = swab_long (sblock->fs_sblkno);
- sblock->fs_cblkno = swab_long (sblock->fs_cblkno);
- sblock->fs_iblkno = swab_long (sblock->fs_iblkno);
- sblock->fs_dblkno = swab_long (sblock->fs_dblkno);
- sblock->fs_cgoffset = swab_long (sblock->fs_cgoffset);
- sblock->fs_cgmask = swab_long (sblock->fs_cgmask);
- sblock->fs_time = swab_long (sblock->fs_time);
- sblock->fs_size = swab_long (sblock->fs_size);
- sblock->fs_dsize = swab_long (sblock->fs_dsize);
- sblock->fs_ncg = swab_long (sblock->fs_ncg);
- sblock->fs_bsize = swab_long (sblock->fs_bsize);
- sblock->fs_fsize = swab_long (sblock->fs_fsize);
- sblock->fs_frag = swab_long (sblock->fs_frag);
- sblock->fs_minfree = swab_long (sblock->fs_minfree);
- sblock->fs_rotdelay = swab_long (sblock->fs_rotdelay);
- sblock->fs_rps = swab_long (sblock->fs_rps);
- sblock->fs_bmask = swab_long (sblock->fs_bmask);
- sblock->fs_fmask = swab_long (sblock->fs_fmask);
- sblock->fs_bshift = swab_long (sblock->fs_bshift);
- sblock->fs_fshift = swab_long (sblock->fs_fshift);
- sblock->fs_maxcontig = swab_long (sblock->fs_maxcontig);
- sblock->fs_maxbpg = swab_long (sblock->fs_maxbpg);
- sblock->fs_fragshift = swab_long (sblock->fs_fragshift);
- sblock->fs_fsbtodb = swab_long (sblock->fs_fsbtodb);
- sblock->fs_sbsize = swab_long (sblock->fs_sbsize);
- sblock->fs_csmask = swab_long (sblock->fs_csmask);
- sblock->fs_csshift = swab_long (sblock->fs_csshift);
- sblock->fs_nindir = swab_long (sblock->fs_nindir);
- sblock->fs_inopb = swab_long (sblock->fs_inopb);
- sblock->fs_nspf = swab_long (sblock->fs_nspf);
- sblock->fs_optim = swab_long (sblock->fs_optim);
- sblock->fs_npsect = swab_long (sblock->fs_npsect);
- sblock->fs_interleave = swab_long (sblock->fs_interleave);
- sblock->fs_trackskew = swab_long (sblock->fs_trackskew);
- sblock->fs_headswitch = swab_long (sblock->fs_headswitch);
- sblock->fs_trkseek = swab_long (sblock->fs_trkseek);
- sblock->fs_csaddr = swab_long (sblock->fs_csaddr);
- sblock->fs_cssize = swab_long (sblock->fs_cssize);
- sblock->fs_cgsize = swab_long (sblock->fs_cgsize);
- sblock->fs_ntrak = swab_long (sblock->fs_ntrak);
- sblock->fs_nsect = swab_long (sblock->fs_nsect);
- sblock->fs_spc = swab_long (sblock->fs_spc);
- sblock->fs_ncyl = swab_long (sblock->fs_ncyl);
- sblock->fs_cpg = swab_long (sblock->fs_cpg);
- sblock->fs_ipg = swab_long (sblock->fs_ipg);
- sblock->fs_fpg = swab_long (sblock->fs_fpg);
- sblock->fs_cstotal.cs_ndir = swab_long (sblock->fs_cstotal.cs_ndir);
- sblock->fs_cstotal.cs_nbfree = swab_long (sblock->fs_cstotal.cs_nbfree);
- sblock->fs_cstotal.cs_nifree = swab_long (sblock->fs_cstotal.cs_nifree);
- sblock->fs_cstotal.cs_nffree = swab_long (sblock->fs_cstotal.cs_nffree);
- /* fs_fmod, fs_clean, fs_ronly, fs_flags, fs_fsmnt are all char */
- sblock->fs_cgrotor = swab_long (sblock->fs_cgrotor);
- sblock->fs_cpc = swab_long (sblock->fs_cpc);
- sblock->fs_contigsumsize = swab_long (sblock->fs_contigsumsize);
- sblock->fs_maxsymlinklen = swab_long (sblock->fs_maxsymlinklen);
- sblock->fs_inodefmt = swab_long (sblock->fs_inodefmt);
- sblock->fs_maxfilesize = swab_long_long (sblock->fs_maxfilesize);
- sblock->fs_qbmask = swab_long_long (sblock->fs_qbmask);
- sblock->fs_state = swab_long (sblock->fs_state);
- sblock->fs_postblformat = swab_long (sblock->fs_postblformat);
- sblock->fs_nrpos = swab_long (sblock->fs_nrpos);
- sblock->fs_postbloff = swab_long (sblock->fs_postbloff);
- sblock->fs_rotbloff = swab_long (sblock->fs_rotbloff);
- sblock->fs_magic = swab_long (sblock->fs_magic);
-
- /* Tables */
- if (sblock->fs_postblformat == FS_42POSTBLFMT)
- for (i = 0; i < 16; i++)
- for (j = 0; j < 8; j++)
- sblock->fs_opostbl[i][j] = swab_short (sblock->fs_opostbl[i][j]);
- else
- for (i = 0; i < sblock->fs_cpc; i++)
- for (j = 0; j < sblock->fs_nrpos; j++)
- fs_postbl(sblock, j)[i]
- = swab_short (fs_postbl (sblock, j)[i]);
-
- /* The rot table is all chars */
-}
-
-void
-swab_csums (struct csum *csum)
-{
- int i;
-
- for (i = 0; i < sblock->fs_ncg; i++)
- {
- csum[i].cs_ndir = swab_long (csum[i].cs_ndir);
- csum[i].cs_nbfree = swab_long (csum[i].cs_nbfree);
- csum[i].cs_nifree = swab_long (csum[i].cs_nifree);
- csum[i].cs_nffree = swab_long (csum[i].cs_nffree);
- }
-}
-
-void
-get_hypermetadata (void)
-{
- error_t err;
-
- if (!sblock)
- sblock = malloc (SBSIZE);
-
- /* Free previous values. */
- if (zeroblock)
- munmap ((caddr_t) zeroblock, sblock->fs_bsize);
- if (csum)
- free (csum);
-
- err = diskfs_catch_exception ();
- assert_perror (err);
- bcopy (disk_image + SBOFF, sblock, SBSIZE);
- diskfs_end_catch_exception ();
-
- if ((swab_long (sblock->fs_magic)) == FS_MAGIC)
- {
- swab_disk = 1;
- swab_sblock (sblock);
- }
- else
- swab_disk = 0;
-
- if (sblock->fs_magic != FS_MAGIC)
- {
- fprintf (stderr, "Bad magic number %#lx (should be %#x)\n",
- sblock->fs_magic, FS_MAGIC);
- exit (1);
- }
- if (sblock->fs_bsize > 8192)
- {
- fprintf (stderr, "Block size %ld is too big (max is 8192 bytes)\n",
- sblock->fs_bsize);
- exit (1);
- }
- if (sblock->fs_bsize < sizeof (struct fs))
- {
- fprintf (stderr, "Block size %ld is too small (min is %Zd bytes)\n",
- sblock->fs_bsize, sizeof (struct fs));
- exit (1);
- }
-
- if (sblock->fs_maxsymlinklen > (long)MAXSYMLINKLEN)
- {
- fprintf (stderr, "Max shortcut symlinklen %ld is too big (max is %ld)\n",
- sblock->fs_maxsymlinklen, (long)MAXSYMLINKLEN);
- exit (1);
- }
-
- assert ((__vm_page_size % DEV_BSIZE) == 0);
- assert ((sblock->fs_bsize % DEV_BSIZE) == 0);
- assert (__vm_page_size <= sblock->fs_bsize);
-
- /* Examine the clean bit and force read-only if unclean. */
- ufs_clean = sblock->fs_clean;
- if (! ufs_clean)
- {
- error (0, 0,
- "%s: warning: FILESYSTEM NOT UNMOUNTED CLEANLY; PLEASE fsck",
- diskfs_disk_name);
- if (! diskfs_readonly)
- {
- diskfs_readonly = 1;
- error (0, 0,
- "%s: MOUNTED READ-ONLY; MUST USE `fsysopts --writable'",
- diskfs_disk_name);
- }
- }
-
- /* If this is an old filesystem, then we have some more
- work to do; some crucial constants might not be set; we
- are therefore forced to set them here. */
-
- if (sblock->fs_npsect < sblock->fs_nsect)
- sblock->fs_npsect = sblock->fs_nsect;
-
- if (sblock->fs_interleave < 1)
- sblock->fs_interleave = 1;
-
- if (sblock->fs_postblformat == FS_42POSTBLFMT)
- sblock->fs_nrpos = 8;
-
- if (sblock->fs_inodefmt < FS_44INODEFMT)
- {
- quad_t sizepb = sblock->fs_bsize;
- int i;
-
- oldformat = 1;
- sblock->fs_maxfilesize = sblock->fs_bsize * NDADDR - 1;
- for (i = 0; i < NIADDR; i++)
- {
- sizepb *= NINDIR (sblock);
- sblock->fs_maxfilesize += sizepb;
- }
- sblock->fs_qbmask = ~sblock->fs_bmask;
- sblock->fs_qfmask = ~sblock->fs_fmask;
- }
-
- /* Find out if we support the 4.4 symlink/dirtype extension */
- if (sblock->fs_maxsymlinklen > 0)
- direct_symlink_extension = 1;
- else
- direct_symlink_extension = 0;
-
- csum = malloc (fsaddr (sblock, howmany (sblock->fs_cssize,
- sblock->fs_fsize)));
-
- assert (!diskfs_catch_exception ());
- bcopy (disk_image + fsaddr (sblock, sblock->fs_csaddr),
- csum,
- fsaddr (sblock, howmany (sblock->fs_cssize, sblock->fs_fsize)));
- diskfs_end_catch_exception ();
-
- if (swab_disk)
- swab_csums (csum);
-
- if (store->size < sblock->fs_size * sblock->fs_fsize)
- {
- fprintf (stderr,
- "Disk size (%Ld) less than necessary "
- "(superblock says we need %ld)\n",
- store->size, sblock->fs_size * sblock->fs_fsize);
- exit (1);
- }
-
- zeroblock = mmap (0, sblock->fs_bsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
-
- /* If the filesystem has new features in it, don't pay attention to
- the user's request not to use them. */
- if ((sblock->fs_inodefmt == FS_44INODEFMT
- || direct_symlink_extension)
- && compat_mode == COMPAT_BSD42)
- {
- compat_mode = COMPAT_BSD44;
- error (0, 0,
- "4.2 compat mode requested on 4.4 fs--switched to 4.4 mode");
- }
-}
-
-/* Write the csum data. This isn't backed by a pager because it is
- taken from ordinary data blocks and might not be an even number
- of pages; in that case writing it through the pager would nuke whatever
- pages came after it on the disk and were backed by file pagers. */
-error_t
-diskfs_set_hypermetadata (int wait, int clean)
-{
- error_t err;
-
- pthread_spin_lock (&alloclock);
-
- if (csum_dirty)
- {
- /* Copy into a page-aligned buffer to avoid bugs in kernel device
- code. */
- void *buf = 0;
- size_t read = 0;
- size_t bufsize = round_page (fragroundup (sblock, sblock->fs_cssize));
-
- err = store_read (store,
- fsbtodb (sblock, sblock->fs_csaddr)
- << log2_dev_blocks_per_dev_bsize,
- bufsize, &buf, &read);
- if (err)
- return err;
- else if (read != bufsize)
- err = EIO;
- else
- {
- size_t wrote;
- bcopy (csum, buf, sblock->fs_cssize);
- if (swab_disk)
- swab_csums ((struct csum *)buf);
- err = store_write (store,
- fsbtodb (sblock, sblock->fs_csaddr)
- << log2_dev_blocks_per_dev_bsize,
- buf, bufsize, &wrote);
- if (!err && wrote != bufsize)
- err = EIO;
- }
-
- munmap (buf, read);
-
- if (err)
- {
- pthread_spin_unlock (&alloclock);
- return err;
- }
-
- csum_dirty = 0;
- }
-
- if (clean && ufs_clean && !sblock->fs_clean)
- {
- /* The filesystem is clean, so set the clean flag. */
- sblock->fs_clean = 1;
- sblock_dirty = 1;
- }
- else if (!clean && sblock->fs_clean)
- {
- /* Clear the clean flag */
- sblock->fs_clean = 0;
- sblock_dirty = 1;
- wait = 1; /* must be synchronous */
- }
-
- pthread_spin_unlock (&alloclock);
-
- /* Update the superblock if necessary (clean bit was just set). */
- copy_sblock ();
-
- sync_disk (wait);
- return 0;
-}
-
-/* Copy the sblock into the disk */
-void
-copy_sblock ()
-{
- error_t err;
-
- err = diskfs_catch_exception ();
- assert_perror (err);
-
- pthread_spin_lock (&alloclock);
-
- if (sblock_dirty)
- {
- assert (! diskfs_readonly);
-
- if (sblock->fs_postblformat == FS_42POSTBLFMT
- || oldformat
- || swab_disk)
- {
- char sblockcopy[SBSIZE];
- struct fs *sbcopy = (struct fs *)sblockcopy;
- bcopy (sblock, sblockcopy, SBSIZE);
- if (sblock->fs_postblformat == FS_42POSTBLFMT)
- sbcopy->fs_nrpos = -1;
- if (oldformat)
- {
- sbcopy->fs_maxfilesize = -1;
- sbcopy->fs_qbmask = -1;
- sbcopy->fs_qfmask = -1;
- }
- if (swab_disk)
- swab_sblock (sbcopy);
- bcopy (sbcopy, disk_image + SBOFF, SBSIZE);
- }
- else
- bcopy (sblock, disk_image + SBOFF, SBSIZE);
- record_poke (disk_image + SBOFF, SBSIZE);
- sblock_dirty = 0;
- }
-
- pthread_spin_unlock (&alloclock);
-
- diskfs_end_catch_exception ();
-}
-
-void
-diskfs_readonly_changed (int readonly)
-{
- (*(readonly ? store_set_flags : store_clear_flags)) (store, STORE_READONLY);
-
- mprotect (disk_image, store->size, PROT_READ | (readonly ? 0 : PROT_WRITE));
-
- if (readonly)
- {
- /* We know we are sync'd now. The superblock is marked as dirty
- because we cleared the clean flag immediately after sync'ing.
- But now we want to leave it marked clean and not touch it further. */
- sblock_dirty = 0;
- return;
- }
-
- strcpy (sblock->fs_fsmnt, "Hurd /"); /* XXX */
-
- if (!sblock->fs_clean)
- error (0, 0, "WARNING: UNCLEANED FILESYSTEM NOW WRITABLE");
-}