]> www.opopop.net Git - reminder/blob - booting_linux_from_a_loop_file_system.mdwn
(no commit message)
[reminder] / booting_linux_from_a_loop_file_system.mdwn
1 No general provision seems to exist to boot a Linux system and loop
2 mount as root a file containing a file system, albeit even more
3 complex scenarii, involving the device mapper and its implementations,
4 are supported. It can be useful to have that facility, if
5 repartitioning or using a live CD is not practical. Of course, this
6 makes sense mostly if you don't already run Linux on the target host.
7
8 So in the example below, I will suppose you want to mount a root file
9 system contained in a NTFS file. This NTFS file is part of an
10 underlying Windows machine. Except for the creation of that NTFS
11 file, the rule of the game is to not have to use Windows for the
12 installation step and to not mess with the Windows setup, especially
13 not it's boot process. Booting will happen through an external device
14 (network, CD or USB stick).
15
16 # Similar approaches
17  
18 The above constraint obviously rules out approaches such as
19 [CoLinux](http://www.colinux.org/) and
20 [friends](http://www.topologilinux.com). Other methods which run
21 the installer on Windows such as [Wubi](http://wubi.sourceforge.net) or the [Debian Windows installer](http://en.wikipedia.org/wiki/Win32-loader_(Debian\)) are also out, even if they probably use the
22 same kind of tricks which I will describe below. So this was actually
23 a way for me to learn these!
24
25 # Booting principles
26
27 The current standard way of booting Debian is recalled briefly:
28
29 1. the boot loader (GRUB) loads the kernel image and an initramfs file (line initrd in the GRUB configuration)
30 1. the boot loader uncompresses the kernel and pass control to it
31 1. the initramfs file (a cpio gzipped archive) is uncompressed and mounted as the root file system
32 1. /sbin/init is run and does it's job: essentially loading needed
33 kernel modules which have been prepared inside the initramfs and which
34 are needed for mounting the real root file system, which name is given
35 by kernel options root=
36 1. the real root file system is mounted, presence of initramfs is cleaned up 
37 and control is passed to the /sbin/init there
38
39 More information about initramfs and it's predecessor initrd can be 
40 found on [Wikipedia](http://en.wikipedia.org/wiki/Initrd).
41
42 Our strategy will be to modify the initramfs file system content to be able to 
43 loop mount an NTFS file. But first, you will have to create and populate that file.
44
45 # Installing a Linux root file system in a NTFS file
46
47 The Debian installer has no direct option for that. You could proceed
48 as follows, in case you have only one file system and no swap:
49
50 1. create some big NTFS file, say /somedir/myownrootfs; this is the only step requiring running Windows
51 1. boot a Debian installer CD, and start a shell when asked to define the root partition
52 1. mount the NTFS partition, and create a file system on /somedir/myownrootfs
53 1. exit the shell and continue the installation as normal, naming /somedir/myownrootfs as the root partition and giving the loop option
54 1. at the end of the installation, don't let GRUB write on your NTFS partition
55
56 If you want swap or separate file systems for /usr, /home..., you will have to adapt the above procedure. 
57
58 # Booting in a Linux system whose root file system is a NTFS file
59
60 At that point, your only option to boot in the previously installed
61 system is to run the CD installer in rescue mode, loop mount the NTFS
62 file and pivot_root in it. You will have to do that at least once, as
63 the following procedure requires modifications to some files inside
64 /somedir/myownrootfs, and running a command to generate a new
65 initramfs while the system is live.
66
67 So from now on, I will suppose you have booted in your system as
68 explained just above.
69
70 # initramfs-tools 
71
72 The Debian specific package initramfs-tools contains all that is
73 necessary to manipulate and build the initramfs file. The man page of
74 initramfs-tools explains the organization of the Debian initramfs. In
75 particular, /etc/initramfs-tools is where to put host specific scripts
76 to run inside initramfs, while /usr/share/initramfs-tools contains
77 generic stuff.
78
79 You are encouraged to explore the initramfs file created by the
80 installation process (called like /boot/initrd.img-2.6...) to
81 understand fully how the following works.
82
83 # Modifying initramfs content
84
85 The root file system is to be given as the root= option for the
86 kernel, normally a partition name. In our case, we need 2 pieces of
87 information: the name of the file containing the root file system and
88 it's NTFS partition name. So we need to add an additional kernel
89 option providing that file name; I will use loop=/somedir/myownrootfs,
90 while the NTFS partition will be called /dev/sdb5.
91
92 This implies editing the GRUB configuration file, for instance the kernel line would  be like:
93     <pre>
94     kernel ... root=/dev/sdb5 loop=/somedir/myownrootfs ...
95     </pre>
96
97 Now the modifications to /etc/initramfs-tools:
98
99 * File /etc/initramfs-tools/modules:
100     <pre>
101     loop
102     ntfs
103     </pre>
104
105 This ensures loop.ko and ntfs.ko are included in initrd.
106
107 * File /etc/initramfs-tools/scripts/init-top/loopboot:
108      <pre>
109      #!/bin/sh     
110      PREREQ=""
111      prereqs()
112      {
113          echo "$PREREQ"
114      }
115      case $1 in
116      # get pre-requisites
117      prereqs)
118          prereqs
119          exit 0
120          ;;
121      esac       
122      [ -d ${rootmnt}2 ] || mkdir --mode=0700 ${rootmnt}2
123      </pre>
124
125 This ensures some intermediate mounting point /root2 is created 
126 (rootmnt having value /root from /sbin/init).
127
128 * File /etc/initramfs-tools/scripts/local-premount/loopboot:
129      <pre>
130      #!/bin/sh      
131      PREREQ=""
132      prereqs()
133      {
134          echo "$PREREQ"
135      }
136      case $1 in
137      # get pre-requisites
138      prereqs)
139          prereqs
140          exit 0
141          ;;
142      esac      
143      modprobe -k ntfs
144      mount -n -t ntfs -o nodiratime,noatime ${ROOT} ${rootmnt}2      
145      modprobe -k loop
146      mount -n -t ext2 -o loop ${rootmnt}2${loop} ${rootmnt}
147      </pre>
148
149 This loop mounts effectively the file from loop= option at the
150 expected point. Notice that I have here hardcoded the file system
151 types. It's certainly possible to autodetect them, but then a larger
152 set of file systems modules are to be included in
153 /etc/initramfs-tools/modules
154
155 # Creating a bootable device
156
157 Now you have to run update-initramfs to get the new
158 initrd.img-2.6... file in place. At that point, if you want to reboot
159 without the installer CD, you have these choices:
160
161 * create a bootable device: USB stick, CD-ROM... including the kernel
162   image and initramfs file; GRUB on that device has to be configured
163   to load it from there
164 * in case of network booting, upload kernel
165   image and initramfs file to another host
166   configured as a bootp or dhcp server. For how 
167   to do that, see for instance [[booting_linux_through_the_network]]
168
169 Notice how the /boot directory content on /somedir/myownrootfs will
170 never be used when booting; it is only there to feed the booting
171 method just chosen.
172
173 For the sake of completeness, here is how to create an iso for a bootable CD-ROM:
174
175 1. install package grub-rescue; it contains an iso file 
176 /usr/lib/grub-rescue/grub-rescue-cdrom.iso
177 1. mount that iso as e.g. /media/cdrom
178 1. copy all the content of /media/cdrom to a temporary place, e.g. /tmp/newiso, 
179 while keeping the permissions of the files and directories
180 1. you can now unmount /media/cdrom
181 1. in /tmp/newiso, you can remove boot.catalog, but add to it kernel
182   image and initramfs file
183 1. in /tmp/newiso/boot/grub, edit grub.cfg to boot from 
184 the 2 files just added above, which would look like:
185     <pre>
186     menuentry "GNU/Linux" {
187            set root=(cd)
188            linux /vmlinuz root=/dev/sdb5 loop=/somedir/myownrootfs
189            initrd /initrd.img
190     }
191     </pre>
192 1. create a bootable iso with a command like:
193     <pre>
194     genisoimage -o /tmp/new.iso /tmp/newiso
195     </pre>
196 1. burn the iso:
197     <pre>
198     wodim /tmp/new.iso
199     </pre>
200
201 # The moment of truth
202
203 Then, you can reboot with the just burned CD. In case of problems,
204 [use the break= or debug
205 kernel options](http://wiki.debian.org/InitramfsDebug).
206
207 # Several partitions inside NTFS
208
209 If you have separate /var, /usr or /home partitions as loop filesystems inside the NTFS partition, you will certainly not get a full boot at the first trial. Let's see why.
210
211 When you initramfs has run pivot_root to switch to the final / partition inside the NTFS partition, the new /sbin/init loses all knowledge that the NTFS partition is actually mounted and must rely on information in /etc/fstab to mount the remaining /var, /usr or /home. Obviously, the entry for these partitions will be some loop file mount from the NTFS partition, which must be mounted **first**.
212
213 Because the order of mounting the filesystems in /etc/fstab is random, you have to force mounting the NTFS partition first (which was already mounted inside initramfs, remember; doesn't you head spin now?). Here is a diff from a Squeeze installation which shows my hackish solution:
214
215 <pre>
216 $ diff -C 2 /etc/init.d/checkfs.sh /etc/init.d/checkfs.sh-O 
217 *** /etc/init.d/checkfs.sh      2012-02-09 18:19:55.000000000 +0100
218 --- /etc/init.d/checkfs.sh-O    2011-01-01 06:55:27.000000000 +0100
219 ***************
220 *** 140,145 ****
221   }
222   
223 - mount -a -t ntfs
224
225   case "$1" in
226     start|"")
227 --- 140,143 ----
228 $ diff -C 2 /etc/init.d/mountall.sh /etc/init.d/mountall.sh-O 
229 *** /etc/init.d/mountall.sh     2012-02-09 18:17:40.000000000 +0100
230 --- /etc/init.d/mountall.sh-O   2011-01-01 06:55:27.000000000 +0100
231 ***************
232 *** 28,32 ****
233         #
234         mount_all_local() {
235 !           mount -a -t nontfs,nfs,nfs4,smbfs,cifs,ncp,ncpfs,coda,ocfs2,gfs,gfs2 \
236                 -O no_netdev
237         }
238 --- 28,32 ----
239         #
240         mount_all_local() {
241 !           mount -a -t nonfs,nfs4,smbfs,cifs,ncp,ncpfs,coda,ocfs2,gfs,gfs2 \
242                 -O no_netdev
243         }
244 </pre>
245
246 # Related links
247
248 * comparing initramfs with an [alternative](http://wiki.debian.org/InitrdReplacementOptions)
249 * what is said about initramfs by the [Debian competition](http://en.gentoo-wiki.com/wiki/Initramfs)
250 * as noted at the beginning, there is support in initramfs-tools for the 
251 [device mapper](http://linuxgazette.net/114/kapil.html), so
252 a more generic solution to the problem solved here 
253 may involve some work on top of that, such as [dm-loop](http://sources.redhat.com/lvm2/wiki/DMLoop)