[If you have similar "Mini-HOWTOs" that you'd like to offer the world,
please mail them to me: m...@cs.cornell.edu. We may either include them
in the upcoming Tips-HOWTO, or just include them separately in the HOWTO
archive. There are no strict guidelines for what constitutes a HOWTO;
I just need to be able to maintain the archives. Anything goes. --mdw]
SHARING SWAP SPACES BETWEEN LINUX AND MS-WINDOWS
A mini-HOWTO
by
Peter Anvin <h...@nwu.edu>
Copyright (C) 1994 H. Peter Anvin
VERSION: 1.0 Date: 04 Apr 1994
0. ABSTRACT
Many people use both Linux and MS-Windows. The ability to do so is an
important part of "the Linux revolution"; i.e. letting people
experiment with (and get hooked on) Linux while still being able to
run their off-the-shelf software. Since both Linux and MS-Windows use
virtual memory with swap to disk, a frequently occurring question in
comp.os.linux.help is how to share swap spaces, in order to reduce the
amount of disk space needed.
There are several methods for sharing swap spaces, the one described
in this document is probably the most complicated one but is the only
one I have encountered that allows maximum performance for both
environments without the risk of trashing a disk partition.
1. WHAT YOU NEED
This procedure have a few requirements that need to be filled. I
strongly recommend that you fill these requirements *anyway*, as there
are several problems with older versions.
* MS-DOS 5.0 or newer [tested with 6.2]
* MS-Windows 3.1 or newer
* A shutdown/init that knows to run a file on shutdown.
The SysVinit-2.50 package does this.
2. THE PROCEDURE
* Boot DOS. Create a DOS partition (using FDISK) the size = the size
swap space you want. It will be assigned a drive letter; use that
drive letter instead of X whenever these instructions lists a
command like "LABEL X:" or "COPY FOO X:DUMMY.DAT"
* Format this partition using the DOS FORMAT command.
FORMAT X:
* Set the volume label on this partition to "SWAP SPACE" using the DOS
LABEL command. Verify it by the DIR command. Please do this as a
separate step. Some versions of FORMAT do not seem to put the
volume label in the boot sector as it should.
LABEL X:
DIR X:
* Start Windows. Go to the Control Panel, select "386 Enhanced".
Select "Virtual Memory" and create a Windows Permanent swap file on
drive X: of maximum size (Windows will tell you the maximum size).
Windows may complain saying it will not use a swap file that big.
Ignore the message and create the file anyway.
* Exit Windows.
* [Optional step] Do a DIR on the volume to check the amount of free
space still left. Just so you won't forget and mistakingly use any
slack space on this volume (which would be erased), pick any file
larger than the amount of free space and perform the following
commands (assume the file is C:LARGE.FIL):
COPY C:LARGE.FIL X:DUMMY.FIL
ATTRIB +R X:DUMMY.FIL
ATTRIB +H X:DUMMY.FIL
The COPY command *should* complain there is not enough space; that
is normal since what we wanted to do was to fill all space on the device.
* Boot Linux, then log in as root.
* Use the fdisk command to find the name of the partition and its size
in blocks. Create a symbolic link from /dev/winswap to this
partition. If the paritition is hda7, then type:
ln -s /dev/hda7 /dev/winswap
[NOTE TO PURISTS: Please use a symlink. The name of this partition
is going to go into several configuration files and inconsistencies
could be fatal.]
* The following is a shell script that analyzes the partition and
derives some special information; extract it as "msinfo", set it
executable and run it as:
msinfo /dev/winswap
----[CUT HERE]----
#!/bin/sh
#
# Extract special sector information from an MS-DOS partition
#
PATH=/bin:/usr/bin:/usr/local/bin
if [ "$#" != "1" ]; then
echo "Usage: $0 <partition-name>"
exit 1
fi
if [ ! -r $1 ]; then
echo "$1: Permission denied"
exit 1
fi
DOSVER=`dd 2>/dev/null if=$1 bs=1 count=8 skip=3`
SECSIZE=`dd 2>/dev/null if=$1 bs=1 count=2 skip=11 | hexdump -e '1/2 "%u\n"'`
RESERV=`dd 2>/dev/null if=$1 bs=1 count=2 skip=14 | hexdump -e '1/2 "%u\n"'`
FATS=`dd 2>/dev/null if=$1 bs=1 count=1 skip=16 | hexdump -e '1/1 "%u\n"'`
ROOTDIR=`dd 2>/dev/null if=$1 bs=1 count=2 skip=17 | hexdump -e '1/2 "%u\n"'`
FATSIZE=`dd 2>/dev/null if=$1 bs=1 count=2 skip=22 | hexdump -e '1/2 "%u\n"'`
LABEL=`dd 2>/dev/null if=$1 bs=1 count=11 skip=43`
FILESYS=`dd 2>/dev/null if=$1 bs=1 count=8 skip=54`
let FATSEC=$FATSIZE*$FATS
let ENTPERSEC=$SECSIZE/32
let ROOTSEC=$ROOTDIR/$ENTPERSEC
let EXTRA=$ROOTDIR%$ENTPERSEC
if [ $EXTRA != 0 ]; then let ROOTSEC=$ROOTSEC+1; fi
let SPECIAL=$RESERV+$FATSEC+$ROOTSEC
echo "Formatting DOS version: $DOSVER"
echo "Filesystem: $FILESYS"
echo "Volume label: $LABEL"
echo "Sector size: $SECSIZE"
echo "Reserved sectors: $RESERV"
echo "FAT sectors: $FATSEC (${FATS}x${FATSIZE})"
echo "Root directory sectors: $ROOTSEC"
echo "Total special sectors: $SPECIAL"
----[END OF SCRIPT]----
Take note at the number saying "Total special sectors", and verify
that the volume label says "SWAP SPACE". If it does not, reboot DOS
and re-do the LABEL command. If it still does not work, please
inform me about which version of DOS you are running, and I will try
to help you out.
* Check the name of the shutdown file. For SysVinit this is the file
listed in the following line of /etc/inittab; add it if you don't
have it.
# Runlevel 0 means shut down the system
l0:0:wait:/etc/brc
For the remainder of this file, I will assume the filename was
/etc/brc.
* Type:
dd if=/dev/winswap bs=512 count=XXX | gzip -9 > /etc/winswap.gz
^^^
Replace
... where XXX is replaced with the "Total special sectors" number.
* Add the following piece of code to your /etc/rc file (or whatever
your init calls it), right before the command "swapon -a" (if there
is no such command, add it to your /etc/rc file right before any
mount commands).
If your swapon is in /etc, replace /sbin/swapon with /etc/swapon.
If it is in /bin, replace with /bin/swapon. Do the same for mkswap.
Replace XXXXX with the actual size of the partition in blocks, as
given by fdisk.
---[BEGIN CODE SEGMENT]---
#
# Verify and initialize swap space
#
echo -n 'Verifying swap space... '
if [ `/bin/dd 2>/dev/null if=/dev/winswap bs=1 count=10 skip=4086` \
= 'SWAP-SPACE' ]; then
echo 'Linux signature found'
/sbin/swapon /dev/winswap
elif [ `/bin/dd 2>/dev/null if=/dev/winswap bs=1 count=11 skip=43` \
= 'SWAP SPACE ' ]; then
echo 'DOS signature found'
/sbin/mkswap /dev/winswap XXXXX
/sbin/swapon /dev/winswap
else
echo 'No signature found'
echo 'ERROR: Will not swap'
fi
---[END CODE SEGMENT]---
* Add the following piece of code to your /etc/brc file (or whatever
it is called); put this after any command that might need swap to be
in place.
---[BEGIN CODE SEGMENT]---
#
# Terminate swapping and restore DOS/Windows swap info
#
/sbin/swapoff /dev/winswap
if [ `/bin/dd 2>/dev/null if=/dev/winswap bs=1 count=10 skip=4086` \
= 'SWAP-SPACE' ]; then
echo 'Restoring DOS/Windows swap info'
/bin/zcat /etc/winswap.gz | /bin/dd of=/dev/winswap 2>/dev/null
else
echo 'ERROR: /dev/winswap lacks swap signature, skipping restore'
fi
---[END CODE SEGMENT]---
* Reboot Linux. You should now have swapping on the new swap device.
3. A COUPLE OF NOTES
* Do not add /dev/winswap to your /etc/fstab file.
* If your Linux session crashes or otherwise exits without running
/etc/brc, you will need to reboot and exit Linux before swapping in
Windows will work. It is also possible to FORMAT X: and re-create
the Windows swapfile. The only way around this would be to put the
equivalent of the /etc/brc commands in the DOS AUTOEXEC.BAT file;
unfortunately I don't know of any way of doing that in DOS!
--
INTERNET: h...@nwu.edu FINGER/TALK: h...@ahab.eecs.nwu.edu
IBM MAIL: I0050052 at IBMMAIL HAM RADIO: N9ITP or SM4TKN
FIDONET: 1:115/511 or 1:115/512 STORMNET: 181:294/101